有没有办法知道哪个编译器生成了静态库?

时间:2009-04-07 22:12:31

标签: linker build-process solaris

第三方为我提供了一个静态库(.a)以与solaris站连接。 我尝试使用sunpro编译,但在链接步骤失败。

我认为问题来自我使用的编译器(gcc代替?)或仅仅是它的版本(因为编译器提供的std lib可能会从库AFAIK预期的版本改变,它可能导致链接步骤出错)。

我怎么知道用哪个编译器来生成这个lib?有没有一些工具呢? sunpro / gcc或其他什么选项?

作为提示: 我前段时间读过编译器在生成目标文件时使用不同的修改约定(是吗?)。不过,“nm --demangle”命令行会打印出来自此静态库中调试符号的所有函数名称。它是如何工作的 ?如果我的假设没问题, nm 确实有办法解决静态库中正在使用的约定,不是吗?或者它只是意味着lib是由GNU gcc生成的,因为nm是GNU binutils的一部分?

我不靠近我的工作站,所以我不能复制&从链接器粘贴错误输出(目前不是,但我可以在进一步编辑中复制它们)

4 个答案:

答案 0 :(得分:5)

从存档中提取目标文件,然后在其中一些上运行strings命令(首先是较小的,因为筛选的噪音较少)。许多编译器在目标文件中插入ASCII签名。

例如,以下无意义的源文件foo.c

extern void blah();

在我的Fedora 10机器上通过gcc -c -o foo.o foo.c编译到foo.o时会产生一个647字节foo.o目标文件。在strings上运行foo.o会导致

GCC: (GNU) 4.3.2 20081105 (Red Hat 4.3.2-7)
.symtab
.strtab
.shstrtab
.text
.data
.bss
.comment
.note.GNU-stack
foo.c

这表明编译器是GCC。即使我用-fno-ident编译它,.GNU-stack note ELF部分仍然存在。

您可以使用ar实用程序或Midnight Commander(集成了ar)提取目标文件,或者只需在存档上运行strings(这可能会给您带来更多噪音,并且不太相关,但仍然有帮助。)

答案 1 :(得分:2)

库应该是C还是C ++库?

如果它是一个C库,那么名称重整可能不是问题,因为C中没有。但它可能是错误的格式。 Unices曾经使用a.out格式的库,但几乎所有新版本都转换为更强大的格式,如ELF

如果它是C ++库,则名称重整可能是一个问题。大多数编译器都会在代码中嵌入一些特定于编译器的符号,所以如果你有一个像nm这样的工具来列出符号,你可以从它的编译器中推断出它。

例如,g ++创建一个符号

  

__ gxx_personality_v0

在它的库中

答案 2 :(得分:2)

我倾向于使用strings程序(使用“-a”选项,或者我自己的变体,其中“-a”行为是标准的)并查找告诉迹象。例如,在我自己的一个库中,我发现:

/work1/gcc/v4.2.3/bin/../lib/gcc/sparc-sun-solaris2.10/4.2.3/include
/work1/gcc/v4.3.0/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.0/include
/work1/gcc/v4.3.1/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.1/include
/work1/gcc/v4.3.3/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.3/include

这表明库中的代码已经在几年内用各种版本的GCC编译(实际上,我很惊讶在单个库中找到这么多版本)。

另一个图书馆包含:

cg: Sun Compiler Common 11 Patch 120760-06 2006/05/26
acomp: Sun C 5.8 Patch 121015-02 2006/03/29
iropt: Sun Compiler Common 11 Patch 120760-06 2006/05/26
/compilers/v11/SUNWspro/prod/bin/cc -O -v -Xa -xarch=v9 ...

因此,目标文件中通常有指纹指示使用了哪个编译器。但你必须知道如何寻找它们。

答案 3 :(得分:-1)

您可以尝试使用unix实用程序文件

file foo.a