EXC_BAD_ACCESS
適切に配置するために回避しようとしていると思います。たとえば、このサンプルプログラムで dataptr を説明しているように聞こえます
#include <stdio.h>
int main ()
{
void (*funcptr)(void) = 0;
int *dataptr = 0;
puts ("about to deref dataptr");
printf ("%d\n", *dataptr);
puts ("about to call through f ptr");
funcptr();
puts ("done");
return 0;
}
dataptr
呼び出しの逆参照で最初の EXC_BAD_ACCESS をヒットしprintf
ます。変数を有効な値に変更して、実行を続行できます。ここでの 1 つの秘訣は、コンパイル済みの例では変数dataptr
がスタック上にあるということです。そのため、この時点で読み込まれているレジスタを設定して、それを乗り越える必要があります。ここでは、簡単な例として、このプログラムの有効なアドレスとしての開始アドレスを使用しています。-O0
main()
* thread #1: tid = 0x1f03, 0x0000000100000eb6 a.out`main + 54 at a.c:7, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
-> 7 printf ("%d\n", *dataptr);
(lldb) disass -c 1 --pc
a.out`main + 54 at a.c:7:
-> 0x100000eb6: movl (%rcx), %esi
(lldb) reg read rcx
rcx = 0x0000000000000000
(lldb) p dataptr
(int *) $0 = 0x0000000000000000
(lldb) p dataptr = (int*) main
(int *) $1 = 0x0000000100000e80
(lldb) reg write rcx `$1`
(lldb) c
Process 77491 resuming
-443987883
about to call through f ptr
* thread #1: tid = 0x1f03, 0x0000000000000000, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
#0: 0x0000000000000000
NULL 関数ポインターを介して呼び出したため、停止しました。これを解きほぐすには、x86_64 ABI の知識が少し必要ですが、それほど難しいことではありません。PC を呼び出し元のリターン アドレスに設定し、スタックを 1 ワードポップすれば、元に戻ります。
(lldb) reg write pc `*(unsigned long long *)$sp`
(lldb) reg write sp `$sp + 8`
(lldb) c
Process 77522 resuming
done
Process 77522 exited with status = 0 (0x00000000)
もちろん、これは非常に手動の調整であり、自動化するのは簡単ではありません。null 関数ポインタ deref を python 関数で表現し、lldb コマンドを追加して簡単に実行できますが、null データ ポインタ deref では、どのレジスタがアクセスされているかを知る必要があります。逆アセンブリ命令の巧妙なパターン マッチングによって、一般的なケースでは、いくつかの python 拡張機能を使用して同じことを行います。
それが役立つことを願っています。