c - 为什么 .rodata 部分中的静态字符串在 GCC 中有一个四点前缀?

标签 c gcc assembly

对于下面的代码:

#include <stdio.h>

int main() {
    printf("Hello World");
    printf("Hello World1");
    return 0;
}

调用printf生成的程序集如下(64位):

  400474:   be 24 06 40 00          mov    esi,0x400624
  400479:   bf 01 00 00 00          mov    edi,0x1
  40047e:   31 c0                   xor    eax,eax
  400480:   e8 db ff ff ff          call   400460 <__printf_chk@plt>
  400485:   be 30 06 40 00          mov    esi,0x400630
  40048a:   bf 01 00 00 00          mov    edi,0x1
  40048f:   31 c0                   xor    eax,eax
  400491:   e8 ca ff ff ff          call   400460 <__printf_chk@plt>

.rodata部分如下:

Contents of section .rodata:
 400620 01000200 48656c6c 6f20576f 726c6400  ....Hello World.
 400630 48656c6c 6f20576f 726c6431 00        Hello World1.

根据汇编代码,对 printf 的第一次调用具有地址为 400624 的参数,该参数距 .rodata 的开头有 4 个字节的偏移量。我知道它在这里跳过这 4 个点前缀的前 4 个字节。但我的问题是为什么 GCC/链接器在 .rodata 中为字符串生成这个前缀?我在 Ubuntu 14.04 上使用 4.8.4 GCC。编译命令只是:gcc -Ofast my-source.c -o my-program

最佳答案

对于初学者来说,这不是四个点,点只是表示不可打印的字符。您可以在十六进制转储中看到这些字节是 01 00 02 00

最终程序包含链接器添加的其他目标文件,它们是 C 运行时库的一部分。此数据由那里的代码使用。

可以看到地址是0x400620。然后你可以尝试找到一个匹配的符号,例如你可以将它加载到 gdb 并使用 info symbol 命令:

(gdb) info symbol 0x4005f8
_IO_stdin_used in section .rodata of /tmp/a.out

(注意我有一个不同的地址。)

更进一步,您实际上可以找到 source for this in glibc :

/* This records which stdio is linked against in the application. */
const int _IO_stdin_used = _G_IO_IO_FILE_VERSION;

and

#define _G_IO_IO_FILE_VERSION 0x20001

这对应于您在考虑小端存储时看到的值。

关于c - 为什么 .rodata 部分中的静态字符串在 GCC 中有一个四点前缀?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34733136/

相关文章:

c - 使用 MKL DIA 例程的稀疏矩阵 vector 乘法

c++ - gcc gprof/gcov/other - 如何获得函数调用/退出序列+控制流语句

c - 使用 C 和 gcc 的 OpenMP omp_set_num_threads() 无效

opencv - 优化SIMD直方图计算

c - 为什么当 p 指向数组时 p 和 *p 给出相同的地址?

c - 为什么允许结构中未定义大小的数组?

c - 在串行通信的情况下,tcgetattr 的错误 9 是什么

gcc - 使用 GCC 时如何禁用矢量化?

assembly - vmovdqu在这里做什么?

assembly - 如何将拇指条件指令放入 IT block