[lldb-dev] Stepping into function generates EXC_BAD_INSTRUCTION signal

Greg Clayton gclayton at apple.com
Tue Dec 2 13:46:17 PST 2014


Your functions in the symbol table must be correctly marked as "thumb" functions and they probably aren't.

To mark a function as thumb, you must set the "n_desc" field of all thumb functions to be "0x0008".

Looking at a dump from "dsymutil -s" on a Master Detail template app built for armv7:


% dsymutil -s Carp.app/Carp 
----------------------------------------------------------------------
Symbol table for: 'Carp.app/Carp' (armv7)
----------------------------------------------------------------------
Index    n_strx   n_type             n_sect n_desc n_value
======== -------- ------------------ ------ ------ ----------------
.....
[   105] 00000611 0e (     SECT    ) 01     0008   000000000000a108 '+[SKScene(Unarchive) unarchiveFromFile:]'
[   106] 0000063a 0e (     SECT    ) 01     0008   000000000000a270 '-[GameViewController viewDidLoad]'
[   107] 0000065c 0e (     SECT    ) 01     0008   000000000000a404 '-[GameViewController shouldAutorotate]'
[   108] 00000683 0e (     SECT    ) 01     0008   000000000000a414 '-[GameViewController supportedInterfaceOrientations]'
[   109] 000006b8 0e (     SECT    ) 01     0008   000000000000a494 '-[GameViewController didReceiveMemoryWarning]'
[   110] 000006e6 0e (     SECT    ) 01     0008   000000000000a4d8 '-[GameViewController prefersStatusBarHidden]'
[   111] 00000713 0e (     SECT    ) 01     0008   000000000000a4e8 '-[AppDelegate application:didFinishLaunchingWithOptions:]'
[   112] 0000074d 0e (     SECT    ) 01     0008   000000000000a530 '-[AppDelegate applicationWillResignActive:]'
[   113] 00000779 0e (     SECT    ) 01     0008   000000000000a558 '-[AppDelegate applicationDidEnterBackground:]'
[   114] 000007a7 0e (     SECT    ) 01     0008   000000000000a580 '-[AppDelegate applicationWillEnterForeground:]'
[   115] 000007d6 0e (     SECT    ) 01     0008   000000000000a5a8 '-[AppDelegate applicationDidBecomeActive:]'
[   116] 00000801 0e (     SECT    ) 01     0008   000000000000a5d0 '-[AppDelegate applicationWillTerminate:]'
[   117] 0000082a 0e (     SECT    ) 01     0008   000000000000a5f8 '-[AppDelegate window]'
[   118] 00000840 0e (     SECT    ) 01     0008   000000000000a614 '-[AppDelegate setWindow:]'
[   119] 0000085a 0e (     SECT    ) 01     0008   000000000000a640 '-[AppDelegate .cxx_destruct]'
[   120] 00000877 0e (     SECT    ) 01     0008   000000000000a668 '-[GameScene didMoveToView:]'
[   121] 00000893 0e (     SECT    ) 01     0008   000000000000a830 '_CGPointMake'
[   122] 000008a0 0e (     SECT    ) 01     0008   000000000000a868 '-[GameScene touchesBegan:withEvent:]'
[   123] 000008c5 0e (     SECT    ) 01     0008   000000000000ab84 '-[GameScene update:]'
[   124] 000008da 1e (PEXT SECT    ) 01     0008   000000000000ac4c '_objc_autoreleaseReturnValue$shim'


Note all of these symbol table entries have "n_desc" set to 0x0008 to indicate they are thumb functions.

Greg Clayton

