1

関数_dl_start(ダイナミックリンカのエントリポイント)のアドレスを取得したい。gdb を使用してブレークポイントを設定できます。readelf を使用してシンボルを見つけることを期待していましたが、見つかりませんでした。アドレスを取得するにはどうすればよいですか / gdb は _dl_start をどのように解決しますか?

gdb を使用してブレークポイントを設定するサンプル ソース (main.cpp) は次のとおりです。

int main( int argc, char** argv, char** envp )
{

  return 0;
}

でコンパイルしました

 g++ main.cpp -o teststart 

プログラム実行時のgdb出力は

(gdb) b _dl_start
Function "_dl_start" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (_dl_start) pending.
(gdb) r
Starting program: /tmp/teststart 

Breakpoint 1, 0x00007fa7ee8c4fc4 in _dl_start () from /lib64/ld-linux-x86-64.so.2
4

2 に答える 2

4

_dl_startシンボルはld-linux-x86-64.so.2(動的ローダー) にあり、そのシンボルはld -linux にプライベートです。つまり、プログラム内からそれを見つける唯一の方法は、GDB と同じことを行うことです。つまり、 のシンボル テーブルを読み取り、ld-linux"_dl_start" 関数を (名前で) 検索します。(Martinが提案したように)直接リンクすることはできず、機能しません(すでに発見したように)。

ELF シンボル テーブルの読み取りはそれほど複雑ではありません。セクションを見つけ.symtabて、エントリのテーブルとして読み取る必要があります。または(ここから開始) を使用します。.strtab.symtabElf64_Symlibelf

追加の複雑さは、ld-linux取り除かれる可能性があることです (機能するためにシンボルテーブルは必要ありません)。それが除去された場合、GDB もプログラムも を見つけることができなくなります_dl_start

最後に、検索の試み_dl_startが無意味である可能性があります。この関数は、プログラムの最初の命令が実行されるずっと前に呼び出されることに気付きます。あなたが をヒットするまでに、は長い間終了しており、二度と呼び出されることはありません。main_dl_start

更新:

gdb が ld-linux で _dl_start のアドレスを取得する方法についてはまだ疑問に思っています (削除されています)。

が削除されている場合ld-linux、GDB はそれを見つけることができません_dl_start。あなたはGDBがそれを見つけるので、どちらか

  1. あなたld-linuxが実際にストリップされていない、または
  2. glibc 用の「個別の debuginfo」パッケージがインストールされています。

ld-linuxが本当に完全に削除されていることを確認するには、 and を実行nm /lib64/ld-linux-x86-64.so.2 | grep _dl_startreadelf -S /lib64/ld-linux-x86-64.so.2 | grep symtabます。どちらのコマンドも出力を生成しません。

GDB がシンボルをロードしている場所を確認するには、set print symbol-loading on(実行可能ファイルを実行する前に) コマンドを使用できます。

_dl_start を呼び出して (スタックを準備し、補助ベクトルを調整した後)、既にメモリに格納されているプログラムの実行可能イメージ (ファイル表現) を作成したかったのです...

それがどのように機能するのかわかりませ。は、呼び出される前に特定の状態 (たとえば、そのグローバル変数がゼロに設定されている) を想定しているため、補助ベクトルを調整しなくても、再度_dl_start呼び出すとアサーションが失敗する可能性が非常に高くなります。そして、(明らかに)あなたの目標である自明ではない方法でauxベクトルを調整する、アサートの可能性がさらに高くなります。

于 2012-08-14T06:10:05.810 に答える
0

_dl_start はプログラム自体の一部ではなく、ランタイム ローダーに含まれています (出力 "..._dl_start () from /lib64/ld-linux-x86-64.so.2" からわかるように)。ブレークポイントは実行可能ファイルに含まれていないため、GDB は最初はブレークポイントを設定できません。_dl_start のアドレスをプログラム内から知りたいのか、外部から知りたいのか、私には少しわかりませんか? 内部から、たとえば次のように void* 変数に単純に割り当てることができるはずです。

void* address = dl_start;
于 2012-08-13T11:40:31.673 に答える