Using gdb, display multiple vars in one line? - debugging

How can I ask to display multiple vars in one line? So I want to get output like:
30 if(s[i] != '\0')
5: s[i] = 101 'e'
4: exp = 14
3: val = 123.45
2: sign = 1
1: i = 6
I've been typing in disp s[i] ENTER disp exp ENTER (etc, etc) and I just know there's got to be a better way to do this in one line of typing.

To establish multiple active "variable displays" without re-typing each of display i, display s[i], etc. every time you restart GDB, use a GDB "canned command sequence".
For example, add this to your ~/.gdbinit:
define disp_vars
disp i
disp sign
disp val
disp exp
disp s[i]
end
Now you can add all the displays at once by typing disp_vars at the GDB prompt.

Employed Russian gave the correct solution but for those that want see it used in an example see below. If you're not sure if you want to commit to putting the .gdbinit in your home directory, you can also put it in the directory you're executing the program from to experiment.
$ gcc -g atof_ex4.2.c
$ gdb ./a.out
(gdb) b 30
Breakpoint 1 at 0x1907: file atof_ex4.2.c, line 30.
(gdb) h user-defined
List of commands:
disp_vars -- User-defined
(gdb) disp_vars #this will enable the user defined canned sequence (but I haven't done run yet! So I'll this actually doesn't work yet.)
No symbol "i" in current context.
(gdb) r
Starting program: a.out
Breakpoint 1, atof (s=0xbffff028 "123.45e-6") at atof_ex4.2.c:30
30 if(s[i] != '\0')
(gdb) s # No disp_vars output yet because I have to do it AFTER 'run' command
32 if(s[i] == 'e' || s[i] == 'E')
(gdb) disp_vars # Now it will work ;)
(gdb) s
35 sign = (s[i] == '-') ? -1 : 1;
5: s[i] = 45 '-'
4: exp = 14
3: val = 123.45
2: sign = 1
1: i = 7
Of course 'r' is for run, 's' is for step, 'b' is for break, etc. I've also omitted some output. Notice that I had to enter the 'disp_vars' command again after 'run'. Thanks Employed Russian.

Related

How can I detect breakpoints in GDB command files and stop the execution?

