nm 命令中的“符号值”是啥意思?

Posted

技术标签:

【中文标题】nm 命令中的“符号值”是啥意思?【英文标题】:What does "symbol value" from nm command mean?nm 命令中的“符号值”是什么意思? 【发布时间】:2009-12-07 23:24:06 【问题描述】:

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

另外,多个符号可以具有相同的符号值吗?一堆不同的符号都具有 00000000 的符号值有什么问题吗?

【问题讨论】:

nm,在处理目标文件的情况下,他们的文档需要更加清晰。它返回的“价值”字段可能对某人有用,但它的描述对我来说就像它的潜在用途一样晦涩难懂。它看起来像是某种偏移量,但不幸的是,文档没有提供任何关于它的线索...... 【参考方案1】:

这是我用 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 主 u printf

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

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

部分.text的反汇编: 0000000000000000 : 0: 55 推送 %rbp 1: 48 89 e5 移动 %rsp,%rbp 4: 48 83 ec 10 sub $0x10,%rsp 8: 89 7d fc mov %edi,-0x4(%rbp) b: 48 89 75 f0 移动 %rsi,-0x10(%rbp) f: b8 00 00 00 00 移动 $0x0,%eax 14:e8 00 00 00 00 呼叫 19 19:c9 离开 1a:c3 retq 000000000000001b: 1b: 55 推送 %rbp 1c: 48 89 e5 移动 %rsp,%rbp 1f: b8 00 00 00 00 移动 $0x0,%eax 24: 48 89 c7 移动 %rax,%rdi 27: b8 00 00 00 00 移动 $0x0,%eax 2c: e8 00 00 00 00 呼叫 31 31:c9 离开 32: c3 重新调用

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

至于您的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 处只有一个一个文本段符号。

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

希望这会有所帮助。

【讨论】:

如果你用x86_64-w64-mingw32-g++编译你的例子,你会看到nm有多个引用零地址并带有A标记的符号,也就是说,地址不会是未来改变了。例如。 0000000000000000 A __dll__ 0000000000000000 A __dll_characteristics__。切中要害——I've seen that there were 映射了实际有用的函数。我想知道,这意味着什么?【参考方案2】:

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

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

【讨论】:

【参考方案3】:

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

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

【讨论】:

以上是关于nm 命令中的“符号值”是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

如何阅读 nm 命令:nm 选项 -T 和 -U(未定义)是啥意思?

Linux的nm查看动态和静态库中的符号

这个 nm 输出是啥意思?

这个 nm 输出“V typeinfo name for void*”是啥意思?

Boost.Exception 符号出现在“nm”输出中是啥意思?它们会导致 ODR 违规吗?

这个 curl 命令行中的“OPEN”是啥意思?