3

ベアメタルに再配置可能なコードを持つプロジェクトを構築しています。Cortex M3 組み込みアプリケーションです。私はダイナミック リンカを持っておらず、スタートアップ コードにすべての再配置を実装しました。

ほとんどの場合は機能していますが、ローカルの静的変数が正しく配置されていないようです。それらのアドレスは、実行可能ファイルがメモリ内でオフセットされる量だけオフセットされます。つまり、メモリ位置 0 にロードされているかのようにコードをコンパイルしますが、実際には 0x8000 にあるメモリにロードします。静的ローカル変数のメモリ アドレス オフセットは 0x8000 です。これは適切ではありません。

私のグローバル変数はGOTによって適切に配置されていますが、静的ローカル変数はGOTにまったくありません(少なくとも、実行時に表示されませんreadelf -r)。私は自分のコードをコンパイルしており-fpic、リンカは指定されています。静的ローカル変数にGOTを使用する ように指示するか、それらに絶対アドレス指定を使用するように指示するコンパイルおよび/またはリンクオプションが欠落しているに違いないと思います。-fpic-piegcc

現在、コードは静的ローカル変数の場所に PC を追加しているようです。

4

2 に答える 2

3

私はあなたが見ていることを繰り返したと思います:

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 を使用するようにするにはどうすればよいかということだと思いますが、その答えはわかりませんが、上記のような単純な例を使用すると、見つかるまで多くのコマンド ライン オプションを使用できます。出力を変更するもの。

于 2011-02-23T23:57:38.107 に答える