How to switch GDB disassembly from Thumb to ARM?
How to switch GDB disassembly from Thumb to ARM?
- Subject: How to switch GDB disassembly from Thumb to ARM?
- From: Don Quixote de la Mancha <email@hidden>
- Date: Wed, 09 Nov 2011 09:39:58 -0800
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 )
{
void_no_args();
VoidNoArgs();
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 2
.code 16
.thumb_func _IntNoArgs
_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 4
.code 32
Larm1:
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.
Thanks for any help you can give me,
Don Quixote
--
Don Quixote de la Mancha
Dulcinea Technologies Corporation
Software of Elegance and Beauty
http://www.dulcineatech.com
email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden