以前のバージョンの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にパッケージ化されたバージョン)の回帰でした...
答えはKBではありませんが、Debianのgccパッケージは '--enable-default-pie'でビルドされています。リンク時に決定されたアドレスを取得するためにコマンドラインをリンクするために '-no-pie'を追加してください。 –
@R ..確かに、検証済み!あなたが答えとしてあなたのコメントを追加するなら、私はそれを受け入れます。 Debianがこれをする理由を知っていますか? – ttsiodras
心配しないで、私はPIEについて読んで理解します。再度、感謝します! – ttsiodras