为什么.bss / .rodata符号在剥离后保持二进制?

时间:2014-11-13 13:04:53

标签: c gcc ffmpeg linker elf

据我所知,真正需要的可执行二进制文件中只有一种符号,即动态符号。这些符号用于重定位操作,因为它们是动态链接的。另一方面,不需要静态链接函数/变量,因此可以剥离它。

然而,当我检查剥离的 ffmpeg二进制文件时,这就是我所得到的:

>nm -D ffmpeg
...
                 U __vfprintf_chk
                 U __vsnprintf_chk
                 U write
00000000018fa880 B x264_cabac_contexts
0000000001052a40 R x264_cabac_range_lps
0000000001052940 R x264_cabac_transition
0000000001970580 B x264_cabac_transition_unary
0000000001056820 R x264_last_coeff_flag_offset
0000000001056860 R x264_significant_coeff_flag_offset
0000000001056900 R x264_significant_coeff_flag_offset_8x8
                 U __xpg_strerror_r
                 U __xstat64
...

我可以验证libx264是静态链接到ffmpeg:

> ldd ffmpeg
linux-vdso.so.1 =>  (0x00007fff26d61000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f7c707e7000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f7c704e1000)
liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f7c702be000)
libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0 (0x00007f7c700ae000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f7c6fe95000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f7c6fc76000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7c6f8b0000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7c70b0a000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f7c6f69a000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f7c6f495000)

所以,我不明白为什么像x264_cabac_contexts这样的符号没有被删除。 (它在libx264 /.../ cabac.c中定义):

uint8_t x264_cabac_contexts[4][QP_MAX_SPEC+1][1024];

困扰了我几个小时,我在谷歌上找不到任何东西......希望有人能解释一下......提前致谢!

2 个答案:

答案 0 :(得分:1)

  

据我所知,真正需要的可执行二进制文件中只有一种符号,即动态符号

正确。

  

所以,我不明白为什么像x264_cabac_contexts这样的符号没有被剥离。

因为它们是动态符号(这正是nm -D正在打印的内容)。

您应该问的问题不是为什么动态符号没有被剥离,而是为什么x264_cabac_contexts是动态符号。

有两种可能的答案:

  1. ffmpeg二进制文件与--export-dynamic或等效标志或
  2. 相关联
  3. 该符号由参与该链接的某个共享库引用。
  4. 查看ldd输出中的共享库列表,答案#2似乎不太可能。所以回答#1可能是正确的。

      

    不,我不是用-rdynamic

    编译它

    编译与此无关。重要的是链接。你没有显示你的链接命令,但它可能有一些标志,这意味着“导出所有符号”(即相当于-rdynamic)。或者您使用执行相同操作的链接描述文件。

答案 1 :(得分:0)

什么?

如果您的代码中有实际的常量只读数据,例如

const char *serialNumber = "451722-145252";

然后当然必须住在某个地方,如果你剥离它就会破坏程序,以免被删除。

如果serialNumber此处不是static,则无法删除。