Re: GDB and ARM Frame Pointer strangeness

Steven Johnson
2004-06-10T04:37:57Z

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
>
>
>
>