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]

Stack Frame Unwinding



I had previous discussions on this list about this "feature" of GDB and its effect on an ARM Embedded Target.


Well now, ive been trying to use CVS_HEAD of GDB on a powrpc embedded target. Ive been using GDB for years for powerpc targets, and all of the things i used to be able to rely upon, i can no longer. To the extent that to get my target initialised and running a progrm reliably ive had to introduce "monitor" commands to get around the current "sledge hammer" stack unwinding approach in GDB.

Im using a PowerPC:MPC860 variant. They have tons of registers.

One of them is the "DER" or Debug Enable Register.

It is outside the program's ABI. It is a special purpose register, and amounts to a peripheral register inside the powerpc. there are lots of these in powerpc, usually far more than the base registers, they control things like caches, debug engines, timers, etc. If i tell GDB to write one, before it does, it "stack unwinds" which causes GDB to dereference the value in another register, and then scan through memory.

What for. The DER and these other SPR's are not program registers, it can not have a "place" on the stack, depending on where our "frame" is in the stack. This is crazy. It slows things down for no valid reason, and doesnt achieve anything.

Also, for embedded targets, especially those that use JTAG for connection (dare i say all (or at least most) modern processors used in the embedded space use this as the "preffered" option for debuggin". When you "connect" with GDB to those targets, you hav access to the raw hardware, straight after a reset. Not some nice clean envirmonment a "debug stub" has set up for you. The obvious advantage with this, is that many many times the presence of a "debug stub" actually changes the behaviour of your program, so your program might work with the stub there, compile it up for a release build, and it fails to run. But you cant debug it, because there is no stub. So for many years stubs have been seen as a poor mans tool, compared to expensive "in circuit emulators" well "jtag" debugging gives most of the advantages of "in circuit emulators" but they dont carry the traditionaly high cost. Well with these tools, after a target reset, there is no stack, there is no stack pointer worth anything. It just doesnt exist. I have had situations wher GDB has said "lets unwind the stack" and it has merilly gone and itterated through memory, 4 bytes at a time, never finding anything that tells it to terminate its stack frame unwinding, so it just keeps going and going and going (an hour later i killed it out of chronic frustration). Why, because after a reset, memory is crap, and there is no stack frame. For me recently, this was happening 2 or 3 times out of every 5 resets.

I know this is a boundary condition, but it is a very real boundary condition, that will effect the debugging of every embedded target that has a good solid hold over the target CPU (like a jtag interface).

I think the whole brute force, everytime we touch a memory address, or write a register we will force a stack unwind, because maybe it has changed, needs to be rethought. It is unusable for any embedded development i have been involved with the way it is at the moment. At the very least, there needs to be a switch that says "Dont unwind the stack frame, use a dummy emtpy stack frame for the purposes of GDB". And for remote targets, this should be enabled by default. Maybe it should change automatically after the first target "load" but that is up for debate. There needs to be a way to prevent GDB accessing memory when the known result is that the memory is crap, and GDB isnt going to get any useful information anyway.

Further, it just simply shouldnt do it at all, unless the register is a part of the ABI. (Eg, SPR's on the PowerPC should never force a stack frame unwind.)

It does not seem that when this was concieved the effect it has on embedded targets, like ive described, was considered much at all.

I have spent the last 2 days trying to find an elegant way to introduce such a switch, and i just cant see one. It is just in so many places (it seems) that i couldnt find a nice place to put the switch, without fear of missing some places, or producing unwanted side effects. Also, i couldnt for the life of me work out what one would do to produce an "empty" or "default nothing in there" stack frame, so that GDB was satisfied with its "GDB always must have a stack frame" necessity. Its fine for GDB to always need a stack frame, but this is a new requirement, and some thought should have been given to debug targets that in actuallity dont always have a stack frame. Such a rule is actually false for embedded targets, and GDB should have some way of satisfying its own internal requirements without imposing those on an external target.

Even though the remote serial protocol hasnt changes, i believe GDB's use of it in this context has broken backwards compatibility, becuase things you could rely on before, you can no longer rely on. (Like GDB not accessing memory, unless you gave it a specific command to access memory, and then it only accessed what you told it to, and didnt make a running rampage through random memory in a random way)

As it stands, the stack unwinder for an embedded target, at certain points in debugging can serve no good purpose "garbage in, garbage out". Another example is programs that are completely written in assembler, they do not need to behave to anyones "rules" of what constitutes a valid stack frame, and so it is unlikely GDB is going to make much sense of them either. This is another reason why "Brute force, stack unwinding needs to be able to be disabled".

The only way ive been able to proceed to use GDB is to introduce mechanisms into the remote handler, that allow me to byspass the GDB register and memory writing mechanisms, so i can write memory and registers directly, just like GDB used to do. This is highly sub optimal. At the stage i am at with this, i am not sure, that some other necessary operations, will incur unnecessary stack unwinding.

Also, dont get me wrong, i can see the point of it, probably for 95% of the cases when you are in the "middle" of debugging a high level language, it is just there are numerous cases where its not appropriate as well.

This email is to serve two purposes,

1. Discuss my experiences with the stack unwinder, and
2. Hopefully trigger some meaningful debate on ways we might proceed to make GDB even better.


If a clear way forward can be identified, that the majority, and especially the maintainers are happy with, i am more than capable and happy to implement it (im not asking someone to do this for me, i understand it is free software). There is just no point me doing anything about this unilateraly as its likely to be rejected. (It not being a simple thing).

Best Regards,
Steven Johnson




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