I want to understand how to build a call stack as gdb does on running backtrace command. This was asked in an interview and I answered it based on my knowledge of call stack and stack frames. I think this is done using the stack pointer, the return address/instruction of the caller and mapping it to the executable / assembly instructions. I have been looking for how it is actually done or a good explanation of this stack walk. All the information I found on googling was related to microsoft API to this walk programmatically and I am looking for a generic explanation of how to approach building a call stack.
Share
A google search led me here.
Consider the very simple
ix86calling convention with frame pointers. Every time you call a routine, the address of the next instruction is pushed onto the stack. Called routine immediately upon entry executespush %ebp; mov %esp,%ebpinstructions. You then end up exactly with the layout from the page above.Let’s say you are stopped in routine
foo, called frombar, called frombaz, called frommain.You examine two words pointed to by
%ebp. The first word is the previous value of%ebp(let’s call itprev_ebp, the second is the return address — instruction pointer somewhere insidebar.You now examine two words pointed to by
prev_ebp. The first one will beprev_prev_ebp, the second will be a return address — instruction pointer somewhere insidebaz.Repeat until you reach main, and you have executed roughly the procedure that GDB uses.
There are many practical complications, such as frames that don’t use frame pointer, but you are not expected to understand that 🙂