I am adding a breakpoint in lldb like so:
(lldb) breakpoint set -s MyApp --func-regex .
(lldb) breakpoint command add 1
Enter your debugger command(s). Type 'DONE' to end.
> p __PRETTY_FUNCTION__
> continue
> DONE
(lldb) process attach --name MyApp --waitfor
(lldb) continue
My goal is to print each of the methods called in the my app. The results looks like:
(lldb) p __PRETTY_FUNCTION__
(const char [26]) $0 = "void $__lldb_expr(void *)"
(lldb) continue
Process 96238 resuming
Command #1 'continue' continued the target.
(lldb) p __PRETTY_FUNCTION__
(const char [47]) $1 = "-[AppDelegate($__lldb_category) $__lldb_expr:]"
(lldb) continue
Process 96238 resuming
Command #1 'continue' continued the target.
(lldb) p __PRETTY_FUNCTION__
(const char [47]) $2 = "-[AppDelegate($__lldb_category) $__lldb_expr:]"
(lldb) continue
Process 96238 resuming
Command #1 'continue' continued the target.
(lldb) p __PRETTY_FUNCTION__
(const char [47]) $3 = "-[AppDelegate($__lldb_category) $__lldb_expr:]"
(lldb) continue
Process 96238 resuming
Command #1 'continue' continued the target.
(lldb) p __PRETTY_FUNCTION__
(const char [47]) $4 = "-[AppDelegate($__lldb_category) $__lldb_expr:]"
(lldb) continue
The question is how do I remove the $__lldb_category and the $__lldb_expr: with the actual values of the method name and it's selectors?
I would use lldb commands to print this information, for instance:
(lldb) frame info
frame #0: 0x0000000100018dc7 Sketch`main(argc=1, argv=0x00007fff5fbff628) + 55 at SKTMain.m:17
would do what you want I think. If you want more or less info, you can also tailor the output of frame info as described here:
http://lldb.llvm.org/formats.html
Related
I've asked people before about why the stack doesn't start at 0x7fff...c before, and was told that typically 0x800... onwards is for the kernel, and the cli args and environment variables live at the top of the user's stack which is why it starts below 0x7fff...c. But I recently tried to examine all the strings with the following program
#include <stdio.h>
#include <string.h>
int main(int argc, const char **argv) {
const char *ptr = argv[0];
while (1) {
printf("%p: %s\n", ptr, ptr);
size_t len = strlen(ptr);
ptr = (void *)ptr + len + 1;
}
}
However, after displaying all my environment variables, I see the following (I compiled the program to an executable called ./t):
0x7ffc19f84fa0: <final env variable string>
0x7ffc19f84fee: _=./t
0x7ffc19f84ff4: ./t
0x7ffc19f84ff8:
0x7ffc19f84ff9:
0x7ffc19f84ffa:
0x7ffc19f84ffb:
0x7ffc19f84ffc:
0x7ffc19f84ffd:
0x7ffc19f84ffe:
0x7ffc19f84fff:
So it appears there's one extra empty byte after the null terminator for the ./t string at bytes 0x7ffc19f84ff4..0x7ffc19f84ff7, and after that I segfault so I guess that's the base of the stack. What actually lives in the remaining "empty" space before kernel memory starts?
Edit: I also tried the following:
global _start
extern print_hex, fgets, puts, print, exit
section .text
_start:
pop rdi
mov rcx, 0
_start_loop:
mov rdi, rsp
call print_hex
pop rdi
call puts
jmp _start_loop
mov rdi, 0
call exit
where print_hex is a routine I wrote elsewhere. It seems this is all I can get
0x00007ffcd272de28
./bin/main
0x00007ffcd272de30
abc
0x00007ffcd272de38
def
0x00007ffcd272de40
ghi
0x00007ffcd272de48
make: *** [Makefile:47: run] Segmentation fault
so it seems that even in _start we don't begin at 0x7fff...
I have a a.c
#include <stdio.h>
int main() {
int a = 1;
int b = 2;
int c = a + b;
return 0;
}
when compiling with clang -g a.c, I can't get debug symbols.
joey#voyager-arch /t/a4> lldb a.out
(lldb) target create "a.out"
Current executable set to '/tmp/a4/a.out' (x86_64).
(lldb) l
(lldb)
But if I use gcc, I can successfully got the debug symbols, compile with gcc -g a.c
joey#voyager-arch /t/a4> gdb a.out
GNU gdb (GDB) 11.1
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...
(gdb) l
1 #include <stdio.h>
2
3 int main() {
4 int a = 1;
5 int b = 2;
6 int c = a + b;
7 return 0;
8 }
(gdb)
I'm using archlinux with amd ryzen 7 cpu.
clang: 12.0.1
lldb: 12.0.1
gcc: 11.1.0
gdb: 11.1
May be a lldb 12 incompatible bug, downgrade to lldb 10 solved this problem.
Const variables are good. However, sometimes I want to dynamically change their values when debugging to trace some specific behavior.
When I po flag = NO I receive this error:
error: <user expression 0>:1:34: cannot assign to variable 'flag' with const-qualified type 'const BOOL &' (aka 'const bool &')
Is there any workaround?
You can make the expression succeed by using const_cast, but it is likely to not do what you want. For instance:
(lldb) run
Process 32640 launched: '/tmp/foo' (x86_64)
Process 32640 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100003f66 foo`main at foo.c:7
4 main()
5 {
6 const int foo = 10;
-> 7 printf("%d\n", foo);
^
8 return 0;
9 }
Target 0: (foo) stopped.
(lldb) expr foo = 20
error: <user expression 0>:1:5: cannot assign to variable 'foo' with const-qualified type 'const int &'
foo = 20
~~~ ^
note: variable 'foo' declared const here
const_cast to the rescue:
(lldb) expr *(const_cast<int*>(&foo)) = 20
(int) $1 = 20
We really did change the value in the foo slot, as you can see by:
(lldb) expr foo
(const int) $2 = 20
and:
(lldb) frame var foo
(const int) foo = 20
But the compiler is free to inline the value of const variables, which it does pretty freely even at -O0 (*). For instance, the call to printf compiled on x86_64 at -O0 to:
-> 0x100003f66 <+22>: leaq 0x39(%rip), %rdi ; "%d\n"
0x100003f6d <+29>: movl $0xa, %esi
0x100003f72 <+34>: movb $0x0, %al
0x100003f74 <+36>: callq 0x100003f86 ; symbol stub for: printf
Note that it doesn't reference any variables, it just puts 0xa into the second argument passing register directly. So unsurprisingly:
(lldb) c
Process 33433 resuming
10
(*) At higher optimization levels there probably wouldn't even be a variable allocated on the frame for const variables. The value would just get inserted immediately as above, and the debug information would also record it for the debugger's display, but there wouldn't be anything in memory to change from the old to the new value.
I use following code to dump stack frame at the moment of an exception:
...
var
FTraceList: TStringList;
...
procedure TTraceForm.LogException(ExceptObj: TObject; ExceptAddr: Pointer; IsOS: Boolean);
begin
...
StackList := JclCreateStackList(false, 0, Caller(0, false));
try
FTraceList.Add('');
FTraceList.Add('Stack trace at the moment of the exception:');
StackList.AddToStrings(FTraceList, true, true, true, true);
finally
Stacklist.Free;
end;
end;
But it behaves differently in Debug and Release mode.
For an intended exception (exception for testing purposes) in main form's OnKeyDown when compiling in Debug mode (Delphi debug info) the result is:
Stack trace at the moment of the exception:
(00591276){Main.exe } [00992276] DlgTraceException.TTraceForm.LogException (Line 162, "DlgTraceException.pas" + 55) + $4
(0058B8FF){Main.exe } [0098C8FF] JclDebug.JclCreateStackList + $17
(00591281){Main.exe } [00992281] DlgTraceException.TTraceForm.LogException (Line 162, "DlgTraceException.pas" + 55) + $F
(00582AE3){Main.exe } [00983AE3] JclHookExcept.TNotifierItem.DoNotify + $43
(00582CCB){Main.exe } [00983CCB] JclHookExcept.DoExceptNotify + $CF
(00582DAD){Main.exe } [00983DAD] JclHookExcept.HookedExceptObjProc + $1D
(0000606F){Main.exe } [0040706F] System.#HandleAnyException + $33
(00598DE3){Main.exe } [00999DE3] Main.TMainForm.FormKeyDown (Line 658, "Main.pas" + 2) + $7
And this I get in Release mode (JCL debug info added to binary with JCL Debug Expert):
Stack trace at the moment of the exception:
(0053BA27){Main.exe } [0093CA27] DlgTraceException.TTraceForm.LogException + $377
(00536427){Main.exe } [00937427] JclDebug.JclCreateStackList + $17
(0053BA32){Main.exe } [0093CA32] DlgTraceException.TTraceForm.LogException + $382
(0052D60B){Main.exe } [0092E60B] JclHookExcept.TNotifierItem.DoNotify + $43
(0052D7F3){Main.exe } [0092E7F3] JclHookExcept.DoExceptNotify + $CF
(0052D8D5){Main.exe } [0092E8D5] JclHookExcept.HookedExceptObjProc + $1D
(0000606F){Main.exe } [0040706F] System.#HandleAnyException + $33
In second case FormKeyDown entry is missing. Is there somebody who knows why this is happening? I would like to know the entire stack trace in release mode as well.
After playing a bit with compiler options (toggling them on and off) I could isolate the cause. The stack frame has been optimized out. When I turned Optimization off the FormKeyDown call was recorded even in Release mode. The Stack Frames generation option mentioned in comments above did not influence the results.
Of course I'll keep optimizations on in release mode. It will be harder to find the cause of the exception but there is other info about it JCL debug provides which should be (hopefully) sufficient to find the cause of the exception.
In Xcode I use "All Objective-C exception" breakpoint, but i want to skip some specific NSException.
I found in this article all the information about how to skip some specific NSException's name and it works perfectly for all the #try{} #catch I've put in my code.
Unfortunately I'm forced to use a library that does a massive use of #try #catch as a way to communicate between object, and when applications stops at the breakpoint I'm not able to know the exact NSException name.
This is the point where the code stops:
eax = 0x0d3c73f0
ebx = 0x00a675a8 #"databaseName"
ecx = 0x00b61d01
edx = 0x00b61d01
edi = 0x00a655a8 #"MessagingClientLib: initInstance must be called prior to getInstanceRuntimeException: Application ID is required"
esi = 0x000039d1 iDCP`-[UIView(FrameMucking) setOrigin:] + 65 at UIView+FrameMocking.h:103
ebp = 0xbfffc928
esp = 0xbfffc91c
ss = 0x00000023
eflags = 0x00000286
eip = 0x03a738b9 libobjc.A.dylib`objc_exception_throw
cs = 0x0000001b
ds = 0x00000023
es = 0x00000023
fs = 0x00000000
gs = 0x0000000f
Any advice?
Select the stack frame for objc_exception_throw and then enter this command:
(lldb) po *(id *)($esp + 4) // reason
(lldb) po *(id *)($esp + 12) // name