Post

binutils nm

nm 是一个用于显示目标文件(如 .o 文件、静态库 .a 文件或共享库 .so 文件)中符号信息的工具。它可以帮助你查看符号的名称、类型、可见性等。


1. nm 输出的符号可见性

nm 输出的符号可见性主要通过符号的类型字符来表示。以下是常见的符号类型及其含义:

符号类型含义
A全局绝对符号(Absolute),通常用于未定义的符号。
B未初始化的全局数据(BSS)。
C未初始化的公共符号(Common)。
D已初始化的全局数据(Data)。
G已初始化的全局数据(Small Data)。
I间接引用其他符号的符号(Indirect)。
N调试符号(Debugging symbol)。
R只读数据(Read-only data)。
S未初始化的全局数据(Small BSS)。
T全局函数或代码段中的符号(Text)。
U未定义的符号(Undefined),通常表示需要从其他库中解析的符号。
V弱符号(Weak symbol),可以被其他符号覆盖。
W未标记的弱符号(Weak symbol without a default value)。
-调试符号(Debugging symbol)。
?未知符号类型。

2. 符号可见性的定义

符号的可见性(Visibility)是指符号在链接时是否可以被其他目标文件或库访问。符号可见性通常分为以下几种:

(1) 全局符号(Global)

  • 定义:全局符号可以被其他目标文件或库访问。
  • nm 输出:符号类型为大写字母(如 TDB 等)。
  • 示例
    1
    
    0000000000000000 T main
    

    T 表示 main 是一个全局函数。

(2) 局部符号(Local)

  • 定义:局部符号只能在定义它的目标文件中访问。
  • nm 输出:符号类型为小写字母(如 tdb 等)。
  • 示例
    1
    
    0000000000000000 t helper_function
    

    t 表示 helper_function 是一个局部函数。

(3) 弱符号(Weak)

  • 定义:弱符号可以被其他符号覆盖,通常用于提供默认实现。
  • nm 输出:符号类型为 VW
  • 示例
    1
    
    0000000000000000 V default_function
    

    V 表示 default_function 是一个弱符号。

(4) 未定义符号(Undefined)

  • 定义:未定义符号需要在链接时从其他目标文件或库中解析。
  • nm 输出:符号类型为 U
  • 示例
    1
    
                    U printf
    

    U 表示 printf 是一个未定义的符号。


3. nm 输出示例

假设有一个目标文件 example.onm 的输出可能如下:

1
2
3
4
5
6
0000000000000000 T main
0000000000000010 t helper_function
0000000000000020 D global_variable
0000000000000030 B uninitialized_variable
                  U printf
0000000000000040 V weak_function
  • main 是一个全局函数。
  • helper_function 是一个局部函数。
  • global_variable 是一个已初始化的全局变量。
  • uninitialized_variable 是一个未初始化的全局变量。
  • printf 是一个未定义的符号。
  • weak_function 是一个弱符号。

4. 控制符号可见性

在编程时,可以通过以下方式控制符号的可见性:

(1) static 关键字

将符号定义为 static,使其成为局部符号:

1
2
3
static void helper_function() {
    // ...
}

(2) __attribute__((visibility("...")))

使用 GCC 的 visibility 属性显式控制符号的可见性:

1
2
3
4
5
6
7
__attribute__((visibility("default"))) void public_function() {
    // ...
}

__attribute__((visibility("hidden"))) void private_function() {
    // ...
}

(3) 链接器脚本

通过链接器脚本控制符号的可见性。


5. 总结

  • 全局符号(大写字母)可以被其他目标文件或库访问。
  • 局部符号(小写字母)只能在定义它的目标文件中访问。
  • 弱符号(VW)可以被其他符号覆盖。
  • 未定义符号(U)需要在链接时解析。
This post is licensed under CC BY 4.0 by the author.

© SimonCho. Some rights reserved.

Using the Chirpy theme for Jekyll.

Trending Tags