> On Nov 26, 2014, at 8:26 AM, Mario Zechner <badlogicgames at gmail.com> wrote:
> 
> Hi,
> 
> we generate thumbv7 binaries for iOS devices. We deploy, launch and debug those via LLDB. Stepping into functions seems to almost always generate a EXC_BAD_INSTRUCTION signal. The signal is not generated when running the app without the debugger attached. It is also not generated when we attach a debugger, but simply let the app run without breakpoints or any stepping.
> 
> Here's one of these function's LLVM IR:
> 
> =======================
> define external void @"[J]java.lang.Object.<init>()V"(%Env* %p0, %Object* %p1) nounwind noinline optsize {
> label0:
>     call void @"llvm.dbg.declare"(metadata !{%Env* %p0}, metadata !19), !dbg !{i32 136, i32 0, metadata !{i32 786478, metadata !0, metadata !1, metadata !"[J]java.lang.Object.<init>()V", metadata !"[J]java.lang.Object.<init>()V", metadata !"", i32 136, metadata !15, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (%Env*, %Object*)* @"[J]java.lang.Object.<init>()V", null, null, metadata !17, i32 136}, null}
>     %r0 = alloca %Object*
>     store %Object* null, %Object** %r0
>     call void @"llvm.dbg.declare"(metadata !{%Object** %r0}, metadata !21), !dbg !{i32 136, i32 0, metadata !14, null}
>     store %Object* %p1, %Object** %r0
>     call void @"register_finalizable"(%Env* %p0, %Object* %p1), !dbg !{i32 136, i32 0, metadata !18, null}
>     ret void, !dbg !{i32 136, i32 0, metadata !18, null}
> }
> =======================
> 
> The corresponding thumbv7 assembler code as generated by LLVM:
> 
> =======================
> 	.globl	"_[J]java.lang.Object.<init>()V"
> 	.align	2
> 	.code	16                      @ @"[J]java.lang.Object.<init>()V"
> 	.thumb_func	"_[J]java.lang.Object.<init>()V"
> "_[J]java.lang.Object.<init>()V":
> 	.cfi_startproc
> Lfunc_begin18:
> 	.loc	1 136 0                 @ Object.java:136:0
> @ BB#0:                                 @ %label0
> 	.loc	1 136 0                 @ Object.java:136:0
> 	push	{r7, lr}
> 	mov	r7, sp
> 	sub	sp, #4
> 	@DEBUG_VALUE: [J]java.lang.Object.<init>()V:__$env <- R0
> 	movs	r2, #0
> 	str	r2, [sp]
> 	str	r1, [sp]
> 	.loc	1 136 0 prologue_end    @ Object.java:136:0
> Ltmp6:
> 	ldr	r2, [r1]
> 	ldr	r2, [r2, #48]
> 	tst.w	r2, #1048576
> Ltmp7:
> 	@DEBUG_VALUE: [J]java.lang.Object.<init>()V:__$env <- R0
> 	it	ne
> 	blxne	__bcRegisterFinalizer
> 	add	sp, #4
> 	pop	{r7, pc}
> Ltmp8:
> Lfunc_end18:
> "L_[J]java.lang.Object.<init>()V_end":
> 
> 	.cfi_endproc
> =======================
> 
> Now, when stepping into this function, LLDB receives a signal from the debug server:
> 
> =======================
> (lldb) s
> Process 176 stopped
> * thread #1: tid = 0x11f5, 0x0023e2ec AttachTestIOSDev`[J]java.lang.Object.<init>(__$env=0x0169efc8, __$this=0x0174cd10)V + 24 at Object.java:136, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_ARM_UNDEFINED, subcode=0xffd1b001)
>     frame #0: 0x0023e2ec AttachTestIOSDev`[J]java.lang.Object.<init>(__$env=0x0169efc8, __$this=0x0174cd10)V + 24 at Object.java:136
> =======================
> 
> Disassembling around the PC gives:
> 
> =======================
> (lldb) disassemble --pc
> AttachTestIOSDev`[J]java.lang.Object.<init>()V + 24 at Object.java:136:
> -> 0x23e2ec:  .long  0xb001ffd1                ; unknown opcode
>    0x23e2f0:  pop    {r7, pc}
> 
> AttachTestIOSDev`[J]java.lang.Object.<init>()V + 30:
>    0x23e2f2:  nop
> 
> Disassembling until the beginning of the frame gives:
> 
> (lldb) disassemble -f
> AttachTestIOSDev`[J]java.lang.Object.<init>()V at Object.java:136:
>    0x23e2d4:  push   {r7, lr}
>    0x23e2d6:  mov    r7, sp
>    0x23e2d8:  sub    sp, #0x4
>    0x23e2da:  movs   r2, #0x0
>    0x23e2dc:  str    r2, [sp]
>    0x23e2de:  str    r1, [sp]
>    0x23e2e0:  ldr    r2, [r1]
>    0x23e2e2:  ldr    r2, [r2, #0x30]
>    0x23e2e4:  tst.w  r2, #0x100000
>    0x23e2e8:  it     ne
>    0x23e2ea:  blne   0x429290                  ; _bcRegisterFinalizer
>    0x23e2ee:  add    sp, #0x4
>    0x23e2f0:  pop    {r7, pc}
> 
> Accprding to this, execution should never end up at address 0x23e2ec. That's right in the middle of the blne and add instructions in the second disassembly. I have a hunch that the debugserver on the device may interfere here, e.g. add a trap instruction to implement the stepping. I'm not quite sure what to make of it.
> 
> I'd appreciate any hints. If you require more information, i got plenty of logs :)
> 
> Thanks,
> Mario
> _______________________________________________
> lldb-dev mailing list
> lldb-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev





More information about the lldb-dev mailing list