How to Switch Xcode 4.2's iOS disassembly from Thumb to ARM?

My iOS App is build with the Apple LLVM 3.0 compiler in Thumb mode. For armv7, I'm pretty sure that's actually Thumb-2.

I'm reimplementing my two most time-consuming functions in ARM assembly code. The callers of these functions are Thumb, so I use Thumb to ARM interworking instructions to switch to ARM in the prologue of my functions so I have acesss to ARM's richer instruction set and greater number of registers. At function exit I use ARM to Thumb interworking to return to ARM mode.

GDB's disassembly is correct for the Thumb code, but when I am in ARM mode, it disassembles the ARM instructions as if each one were a pair of completely nonsensical Thumb instructions. Is there some way I can tell GDB to switch to ARM disassembly, then upon returning to Thumb code, use the Thumb disassembler?

Google is no help. There are apparently other forks of GDB that can do that, but I haven't figured out a way to do it with GDB.

LLDB apparently supports ARM debugging, but it does not yet work on iOS devices in Xcode 4.2. When I choose the LLDB debugger in Product -> Edit Scheme, then set a breakpoint in my code, my App hangs before hitting the breakpoint.

It's been a long time since I've done any assembly of any sort, so I am brushing up on the ARM calling conventions by implementing functions that take various parameters and return various types of results in both C and ARM assembly. The lower_case functions are C and the CamelCase functions are assembly. I call abiTest the very first thing from main(), and use assert() to ensure that it returns YES

BOOL abiTest( void )

    if ( 42 != int_no_args() )
        return NO;

    if ( 42 != IntNoArgs() )
        return NO;

    return YES;

Here is the source for IntNoArgs. .thumb_func is a directive for the linker. My research seems to indicate that you want it even for ARM functions, if one mixes the two types of code

.globl _IntNoArgs
.align 1
.code 16
.thumb_func _IntNoArgs

    @ int IntNoArgs( void );
    .loc 1 __LINE__ 0

    adr r0, Larm1     @ Larm1 is a PC-relative address.  r0's low bit will be cleared
    bx r0                   @ Switch to ARM mode then branch to Larm1.  That's the next instruction

    .align 2
    .code 32
    stmfd sp!, { r7, lr }

    mov r0, #42

    ldmfd sp!, { r7, lr }
    bx lr

Here is how GDB disassembles the _IntNoArgs. The first two lines are correct, the remainder are completely wrong

0x000172c8  <+0000>  add    r0, pc, #0  (adr r0, 0x172cc <VoidNoArgs+4>)
0x000172ca  <+0002>  bx r0
0x000172cc  <+0004>  lsls   r0, r0
0x000172ce  <+0006>  stmdb  sp!, {r1, r3, r5}
0x000172d2  <+0010>  b.n    0x17a16
0x000172d4  <+0012>  lsls   r0, r0
0x000172d6  <+0014>  ldmia.w    sp!, {r1, r2, r3, r4, r8, r9, r10, r11, r12, sp, lr, pc}

The disassembly stops here because the ldmia.w instruction appears to be putting a new value into the program counter after taking it from the stack, thereby returning from the subroutine. After I step over this instruction with "si" the disassembly pane show:

0x000172d8  <+0016>  vrhadd.u16 d14, d14, d31

The si instruction always does the right thing, by advancing just one instruction whether we are in Thumb or ARM mode. So GDB must know the current instruction set architecture, it's just that the disassembler is not getting that information.

There is a bit in one of the ARM's register that indicates the current mode. Some forks of GDB have the ability to use the value of that bit when determining which ISA to disassemble as, but this is apparently not the case with Xcode 4.2's GDB.

Xcode's GDB has a command "set arm disassembler" and its corresponding "show arm disassembler" that looks like it would help, but it doesn't. That apparently is meant to support other kinds of ARM variants than what the iOS devices use.

"set fallback-mode" can be set to arm, thumb or auto in other forks of GDB, but not Xcodes. Ditto for "set disassembler-flavor".

What I would REALLY REALLY REALLY like is a machine debugger that worked just like MacsBug did on the Classic Mac OS. While GDB is generally capable of doing assembler debugging, it totally sucks for that purpose. That's not anyone's fault, really, because it is designed for source debugging. A good assembly debugger is designed to do it that way from the ground up.


The ABI function call guide states that switching between ARM and Thumb mode can be done only at function boundaries in iOS. Make sure your functions are either ARM or Thumb-only, and the debugger will work fine.

Need Your Help

PHP - Problems logging data to a file from a script called from AJAX

php jquery ajax

I've just started learning PHP and I'm trying to log data to a .txt file so I can see whats going on as the program runs.

Cutting off textscan after a character

matlab file-io comments textscan

I'm working on a function in MATLAB that reads input from a file. So far (after reading a bit here about scanf vulnerabilities) I decided to use fgets to get each line, and then textscan to extract...