I am trying to implement a single stepping using GDB command file. I would like to stop executing the command file whenever I encounter any breakpoint.
Is there a way to detect that a breakpoint was hit? and also how can I stop executing the command file after that.
I checked the documantation and it seems like I only can have break commands for certain breakpoints. But not for a random breakpoint.
I have something like this:
printf "single stepping\n"
set $steps_count = 0
while ($steps_count < 5)
set $steps_count = $steps_count + 1
printf "program counter 0x%x\n", $pc
printf "next #%d\n", $steps_count
next
end
And this is what I want to achieve:
printf "single stepping\n"
set $steps_count = 0
while (# breakpoint is not hit)
set $steps_count = $steps_count + 1
printf "program counter 0x%x\n", $pc
printf "next #%d\n", $steps_count
next
end
# end the execution of the command file.
update:
I tried to use the follwing:
# set the end breakpoint
break *0x199e
commands
stop 1
quit
end
break *0x1980
# set a certain once we encounter the first breakpoint
commands
set $count = 0
while $count < 5
printf "#PC: 0x%x", $pc
set $count = $count + 1
stepi
end
end
This should start logging the program counter once the first breakpoint is hit. But I don't know why this break command doesn't work. Once the breakpoint is hit the program stops and the while loop is not entered!
Update:
according to the gdb documentation:
Any other commands in the command list, after a command that resumes execution, are ignored. This is because any time you resume execution (even with a simple next or step), you may encounter another breakpoint--which could have its own command list, leading to ambiguities about which list to execute.
so I don't think it is a good idea to put a loop that has step or next in break commands.
Try something like:
commands 1-10 # for breakpoints number 1 through 10
set $breakpoint_hit = 1
end
Then check for that in your loop.

Can strace tell me where in my code a syscall is called?

I'm trying to debug why ngspice prints annoying newlines to stderr while running a simulation. I'm trying to locate it in one of the 2400 source files tracing back to 1993 but it's not as easy as it sounds! It does however mean that I have a binary with all debug information embedded.
My first idea was that strace could help me locate what I believe is the offending call and trace it back to the source code. For example, I'm pretty sure that this is the offending syscall:
brk(0x55d1a84e9000) = 0x55d1a84e9000
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, {tv_sec=0, tv_nsec=61462905}) = 0
>> write(2, "\n", 1) = 1
getrusage(RUSAGE_SELF, {ru_utime={tv_sec=0, tv_usec=26269}, ru_stime={tv_sec=0, tv_usec=35243}, ...}) = 0
openat(AT_FDCWD, "/proc/self/statm", O_RDONLY) = 3
I had hoped that if I traced an executable that had debug information, strace would show me the place in the source code, but that did not happen automatically and the manual is a little overwhelming.
I found a section in the manual called Tracing but couldn't find anything specific.
Is it possible with strace, and if so: How? If not, do you have any other suggestions?
Obvious in hindsight, but one very useful flag is -k. From the man-page:
-k Print the execution stack trace of the traced processes after each system call.
This needs a binary with debug information, and it will get extremely noisy, but combined with a simple filter (-e write in this case) you will eventually get something that looks like this:
write(2, "\n", 1
) = 1
> /lib/x86_64-linux-gnu/libc-2.28.so(__write+0x14) [0xea504]
> /lib/x86_64-linux-gnu/libc-2.28.so(_IO_file_write+0x2d) [0x7b3bd]
> /lib/x86_64-linux-gnu/libc-2.28.so(_IO_file_setbuf+0xef) [0x7a75f]
> /lib/x86_64-linux-gnu/libc-2.28.so(_IO_do_write+0x19) [0x7c509]
> /lib/x86_64-linux-gnu/libc-2.28.so(_IO_file_overflow+0x103) [0x7c8f3]
> /home/pipe/src/ngspice/debug/src/ngspice(OUTendPlot+0x1ae) [0xd7643]
> /home/pipe/src/ngspice/debug/src/ngspice(DCop+0x167) [0x4cd788]
> /home/pipe/src/ngspice/debug/src/ngspice(CKTdoJob+0x428) [0x4c70dd]
> /home/pipe/src/ngspice/debug/src/ngspice(if_run+0x3b9) [0xe5d3e]
> /home/pipe/src/ngspice/debug/src/ngspice(dosim+0x428) [0xe02ee]
From this I could eventually find the right place after tracking some function inline optimizations.
Using gdb, you can set conditional syscall catchpoints based on the args to the system call (analogous to the way you'd set conditional breakpoints on entry to a function based on the args to the function call). Then, when the catchpoint is triggered, you can see where the caller is (file name, line number, and source code).
Here's an example for x86_64.
$ cat gtest.c
#include <unistd.h>
int main()
{
write(1, "text\n", 5);
write(2, "text2\n", 6);
write(2, "\n", 1);
return 0;
}
$ cc gtest.c -g -o gtest
$ gdb -q gtest
Reading symbols from gtest...done.
(gdb) list
1 #include <unistd.h>
2 int main()
3 {
4 write(1, "text\n", 5);
5 write(2, "text2\n", 6);
6 write(2, "\n", 1);
7 return 0;
8 }
(gdb) catch syscall write
Catchpoint 1 (syscall 'write' [1])
(gdb) condition 1 $rdi == 2 && *(char *)$rsi == '\n' && $rdx == 1
(gdb) r
Starting program: /home/mp/gtest
text
text2
Catchpoint 1 (call to syscall write), 0x00007fffff13b970 in __write_nocancel ()
at ../sysdeps/unix/syscall-template.S:84
84 ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) bt
#0 0x00007fffff13b970 in __write_nocancel () at ../sysdeps/unix/syscall-template.S:84
#1 0x00000000080006f6 in main () at gtest.c:6
(gdb) up
#1 0x00000000080006f6 in main () at gtest.c:6
6 write(2, "\n", 1);
(gdb)
My first idea was that strace could help me locate what I believe is the offending call and trace it back to the source code.
You guessed right, but must have overlooked this in the strace manual page:
-i Print the instruction pointer at the time of the system call.

