How do I access variables local to a function using dtrace?
For example, in the following snippet I would like to know the value of variable x using dtrace.
void foo(int a){
int x=some_fun(a);
}
Tracing local variables is impossible for kernel code because there is no mechanism to instrument arbitrary kernel instructions. Even in user-land, tracing local variables is somewhat convoluted and so, for the specific example you give, it would make a lot more sense to trace the return value of some_fun() instead.
If you must trace an arbitrary local variable then you will need to determine its location (typically a register or a location in memory) at the specific point of interest. For simple cases you may be able to do this by disassembling the function and inspecting the output. For more complex cases it may be helpful to build the object with DWARF and then find the DW_AT_location attribute of the local variable's DIE.
One you find the variable's location you'll need to express it in D; note that registers are exposed through the uregs[] array. Furthermore, you'll need to describe your probe using the offset within the function since dtrace(1) has no way of understanding line numbers. See the section on "User Process Tracing" in the Oracle Solaris Dynamic
Tracing Guide for more.
As an example, I wrote a trivial program containing
int
foo(int i)
{
int x;
...
for (x = 0; x < 10; x++)
i += 2;
and built it, as an amd64 executable, with DWARF...
cc -m64 -g -o demo demo.c
...before looking for foo() and its definition of x in the output
of dwarfdump demo:
< 1><0x000000e4> DW_TAG_subprogram
DW_AT_name "foo"
...
DW_AT_frame_base DW_OP_reg6
< 2><0x00000121> DW_TAG_variable
DW_AT_name "x"
...
DW_AT_location DW_OP_fbreg -24
x is described as DW_OP_fbreg -24 but DW_OP_fbreg itself must be
substituted by the result of the parent function's DW_AT_frame_base
attribute, i.e. DW_OP_reg6. DWARF uses its own architecture-agnostic
numbering for registers and the mapping to individual registers is up to
the appropriate standards body. In this case, the AMD64 ABI tells
us that DWARF register 6 corresponds to %rbp. Thus x is stored at
%rbp - 0x18. (For more about DWARF itself I recommend Michael Eager's
Introduction to the DWARF Debugging Format.)
Thus, if you had found that the line of source in which you're
interested is at offset 0x32 (perhaps by inspecting the DWARF
line table) then you might write a probe like:
pid$target:a.out:foo:32
{
self->up = (uintptr_t)(uregs[R_RBP] - 0x18);
self->kp = (int *)copyin(self->up, sizeof (int));
printf("x = %d\n", *self->kp);
self->up = 0;
self->kp = 0;
}
This is what I see when I run the demo program:
# dtrace -q -s test.d -c /tmp/demo
x = 1
x = 2
x = 3
x = 4
x = 5
x = 6
x = 7
x = 8
x = 9
x = 10
#
Related
Having just switched to lldb, I'm trying to do the equivalent of gdb's watch i being I'm inside a for loop in my code.
(lldb) f
frame #0: 0x0000000100000664 a.out`MaxPairwiseProduct(numbers=size=5) + 4 at max_pairwise_product.cpp:19 [opt]
16 // Find max value in vector
17
18 for (int i=1; i<numbers.size(); i++) {
-> 19 if (numbers[i] > numbers[i-1]) {
20 second_max = max;
21 max = numbers[i];
22 if (numbers[i] < max && numbers[i] > second_max)
(lldb)
As you can see above, int i has already been declared.
Checking which watchpoints I have yields
(lldb) watchpoint list -b
Number of supported hardware watchpoints: 4
No watchpoints currently set.
(lldb)
Now trying to set a watchpoint to i (according to the lldb reference) I get
(lldb) wa s v i
error: Watchpoint creation failed (addr=0xffffffffffffffff, size=0, variable expression='i').
error: cannot set a watchpoint with watch_size of 0
(lldb)
I don't understand why this is, being the variable has been declared. Googling the error didn't help much as most issues seem to be related with hitting the max number of watchpoints, which is not my case as can be seen above. Any help would be much appreciated!
I changed the way I was compiling the program to clang++ -Wall -g -o max_pairwise max_pairwise.cpp and it started showing me the right information, including tracking the value of i
I have a hex stream of hex data that is printed like
0x3a45 0x1234 0x0352 (in real far longer)
I know that it is content in a struct. Is there a way in gdb to map this on the struct? Gdb seems only to accept single values for doing this.
Like:
(gdb) print (myStruct) 0x3a45 0x1234 0x0352
$1 = { a = 3a, b = 45, f = 0x1234, c = 03, e = 52}
In this case it's very simple but there is complex struct and the hex string is far larger.
I think there are a couple viable ways to do this in gdb.
The simplest way is to write the data into the inferior's memory somehow. It might look something like:
(gdb) set $mem = malloc(50) # number of bytes
(gdb) set $mem[0] = 0x72
(gdb) set $mem[1] = 0xff
# etc - you can find faster ways to do this
(gdb) print *(struct whatever *) $mem
Filling the memory is a pain, but this can be scripted. For example you can write a little shell script to convert the raw bytes into a sequence of set commands and then source it. Or you can just write a new gdb command in Python that automates it all.
gdb also has an extension to let one create an array on the command line, and do a kind of "reinterpret cast" on it. I found this method a bit less handy, because I could only make the array feature create arrays of int, not char. But anyhow, consider this little program:
struct x {
int a;
long b;
};
int main() {
struct x x = { 23, 97 };
return 0;
}
I start gdb and stop on the return, then examine the memory:
(gdb) p sizeof(int)
$1 = 4
(gdb) p sizeof(x)
$2 = 16
(gdb) x/4xw &x
0x7fffffffe240: 0x00000017 0x00007fff 0x00000061 0x00000000
(That second word is garbage because it is in the struct padding...)
Now we can recreate x by hand from the raw data:
(gdb) print {struct x}{0x17, 0x7fff, 0x61, 0}
$3 = {
a = 23,
b = 97
}
This expression uses two extensions to C expressions that gdb provides. First, {0x17, 0x7fff...} is a way to write an array. Second, {struct x} is a kind of "reinterpret cast" - it reinterprets the raw bytes of the value as named type.
In GDB, info registers or info all-registers will show you all of the register symbol names and their values.
Question:
How do I get the variable name (i.e. from the source code) that is stored in that register? (or a line number in source code, or anything)
For example:
int my_reg = /* something */;
float another_reg = /* something else */;
...
Then perhaps, info all-registers will return:
R0 0x0 0
R1 0xfffbf0 16776176
R2 0x0 0
R3 0x0 0
R4 0x6 6
How do I determine which register (R0? R2? R4?) is "associated" with my_reg?
If you have access to the debug symbols (and understand how to read them - that is, you have some code that parses the debug symbols), it is possible to trace exactly which register corresponds to which register. However, this is quite possibly changing from one line to the next, as the compiler decides to move things around for one reason or another (e.g. some calculation starts with R1, and ends up with the result in R2, because that's better than trying to retain the value in R1 [or we need the original value in R1 too - think array[x++] - now we have the new value of x, hopefully in a register, and the value of the old x that we need to use for indexing, also needed to be in a register to add to the base-address of array.
Not all variables end up in registers (depending on processor, and "what registers are available").
The debugger WILL know where each variable is at any given time - but sometimes it can be a big confused, e.g:
int array[10000];
...
for(int i = 0; i < 10000; i++)
{
array[i] = rand();
}
may translate to something like this during optimization:
int array[10000];
int *ptr = array;
int *ptr2 = &array[10000];
while(ptr < ptr2)
{
*ptr++ = rand();
}
Now try printing i... ;)
There might be one register, multiple registers, or even no registers associated with any given C variable at any given point in time. You'll have to inspect the disassembly to see what's going on.
Why not just print my_reg to see the value?
l *$pc will list the source code around the current instruction being executed.
Supposing to have something like this:
#include <map>
int main(){
std::map<int,int> m;
m[1] = 2;
m[2] = 4;
return 0;
}
I would like to be able to inspect the contents of the map running the program from gdb.
If I try using the subscript operator I get:
(gdb) p m[1]
Attempt to take address of value not located in memory.
Using the find method does not yield better results:
(gdb) p m.find(1)
Cannot evaluate function -- may be inlined
Is there a way to accomplish this?
The existing answers to this question are very out of date. With a recent GCC and GDB it Just WorksTM thanks to the built-in Python support in GDB 7.x and the libstdc++ pretty printers that come with GCC.
For the OP's example I get:
(gdb) print m
$1 = std::map with 2 elements = {[1] = 2, [2] = 4}
If it doesn't work automatically for you see the first bullet point on the STL Support page of the GDB wiki.
You can write Python pretty printers for your own types too, see Pretty Printing in the GDB manual.
I think there isn't, at least not if your source is optimized etc. However, there are some macros for gdb that can inspect STL containers for you:
http://sourceware.org/ml/gdb/2008-02/msg00064.html
However, I don't use this, so YMMV
There's always the obvious: Define your own test-function... Call it from gdb. E.g.:
#define SHOW(X) cout << # X " = " << (X) << endl
void testPrint( map<int,int> & m, int i )
{
SHOW( m[i] );
SHOW( m.find(i)->first );
}
int
main()
{
std::map<int,int> m;
m[1] = 2;
m[2] = 4;
return 0; // Line 15.
}
And:
....
Breakpoint 1 at 0x400e08: file foo.C, line 15.
(gdb) run
Starting program: /tmp/z/qD
Breakpoint 1, main () at qD.C:15
(gdb) call testPrint( m, 2)
m[i] = 4
(*m.find(i)).first = 2
(gdb)
The stl-views.gdb used to be the best answer there was, but not anymore.
This isn't integrated into the mainline GDB yet, but here is what you get using the 'archer-tromey-python' branch:
(gdb) list
1 #include <map>
2 int main(){
3 std::map<int,int> m;
4 m[1] = 2;
5 m[2] = 4;
6 return 0;
7 }
(gdb) break 6
Breakpoint 1 at 0x8048274: file map.cc, line 6.
(gdb) run
Breakpoint 1, main () at map.cc:6
6 return 0;
(gdb) print m
$1 = std::map with 2 elements = {
[1] = 2,
[2] = 4
}
(gdb) quit
Try De-Referencing STL Containers: on this page: http://www.yolinux.com/TUTORIALS/GDB-Commands.html
The answers above are working and fine. In case you are using stl-views.gdb, here is the proper way of viewing the maps and elements inside it.
Let your map is as follows :
std::map<char, int> myMap;
(gdb) pmap myMap char int
i.e. pmap <variable_name> <left_element_type> <right_element_type> to see the elements in the map.
Hope that helps.
You can get around the second problem (Cannot evaluate function -- may be inlined) by making sure that your compiler uses DWARF-2 (or 3 or 4) debugging information when you compile your program. DWARF-2 includes inlining information, so you should be able to use either of the methods you described to access elements of your std::map container.
To compile with DWARF-2 debug info, add the -gdwarf-2 flag to your compile command.
I am running an application through gdb and I want to set a breakpoint for any time a specific variable is accessed / changed. Is there a good method for doing this? I would also be interested in other ways to monitor a variable in C/C++ to see if/when it changes.
watch only breaks on write, rwatch let you break on read, and awatch let you break on read/write.
You can set read watchpoints on memory locations:
gdb$ rwatch *0xfeedface
Hardware read watchpoint 2: *0xfeedface
but one limitation applies to the rwatch and awatch commands; you can't use gdb variables
in expressions:
gdb$ rwatch $ebx+0xec1a04f
Expression cannot be implemented with read/access watchpoint.
So you have to expand them yourself:
gdb$ print $ebx
$13 = 0x135700
gdb$ rwatch *0x135700+0xec1a04f
Hardware read watchpoint 3: *0x135700 + 0xec1a04f
gdb$ c
Hardware read watchpoint 3: *0x135700 + 0xec1a04f
Value = 0xec34daf
0x9527d6e7 in objc_msgSend ()
Edit: Oh, and by the way. You need either hardware or software support. Software is obviously much slower. To find out if your OS supports hardware watchpoints you can see the can-use-hw-watchpoints environment setting.
gdb$ show can-use-hw-watchpoints
Debugger's willingness to use watchpoint hardware is 1.
What you're looking for is called a watchpoint.
Usage
(gdb) watch foo: watch the value of variable foo
(gdb) watch *(int*)0x12345678: watch the value pointed by an address, casted to whatever type you want
(gdb) watch a*b + c/d: watch an arbitrarily complex expression, valid in the program's native language
Watchpoints are of three kinds:
watch: gdb will break when a write occurs
rwatch: gdb will break wnen a read occurs
awatch: gdb will break in both cases
You may choose the more appropriate for your needs.
For more information, check this out.
Assuming the first answer is referring to the C-like syntax (char *)(0x135700 +0xec1a04f) then the answer to do rwatch *0x135700+0xec1a04f is incorrect. The correct syntax is rwatch *(0x135700+0xec1a04f).
The lack of ()s there caused me a great deal of pain trying to use watchpoints myself.
I just tried the following:
$ cat gdbtest.c
int abc = 43;
int main()
{
abc = 10;
}
$ gcc -g -o gdbtest gdbtest.c
$ gdb gdbtest
...
(gdb) watch abc
Hardware watchpoint 1: abc
(gdb) r
Starting program: /home/mweerden/gdbtest
...
Old value = 43
New value = 10
main () at gdbtest.c:6
6 }
(gdb) quit
So it seems possible, but you do appear to need some hardware support.
Use watch to see when a variable is written to, rwatch when it is read and awatch when it is read/written from/to, as noted above. However, please note that to use this command, you must break the program, and the variable must be in scope when you've broken the program:
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.
In addition to what has already been answered/commented by asksol and Paolo M
I didn't at first read understand, why do we need to cast the results. Though I read this: https://sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints.html, yet it wasn't intuitive to me..
So I did an experiment to make the result clearer:
Code: (Let's say that int main() is at Line 3; int i=0 is at Line 5 and other code.. is from Line 10)
int main()
{
int i = 0;
int j;
i = 3840 // binary 1100 0000 0000 to take into account endianness
other code..
}
then i started gdb with the executable file
in my first attempt, i set the breakpoint on the location of variable without casting, following were the results displayed
Thread 1 "testing2" h
Breakpoint 2 at 0x10040109b: file testing2.c, line 10.
(gdb) s
7 i = 3840;
(gdb) p i
$1 = 0
(gdb) p &i
$2 = (int *) 0xffffcbfc
(gdb) watch *0xffffcbfc
Hardware watchpoint 3: *0xffffcbfc
(gdb) s
[New Thread 13168.0xa74]
Thread 1 "testing2" hit Breakpoint 2, main () at testing2.c:10
10 b = a;
(gdb) p i
$3 = 3840
(gdb) p *0xffffcbfc
$4 = 3840
(gdb) p/t *0xffffcbfc
$5 = 111100000000
as we could see breakpoint was hit for line 10 which was set by me. gdb didn't break because although variable i underwent change yet the location being watched didn't change (due to endianness, since it continued to remain all 0's)
in my second attempt, i did the casting on the address of the variable to watch for all the sizeof(int) bytes. this time:
(gdb) p &i
$6 = (int *) 0xffffcbfc
(gdb) p i
$7 = 0
(gdb) watch *(int *) 0xffffcbfc
Hardware watchpoint 6: *(int *) 0xffffcbfc
(gdb) b 10
Breakpoint 7 at 0x10040109b: file testing2.c, line 10.
(gdb) i b
Num Type Disp Enb Address What
6 hw watchpoint keep y *(int *) 0xffffcbfc
7 breakpoint keep y 0x000000010040109b in main at testing2.c:10
(gdb) n
[New Thread 21508.0x3c30]
Thread 1 "testing2" hit Hardware watchpoint 6: *(int *) 0xffffcbfc
Old value = 0
New value = 3840
Thread 1 "testing2" hit Breakpoint 7, main () at testing2.c:10
10 b = a;
gdb break since it detected the value has changed.