Thursday, January 28, 2010

gdb advanced debugging.

1 How do I examine memory?

Use the x command to examine memory. The syntax for the x command is x/FMT ADDRESS. The FMT field is a count followed by a format letter and a size letter. There are many options here, use the help command 'help x' to see them all. The ADDRESS argument can either be a symbol name, such as a variable, or a memory address.

If we have char *s = "Hello World\n", some uses of the x command could be:

Examine the variable as a string:

(gdb) x/s s
0x8048434 <_IO_stdin_used+4>: "Hello World\n"

Examine the variable as a character:

(gdb) x/c s
0x8048434 <_IO_stdin_used+4>: 72 'H'

Examine the variable as 4 characters:

(gdb) x/4c s
0x8048434 <_IO_stdin_used+4>: 72 'H' 101 'e' 108 'l' 108 'l'

Examine the first 32 bits of the variable:

(gdb) x/t s
0x8048434 <_IO_stdin_used+4>: 01101100011011000110010101001000

Examine the first 24 bytes of the variable in hex:

(gdb) x/3x s
0x8048434 <_IO_stdin_used+4>: 0x6c6c6548 0x6f57206f 0x0a646c72


2. How do I see what is in the processor registers?

Use the info registers command. The output of this command depends on the hardware architecture. The following is part of the output on an intel machine:

(gdb) info registers
eax 0x40123460 1074934880
ecx 0x1 1
edx 0x80483c0 134513600
ebx 0x40124bf4 1074940916
esp 0xbffffa74 0xbffffa74
ebp 0xbffffa8c 0xbffffa8c
esi 0x400165e4 1073833444
...


3 How do I debug with a core file?

When your program segfaults and leaves a core dump file, you can use gdb to look at the program state when it crashed. Use the core command to load a core file. The argument to the core command is the filename of the core dump file, which is usually "core", making the full command core core.

prompt > myprogram
Segmentation fault (core dumped)
prompt > gdb myprogram
...
(gdb) core core
...


4 How do I step through my code at the instruction level?

There are two commands, nexti and stepi, that work similar to next and step. See the usage of those commands for an idea of how to use these two.

5 How do I see the assembly code my program is running?

Use the disassemble command. The argument to this command is a memory address. Here is an example of the disassembly for the main function of a simple program on an intel machine:

(gdb) disassemble main
Dump of assembler code for function main:
0x80483c0
: push %ebp
0x80483c1 : mov %esp,%ebp
0x80483c3 : sub $0x18,%esp
0x80483c6 : movl $0x0,0xfffffffc(%ebp)
0x80483cd : mov 0xfffffffc(%ebp),%eax
0x80483d0 : movb $0x7,(%eax)
0x80483d3 : xor %eax,%eax
0x80483d5 : jmp 0x80483d7
0x80483d7 : leave
0x80483d8 : ret
End of assembler dump.

Watch Points
Watchpoints are similar to breakpoints. However, watchpoints are not set for functions or lines of code. Watchpoints are set on variables. When those variables are read or written, the watchpoint is triggered and program execution stops.

1 How do I set a write watchpoint for a variable?

Use the watch command. The argument to the watch command is an expression that is evaluated. This implies that the variabel you want to set a watchpoint on must be in the current scope. So, to set a watchpoint on a non-global variable, you must have set a breakpoint that will stop your program when the variable is in scope. You set the watchpoint after the program breaks.

*NOTE* You may notice in the example below that the line of code printed doesn't match with the line that changes the variable x. This is because the store instruction that sets off the watchpoint is the last in the sequence necessary to do the 'x=y' assignment. So the debugger has already gone on to the next line of code. In the examples, a breakpoint has been set on the 'main' function and has been triggered to stop the program.

(gdb) watch x
Hardware watchpoint 4: x
(gdb) c
Continuing.
Hardware watchpoint 4: x

Old value = -1073743192
New value = 11
main (argc=1, argv=0xbffffaf4) at test.c:10
10 return 0;


2 How do I set a read watchpoint for a variable?

Use the rwatch command. Usage is identical to the watch command.

(gdb) rwatch y
Hardware read watchpoint 4: y
(gdb) continue
Continuing.
Hardware read watchpoint 4: y

Value = 1073792976
main (argc=1, argv=0xbffffaf4) at test.c:8
8 x = y;


3 How do I set a read/write watchpoint for a variable?

Use the awatch command. Usage is identical to the watch command.

4 How do I disable watchpoints?
Active watchpoints show up the breakpoint list. Use the info breakpoints command to get this list. Then use the disable command to turn off a watchpoint, just like disabling a breakpoint.

(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x080483c6 in main at test.c:5
breakpoint already hit 1 time
4 hw watchpoint keep y x
breakpoint already hit 1 time
(gdb) disable 4

Tuesday, August 4, 2009

Macro to return offset for structure member variable

#define offsetof(type, member) ((size_t)(&((type *)0)->member))

Very useful macro when dealing with file operations or from a buffer

Tuesday, July 28, 2009

Lambda Expressions

Often when using STL algorithms, you have to define a function pointer or a function object as a predicate to check a condition.
Lambda expressions or lambda functions also known as Closures in other popular languages like ruby, python etc allows you to define an anonymous (nameless) function, that allows you to maintain state.

Here's an example first using Lambda Expression and second using a Function Object.

Using Lambda Expression

Code

// even_lambda.cpp
// compile with: /EHsc
#include
#include
#include
using namespace std;

int main()
{
// Create a vector object that contains 10 elements.
vector v;
for (int i = 0; i < 10; ++i)
{
v.push_back(i);
}

// Count the number of even numbers in the vector by
// using the for_each function and a lambda expression.
int evenCount = 0;
for_each(v.begin(), v.end(), [&evenCount] (int n) {
cout << n;

if (n % 2 == 0)
{
cout << " is even " << endl;

// Increment the counter.
evenCount++;
}
else
{
cout << " is odd " << endl;
}
});

// Print the count of even numbers to the console.
cout << "There are " << evenCount
<< " even numbers in the vector." << endl;
}

Output

0 is even
1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd

Using a Function Object
// even_functor.cpp
// compile with: /EHsc
#include
#include
#include
using namespace std;

class Functor
{
public:
// The constructor.
explicit Functor(int& evenCount)
: _evenCount(evenCount)
{
}

// The function-call operator prints whether the number is
// even or odd. If the number is even, this method updates
// the counter.
void operator()(int n)
{
cout << n;

if (n % 2 == 0)
{
cout << " is even " << endl;

// Increment the counter.
_evenCount++;
}
else
{
cout << " is odd " << endl;
}
}

private:
int& _evenCount; // the number of even variables in the vector
};


int main()
{
// Create a vector object that contains 10 elements.
vector v;
for (int i = 0; i < 10; ++i)
{
v.push_back(i);
}

// Count the number of even numbers in the vector by
// using the for_each function and a function object.
int evenCount = 0;
for_each(v.begin(), v.end(), Functor(evenCount));

// Print the count of even numbers to the console.
cout << "There are " << evenCount
<< " even numbers in the vector." << endl;
}