c - 链接器在节中添加额外的填充?

标签 c gcc linker ld

我正在使用 GCC,并尝试让链接器从自定义部分中的不同文件创建数据对象数组。我已将此部分添加到链接描述文件中:

.mydata :
{
  __mydata_start = .;
  KEEP (*(.mydata))
  __mydata_end = .;
}

这是我的数据结构:

struct my_type_t {
    unsigned char a;
    size_t b;
    void *c;
    const void *d;
    const void *e;
    const char *f;
};

我使用的是 64 位平台,sizeof(struct my_type_t) 给出 48。但是,链接器似乎希望将这些结构与 64 字节对齐。

我的声明:

struct my_type_t a1 __attribute__((section(".mydata"))) = {
    1, 2, (void *)3, (void *)4, (void *)5, (void *)6,
};
struct my_type_t a2 __attribute__((section(".mydata"))) = {
    7, 8, (void *)9, (void *)10, (void *)11, (void *)12,
};

链接器输出:

$ gcc -o ldtest ldtest.c -Wl,-Tlink.ld
$ objcopy -Obinary -j .mydata ldtest mydata
$ hd mydata
00000000  01 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00  |................|
00000010  03 00 00 00 00 00 00 00  04 00 00 00 00 00 00 00  |................|
00000020  05 00 00 00 00 00 00 00  06 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000040  07 00 00 00 00 00 00 00  08 00 00 00 00 00 00 00  |................|
00000050  09 00 00 00 00 00 00 00  0a 00 00 00 00 00 00 00  |................|
00000060  0b 00 00 00 00 00 00 00  0c 00 00 00 00 00 00 00  |................|

如果我将其声明为数组:

struct my_type_t a1[2] __attribute__((section(".mydata"))) = {
    {
    1, 2, (void *)3, (void *)4, (void *)5, (void *)6,
    },
    {
    7, 8, (void *)9, (void *)10, (void *)11, (void *)12,
    },
};

正如预期的那样,没有填充:

00000000  01 00 00 00 00 00 00 00  02 00 00 00 00 00 00 00  |................|
00000010  03 00 00 00 00 00 00 00  04 00 00 00 00 00 00 00  |................|
00000020  05 00 00 00 00 00 00 00  06 00 00 00 00 00 00 00  |................|
00000030  07 00 00 00 00 00 00 00  08 00 00 00 00 00 00 00  |................|
00000040  09 00 00 00 00 00 00 00  0a 00 00 00 00 00 00 00  |................|
00000050  0b 00 00 00 00 00 00 00  0c 00 00 00 00 00 00 00  |................|

为什么链接器添加超出编译器认为必要的额外填充,以及如何摆脱它?

最佳答案

我不知道为什么它要在 64 字节上对齐,但你可以这样做:

struct my_type_t {
    unsigned char a;
    size_t b;
    void *c;
    const void *d;
    const void *e;
    const char *f;
} __attribute__ ((aligned (64)));

为了使 gcc 自动将每个结构填充到最近的较高 64 字节地址,并使 sizeof(struct my_type_t) 也包含填充。这使得这样的操作可以正常工作:

struct my_type_t *s = &__mydata_start;
s++; // Jump to next entry
s[0]; // First entry
s[1]; // Second entry

关于c - 链接器在节中添加额外的填充?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39728871/

相关文章:

c - 使用 lseek 时不打印第一个字节

c - 使用镜像算法进行快速位反转

转换双指针以及如何在 C 中使用

c - 带条件扩展的 GCC 宏?

c - 如何从共享对象中删除符号?

python - 将 .c 文件编译为 .pyd

c - gcc 汇编字符串表示

c++ - 使用 MinGW 编译 OpenGL 并出现过剩链接器错误

c++ - 如何在将测试 exe 与 gradle 链接时排除第二个主程序?

c - 如何从C获取ld链接程序脚本中定义的变量的值