LLDB print out NSException name or class from library - ios

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

Related

Change value of const variables in LLDB

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.

Why do crashes in iOS relating to dyld_stub_binder occur?

It's widely known that dynamic link libraries aren't allowed in iOS apps, they may only link to dynamic system libraries. But I do run into some pretty confusing crashes with the 3rd frame from the top of the stack being dyld_stub_binder.
It's tough to find some solid information, but I'm guessing that dyld_stub_binder actually performs late linking of a dynamic system library.
I tend to run into crashes where the exception is EXC_BREAKPOINT UNKNOWN and the crash always seems to occur in the context of dyld_stub_binder.
The implementation of dyld_stub_binder is on the apple open source website. I don't quite understand the assembly, but perhaps someone who does could interpret why this error happens or whether or not it's something that is out of the application's direct control. The assembly code may not be useful though, as I'm talking about the iOS (arm) implementation and this code is i386 and x86_64.
EDIT: An interesting piece of information is that I think I started seeing this crash during efforts for porting to arm64. Is it possible that a runtime exception like this is due to some kind of misalignment?
As you've stated, the asm for the ARM case is not available, but it's fairly straightforward to figure out since you can decompile fairly easily. What dyld_stub_binder does (on all architectures) is to handle the lazy symbols in a binary. For example, consider the following:
$ cat a.c
void main(int argc, char **argv)
{
printf("%s", argv[1]);
}
$ gcc-iphone a.c -o a
$ jtool -d a
Disassembling from file offset 0x7f44, Address 0x100007f44
_main:
100007f44 STP X29, X30, [X31,#-16]!
100007f48 ADD x29, x31, #0x0 ; ..R29 = R31 (0x0) + 0x0 = 0x1f
100007f4c SUB X31, X31, #32
100007f50 STUR X0, X29, #-4 ; *((1) + 0x0) = ???
100007f54 STR X1, [ X31, #2] ; *((2) + 0x0) = ???
100007f58 LDR X1, [X31, #0x10] ; R1 = *(10) = 0x100000cfeedfacf
100007f5c LDR X1, [X1, #0x8] ; R1 = *(100000cfeedfad7) = 0x100000cfeedfacf
100007f60 ADD x8, x31, #0x0 ; ..R8 = R31 (0x0) + 0x0 = 0x1f
100007f64 STR X1, [ X8, #0] ; *(0x0) = 0xfeedfacf
100007f68 ADRP x0, 0 ; ->R0 = 0x100007000
100007f6c ADD x0, x0, #0xfb4 ; ..R0 = R0 (0x100007000) + 0xfb4 = 0x100007fb4 "%s"
100007f70 BL _printf ; 0x100007f84
; _printf("%s",arg..);
100007f74 STR X0, [ X31, #3] ; *((254) + 0x0) = ???
100007f78 ADD x31, x29, #0x0 ; ..R31 = R29 (0x1f) + 0x0 = 0x1d
100007f7c LDP X29, X30, [X31],#16
100007f80 RET
see that printf up there? 0x100007f84? Let's see what that is (The built-in otool can't decompile that part, but jtool can:)
_printf:
100007f84 NOP
100007f88 LDR X16, #34 ; R16 = *(100008010) = 0x100007fa8
100007f8c BR X16
So you just to 0x100007fa8. Once again applying jtool:
$ jtool -d 0x100007fa8 a
Disassembling from file offset 0x7fa8, Address 0x100007fa8
100007fa8 LDR X16, #2
100007fac B 0x100007f90
And now we have 0x100007f90, which is ...
100007f90 ADR x17, 120 ; ->R17 = 0x100008008
100007f94 NOP
100007f98 STP X16, X17, [X31,#-16]!
100007f9c NOP
100007fa0 LDR X16, #24 ; R16 = *(100008000) dyld_stub_binder
100007fa4 BR X16
Now, go back to that 0x...8010 which gets loaded - that will be the address of printf(), but it is only bound after the first "hit" or access. You can verify that with dyldinfo, or jtool -lazy_bind:
$ jtool -lazy_bind a
bind information:
segment section address type addend dylib symbol
__DATA __la_symbol_ptr 0x100008010 ... 0 libSystem.B.dylib _printf
Meaning, on first access, the stub_binder finds the address of printf in lib system, and embeds it there.
If the symbol cannot be bound, you get an exception. Though that can be for oh-so-many-reasons. You might want to add the crash log here. If it's a breakpoint, that's a voluntary crash by dyld which usually occurs when symbol was not found. If a debugger (lldb) is attached, it will break there and then. Else - with no debugger - it crashes.

Calling a function crashes when the stack pointer is changed with inline assembly

I have written some code that changes the current stack used by modifying the stack pointer in inline assembly. Although I can call functions and create local variables, calls to println! and some functions from std::rt result in the application terminating abnormally with signal 4 (illegal instruction) in the playpen. How should I improve the code to prevent crashes?
#![feature(asm, box_syntax)]
#[allow(unused_assignments)]
#[inline(always)]
unsafe fn get_sp() -> usize {
let mut result = 0usize;
asm!("
movq %rsp, $0
"
:"=r"(result):::"volatile"
);
result
}
#[inline(always)]
unsafe fn set_sp(value: usize) {
asm!("
movq $0, %rsp
"
::"r"(value)::"volatile"
);
}
#[inline(never)]
unsafe fn foo() {
println!("Hello World!");
}
fn main() {
unsafe {
let mut stack = box [0usize; 500];
let len = stack.len();
stack[len-1] = get_sp();
set_sp(std::mem::transmute(stack.as_ptr().offset((len as isize)-1)));
foo();
asm!("
movq (%rsp), %rsp
"
::::"volatile"
);
}
}
Debugging the program with rust-lldb on x86_64 on OS X yields 300K stack traces, repeating these lines over and over:
frame #299995: 0x00000001000063c4 a`rt::util::report_overflow::he556d9d2b8eebb88VbI + 36
frame #299996: 0x0000000100006395 a`rust_stack_exhausted + 37
frame #299997: 0x000000010000157f a`__morestack + 13
morestack is assembly for each platform, like i386 and x86_64 — the i386 variant has more description that I think you will want to read carefully. This piece stuck out to me:
Each Rust function contains an LLVM-generated prologue that compares the stack space required for the current function to the space remaining in the current stack segment, maintained in a platform-specific TLS slot.
Here's the first instructions of the foo method:
a`foo::h5f80496ac1ee3d43zaa:
0x1000013e0: cmpq %gs:0x330, %rsp
0x1000013e9: ja 0x100001405 ; foo::h5f80496ac1ee3d43zaa + 37
0x1000013eb: movabsq $0x48, %r10
0x1000013f5: movabsq $0x0, %r11
-> 0x1000013ff: callq 0x100001572 ; __morestack
As you can see, I am about to call into __morestack, so the comparison check failed.
I believe that this indicates that you cannot manipulate the stack pointer and attempt to call any Rust functions.
As a side note, let's look at your get_sp assembly:
movq %rsp, $0
Doing a check check for the semantics of movq:
Copies a quadword from the source operand (second operand) to the destination operand (first operand).
That seems to indicate that your assembly is backwards, in addition to all the other problems.

ARM: Unexpected Link Register Content on Crashing Thread

I have an iOS Crash-dump [EXC_BAD_ACCESS / KERN_INVALID_ADDRESS] with register-state and stack-memory for crashed thread.
register Contents are:
r0 = 0x00000000 r1 = 0x288bf020 r2 = 0x01e7afe0 r3 = 0xd7741000
r4 = 0x01e7b000 r5 = 0x00000000 r6 = 0x1665a924 r11 = 0x00000000
r8 = 0x14e11af0 r9 = 0x00000000 r10 = 0x1df94d0c r12 = 0x00000000
r7 = 0x1df94bb8 sp = 0x1df94bb8 lr = 0x00000000 pc = 0x3991a44a
LinkRegister(lr) and FramePointer(r7) seems to be inconsistent here.
If I ignore LinkRegister and trust FramePointer and use stack-memory to unwind call-stack with the help of FramePointer linkage, I get a reasonable back-trace(with ~15 frames).
If I trust LinkRegister which is 0 means there is no return address, I have no-where to go(no trace).
I don't understand why is LinkRegister 0? What could possibly be happening?
How can I reproduce this? or am I missing something.

Stack trace: stack scanning vs call frame vs given as instruction pointer in context

I'm using breakpad in my project to handle crashes and generate stack trace.
In stack trace, there are different ways how function calls info found by stackwalker. Process described here Finding_the_caller_frame:
Found by: stack scanning
Found by: call frame info
Found by: given as instruction pointer in context
What`s the difference between them? And more importantly how they could help in terms of debugging?
Thread 0 (crashed)
0 test_google_breakpad!crash [test_breakpad.cpp : 17 + 0x4]
r4 = 0x00015530 r5 = 0xbea2cbe4 r6 = 0xffffff38 r7 = 0xbea2cb5c
r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 fp = 0x00000000
sp = 0xbea2cb50 lr = 0x00009025 pc = 0x00008f84
Found by: given as instruction pointer in context
1 test_google_breakpad!main [test_breakpad.cpp : 25 + 0x3]
r4 = 0x00015530 r5 = 0xbea2cbe4 r6 = 0xffffff38 r7 = 0xbea2cb5c
r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 fp = 0x00000000
sp = 0xbea2cb50 pc = 0x00009025
Found by: call frame info
2 libc.so + 0x164e5
r4 = 0x00008f64 r5 = 0xbea2cc34 r6 = 0x00000001 r7 = 0xbea2cc3c
r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 fp = 0x00000000
sp = 0xbea2cc18 pc = 0x400c34e7
Found by: call frame info
The instruction pointer method means that there's a CPU register already pointing at the function's memory location so there was no need to search for the function. This is the easiest and most reliable way to find the current stack frame.
Next using the call frame technique you can find the caller of the current function by looking at the place in stack memory where the return address is stored. This is the exact technique that a "return" would use to find its return destination. This technique can be chained because each previous call also put its return value on the stack. This is pretty reliable, but can fail if some stack memory got corrupted (maybe stack overflow, maybe buggy pointer write) and one or more return addresses were obliterated.
Finally the least reliable technique is to just search the stack memory for anything that looks like a function address. This can help you recover from a corrupted stack but it can be hard to tell data (including function pointers!) apart from function addresses so it's guesswork. If you find one, though, you can often then chain back to the call frame technique if you find some stack that wasn't trashed.

Resources