Assignment 6 advice

Written by Julie Zelenski

Getting oriented

There is not a particularly large amount of code to write for this project and it doesn't involve a tricky algorithm like edit distance or the delicate pointer-rewiring of CMap rehash. Past students have told us the most daunting issues were getting started in the first place and keeping track of the big picture: which data is where, how to access it, and how the parts relate. So take a deep breath, spend time up front to get oriented, ask questions, draw pictures, and poke around in gdb to be sure your understanding of the big picture is solid before tackling the code.

ELF format

Symbols module

Namelist

Dissecting the runtime stack

The runtime stack, its calling conventions, and the call/return protocol have been studied in lecture, lab, the textbook, the previous assignment, and by now you have a solid understanding of its operation. Despite this, you may still be skeptical that the runtime reality truly matches the abstraction as we've studied it. They are one and the same! If you can accurately draw the contents of the runtime stack and identify the parts (return address, saved base pointer, parameters, etc.), then you have the necessary knowledge to dissect that stack to produce the backtrace.

Verify that you can answer these critical questions about how the stack operates:

Take care to mind the difference between a saved ebp (base/frame pointer) and saved eip (return address). Although they are neighbors in the stack frame and have similar register names, they serve completely different purposes and conflating the two only leads to heartache and headache.

A word of therapy: You may feel vaguely unsettled by how the crash reporter code seems overly dependent on the precise details of the IA32 and linux calling conventions. It's great if your instincts are picking this up, as it shows you are developing an intuition about what makes for portable code and what doesn't. Stack dissection by its very nature is only made possible by leveraging intimate knowledge of the particular details of how the stack is laid out and how a function call operates, making a stack crawl platform-specific and unportable. Don't let this fluster you! Accept the inevitability of the presumptions you must make, but use good practice to avoid adding any unnecessary assumptions. For example, your program will absolutely embed a fixed assumption about the relative position of the saved ebp versus the saved eip that cannot be avoided or finessed away. But don't let that lull you into discarding all consideration of portability. There is no reason to use a number when you could use sizeof to determine the number of bytes, and if you needed to access a memory location two pointers away from another, advancing a void** by 2 would be preferable to hard-coding the constant 8.

Crash reporter

Code quality

Testing

Program facts