関数ptraceで呼び出しを検出できるプログラムを実行しようとしています。PTRACE_SINGLESTEP を使用すると、命令ごとにプログラム命令を実行できます。次に、レジスタ RIP が指す OP_CODE 0xe8 を取得したら、PTRACE_PEEKTEXT を使用して、RIP が指すアドレスの次の 4 バイトを取得します。次に、インターネットで見つけたドキュメントによると、4バイトはジャンプする場所を参照するオフセットを表しています。PTRACE_PEEKTEXT が奇妙な値を返しているようで、オフセットが大きすぎます。以下の私のコード:
instr_num = ptrace(PTRACE_PEEKTEXT, this->pid, regs.rip, 0);
dest = ptrace(PTRACE_PEEKTEXT, this->pid, regs.rip + 1, 0);
if (instr_num == 0xe8)
{
printf("call : %ld\n", regs.rip + dest);
}
出力は次のとおりです。
call : -2853719444197214464
call : -2853719444197214464
call : -2853719444197214464
これは objdump -D の出力です。ご覧のとおり、main からの呼び出しと関数 func の先頭の間に 15 バイトのオフセットがあります。
00000000004004c4 <func>:
4004c4: 55 push %rbp
4004c5: 48 89 e5 mov %rsp,%rbp
4004c8: 5d pop %rbp
4004c9: c3 retq
00000000004004ca <main>:
4004ca: 55 push %rbp
4004cb: 48 89 e5 mov %rsp,%rbp
4004ce: b8 00 00 00 00 mov $0x0,%eax
4004d3: e8 ec ff ff ff callq 4004c4 <func>
4004d8: 5d pop %rbp
4004d9: c3 retq
呼び出しを検出した直後に ptrace(PTRACE_SINGLESTEP) を 1 回実行すると、ジャンプ先の関数のアドレスが RIP に含まれますか? 私のテストによると、そうではないようですが、そうすべきだと思います。