共享库中的符号查找

时间:2017-03-12 13:11:20

标签: c gcc function-interposition library-interposition

我在下面测试了这么简单的程序

            case 1 : 
                System.out.println("Enter integer element to insert");
                list.insert( scan.nextInt() );                     
                break;  

我的主要节目是这样的:

/* a shared library */
dispatch_write_hello(void)
{
        fprintf(stderr, "hello\n");
}

extern void
print_hello(void)
{
        dispatch_write_hello();
}

程序的结果是"覆盖"。为了弄清楚为什么会发生这种情况,我使用了gdb。呼叫链是这样的:
extern void dispatch_write_hello(void) { fprintf(stderr, "overridden\n"); } int main(int argc, char **argv) { print_hello(); return 0; }
我发现glibc中_dl_runtime_resolve -> _dl_fixup ->_dl_lookup_symbol_x的定义是

  

搜索已加载的对象'用于符号UNDEF_NAME定义的符号表,可能带有符号

的请求版本

所以我想在尝试找到符号_dl_lookup_symbol_x时,它首先在主对象文件中查找,然后在共享库中查找。这就是这个问题的原因。我的理解是对的吗?非常感谢你的时间。

1 个答案:

答案 0 :(得分:2)

鉴于您提到dispatch_write_hello,我认为您使用的是Linux系统(感谢@Olaf澄清这一点)。

对您的问题的简短回答 - 是的,在符号插入期间,动态链接器将首先查看可执行文件内部,然后再扫描共享库。因此dispatch_write_hello的定义将占上风。

修改

如果你想知道为什么运行时链接器需要解析print_hellodispatch_write_hello对同一翻译单元中除-fPIC之外的任何内容的调用 - 这是由所谓的语义插入支持引起的在GCC。默认情况下,编译器将库代码中的任何调用(即使用-fvisibility-hidden编译的代码)视为在运行时可能是可插入的,除非您通过-Wl,-Bsymbolic-fno-semantic-interposition,{{1}明确告知它}或__attribute__((visibility("hidden")))。这已在网上多次讨论,例如在臭名昭着的Sorry state of dynamic libraries on Linux

作为旁注,与其他编译器(Clang,Visual Studio)相比,此功能会带来显着的性能损失。