私はあなたが見ていることを繰り返したと思います:
statloc.c
符号なしの int グロブ。
unsigned int fun ( unsigned int a )
{
static unsigned int loc;
if(a==0) loc=7;
return(a+glob+loc);
}
arm-none-linux-gnueabi-gcc -mcpu=cortex-m3 -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -fpic -pie -S statloc.c
これにより、次のことが得られます。
.cpu cortex-m3
.fpu softvfp
.thumb
.text
.align 2
.global fun
.thumb
.thumb_func
fun:
ldr r3, .L6
.LPIC2:
add r3, pc
cbnz r0, .L5
ldr r1, .L6+4
movs r2, #7
.LPIC1:
add r1, pc
ldr ip, .L6+8
str r2, [r1, #0]
ldr r1, [r3, ip]
ldr r3, [r1, #0]
adds r0, r0, r3
adds r0, r0, r2
bx lr
.L5:
ldr ip, .L6+8
ldr r2, .L6+12
ldr r1, [r3, ip]
.LPIC0:
add r2, pc
ldr r2, [r2]
ldr r3, [r1, #0]
adds r0, r0, r3
adds r0, r0, r2
bx lr
.L7:
.align 2
.L6:
.word _GLOBAL_OFFSET_TABLE_-(.LPIC2+4)
.word .LANCHOR0-(.LPIC1+4)
.word glob(GOT)
.word .LANCHOR0-(.LPIC0+4)
.size fun, .-fun
.comm glob,4,4
.bss
.align 2
.LANCHOR0 = . + 0
.type loc.823, %object
.size loc.823, 4
loc.823:
.space 4
また、起動コードを追加し、バイナリをコンパイルして逆アセンブルし、何が起こっているのかをさらに理解/検証しました。
これは、PC から .got までのオフセットです。
ldr r3、.L6
pc を追加して、r3 が .got への位置に依存しないオフセットを保持するようにします。
r3、pcを追加
グロブのアドレスに対する get のオフセット
ldr ip, .L6+8
取得したグローバル変数の絶対アドレスを読み取る
ldr r1、[r3、ip]
最後にグローバル変数をr3に読み込みます
ldr r3、[r1、#0]
これは、PC から .bss 内の静的ローカルへのオフセットです。
ldr r2, .L6+12
pc を追加して、r2 が静的ローカルへの位置に依存しないオフセットを保持するようにします。
.bss で
r2、pcを追加
.bss の静的ローカルを読み取る
ldr r2、[r2]
したがって、.text がロードされる場所を変更し、.got と .bss の両方が .text に対してロードされる場所を変更すると、.got の内容が正しくなくなり、グローバル変数が間違った場所。
.text がロードされる場所を変更する場合は、.bss をリンカが配置した場所に残し、.got を .text に対して相対的に移動します。次に、グローバルは適切な場所からプルされ、ローカルはプルされません
.text がロードされる場所を変更し、.got と .bss の両方がロードされる場所を .text に対して相対的に変更し、.got の内容を変更して .text がロードされる場所を反映する場合、ローカル変数とグローバル変数の両方が適切な場所。
そのため、ローダーと gcc/ld はすべて同期している必要があります。私の当面の推奨事項は、静的ローカルを使用せず、グローバルのみを使用することです。それまたは位置に依存しないコードについて心配しないでください。結局のところ、これはcortex-m3であり、リソースが多少制限されているため、メモリマップを前もって定義するだけです。問題は、gcc がローカル グローバルに .got を使用するようにするにはどうすればよいかということだと思いますが、その答えはわかりませんが、上記のような単純な例を使用すると、見つかるまで多くのコマンド ライン オプションを使用できます。出力を変更するもの。