重新排列对齐的物体以最小化空间使用

6

我有一个需要4-KiB对齐的数据结构。我可以使用__attribute__ ((aligned (4096)))来强制执行这个要求。

问题是,这种对齐要求会浪费内存。这是链接器放置符号的方式(pg_dir是对齐的数据结构):

00011000 <cursor_loc>:
00012000 <pg_dir>:
00013000 <idt>:

cursor_loc 只有四个字节的大小。这样会更好:

00011000 <pg_dir>:
00012000 <cursor_loc>:
00012008 <idt>:

(此处必须将idt调整为8字节对齐。)


您可以通过使用多个类似以下文件来重现它:

test1.c:

char aligned[4096] __attribute__ ((aligned (4096)));
int i;

test2.c:

int j;

int main(void) { }

然后使用以下命令构建:

gcc test1.c test2.c

执行objdump -D a.out命令后,输出结果如下:

0000000000602004 <j>:
        ...

0000000000603000 <aligned>:
        ...

0000000000604000 <i>:

如何移动GNU ld以重新排列符号以最小化空间浪费?我真的很想知道为什么它不会自动完成。

1个回答

3

有一些成语需要按照命令行中指定的对象顺序进行排列(这就是为什么您的结果可能有点奇怪,可能是由于常见符号造成的),而且不能对对象内的定义进行重新排序。要解决这个问题,您需要像这样做:

gcc -fno-common -fdata-sections -Wl,--sort-section=alignment test1.c test2.c

-fno-common 禁用公共符号,-fdata-sections 允许链接器重新排序同一文件中的符号,-Wl,--sort-section=alignment 最后启用对齐方式排序。


非常好,这很整洁。我只是想知道为什么当我使用-fno-common-fdata-sections时,符号仍然出现在.bss中,即使我使用objdump查看它们。实际上,我需要它们在.bss中,但我不明白为什么这些开关不能改变它们所属的部分。 - cadaniluk
是的,我对 .bss 段感到困惑。如果您指定了初始化程序,并且该程序仍然为零,则只能从 .bss 中获取零初始化的符号。编译时可以使用 -fno-zero-initialized-in-bss(以禁止 .bss 优化)。很高兴您需要 .bss 符号。 - Florian Weimer
我尝试了-Wl,--sort-common,但是没有得到期望的效果。 - Florian Weimer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接