编译器如何使用lib文件?

4
我很好奇c/c++编译器如何分析lib文件?我的意思是,如果我创建了一个包含一些类的库,我在主程序中使用该库。编译器如何知道该库中有哪些类名。当然,这些信息以二进制格式存在,我想在我的程序中使用这种功能,具体来说,我有一个二进制lib文件,并且我想知道该lib文件中包含的所有类和属性/函数。
可能吗?如果编译器可以做到这一点,为什么某个库不能呢?
谢谢任何线索
4个回答

6
编译器并不会做你所建议的事情,而连接器会做。编译器知道与库文件相关的头文件中所需的信息。连接器将你包含的声明和库文件以及其它对象文件组合在一起。虽然可能可以通过反编译.lib文件来获取信息,但这需要很多工作,而且可能不是你想要做的。

我们能在我们的程序中使用那个功能吗?有没有一个库可以像连接器一样知道类名和其属性的工作? - Xinus
@Xinux:可能有,但我不知道。 - Brian R. Bondy

1
通常,.a 库只是一个存档文件,其中包含一堆目标文件。这些命令在 Linux 上执行,不同平台可能会有所不同。您通常可以通过运行 nm libxxx.a 来检查存档文件的基本内容。
/usr/lib> nm libc.a | head -10
init-first.o:
         U abort
         U _dl_non_dynamic_init
0000000000000000 T _dl_start
         w _dl_starting_up
         U __environ
         U __fpu_control
         U __init_misc
0000000000000004 C __libc_argc

nm 的 manpage 上有很多关于输出含义的详细信息。

ar 命令可以为您提取单个文件,例如:

~/tmp> ar x libc.a init-first.o
~/tmp> file init-first.o
init-first.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped

如上所述,这里的对象是ELF格式的,因此对于您所问的复杂部分,您真正需要的是能够检查ELF二进制文件的工具。Linux通常附带命令readelf,它可以在命令行提供大量信息:

~/tmp> readelf -s init-first.o
Symbol table '.symtab' contains 19 entries:
Num:    Value  Size Type    Bind   Vis      Ndx Name
 0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
 1: 00000000     0 SECTION LOCAL  DEFAULT    1
 2: 00000000     0 SECTION LOCAL  DEFAULT    3
 3: 00000000     0 SECTION LOCAL  DEFAULT    4
 4: 00000000     0 SECTION LOCAL  DEFAULT    5
 5: 00000000     0 SECTION LOCAL  DEFAULT    6
 6: 00000000    11 FUNC    GLOBAL DEFAULT    1 _dl_start
 7: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND abort
 8: 00000010   133 FUNC    GLOBAL DEFAULT    1 __libc_init_first
 9: 00000000     0 NOTYPE  WEAK   DEFAULT  UND _dl_starting_up
...

有一个库libelf,很可能可以做你想要的事情,并以编程方式访问此信息。 我从未使用过它,因为我总是从可用的命令行工具中获取所需的信息。

http://directory.fsf.org/wiki/Libelf


1
根据您的系统(我知道这对Linux上的.a文件是正确的,但对于Windows就不太确定了),库文件只是一个存档文件(因此是.a),其中包含一堆普通的对象文件。想象一下tar或zip,你会很接近。链接器更多地是从存档中提取文件,在命令行中添加它们并将所有内容链接在一起(实际上它并不这样做,因为它有一些特殊规则,比如只懒加载获取东西,但它已经足够处理手头的问题了)。
如果您想知道里面有什么,请获取库工具(在Linux上是IIRC ar)并查阅文档。甚至可以用货币来打赌这个工具将能够提取对象文件,然后您可以使用标准工具来提取其内容。

0
为了补充Brian R. Bondy的答案,当代码到达链接器时,对于人类最有用的信息已被剥离。例如,您可以从目标文件(库)中提取以下信息:
class SomeClass implements SomeInterface {
    int get(class &otherClass c, float x);
    bool reallyCoolMethod(int x);
    ...
}

这真的没什么帮助。库的文档应该解释为什么你想要使用它以及如何使用;如果库没有进行充分的文档说明,你可能需要一个更好的库。


我认为C++没有接口:\ - Billy ONeal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接