g ++链接器如何解析.so文件中的符号

时间:2014-11-06 06:01:46

标签: linker g++

我理解在链接期间对象排序非常重要。在尝试让ld解决所有符号之前,我遇到了很多麻烦。这次ld没有产生任何错误,但输出错误!

项目很大(50K + C ++行)我无法生成简化版本,因此我将尝试描述我遇到的内容。希望有些专家能帮助我弄明白。

g++ -o bad.out a.o b.o ... x.so y.so
g++ -o good.out a.o b.o ... y.so x.so

虽然good.out运行正常,但bad.out却没有。 x.so和y.so都是由独立供应商提供的,因此它们的排序无关紧要。以下是更多线索:

  • a.o使用x.so
  • b.o使用y.so
  • a.o和b.o是独立的,但他们都使用一些共同的类

不正确的行为表现为函数OnRspLogin()从未回调过。这是在y.so中定义的纯虚函数,在b.o中实现。 “grep OnRspLogin * .o * .so”仅在y.so和b.o中找到匹配。

显然ld没有将OnRspLogin()解析为b.o中的那个,但是哪一个解决了?这让我担心,因为链接器没有产生任何错误或警告。

我在CentOS 6.5上使用gcc 4.4.7-4。

修改 我发现x.so和y.so都包含一些常见的符号(例如T TcpClient),所以我猜在解析b.o:TcpClient时链接器选择了x.so:TcpClient(而不是y.so:TcpClient)。虽然更改.so命令可能会解决此问题,但我担心链接器可能会错误地解析a.o中的其他一些符号。那么有没有告诉链接器只使用y.so来解析b.o?请注意,这些.so文件由第三方提供,我无法更改它们。

1 个答案:

答案 0 :(得分:1)

  

我发现x.so和y.so都包含一些常见的符号(例如T TcpClient)

是个问题。如果这些符号应该是不同的,那么可以将这两个库链接在一起 - 它们不是链接兼容的。

供应商解决这些问题的通常的方式是,他们在所有导出的符号(例如vendorA_TcpClient)上使用不同的特定于供应商的前缀,并隐藏所有其他符号。

  

请注意,这些.so文件由第三方提供,我无法更改。

您可以告诉供应商您不能使用他们的库,除非他们避免定义没有前缀为其唯一标识符的符号,并且除非他们解决了这个问题,否则您不会支付它们。这样做时,供应商通常会变得非常敏感。