When a program fails because of an assertion violation, segmentation fault or some other cause, the amount of information provided on most systems is fairly minimal.
One piece of information that I would like to see would be the stack trace (or call history) for the program. For instance, I'd like to see a message of the form:
pc=0x4f1c09 int_stack.c: 53 pc=0x40300e eval_expr.c: 1140 pc=0x530ef7 parse_file.c: 5131 pc=052d94de main.c: 1926 assertion "len_int_stack(stack) > 0" failed: file int_stack.c, line 53
This immediately gives me some insight into what could be going wrong, and where to focus debugging.
Clearly, one could get the same information by rerunning the program under the debugger, and then asking for a stack-trace when the program fails. However:
When working on a large project, we build a module to dump the stack-trace for us. This is extremely system dependent, so I won't be able to give you an implementation. Instead, I shall describe the steps involved, and you will have to figure out how to do it in your environment.
Before we get into how to implement stack tracing, lets go over the stack organization of most systems.
--------- stack-pointer-->| X | | | | | | | --------- X -->| Y | | pc0 | | | | | --------- Y -->| Z | | pc1 | | | | | --------- Z -->| 0 | | pc2 | | | | | ---------
The piece of ASCII art above indicates a possible stack. In this stack, there are 4 frames. The back-chain consists of
Z. The function currently executing will return to
pc0, which in turn returns to
pc1, which in turn returns to
pc2 is probably the system function that called
The steps involved in writing a stack trace module are:
struct sigcontextargument. One of the fields of the structure will contain the actual top-of-stack. The structure will also contain the pc for the top-most routine.
gdbport to the system I am working on, I look to see how
gdbdoes it. Of course, if the environment you are working in is based on the
binutils, then you can use functions provided by
libbfd.a. Look at:
bfd_init(): to enable use of
bfd_set_default_target(): to setup the target type.
bfd_openr(): to open the executable.
bfd_get_section_by_name(): to extract the
bfd_find_nearest_line(): to map pc onto source name/line number.