返回「计算机、信息技术与工程」

ELF文件-符号表与符号可见性

ELF文件 符号表与符号可见性

更多
Markdown 结构化数据
本文目录 6 个章节

ELF文件-符号表与符号可见性

# ELF文件-符号表与符号可见性

符号表

  • .symtab 是静态符号表,包含了所有符号(包括调试符号),用于静态链接。
  • .dynsym 是动态符号表,包含了动态链接需要的符号,用于运行时符号解析。

.symtab (静态)符号表

.symtab 是 ELF 文件中的符号表,包含了程序或库中所有的符号信息,包括函数、全局变量等。它通常用于静态链接调试。符号表包含符号的名称、地址、类型等信息,并且支持调试信息和符号的重定位。

    • 内容
      • 符号的名称。
      • 符号的地址(如果已知)。
      • 符号的类型和绑定信息(例如,是否是函数、变量等)。
      • 符号的段或节(例如,.text.data)。
  • 用途
    • 静态链接:编译器和链接器会通过 .symtab 来解析符号,进行符号重定位。
    • 调试:.symtab 保存了符号信息和调试信息,使得调试器能够读取符号名称、源代码行号等信息。
  • 特点
    • 包含所有符号的详细信息。
    • 静态链接时使用。
    • 可以包含调试信息。
$ readelf -s my_program.o

列出 .symtab 中的符号信息。

.dynsym(动态符号表)

.dynsym 是 ELF 文件中的动态符号表,专门用于动态链接。它只包含程序运行时需要解析的符号,通常用于动态链接(即共享库)。.dynsym 中的符号不包含调试信息和一些其他的静态符号信息,它包含的是在运行时需要查找和链接的符号。

  • 内容
    • 符号的名称(存储在 .dynstr 字符串表中)。
    • 符号的类型、地址(通常在运行时解析)。
    • 符号的绑定信息(如共享库的符号)。
  • 用途
    • 动态链接:当程序需要加载共享库时,动态链接器会通过 .dynsym 来查找符号,完成符号的解析和链接。
    • 符号解析:动态加载时,.dynsym 中的符号会被动态链接器处理,确保外部函数和变量的调用能够正确映射。
  • 特点
    • 只包含动态链接所需的符号。
    • 不包含调试信息。
    • 仅用于动态链接时解析符号。
$ readelf -sW my_program.so

列出 .dynsym 中的符号信息。

函数名称修饰

extern "C":禁用名称修饰

让 C++ 符号变得与 C 符号一样,不会进行名称修饰,这样在不同语言间(如 C/C++、Java)进行调用时,可以确保符号一致性,避免因名称修饰导致的链接错误。

在 C++ 中,函数名称通常会被编译器名称修饰(name mangling)以支持函数重载等特性。extern "C" 是一种指示编译器使用 C 的链接方式,禁止对符号进行名称修饰,使得 C++ 编译器生成的符号与 C 编译器一样,保持简单的函数名。

__attribute__((visibility("default"))):控制符号的可见性

__attribute__((visibility("default"))) 用于控制符号在共享库中的可见性。它告诉编译器将符号暴露给外部程序或库,使得该符号可被动态链接器找到。

默认情况下,C++ 编译器会将符号标记为“隐藏”(“hidden”),这意味着只有定义它的模块内部可以访问该符号。

通过 visibility("default"),符号将变为“公共的”,可以被其他程序链接和使用。

  • 对于动态链接的库,只有可见的符号(标记为 default)会被添加到动态符号表(.dynsym)中,这些符号可以被外部程序或其他共享库引用和解析。
  • 如果符号的可见性是 hidden,则该符号不会出现在动态符号表中,其他程序无法通过动态链接找到该符号。