2017-07-28 17 views
3

以前のバージョンのGCCでは、コードの実際の実行時に使用されたシンボルオフセットと一致したシンボルオフセットがobjdumpでした。たとえば:残念ながらobjdumpによって報告されたシンボルオフセットは実行時オフセットに一致しません

$ gdb ./example 
... 
(gdb) start 
Temporary breakpoint 1, main() at example.c:10 
10   printf("%d\n", g_someGlobal); 

(gdb) p/x &g_someGlobal 
$1 = 0x80496f4 

、同じシーケンスを繰り返す:バイナリを実行しているときに

$ cat example.c 
#include <stdio.h> 

int g_someGlobal = 0; 

int main() 
{ 
    printf("%d\n", g_someGlobal); 
    return 0; 
} 

$ gcc-6 -v 
... 
gcc version 6.1.1 20160802 (Debian 6.1.1-11) 


$ gcc-6 -O0 -g -o example example.c 

$ objdump -x example | grep Global 
... 
080496f4 g  O .bss  00000004    g_someGlobal 
... 

そして実際、実行時に使用されるシンボルの実際のアドレスは、objdumpのによって報告されたのと同じものです最近リリースされたDebianのストレッチのコマンドの、これは代わりに起こる:

$ gcc-6 -v 
... 
gcc version 6.3.0 20170415 (Debian 6.3.0-14) 


$ gcc-6 -O0 -g -o example example.c 

$ objdump -x example | grep Global 
00002020 g  O .bss 00000004    g_someGlobal 

今オフセットシンボルは、はるかに小さい値であるように思わ - どの...

$ gdb ./example 
... 
(gdb) start 
... 
Temporary breakpoint 1, main() at example.c:7 
7    printf("%d\n", g_someGlobal); 
(gdb) p/x &g_someGlobal 
$1 = 0x80002020 

...実行時に使用されたものと一致しなくなりました。

ここをクリックしてください?その間にツールの使用が変更されましたか?そうでない場合は、この変更の背景にある理由は何ですか?

理論的には、理論上、変数をホストする.bssセグメントの「期待される実行時オフセット」を得る方法が必要です(objdumpは、どのセクションが配置されるかを報告するので、最終実行時位置は、.bssオフセットを追加することで計算できます)。そうする私の予備的な試みで、私はしかし、これを取得する方法を発見していない:

$ readelf --sections example | grep bss 
[26] .bss   NOBITS  0000201c 00101c 000008 00 WA 0 0 4 

をこれがで.bss -hosted変数に起こるようですが0x80000000の「シフト」を報告していないようですこの例。

(つまり、この新しい実行環境のための「魔法の定数」であっても、それはあまりにも、.data変数には適用されず、正直に言うと、私は魔法の値を憎む - ?以前、objdump -xから出てきたものは何でも正確でした、シンボルがどこにあったかにかかわらず)

これを解決するための情報は、大歓迎です。理想的には、私はobjdump -xという古い振る舞いを再現したいと思います。すなわち、実行時ではなく静的にシンボルのランタイムアドレスの値をホストするELFから取得します。

更新:私はGCC7.1.0のカスタムコンパイルを行いましたが、これはもはや再現性がありません。おそらく、これはGCC 6.3(Debian Stretchにパッケージ化されたバージョン)の回帰でした...

+1

答えはKBではありませんが、Debianのgccパッケージは '--enable-default-pie'でビルドされています。リンク時に決定されたアドレスを取得するためにコマンドラインをリンクするために '-no-pie'を追加してください。 –

+0

@R ..確かに、検証済み!あなたが答えとしてあなたのコメントを追加するなら、私はそれを受け入れます。 Debianがこれをする理由を知っていますか? – ttsiodras

+0

心配しないで、私はPIEについて読んで理解します。再度、感謝します! – ttsiodras

答えて

3

なぜなら、Debianのgccパッケージは--enable-default-pieで構築されているからです。 PIE実行可能ファイルでは、ELFセグメントは、通常はローダーによってランダムに選択された任意の(適切に整列されている限り)ベースアドレスでロードできます。 ELFファイルに表示されるシンボルアドレスは、絶対仮想アドレスではなく、ロードされているベースアドレスに相対的なオフセットです。

PIEが不要/不要な場合は、コマンドラインをリンクするために-no-pieを追加して、これまでのようにリンク時に決定されたアドレスを取得できます。

関連する問題