10

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

我想问题来自我使用的编译器(而不是 gcc?)或只是它的版本(因为编译器提供的 std lib 可能会从库 AFAIK 预期的版本发生变化,它可能会导致链接步骤出错)。

我怎么知道使用哪个编译器生成这个库?有没有一些工具可以做到这一点?sunpro/gcc 中的一些选项或其他什么?

作为提示:我前段时间读到编译器在生成目标文件时使用不同的修饰约定(真的吗?)。尽管如此,“nm --demangle”命令行仍然可以很好地打印出这个静态库中调试符号的所有函数名称。它是如何工作的 ?如果我的假设没问题,nm确实有办法解决静态库中使用的约定,不是吗?还是仅仅意味着 lib 是由 GNU gcc 生成的,因为 nm 是 GNU binutils 的一部分?

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

4

4 回答 4

6

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

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

extern void blah();

当在我的 Fedora 10 机器上编译成 foo.o 时,gcc -c -o foo.o foo.c结果是一个 647 字节的foo.o目标文件。运行结果strings_foo.o

GCC:(GNU)4.3.2 20081105(红帽 4.3.2-7)
.symtab
.strtab
.shstrtab
。文本
。数据
.bss
。评论
.note.GNU 堆栈
foo.c

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

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

于 2009-04-07T23:51:00.337 回答
4

我倾向于使用该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 ...

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

于 2009-04-08T04:31:36.543 回答
2

该库应该是 C 或 C++ 库吗?

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

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

例如 g++ 创建一个符号

__gxx_personality_v0

在它的图书馆里

于 2009-04-07T23:27:54.790 回答
-1

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

file foo.a
于 2009-04-07T22:22:25.307 回答