rx-elf-gccと.rodata.str1.1の問題による不具合
RXduino & 特電HALのデバッグをおこなっていて、問題を見つけました。
どのようなプログラムでバグが起きるかというと、
char tokuden[] = "tokuden hogehoge.....";
のような、初期値を持ったグローバル変数のデータを使うプログラムであって、
printf("%x",
のように16進表示を行う場合です。
printfやsprintfを使うと、libcの中のlib_a-svfiprintf.oというファイルの中にあるコードが呼び出されます。
mapファイルを見ると、.rodataセクションの中に、
・・・
.rodata.p05.2377
0xfff892c0 0xc lib/gcc/libc.a(lib_a-mprec.o)
.rodata.str1.1
0x00000000 0x29 lib/gcc/libc.a(lib_a-svfiprintf.o)
.rodata._svfiprintf_r
0xfff892cc 0x164 lib/gcc/libc.a(lib_a-svfiprintf.o)
.rodata.blanks.3804
0xfff89430 0x10 lib/gcc/libc.a(lib_a-svfiprintf.o)
・・・
と、 .rodata.str1.1というセクションが作られていて、0x29バイトのデータが0x00000000番地に配置されているのがわかります。このデータというのは何かというと、"0123456789ABCDEF"と"0123456789abcdef"と"(null)"が格納されています。問題は、このセクションだけなぜか0x00000000番地に配置されてしまっていることです。
したがって、次の.dataセクションが0x00000000番地に配置されるとすると、問題が生じます。
.dataセクションに配置されるデータというのは、例えば、
char tokuden[] = "tokuden hogehoge.....";のように、グローバル変数領域に書かれたものです。
まだ詳しいメカニズムはわかっていませんが、とにかく.rodata.str1.1のセクションと.dataセクションが被っていると、だんだんおかしなことになってくるのは間違いありません。
どのように解決すればよいかというと、リンカスクリプト(rx62n_rom_standalone.ld)を開いて、
KEEP (*(.eh_frame))
KEEP (*(.gcc_except_table)) *(.gcc_except_table.*)
. = ALIGN(4);
__rodataend = .;
}.data 0x00000000 : AT (__rodataend) {
・・・
のようになっている箇所を
KEEP (*(.eh_frame))
KEEP (*(.gcc_except_table)) *(.gcc_except_table.*)
. = ALIGN(4);
__rodataend = .;
}.data 0x00001000 : AT (__rodataend) {
・・・
と変更して、.dataセクションの開始番地を0x1000番地に移動してください。
.rodata.str1.1自体を然るべき場所に移動する方法はまだわかっていません。
この問題は次のrxduino-071でFIXする予定です。



















最近のコメント