Cus*_*zer 8 c c++ typedef c-preprocessor
我正在尝试在任意C++或C项目中自动解析typedef .
因为某些typedef是在系统头文件中定义的(例如uint32),我现在正试图通过在我的代码文件上运行gcc预处理器然后扫描预处理文件中的typedef来实现这一点.然后我应该能够替换项目代码文件中的typedef.
我想知道,如果还有另一种,也许更简单的方法,我就会失踪.你能想到一个吗?
原因,我为什么要这样做:我正在使用不同的工具从C/C++项目中提取代码度量.指标是基于方法的.提取指标后,我必须合并由不同工具生成的数据.问题是,其中一个工具解析了typedef而其他工具则没有.如果有typedef用于方法的参数类型,我将度量标准映射到不同的方法名称,这些方法名称实际上是指源代码中的相同方法.
在源代码中考虑这个方法:int test(uint32 par1, int par2)
运行我的工具后,我有指标,映射到一个名为的方法int test(uint32 par1, int par2),我的一些指标被映射到int test(unsigned int par1, int par2).
如果您不关心确定它们的定义位置,可以使用objdump转储解析typedef的C++符号表.
lorien$ objdump --demangle --syms foo
foo: file format mach-o-i386
SYMBOL TABLE:
00001a24 g 1e SECT 01 0000 .text dyld_stub_binding_helper
00001a38 g 1e SECT 01 0000 .text _dyld_func_lookup
...
00001c7c g 0f SECT 01 0080 .text foo::foo(char const*)
...
Run Code Online (Sandbox Code Playgroud)
此代码段来自以下结构定义:
typedef char const* c_string;
struct foo {
typedef c_string ntcstring;
foo(ntcstring s): buf(s) {}
std::string buf;
};
Run Code Online (Sandbox Code Playgroud)
这确实需要您编译所有内容,它只会在生成的可执行文件中显示符号,因此存在一些限制.另一种选择是让链接器转储符号映射.对于GNU工具,add -Wl,-map和-Wl,namewhere name是要生成的文件的名称(请参阅注释).这种方法不会对名称进行解码,但只需要做一些工作就可以对编译器的修改约定进行反向工程.上一个代码段的输出将包含以下内容:
0x00001CBE 0x0000005E [ 2] __ZN3fooC2EPKc
0x00001D1C 0x0000001A [ 2] __ZN3fooC1EPKc
Run Code Online (Sandbox Code Playgroud)
您可以使用C++ ABI规范对这些进行解码.一旦你对它的工作原理感到满意,ABI附带的破碎表就变得无价了.在这种情况下的推导是:
<mangled-name> ::= '_Z' <encoding>
<encoding> ::= <name> <bare-function-type>
<name> ::= <nested-name>
<nested-name> ::= 'N' <source-name> <ctor-dtor-name> 'E'
<source-name> ::= <number> <identifier>
<ctor-dtor-name> ::= 'C2' # base object constructor
<bare-function-type> ::= <type>+
<type> ::= 'P' <type> # pointer to
<type> ::= <cv-qualifier> <type>
<cv-qualifier> ::= 'K' # constant
<type> ::= 'c' # character
Run Code Online (Sandbox Code Playgroud)
注意:看起来GNU会更改参数,ld因此您可能需要检查本地手册(man ld)以确保映射文件生成命令-mapfilename在您的版本中.在最新版本中,使用-Wl,-Mstdout并将其重定向到文件.