How to view va_list variables via gdb

By | March 7, 2016

Viewing variable values via gdb of a va_list is not as straight forward as gdb> p myvar. It requires a few extra steps not only in execution but in understanding. Read on if you want to know how va_* works and how to view the underlying variables.

Step 1:

The first step is to understand the underlying structure of variable arguments and in particular va_list. This blog https://bobobobo.wordpress.com/2008/01/28/how-to-use-variable-argument-lists-va_list/ does a really good job.

The summary from this site:

  • va_list, va_start, va_end, va_arg are the macros needed.
  • The very first step is to create a pointer to point to the first element of the variable argument list. (va_list myListPointer;)
  • use va_start(myListPointer, numargs) to actually make myListPointer point to the first variable. (You need to at least step past this line in order to start inspecting memory).
  • The rest involves looping through and printing/calculating the values.

Step 2:

Copy the sample code from https://en.wikipedia.org/wiki/Variadic_function and compile it. Change the input to average as required.

Step 3:

Read through these 2 further posts that shows you the gdb command to run in order to view the value of your variable.

The summary is that you need to type this in gdb:

  • p *(int *)(((char *)args[0].reg_save_area)+args[0].gp_offset)

Note to change args to the name of your variable .

Here is another angle. The key is “gp_offset is how many bytes after reg_save_area the first argument is”. So you could find the pointer of first argument via:

>>  ap[0].reg_save_area+ap[0].gp_offset

Then you can view it via:

>> x/c 0x7fff5fbffa18

Screen Shot 2016-03-07 at 12.05.53 PM

My variable here was ‘8’. To get the content of the next variable, you have to increment the reg_save_area by the number of bytes you know the argument to take. ie run through the loop again calling va_arg(). This will then increment gp_offset.

“…gp_offset will be only incremented after calling va_arg() macro, if you want to see more arguments you must increment reg_save_area by the number of bytes you know arguments take…”

Step 4:

Check out the definition of reg_save_area, overflow_arg_area, gp_offset and fp_offset at: http://stackoverflow.com/questions/4958384/what-is-the-format-of-the-x86-64-va-list-structure

Reason being is if you tried gdb> p args, you would come across these variables. Note my variable is called “ap”

Screen Shot 2016-03-07 at 11.44.17 AM

Step 5:

This post does a great job explaining step 4.

https://blog.nelhage.com/2010/10/amd64-and-va_arg/

Conclusion

This is not for the faint hearted, but if you want to truely understand how it actually works, put in the time and figure it out.

One thought on “How to view va_list variables via gdb

  1. CS QGB

    (gdb) p *ap Attempt to dereference a generic pointer. (gdb) p ap $13 = (va_list) 0x3fc93014 (gdb) p *(int *)(((char *)ap[0].reg_save_area)+ap[0].gp_offset) Attempt to dereference a generic pointer.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *