Mac OS X でソースを持っていないプログラムをデバッグしようとしていますgettattrlist()
。2 つの異なるボリュームについて (比較して確認するために)、どの引数で呼び出しているかを知りたいです。一方のボリュームを使用でき、もう一方のボリュームを使用できないのはなぜですか)。
私は最初に試しdtruss
ました。しかし、それは役に立たないgetattrlist()
; 渡されるポインターのみが表示されますgetattrlist()
(引数の数もわかりませんgetattrlist()
)。
635/0x1dc5: getattrlist("/Volumes/MyVolume\0", 0x113FA6380, 0x113FA5FD0) = 0 0
635/0x1dc5: getattrlist("/Volumes/MyVolume\0", 0x113FA4F00, 0x113FA4B30) = 0 0
635/0x1dc5: getattrlist("/Volumes/MyVolume\0", 0x113FA5870, 0x113FA54C0) = 0 0
635/0x19c6: getattrlist("/Volumes/MyVolume\0", 0x7FFF5FBF9140, 0x7FFF5FBF8D70) = 0 0
635/0x19c6: getattrlist("/Volumes/MyVolume\0", 0x7FFF5FBFA8A0, 0x7FFF5FBFA4F0) = 0 0
そこで、GDBを試しました。に無条件のブレークポイントを設定しgetattrlist()
、その最初の引数を調べることができますが、あまりにも頻繁に呼び出されて役に立ちません。
(gdb) break getattrlist
Breakpoint 1 at 0x7fff8e90b6ac
(gdb) cont
Continuing.
Breakpoint 1, 0x00007fff8e90b6ac in getattrlist ()
(gdb) p (char *)$rdi
$1 = 0x7fff5fbfd67e "/some/random/path"
したがって、最初の引数が関心のあるパスと一致する場合にのみブレークする条件付きブレークポイントが必要になるでしょう。
(gdb) delete
Delete all breakpoints? (y or n) y
(gdb) break getattrlist if ((int)strcmp((char *)$rdi, "/Volumes/My Volume")) == 0
Breakpoint 2 at 0x7fff8e90b6ac
(gdb) cont
Continuing.
Canceling call as the malloc lock is held so it isn't safe to call the runtime.
Issue the command:
set objc-non-blocking-mode off
to override this check if you are sure your call doesn't use the malloc libraries or the ObjC runtime.
Error in testing breakpoint condition:
Canceling call as the malloc lock is held so it isn't safe to call the runtime.
Issue the command:
set objc-non-blocking-mode off
to override this check if you are sure your call doesn't use the malloc libraries or the ObjC runtime.
Breakpoint 2, 0x00007fff8e90b6ac in getattrlist ()
(gdb) p (char *)$rdi
$12 = 0x7fff5fbfd67e "/some/other/random/path"
これは何ですか?malloc()
ObjC ランタイムを呼び出す可能性があるため、GDB は私の状態を無視しましたか? OK、まあ、strcmp()
呼び出すべきではありませんmalloc()
。ヌル文字になるまで、文字列をバイトごとに比較するだけです。そのため、チェックを上書きするようにメッセージが推奨するオプションを設定しましょう。
(gdb) set objc-non-blocking-mode off
(gdb) cont
Continuing.
Segmentation fault: 11
サイコロはありません。GDB とアプリケーションの両方が停止します。
この問題に遭遇することなく、GDB からの文字列に条件付きウォッチポイントを設定する方法について何か提案はありますか? または、 の引数と戻り値 (出力引数を介して格納される) をキャプチャする他の方法はgetattrlist()
、dtruss()
?
編集
マットの解決策を試しましたが、うまくいきませんでした:
(gdb) set $vol = (char *) malloc((int)strlen("/Volumes/My Volume") + 1)
(gdb) call (int)strcpy($vol, "/Volumes/My Volume")
$1 = 236411760
(gdb) break getattrlist if ((int)strcmp((char *)$rdi, $vol)) == 0
Breakpoint 1 at 0x7fff8e90b6ac
(gdb) cont
Continuing.
Unsafe to run code: malloc zone lock is held for some zone..
Error in testing breakpoint condition:
Canceling call as the malloc lock is held so it isn't safe to call the runtime.
Issue the command:
set objc-non-blocking-mode off
to override this check if you are sure your call doesn't use the malloc libraries or the ObjC runtime.
Breakpoint 1, 0x00007fff8e90b6ac in getattrlist ()
(gdb) p (char *)$rdi
$4 = 0x11a715838 "/some/other/random/path"
memcmp()
の代わりに試してみることにしましたstrcmp()
。運もありません:
(gdb) break getattrlist if ((int)memcmp((char *)$rdi, $vol, 18)) == 0
Breakpoint 1 at 0x7fff8e90b6ac
(gdb) cont
Continuing.
Unsafe to run code: malloc zone lock is held for some zone..
Error in testing breakpoint condition:
Canceling call as the malloc lock is held so it isn't safe to call the runtime.
Issue the command:
set objc-non-blocking-mode off
to override this check if you are sure your call doesn't use the malloc libraries or the ObjC runtime.
Breakpoint 1, 0x00007fff8e90b6ac in getattrlist ()
(gdb)
この時点で、「OK、今は本当に何も使用していないはずですmalloc()
」と判断したので、もう一度set objc-non-blocking-mode off
やり直すことにしました。まだ運がない:
(gdb) set objc-non-blocking-mode off
(gdb) cont
Continuing.
Reading symbols for shared libraries ... done
Reading symbols for shared libraries . done
Reading symbols for shared libraries ....... done
[Switching to process 5456 thread 0x2971b]
[Switching to process 5456 thread 0x29e2f]
warning: Unable to restore previously selected frame.
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000000
[Switching to process 5456 thread 0x29e2f]
0x0000000000000000 in ?? ()
Error in testing breakpoint condition:
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on"
Evaluation of the expression containing the function (memcmp) will be abandoned.
Breakpoint 1, 0x0000000000000000 in ?? ()
Error in testing breakpoint condition:
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on"
Evaluation of the expression containing the function (memcmp) will be abandoned.
Breakpoint 1, 0x0000000000000000 in ?? ()
うーん。私はどのような状態ですか?
(gdb) bt
#0 0x0000000000000000 in ?? ()
#1 0x000000011e6ec070 in ?? ()
イク。それはよく見えません。ここで続けたらどうですか?
(gdb) cont
Continuing.
[Switching to process 5456 thread 0x2971b]
(gdb) bt
#0 0x00007fff8e90b6ac in getattrlist ()
#1 0x00007fff897c9c4b in GetPathVolFSAttributes ()
#2 0x00007fff897c9459 in PathGetObjectInfo ()
#3 0x00007fff897c9279 in FSPathMakeRefInternal ()
#4 0x00007fff8767b3ee in FSNodePrepareFSRef ()
... snip ...
(gdb) p (char *)$rdi
$2 = 0x10db1c2b0 "/System/Library/CoreServices/CoreTypes.bundle"
いいえ。getattrlist()
;への正しい呼び出しをまだ実際に中断していません。ヌルポインタの逆参照により、その間にすべてが停止しました。