リンカスクリプトでシンボル単位にアドレスを指定する方法
リンカスクリプトでシンボル単位にアドレスを指定する方法を紹介します。
1.問題点
C/C++で下記の簡単なサンプルを作りました。
#include <stdio.h>
int a;
int b[10];
char c[10];
int main(void) {
printf("&a:%p\n", &a);
printf("&b:%p\n", &b);
printf("&c:%p\n", &c);
a = 100;
b[0] = 1;
c[0] = 'x';
printf("a=%d\n", a);
printf("b[0]=%d\n", b[0]);
printf("c[0]=%c\n", c[0]);
return 0;
}
実行結果
% ./a.out
&a:0x10020180
&b:0x10020184
&c:0x10020318
a=100
b[0]=1
c[0]=x
この実行ファイルのマップは次のようになっています(マップを出力するにはgccまたはg++に"-Wl,-M"を設定)。
.bss 0x0000000010020180 0x1fc /tmp/ccuc7H46.o
0x0000000010020180 a
0x0000000010020184 b
0x0000000010020318 c
このa,b,cの3つのシンボル(変数)について個別にアドレスを指定したいのですが、方法がわかりません。
ということで、リンカスクリプトでシンボル単位にアドレスを指定する方法を紹介します。
2.シンボル単位にアドレスを指定する
シンボル単位にアドレスを指定するには、下記赤色(リンカスクリプト抜粋)の部分を追加します。
.bss :
{
*(.bss)
a = ABSOLUTE(0);
b = ABSOLUTE(4);
c = ABSOLUTE(100);
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we don't
pad the .data section. */
. = ALIGN(. != 0 ? 64 / 8 : 1);
}
シンボルにアドレスを指定するフォーマットは次のとおりです。
SECTIONS
{
<section> :
{ *(<section>)
<symbol> = ABSOLUTE(<address>);
}
}
アドレスにはセクション内の相対アドレスを設定します。
今回の設定では、
SECTIONS
{
:
.bss :
{
*(.bss)
a = ABSOLUTE(0);
b = ABSOLUTE(4);
c = ABSOLUTE(100);
:
}
:
}
という風に、ABSOLUTEに.bssセクションからの相対アドレスを設定することで期待する動作になりました。
aの"0"は、.bssセクションから+0番地、bの"4"は、.bssセクションから+4番地、cの"100"は、.bssセクションから+100番地になります。
実行結果
% ./a.out
&a:0x10020178
&b:0x1002017c
&c:0x100201dc
a=100
b[0]=1
c[0]=x
アドレスはうまく設定されているようですが、マップ上のアドレスは相対指定した値がそのまま入っています。
.bss 0x000000001002037c 0x0 /usr/lib/gcc/ppc64-redhat-linux/4.8.5/../../../../lib64/crtn.o
0x0000000000000000 a = 0x0
0x0000000000000004 b = 0x4
0x0000000000000064 c = 0x64
nmコマンドではアドレスが割り当てられています。
% nm ./a.out
:
0000000010020178 B a
000000001002017c B b
0000000010020178 b completed.8008
0000000010020000 W data_start
0000000010020038 d deregister_tm_clones
0000000010020068 d frame_dummy
0000000010020078 D main
U printf@@GLIBC_2.4
0000000010020048 d register_tm_clones
00000000100201dc B c
:
ちなみに下記のように絶対アドレスを設定すると、
SECTIONS
{
:
.bss :
{
*(.bss)
a = ABSOLUTE(0x10020178);
b = ABSOLUTE(0x1002017c);
c = ABSOLUTE(0x100201dc);
:
}
:
}
ビルドはOKですが、Segmentation faultになります。設定アドレスが.bssセクションのアドレスに加算されてしまうためです。
実行結果
% ./a.out
&a:0x200402f0
&b:0x200402f4
&c:0x20040354
Segmentation fault (コアダンプ)
ということで、シンボルにアドレスを指定する場合は現在のアドレスからの相対アドレスになります。
3.参考サイト
参考サイトは下記です。ありがとうございました。
Posted by yujiro このページの先頭に戻る
トラックバックURL
コメントする
greeting