nm命令的“符号值”是什么意思?

时间:2009-12-07 23:24:07

标签: c++ linux

当您列出静态库的符号表时,如nm mylib.a,每个符号旁边显示的8位十六进制是什么意思?这是代码中每个符号的相对位置吗?

此外,多个符号可以具有相同的符号值吗?一堆符号值为00000000的不同符号是否有问题?

3 个答案:

答案 0 :(得分:23)

这是我用C编写的一段代码:


#include 
#include 

void foo();

int main(int argc, char* argv[]) {
    foo();
}

void foo() {
   printf("Foo bar baz!");
}

我在该代码上运行了gcc -c foo.c。以下是nm foo.o显示的内容:

000000000000001b T foo
0000000000000000 T main
                 U printf

对于这个例子,我正在运行Ubuntu Linux 64位;这就是为什么你看到的8位十六进制数字在这里是16位数。 : - )

您看到的十六进制数字是目标文件中相对于.text.部分开头的相关代码的地址。 (假设我们处理从0x0开始的目标文件的部分)。如果您运行objdump -td foo.o,则会在输出中看到以下内容:

Disassembly of section .text:

0000000000000000 :
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 83 ec 10             sub    $0x10,%rsp
   8:   89 7d fc                mov    %edi,-0x4(%rbp)
   b:   48 89 75 f0             mov    %rsi,-0x10(%rbp)
   f:   b8 00 00 00 00          mov    $0x0,%eax
  14:   e8 00 00 00 00          callq  19 
  19:   c9                      leaveq
  1a:   c3                      retq

000000000000001b :
  1b:   55                      push   %rbp
  1c:   48 89 e5                mov    %rsp,%rbp
  1f:   b8 00 00 00 00          mov    $0x0,%eax
  24:   48 89 c7                mov    %rax,%rdi
  27:   b8 00 00 00 00          mov    $0x0,%eax
  2c:   e8 00 00 00 00          callq  31 
  31:   c9                      leaveq
  32:   c3                      retq

请注意,这两个符号与我们在nm的符号表中看到的条目对齐。请记住,如果将此目标文件链接到其他目标文件,这些地址可能会更改。另外,请记住,当您将此文件链接到系统提供的任何libc时,0x2c处的callq将会更改,因为这是对printf的不完整调用(它不知道它现在在哪里)。 / p>

至于你的mylib.a,这里还有更多内容。您拥有的文件是存档;它包含多个目标文件,每个文件都有自己的文本段。作为一个例子,这里是我的盒子上的/usr/lib/libm.a的nm的一部分

e_sinh.o:
0000000000000000 r .LC0
0000000000000008 r .LC1
0000000000000010 r .LC2
0000000000000018 r .LC3
0000000000000000 r .LC4
                 U __expm1
                 U __ieee754_exp
0000000000000000 T __ieee754_sinh

e_sqrt.o:
0000000000000000 T __ieee754_sqrt

e_gamma_r.o:
0000000000000000 r .LC0
                 U __ieee754_exp
0000000000000000 T __ieee754_gamma_r
                 U __ieee754_lgamma_r
                 U __rint

您将看到多个文本段已完成 - 由第二列中的T表示,位于地址0x0处,但每个单独的文件只有 一个文本段符号位于0x0。

对于具有多个符号放在同一地址的单个文件,似乎可能可能。毕竟,它只是一个表中的一个条目,用于确定一块数据的位置和大小。但我不确定。我以前从未见过多个符号引用一个部分的相同部分。任何对此有更多了解的人都可以加入。: - )

希望这会有所帮助。

答案 1 :(得分:3)

十六进制数字是可以找到符号的目标文件中的内存偏移量。它实际上是目标代码中的字节数。

链接器使用该值来定位和复制符号的值。如果将-S选项添加到nm,您可以看到它的布局方式,它会显示每个符号的值大小。

答案 2 :(得分:1)

nm显示符号的值。库或目标文件中的某些符号可能仅显示为零,因为它们尚未被赋予值。他们会在链接时获得实际价值。

有些符号是代码符号,有些是数据等。在链接之前,符号值通常是它所在部分的偏移量,