2017-07-16 80 views
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

0000000000602004 <j>: 
     ... 

0000000000603000 <aligned>: 
     ... 

0000000000604000 <i>: 

我怎樣才能移動GNU LD重新排列爲最小的空間浪費符號:

int j; 

int main(void) { } 

然後用

gcc test1.c test2.c 

objdump -D a.out打印此建呢?我真的很想知道爲什麼它不能自動完成。

回答

2

有一些成語要求對象按照命令行中指定的順序排列(這就是爲什麼你的結果有點奇怪,可能是由於常見的符號),並且對象內定義是不重新排序。要解決這一點,你需要的是這樣的:

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

-fno-common禁用常見的符號,-fdata-sections允許鏈接器從同一文件重新排列的符號,並-Wl,--sort-section=alignment終於能夠通過對準排序。

+0

這工作整齊,謝謝。我只是想知道爲什麼當我objdump時它們仍然出現在'.bss'中,儘管我使用了'-fno-common'和'-fdata-sections'。實際上,我需要它們在'.bss'中,這只是我不明白爲什麼這些開關不會更改它們所屬的部分。 – Downvoter

+0

是的,我對'.bss'感到困惑。如果你指定了一個初始化方法,你只能從'.bss'中得到零初始化的符號,如果它仍然爲零,編譯'-fno-zero-initialized-in-bss'(來禁止'.bss'優化) 。很高興你需要'.bss'符號。 –

+0

不會「-Wl, - sort-common」也起作用嗎? – Hasturkun