This is the mail archive of the gdb@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: GDB and ARM Frame Pointer strangeness


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






Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]