Wednesday 24 April 2013

What's in that wchar_t*?!

So I came across a situation yesterday where I wanted the contents of a wide character string while in GDB. Now for regular strings, GDB has the command 'x' which allows you to examine memory and it also takes a format specifier, so x/s usually does the job. Unfortunately, GDB doesn't have builtin support for printing wide character strings ( or maybe I missed it while going through the docs ). A quick search led me to results like this. Seemed a bit like overkill to me.


So looking at the disassembly of main, we can see that one of the command line arguments passed to the program is converted to a wide character string and stored in a global ( I guess it could be static as well.. but meh ) buffer @ 0x80491a0. The contents of that string is already known so it isn't too interesting. Looking a little further down..


Now we see a comparison taking place between our string and another string. What is it comparing it against? We can see that the string in question is stored in a global as well. In a small program, not containing many wide character strings, there's a very simple but imprecise way of finding out.
There is the linux strings command. Now by default strings will only print regular character strings that are at least 4 characters long and followed by an unprintable character. Luckily for us strings takes a switch which allows us to specify the type of encoding of the strings that we're looking for.

 -e --encoding={s,S,b,l,B,L} Select character size and endianness: s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit

So a strings -el <binary> will get us our answer, somewhere inside a mess of other things. In a small program, this shouldn't be too troublesome but in larger programs this could become annoying.

The better, more precise way to get this done is from within gdb itself. If they're using those wide char functions then libc is probably loaded and available and so the respective functions for printing wide character strings should also be available; wprintf in particular.

So all that is really necessary is to call wprintf and pass the address of the string as the argument.


Now since the output stream is buffered and is flushed when things like newlines are printed, to see our output we either have to print a newline or we can just flush stdout. A call to fflush() does the trick and we can see the contents of the string.

No comments:

Post a Comment