GDB and ARM Frame Pointer strangeness

Steven Johnson sjohnson@neurizon.net
Thu Jun 10 04:37:00 GMT 2004


OK, Ill break it down.
1. We are not using a stub running on our target.
2. We are using the ARM7TDMI JTAG DEBUG Interface, in the context of 
"stub" we have a program running on a PC that translates the GDB Remote 
Serial Protocol into ARM JTAG Debug Commands.

The exact reason why the target is crashing is obscure, we are using a 
SOC, and there arent any real bus state pins one can probe to determine 
the CPU state, and on recovery into a mode where we can inspect things 
again, everything is reset.  The best information we have at the moment 
is, if we access an invalid (unmapped) memory location the processor 
enters a state, which we have not been able to recover from without a 
hardware reset.  Our current guess is it goes into an infinite bus cycle 
waiting for the memory to respond.  The chip does have Memory Mapped IO 
that can wait indefinately on the state of an external XWAIT pin.  But 
what we know for sure, is that immedialtely after reset, a read to an 
invalid memory address crashes the processor, and the only way we have 
found to recover is a hard reset.

The problem is, we want to use GDB to start "investigating" our hardware 
and to start testing our boot code.  But whilever it is making these 
spurious uncontrolled writes to invalid memory addresses, it is 
preventing us from doing this, because they crash our Target CPU.  
Because our "stub" is really a PC, and it is translating the GDB Remote 
Serial Protocol into ARM JTAG operations, it doesnt know anything 
specific about the hardware, it is designed to function with any 
ARM7TDMI chip with this interface.  So it is inappropriate for it to 
filter addresses, because it has no notion of what addresses are valid 
and what are not.  Yes, if the CPU wasnt crashing and it was advising us 
that an invalid memory location was accessed we could report that data 
appropriately to GDB. (Although im not clear what data you return in 
answer to a memory read when the address is invalid). 

NOTE: WE HAVE NO CODE IN OUR TARGET AT THIS STAGE.  THERE ARE NO 
EXCEPTION HANDLERS.  What a software stub in the target does, is largely 
irrelevent for our purposes, our debug interface not being of this 
kind.  And the way things stand, even if we needed to install exception 
handlers or support routines (which i dont think is necessary BTW), we 
are in a deadly embrace, because we would want to download those 
initially using GDB, but the first memory write (which would in this 
example load the exception handlers or support routines) crashes the 
target because it causes a read to invalid memory. CATCH 22.

This isnt the real problem however, yes if possible i need to make my 
JTAG Debugger more resiliant to memory faults. Yes, as it now stands is 
undesirable, but our tests to date are indicating its a deficiency we 
will probably have to live with.  What it dis do is highlight to me a 
defficiency in this logic ,that was the ultimate root of the operation 
crashing the CPU, inside GDB.

In summary, if there is no ABI that GDB knows about in use, it is 
invalid for GDB to assume a register is the Frame Pointer and then to 
start de-referencing it.  The same can be said for the stack pointer on 
architectures that do not have a "Hardware" stack pointer, but just use 
an arbitrary register as one.

Setting the ABI to "none" doesn't appear to do anything.  Should it?  It 
should prevent these "FP" relative accesses if the ABI is set to "none". 
Otherwise when debugging assembler programs, or hand optimised assembler 
routines, GDB could make all sorts of assumptions about the contents of 
the registers that arent correct, which could in turn lead to corruption 
of the running program, target state, (or in our case) crashing the 
CPU.  When otherwise the program is doing exactly what the programmer 
intended, by using the (nominal) FP register for some other purpose.  
Uncontrolled reading of the wrong memory can be destructive to the state 
of a target board, especially if there are Memory mapped IO registers 
that loose their contents once read.  At the very least there needs to 
be some control over these "high level" operations so that "low level" 
things can be debugged without interference from them.

In my opinion, the discussion about the stub is a largely irrelevent 
side issue and ignores the basic underlying question I had which 
concerns ABI's and GDB's handling of them.  Can anyone provide insight 
into GDB's handling of ABI's and these "High Level" operative 
constructs, and the controls that should exist to manipulate GDB's view 
of the ABI's?

Steven

Ian Lance Taylor wrote:

>Steven Johnson <sjohnson@neurizon.net> writes:
>
>  
>
>>3. It is a pipe dream to say "all stubs should be immune to bad memory
>>reads" its certainly an ideal goal, but unfortuantely it can not
>>always be achieved.
>>    
>>
>
>Let's get concrete about this one.  Why can this not always be
>achieved?  Every stub that I've ever worked with achieves it.
>
>For example, let's look at gdb/i386-stub.c, which is a sample stub for
>the i386.  This stub presumes the existence of an external function
>exceptionHandler which causes a specified function to be a trap
>handler for a specifed exception.  For, e.g., exception 13, the stub
>installs a trap handler which, among other things, calls the macro
>CHECK_FAULT.  That macro checks whether the global variable
>_mem_fault_routine is non-zero.  If it is, the exception handler calls
>it in a somewhat tricky fashion, and then returns from the exception.
>
>When the stub is asked to read from a memory location, it sets
>_mem_fault_routine to set_mem_err.  The set_mem_err function just sets
>the global variable mem_err to 1.
>
>The effect is that if the read from memory is from an invalid address,
>the function set_mem_err is called, and the program continue running.
>After the memory is fetched, the code checks mem_err.  If mem_err is
>set, the memory address was invalid, and the stub indicates that to
>the caller.
>
>That is a concrete example of how a common stub handles this issue.
>That general approach is used by every stub I've worked with.  Every
>processor must give you some mechanism to trap invalid memory
>addresses.  If it doesn't, many things become impossible.
>
>If we want to continue this discussion, please explain why your stub
>can not do something similar.
>
>Ian
>
>
>  
>



More information about the Gdb mailing list