Can I tell LLDB to remove the active breakpoint?

When LLDB triggers breakpoint X, is there a command that will disable or remove X and then continue?
That's an interesting idea. There's no built in command to do this in lldb but it would be easy to implement as a user-defined command written in Python. SBThread::GetStopReason() will be eStopReasonBreakpoint if that thread stopped because of a breakpoint. SBThread::GetStopReasonDataCount() will return 2 -- indicating that the breakpoint id and location id are available. SBThread::GetStopReasonDataAtIndex(0) will give you the breakpoint ID, SBThread::GetStopReasonDataAtIndex(1) will give you the location ID. (a single user-specified breakpoint may resolve to multiple locations. e.g. an inlined function, or a function name that occurs in multiple libraries in a single program.)
Here's a quick & dirty example of a python command that does this. I put this in ~/lldb where I save my lldb user-defined commands and then in my ~/.lldbinit file I have a line like command script import ~/lldb/disthis.py.
In use, it looks like this:
% lldb a.out
(lldb) target create "a.out"
Current executable set to 'a.out' (x86_64).
(lldb) br s -n main
Breakpoint 1: where = a.out`main + 15 at a.c:4, address = 0x0000000100000f4f
(lldb) r
Process 67487 launched: '/private/tmp/a.out' (x86_64)
Process 67487 stopped
* thread #1: tid = 0x290c51, 0x0000000100000f4f a.out`main + 15 at a.c:4, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
#0: 0x0000000100000f4f a.out`main + 15 at a.c:4
1 #include <stdio.h>
2 int main()
3 {
-> 4 puts ("HI");
5 puts ("HI");
6 }
(lldb) com scr imp ~/lldb/disthis.py
(lldb) disthis
Breakpoint 1.1 disabled.
(lldb) br li
Current breakpoints:
1: name = 'main', locations = 1
1.1: where = a.out`main + 15 at a.c:4, address = 0x0000000100000f4f, unresolved, hit count = 1 Options: disabled
(lldb)
Pretty straightforward.
# import this into lldb with a command like
# command script import disthis.py
import lldb
def disthis(debugger, command, *args):
"""Usage: disthis
Disables the breakpoint the currently selected thread is stopped at."""
target = None
thread = None
if len(args) == 2:
# Old lldb invocation style
result = args[0]
if debugger and debugger.GetSelectedTarget() and debugger.GetSelectedTarget().GetProcess():
target = debugger.GetSelectedTarget()
process = target.GetProcess()
thread = process.GetSelectedThread()
elif len(args) == 3:
# New (2015 & later) lldb invocation style where we're given the execution context
exe_ctx = args[0]
result = args[1]
target = exe_ctx.GetTarget()
thread = exe_ctx.GetThread()
else:
print "Unknown python function invocation from lldb."
return
if thread == None:
print >>result, "error: process is not paused, or has not been started yet."
result.SetStatus (lldb.eReturnStatusFailed)
return
if thread.GetStopReason() != lldb.eStopReasonBreakpoint:
print >>result, "error: not stopped at a breakpoint."
result.SetStatus (lldb.eReturnStatusFailed)
return
if thread.GetStopReasonDataCount() != 2:
print >>result, "error: Unexpected number of StopReasonData returned, expected 2, got %d" % thread.GetStopReasonDataCount()
result.SetStatus (lldb.eReturnStatusFailed)
return
break_num = thread.GetStopReasonDataAtIndex(0)
location_num = thread.GetStopReasonDataAtIndex(1)
if break_num == 0 or location_num == 0:
print >>result, "error: Got invalid breakpoint number or location number"
result.SetStatus (lldb.eReturnStatusFailed)
return
bkpt = target.FindBreakpointByID (break_num)
if location_num > bkpt.GetNumLocations():
print >>result, "error: Invalid location number"
result.SetStatus (lldb.eReturnStatusFailed)
return
bkpt_loc = bkpt.GetLocationAtIndex(location_num - 1)
if bkpt_loc.IsValid() != True:
print >>result, "error: Got invalid BreakpointLocation"
result.SetStatus (lldb.eReturnStatusFailed)
return
bkpt_loc.SetEnabled(False)
print >>result, "Breakpoint %d.%d disabled." % (break_num, location_num)
return
def __lldb_init_module (debugger, dict):
debugger.HandleCommand('command script add -f %s.disthis disthis' % __name__)

how could the const char * changed?

I am writing a program which can print the directory recursively,
below is the gdb debug segment
note that the d_path (it is a const char * passed as a parameter to print_dir_tree)
is "/home/cifer/.gftp" before step to "if (dr == NULL) {"
however, it is printed "/home/cifer/!\200" after this clause
who can tell me why?
thanks a lot!
Breakpoint 1, print_dir_tree (d_path=0x805b058 "/home/cifer/.gftp", depth=4)
at dir_demo.c:15
15 DIR *dr = opendir(d_path);
(gdb) print d_path
$2 = 0x805b058 "/home/cifer/.gftp"
(gdb) print d_path
$3 = 0x805b058 "/home/cifer/.gftp"
(gdb) step
16 if (dr == NULL) {
(gdb) print d_path
$4 = 0x805b058 "/home/cifer/!\200"
(gdb) step
20 struct dirent *de = NULL;
(gdb) print d_path
$5 = 0x805b058 "/home/cifer/!\200"
(gdb) step
21 while((de = readdir(dr)) != NULL) {
(gdb) print d_path
$6 = 0x805b058 "/home/cifer/!\200"
(gdb)
I would need to see your code to tell for sure but if you are asking if a const can be changed the answer is yes. If you are asking how it can be changed, that is simple, it is treated just like a regular variable but it will give you a warning when it is changed. If you are trying to change it and avoid a warning you can copy the variable and then make changes to it.

View array in LLDB: equivalent of GDB's '#' operator in Xcode 4.1

I would like to view an array of elements pointed to by a pointer. In GDB this can be done by treating the pointed memory as an artificial array of a given length using the operator '#' as
*pointer # length
where length is the number of elements I want to view.
The above syntax does not work in LLDB supplied with Xcode 4.1.
Is there any way how to accomplish the above in LLDB?
There are two ways to do this in lldb.
Most commonly, you use the parray lldb command which takes a COUNT and an EXPRESSION; EXPRESSION is evaluated and should result in a pointer to memory. lldb will then print COUNT items of that type at that address. e.g.
parray 10 ptr
where ptr is of type int *.
Alternatively, it can be done by casting the pointer to a pointer-to-array.
For example, if you have a int* ptr, and you want to view it as an array of ten integers, you can do
p *(int(*)[10])ptr
Because it relies only on standard C features, this method works without any plugins or special settings. It likewise works with other debuggers like GDB or CDB, even though they also have specialized syntaxes for printing arrays.
Starting with the lldb in Xcode 8.0, there is a new built-in parray command. So you can say:
(lldb) parray <COUNT> <EXPRESSION>
to print the memory pointed to by the result of the EXPRESSION as an array of COUNT elements of the type pointed to by the expression.
If the count is stored in a variable available in the current frame, then remember you can do:
(lldb) parray `count_variable` pointer_to_malloced_array
That's a general lldb feature, any command-line argument in lldb surrounded in backticks gets evaluated as an expression that returns an integer, and then the integer gets substituted for the argument before command execution.
The only way I found was via a Python scripting module:
""" File: parray.py """
import lldb
import shlex
def parray(debugger, command, result, dict):
args = shlex.split(command)
va = lldb.frame.FindVariable(args[0])
for i in range(0, int(args[1])):
print va.GetChildAtIndex(i, 0, 1)
Define a command "parray" in lldb:
(lldb) command script import /path/to/parray.py
(lldb) command script add --function parray.parray parray
Now you can use "parray variable length":
(lldb) parray a 5
(double) *a = 0
(double) [1] = 0
(double) [2] = 1.14468
(double) [3] = 2.28936
(double) [4] = 3.43404
With Xcode 4.5.1 (which may or may not help you now), you can do this in the lldb console:
(lldb) type summary add -s "${var[0-63]}" "float *"
(lldb) frame variable pointer
(float *) pointer = 0x000000010ba92950 [0.0,1.0,2.0,3.0, ... ,63.0]
This example assumes that 'pointer' is an array of 64 floats: float pointer[64];
It doesn't seem to be supported yet.
You could use the memory read function (memory read / x), like
(lldb) memory read -ff -c10 `test`
to print a float ten times from that pointer. This should be the same functionality as gdb's #.
Starting with Martin R answer I improved it as follow:
If the pointer is not a simple variable, e.g.:
struct {
int* at;
size_t size;
} a;
Then "parray a.at 5" fails.
I fixed this by replacing "FindVariable" with "GetValueForVariablePath".
Now what if the elements in your array are aggregates, e.g.:
struct {
struct { float x; float y; }* at;
size_t size;
} a;
Then "parray a.at 5" prints: a.at->x, a.at->y, a.at[2], a.at[3], a.at[4] because GetChildAtIndex() returns members of aggregates.
I fixed this by resolving "a.at" + "[" + str(i) + "]" inside the loop instead of resolving "a.at" and then retrieving its children.
Added an optional "first" argument (Usage: parray [FIRST] COUNT), which is useful when you have a huge number of elements.
Made it do the "command script add -f parray.parray parray" at init
Here is my modified version:
import lldb
import shlex
def parray(debugger, command, result, dict):
args = shlex.split(command)
if len(args) == 2:
count = int(args[1])
indices = range(count)
elif len(args) == 3:
first = int(args[1]), count = int(args[2])
indices = range(first, first + count)
else:
print 'Usage: parray ARRAY [FIRST] COUNT'
return
for i in indices:
print lldb.frame.GetValueForVariablePath(args[0] + "[" + str(i) + "]")
def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand('command script add -f parray.parray parray')
I tried to add a comment but that wasn't great for posting a full answer so I made my own answer. This solves the problem with getting "No Value". You need to get the current frame as I believe lldb.frame is set at module import time so it doesn't have the current frame when you stop at a breakpoint if you load the module from .lldbinit. The other version would work if you import or reloaded the script when you stopped at the breakpoint. The version below should always work.
import lldb
import shlex
#lldb.command('parray', 'command script add -f parray.parray parray')
def parray(debugger, command, result, dict):
target = debugger.GetSelectedTarget()
process = target.GetProcess()
thread = process.GetSelectedThread()
frame = thread.GetSelectedFrame()
args = shlex.split(command)
if len(args) == 2:
count = int(args[1])
indices = range(count)
elif len(args) == 3:
first = int(args[1])
count = int(args[2])
indices = range(first, first + count)
else:
print 'Usage: parray ARRAY [FIRST] COUNT'
return
for i in indices:
print frame.GetValueForVariablePath(args[0] + "[" + str(i) + "]")
To inspect variables you can use the frame variable command (fr v is the shortest unique prefix) which has a -Z flag which does exactly what you want:
(lldb) fr v buffer -Z5
(int64_t *) buffer = 0x000000010950c000 {
(int64_t) [0] = 0
(int64_t) [1] = 0
(int64_t) [2] = 0
(int64_t) [3] = 0
(int64_t) [4] = 0
}
unfortunately expression does not support that flag
Well at that point, you may as well write your own custom C function and invoke it with:
call (int)myprint(args)

Resources