In my quest to learn programming, I have started my initial steps with assembly Language programming (ALP). I have been on this endeavour from quite some time.
This post is not about ALP though but about an important option of gdb called layout. layout helps all the newbies who are learning ALP a lot. Before i explain about this option , Consider the below program:
The above program calculates sum of two values (17 and 15) using sum function in alp. The output is saved in ebx register. Let us first assemble and link the program. We are assembling our source code using GNU Assembler with option -gstabs to debug the assembly code through gdb.
From man as:
–gstabs:Generate stabs debugging information for each assembler line. This may help debugging assembler code, if the debugger can handle it.
From the Figure-2 we could see that program “mysum” runs successfully. Let us Run the program through gdb. What we want to know is the following:
i) Values of registers while the code is being executed at each step
ii) Most importantly we want to see the code and registers at the same time.
To accomplish the above goals gdb provides a Text User interface using curses library to show source file. This feature is not limited to source file only but also shows assembly code(asm), registers(regs). In our case we would require to view assembly code and registers and that too at the same time. To view the registers as our asm code executes.
We first start with invoking the program mysum with gdb and setting the break point at the start function:
After setting the break point run the program by typing “run” (or just “r”) at the gdb prompt which will stop at the first break point , which in our case is the _start function. At this point lets invoke “asm” layout by typing “layout asm” at the gdb prompt:
asm layout would look like this:
In Figure-5, we could see our asm code with more details, like address where the particular instruction resides, and the instruction. Our current program counter starts at 0x8048054 which is the start of our program. From here we will keep stepping through our code and view the register values.
To load the register layout type “layout regs” at the gdb prompt and gdb would automatically split the TUI to show both asm code and registers as shown below:
In Figure-6, Instruction to be executed is highlighted and also we could see the values of registers. We will step through the code by typing “step” (or in short “s”) command at gdb prompt which will execute the earlier instruction and the code to be executed next is highlighted:
In Figure-7, we could see now our Program counter points to next instruction at address 0x8048056 which is to push 0xf (15 to stack). And also our register layout shows EIP is pointing to code to be executed and current ESP register value.
As we keep stepping through our code (use “s” at gdb prompt) and when our code enters sum function we should be able to see our base pointer register value (EBP) and if it’s saved with value of ESP register:
Our code has passed values 17 and 15 to the stack and in sum function we are copying these values to General puspose registers ecx and ebx. Figure-9 shows that ecx and edx registers have been loaded with 17 and 15 as mentioned in the code.
Keep stepping through the code and once code reaches to the end of sum function where we exit the function by popping the stack we could see the Register values at register layout Restore the stack pointer and returning back to _start):
Once we are back to _start function we see that the sum of 17 and 15 is stored in ebx register, load “1” to eax register and send the interrupt to call the exit system call. The output of the program i.e sum of values 17 and 15 can be viewed by check the status of exit system call which is value in ebx register.
I hope the above information would be useful for newbies while debugging assembly language code.
Note: “layout regs” doesn’t yet work on gdb version “gdb-7.2-51.el6.i686” on RHEL6 . It crashes gdb. Fedora 15 and latest rawhide has the fix . Hope later versions of the gdb on RHEL6 might have the fix.