6

gcc%pcに定数の相対アドレスを生成させる方法はありますか? 文字列がテキスト セグメントに表示される場合でも、arm-elf-gcc はデータへの定数ポインターを生成し、%pc相対アドレスを介してポインターのアドレスをロードし、逆参照します。さまざまな理由から、中間のステップをスキップする必要があります。例として、この単純な関数:

const char * filename(void)
{
    static const char _filename[]
            __attribute__((section(".text")))
            = "logfile";
    return _filename;
}

を生成します (でコンパイルした場合arm-elf-gcc-4.3.2 -nostdlib -c -O3 -W -Wall logfile.c):

00000000 <filename>:
   0:   e59f0000        ldr     r0, [pc, #0]    ; 8 <filename+0x8>
   4:   e12fff1e        bx      lr
   8:   0000000c        .word   0x0000000c

0000000c <_filename.1175>:
   c:   66676f6c        .word   0x66676f6c
  10:   00656c69        .word   0x00656c69

私はそれがもっと次のようなものを生成することを期待していたでしょう:

filename:
    add r0, pc, #0
    bx lr
_filename.1175:
    .ascii "logfile\000"

問題のコードは、ロード時にメモリ内で再配置されるため、部分的に位置に依存しない必要がありますが、コンパイルされていないコードと統合される-fPICため、グローバル オフセット テーブルはありません。

私の現在の回避策は、非インライン関数(相対アドレスを介して行われます)を呼び出して、コードの動作%pcと同様の手法でコンパイルされた場所からのオフセットを見つけることです。-fPIC

static intptr_t
__attribute__((noinline))
find_offset( void )
{
    uintptr_t pc;
    asm __volatile__ (
            "mov %0, %%pc" : "=&r"(pc)
    );

    return pc - 8 - (uintptr_t) find_offset;
}

ただし、この手法ではすべてのデータ参照を手動で修正する必要があるためfilename()、上記の例の関数は次のようになります。

const char * filename(void)
{
    static const char _filename[]
            __attribute__((section(".text")))
            = "logfile";
    return _filename + find_offset();
}
4

1 に答える 1

1

うーん、PIC を取得するには -fPIC としてコンパイルする必要があるかもしれません。または、単純にアセンブラーで記述します。アセンブラーは、作成している C 言語よりもはるかに簡単です。

00000000 :
   0: e59f300c ldr r3、[pc、#12] ; 14
   4: e59f000c ldr r0、[pc、#12] ; 18
   8: e08f3003 r3、pc、r3 を追加
   c: e0830000 追加 r0、r3、r0
  10: e12fff1e bx lr
  14: 00000004 andeq r0, r0, r4
  18: 00000000 andeq r0, r0, r0

0000001c :
  1c: 66676f6c strbtvs r6、[r7]、-ip、ror #30
  20: 00656c69 rsbeq r6、r5、r9、ror #24

私が受けているのと同じ警告を受けていますか?

/tmp/ccySyaUE.s: アセンブラ メッセージ:
/tmp/ccySyaUE.s:35: 警告: .text の変更されたセクション属性を無視します
于 2010-05-31T04:57:12.020 に答える