elfファイルの特定のシンボルの中身を後から差し替えたい


例えばC言語で下記のように128バイトの領域を確保したとします。

[code]

    const char TABLE[128] = {0};
    
[/code]

このシンボルを含んだオブジェクトファイルをリンクして生成されたelfファイルに対して、後からTABLEが指すアドレスの中身を差し替える、ということがやりたいのです。

elfフォーマットを勉強して、シンボルテーブルをパースして・・・といった手順を踏めば実現できそうに思えますが、今回はそこまで手間をかけている時間もないので、何かツールでできればと思っています。

対称はARMのelfです。binutilsのツールでどうにかできないでしょうか？




`readelf` コマンドを使って、まずは `TABLE` 変数の「メモリアドレス」を表示してみます。ソースコードは yaegashi
さんの回答にあるものと同じであるとします。

[code]

    $ gcc -g -o a a.c # デバッグオプションを付ける
    $ readelf -s a | grep -w TABLE
        70: 080484e0   128 OBJECT  GLOBAL DEFAULT   16 TABLE
    
[/code]

`TABLE` 変数のメモリアドレスは `080484e0` となっています。`TABLE` 変数が格納されている場所を調べてみると、

[code]

    $ objdump -t a | grep -w TABLE
    SYMBOL TABLE:
    080484e0 g     O .rodata    00000080              TABLE
    
[/code]

`.rodata` セクションであることが判ります。

次に、ELF の `.rodata` セクションの情報を表示します。

[code]

    $ LC_MESSAGES=C readelf -S a | sed -rn '/^Section Headers:/,+1p;/\.rodata/{p;q;}'
    Section Headers:
      [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
      [16] .rodata           PROGBITS        080484c0 0004c0 0000a0 00   A  0
    
[/code]

`TABLE` 変数のメモリアドレスは `080484e0`、`.rodata` セクションは `080484c0` で、ファイルオフセットは
`0004c0` です。したがって、`TABLE` 変数のファイルオフセットは以下の様にして求めることができます。

[code]

    $ echo $((0x80484e0 - 0x80484c0 + 0x4c0))
    1248
    
[/code]

それでは実際に `TABLE` 変数の内容を書き換えてみましょう。

[code]

    $ printf 'Hello World!' | dd of=a bs=1 seek=1248 count=12 conv=notrunc
    12+0 records in
    12+0 records out
    12 bytes copied, 0.00128388 s, 9.3 kB/s
    $ ./a
    Hello World!
    
[/code]




`readelf` コマンドを使って、まずは `TABLE` 変数の「メモリアドレス」を表示してみます。ソースコードは yaegashi
さんの回答にあるものと同じであるとします。

[code]

    $ gcc -g -o a a.c # デバッグオプションを付ける
    $ readelf -s a | grep -w TABLE
        70: 080484e0   128 OBJECT  GLOBAL DEFAULT   16 TABLE
    
[/code]

`TABLE` 変数のメモリアドレスは `080484e0` となっています。`TABLE` 変数が格納されている場所を調べてみると、

[code]

    $ objdump -t a | grep -w TABLE
    SYMBOL TABLE:
    080484e0 g     O .rodata    00000080              TABLE
    
[/code]

`.rodata` セクションであることが判ります。

次に、ELF の `.rodata` セクションの情報を表示します。

[code]

    $ LC_MESSAGES=C readelf -S a | sed -rn '/^Section Headers:/,+1p;/\.rodata/{p;q;}'
    Section Headers:
      [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
      [16] .rodata           PROGBITS        080484c0 0004c0 0000a0 00   A  0
    
[/code]

`TABLE` 変数のメモリアドレスは `080484e0`、`.rodata` セクションは `080484c0` で、ファイルオフセットは
`0004c0` です。したがって、`TABLE` 変数のファイルオフセットは以下の様にして求めることができます。

[code]

    $ echo $((0x80484e0 - 0x80484c0 + 0x4c0))
    1248
    
[/code]

それでは実際に `TABLE` 変数の内容を書き換えてみましょう。

[code]

    $ printf 'Hello World!' | dd of=a bs=1 seek=1248 count=12 conv=notrunc
    12+0 records in
    12+0 records out
    12 bytes copied, 0.00128388 s, 9.3 kB/s
    $ ./a
    Hello World!
    
[/code]

