Prevent PLT (procedure linkage table) breakpoints in GDB - c++

In recent versions of GDB, setting a breakpoint on a library function call results in multiple actual breakpoints:
Call into the procedure linkage table (PLT)
The actual function call
This means that when the library function is called, we end up going through two breaks each time. In previous GDB versions, only #2 would be created and hence you only get one break.
So the question is: can one can create a library function call breakpoint without the corresponding PLT breakpoint? I am aware that you can create a regular breakpoint and then explicitly disable the PLT one, but this is really tedious.

I think I found a solution for this problem. You can use the
break *address
syntax of break, but instead of specifying a hex address, you give the name of the function (which evaluates to the function's address). Something like
break *myfunction
That sets a breakpoint only on the main function, and not any of the PLT versions.

add these lines to your ~/.gdbinit file and call disaplts to disable all #plt breakpoints:
define disaplts
python
import gdb
from StringIO import StringIO
lines=gdb.execute("info break", True, True)
for l in StringIO(lines).readlines():
if "#plt" in l:
bp=l.split()[0]
gdb.execute("disa {0}".format(bp))
print("disabling {0}".format(bp))
end
end
# disable on library load
catch load mylibrarywithplt disaplt
Note: mind the spacing in python code. I recommend you use cat to paste the content.
EDIT: added "execute on library load" per #WallStProg

Yup, it can be done.
To simply place breakpoints on all functions, use command:
rbreak .*
So, this will place breakpoints on all the functions including PLT.
Now type:
save breakpoints filename
This will save a list of all breakpoints in a file called as filename.
Now open the file in normal text editor like gedit, and remove all the PLT lines given at the end of the file. And then save the file with only the required functions on which you want to place breakpoints.
or
Remove all the #plt from the function names using the command:
sed 's/#plt//g' filename > newfilename
After this, exit gdb (to unlink gdb from useless PLT breakpoints, added before) and execute gdb again.
Now type command:
source filename
or
source newfilename (in case you used sed command)
At this point, gdb will put breakpoints only on the functions mentioned in the file called as "filename" or "newfilename" (if used sed).
Note: To filter functions more in the file "filename", one can use grep also according to the requirements. :)

Here's a command, rdelete, that is like delete in the same way that rbreak is like break - it deletes breakpoints based on a regexp argument.
$ cat rdelete.py
import gdb
import re
class RDelete(gdb.Command):
"""Delete breakpoints for all locations matching REGEXP."""
def __init__(self):
super (RDelete, self).__init__ ("rdelete", gdb.COMMAND_BREAKPOINTS, gdb.COMPLETE_LOCATION)
def invoke(self, argstr, from_tty):
bppat = re.compile(argstr)
for bp in gdb.breakpoints():
if bppat.search(bp.location):
print("Deleting breakpoint {} at {}".format(bp.number, bp.location))
bp.delete()
RDelete()
$ gdb -q hoist
(gdb) rbreak .*
...
(gdb) i b
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000000580 in main at hoist.c:6
2 breakpoint keep y 0x00000000000007a0 in x at hoist.c:4
3 breakpoint keep y 0x0000000000000530 <_init>
4 breakpoint keep y 0x0000000000000560 <printf#plt>
5 breakpoint keep y 0x00000000000007b0 <__libc_csu_init>
6 breakpoint keep y 0x0000000000000820 <__libc_csu_fini>
7 breakpoint keep y 0x0000000000000824 <_fini>
(gdb) source rdelete.py
(gdb) rdelete #plt
Deleting breakpoint 4 at printf#plt

Related

breakpoint at end of a function

I am trying to log the input and output of a function via gdb script. below is a sample script.
set logging on
b func2
commands
silent
bt 1
continue
end
b func1
commands
silent
bt 1
set logging off
continue
end
It works fine and breakpoints at the specified functions, prints the backtrace and continues.
is there a way to automatically set a breakpoint just before the called function returns to the calling function, so that I can just print output variables via gdb just after this "new" breakpoint.
This will greatly simplify my debug, and help understand the function behavior for different calls in the code.
Any help is highly appreciated.
Thanks a lot in advance !
I have looked into this and cannot find a way to do this with normal GDB breakpoints.
It is possible to implement using the GDB Python extensions API.
source-ing a file with the following content (source FILENAME) from with GDB will allow one to issue the command break-return which will place a temporary break-point at every 'return' in the current file (this is overkill but works). Once any one of the breakpoints is hit they are all deleted.
import gdb
class _ReturnBreakpoint(gdb.Breakpoint):
def stop(self):
for breakpoint in self._siblings:
if breakpoint.number != self.number:
gdb.execute(f"d {breakpoint.number}")
return True
class _BreakReturn(gdb.Command):
def __init__(self):
super(_BreakReturn, self).__init__("break-return", gdb.COMMAND_USER)
def invoke(self, arg, from_tty):
function_name = gdb.selected_frame().name()
source_file = gdb.selected_frame().find_sal().symtab.filename
breakpoints = []
with open(source_file) as o:
for zero_based_index, line in enumerate(o.readlines()):
if not 'return ' in line:
continue
breakpoint = _ReturnBreakpoint(line=zero_based_index+1, temporary=True)
breakpoints.append(breakpoint)
for breakpoint in breakpoints:
breakpoint._siblings = breakpoints
_BreakReturn() # register the command with GDB
Taken from https://github.com/jbcoe/GDB-extensions/blob/master/extensions/break-return.py
Patches are welcome.

gdb rbreak and commands (or dprintf behavior)?

Taking the example from http://shanekirk.com/2017/08/gdb-tips-and-tricks-2-setting-breakpoints-with-regular-expressions/ - when I use rbreak, I get something like:
(gdb) rb TestFixture.h:.
Breakpoint 1 at 0x4008b6: file TestFixture.h, line 5.
void TestFixture::setUp();
Breakpoint 2 at 0x4008d4: file TestFixture.h, line 6.
void TestFixture::tearDown();
Breakpoint 3 at 0x4008f2: file TestFixture.h, line 7.
void TestFixture::testA();
Breakpoint 4 at 0x400910: file TestFixture.h, line 8.
void TestFixture::testB();
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000000004008b6 in TestFixture::setUp() at TestFixture.h:5
2 breakpoint keep y 0x00000000004008d4 in TestFixture::tearDown() at TestFixture.h:6
3 breakpoint keep y 0x00000000004008f2 in TestFixture::testA() at TestFixture.h:7
4 breakpoint keep y 0x0000000000400910 in TestFixture::testB() at TestFixture.h:8
Now, what I want is basically a dprintf-like behavior: once one of this breakpoints is hit, I just want the function name printed out, and then continue (basically, a function call trace)
However, the way I understand gdb - in order to do that, I would issue a rbreak [regex] first, then I get a bunch of breakpoints, then for each and every one of those I'd had to type manually:
commands [number-of-breakpoint]
print "[name of function]"
continue
end
... which quickly becomes a chore, especially if you end up with a lot more breakpoints than the 4 in the above example (say hundreds).
Now, it would be rather cool, if I could use something like "regex dprintf", or rdprintf, as in:
rdprintf TestFixture.h:., "%s\n", $__breakname__
... but as far as I know, there is no such command...
Or, if after issuing a rbreak TestFixture.h:., I could target the commands for those breakpoints as:
commands 1-4
print $__breakname__
continue
end
... but again, I think this does not exist either...
So is there a way to use gdb to provide this kind of a function call trace printout - without me manually typing the names of breakpoints and their commands, similar to how rbreak allows you to set multiple breakpoints with one command?
EDIT: just found List of all function calls made in an application - record function-call-history /ilc might be interesting, but there doesn't seem to be a way to limit the scope of what functions to trace, say with a regex...
Ok, via the link above, found https://stackoverflow.com/a/39124320/277826 - turns out, you can issue command for multiple breakpoints, as found by rbreak; and to print the name of the function, just use backtrace 1:
(gdb) command 1-36
Type commands for breakpoint(s) 1-36, one per line.
End with a line saying just "end".
>silent
>bt 1
>continue
>end
(gdb) r
... or with python, printing the frame at bt 0 and its parent's frame name:
command 1-36
silent
python print("{} <- {}".format( gdb.execute("bt 0", False, True).strip(), gdb.newest_frame().older().name() ))
continue
end
... or even better, python printing bt 0 function name and args, and parent name:
command 1-36
silent
python nf = gdb.newest_frame(); nfb = nf.block()
python nfargs = [ "{}={}".format(sym, nf.read_var(sym, nfb)) for sym in nfb if sym.is_argument ]
python print("#0 {}({}) <- {}".format(nf.name(), ",".join(nfargs), nf.older().name() ))
continue
end
... which would print something like:
#0 Searcher::FlagFromCmd(this=0x7fffffffaed8,cmd=808) <- FindLiveStrip::GrabToggles
#0 Searcher::FlagFromCmd(this=0x7fffffffaed8,cmd=807) <- FindLiveStrip::ToggleChanged
... and this seems to work fine; though if there are other options, I'd love to know about them.

define a fuction that print something at breakpoint in gdb

I know b and command can print things when breakpoint triggers. But in my program, there're lots of memcpy, I need to print the target length and source address when code goes there, which are register $r2 and $r1.
The memcpys are located at:
$my_module_base+0xaaa
$my_module_base+0xbbb
...
I tried to write a function that take the $my_module_base as argument and set these breakpoint automatically
define set_all_bp
set $module_base=$arg0
b *$module_base+0xaaa
command
echo Here is memcpy 1:\n
my_dump $r1 $r2
end
b *$module_base+0xbbb
command
echo Here is memcpy 2:\n
my_dump $r1 $r2
end
end
But it doesn't work, gdb says:
(gdb) source my_script
bp:8: Error in sourced command file:
This command cannot be used at the top level.
(gdb)
Any other way to do this?

setting a breakpoint in a specific line inside a function with 'gdb'

I am trying to set a breakpoint to the fifth line inside a member function of a class(a class that I created) with 'gdb'.
From here I understood just how to set a breakpoint at the begining of the the function,but I want to set it on a specific line inside the function, or a specific offset from the begining of this function.
In general is there a way in 'gdb' to set a breakpoint to a line by setting an offset from another breakpoint I already have ?
Thanks !
You can create a breakpoint at an offset from the current stopped position with gdb breakpoint +<offset>.
You can also create a breakpoint on a specific line number using either gdb break <linenumber> (for the current source file) or gdb break <filename>:<linenumber> (for a file other than the current file).
More details in the docs.
There isn't a way to set a breakpoint relative to the start of a function such that it will retain its relative position if the source file is modified. This would sometimes be useful; but it is just a feature that nobody has added to gdb.
It could maybe be emulated from Python, though it couldn't work exactly the way that ordinary breakpoints work, because Python doesn't have access to the breakpoint resetting mechanism inside gdb.
A one-shot solution can be done either as shown in the other answer or from Python.
When I have needed this sort of functionality -- a breakpoint mid-function that is reasonably robust against source changes -- I have used "SDT" static probe points. These let you name such spots in your source.
info fun <function name>
or fully qualified info functions <function name>
gets functions and their source files
list <function name>
Print lines centered around the beginning of function function.
Will list all function's source code, with some code below.
Choose line you want
break <filename:linenum>
Here's how you can automate it with python scripts for GDB:
class RelativeFunctionBreakpoint (gdb.Breakpoint):
def __init__(self, functionName, lineOffset):
super().__init__(RelativeFunctionBreakpoint.calculate(functionName, lineOffset))
def calculate(functionName, lineOffset):
"""
Calculates an absolute breakpoint location (file:linenumber)
based on functionName and lineOffset
"""
# get info about the file and line number where the function is defined
info = gdb.execute("info line "+functionName, to_string=True)
# extract file name and line number
m = re.match(r'Line[^\d]+(\d+)[^"]+"([^"]+)', info)
if not m:
raise Exception('Failed to find function %s.' % functionName)
line = int(m.group(1))+lineOffset #add the lineOffset
fileName = m.group(2)
return "%s:%d" % (fileName, line)
Basic usage:
RelativeFunctionBreakpoint("yourFunctionName", lineOffset=5)
You can also write a custom breakpoint. See more here:
https://stackoverflow.com/a/46737659/5787022
Using python to script GDB
Official documentation:
https://sourceware.org/gdb/onlinedocs/gdb/Python.html
Some exapmles: http://tromey.com/blog/?p=548

Using less as gdb pager

I noticed that in GDB, when issuing commands with long output like info variables, the output is displayed one page at time, pressing enter to go down and q to quit.
Is it possible to replace the default pager with another one, such as less, so that I can navigate up and down, quitting, searching, etc?
Is it possible to replace the default pager with another one
No: GDB doesn't call into external program to display the output, it simply pauses the output every screenfull (and you can make it not pause by set height 0).
In addtion to running inside emacs, you could also use screen or tmux (learning them will generally help you in a lot of other situations), or ask GDB to log output (set logging on) and then search in gdb.txt with any $PAGER you want.
Starting with version 9.1, GDB has a pipe command, so you can send a command's output to the pager of your choice. From the documentation:
pipe [command] | shell_command
Executes command and sends its output to shell_command. Note that no space is needed around |. If no command is provided, the last command executed is repeated.
run gdb inside of emacs and you should be able to use emacs' paging commands.
run emacs
type M-x gdb return (M stands for meta - alt key or option on Macs)
The Emacs message bar will now display the message:
Run gdb (like this): gdb
More information is available here: http://tedlab.mit.edu/~dr/gdbintro.html
HTH
you can put the following user-defined commands in ~/.gdbinit, then
% cat ~/.gdbinit
python import os
define less1
python os.popen("less","w").write(gdb.execute("$arg0",to_string=True))
end
define less2
python os.popen("less","w").write(gdb.execute("$arg0 $arg1",to_string=True))
end
...
% gdb
(gdb) less2 info var
...
(gdb) less1 disass
...
It is a bit old thread, but I think it is worth to add. #yichun gave a very nice idea here, but to be more practical it can be extended to any number of arguments:
define less
python import os
python os.popen("less","w").write(gdb.execute(' '.join(["$arg{0}".format(i) for i in range(0, argc)]), to_string=True))
end
Then it can also woth adding exceptions handling and waiting for processes to terminate to avoid keyboard glitches and we have something like that:
% cat ~/.gdbinit
define less
python argc = $argc
python
import os
f = None
try:
f = os.popen("less","w")
f.write(gdb.execute(' '.join(["$arg{0}".format(i) for i in range(0, argc)]), to_string=True))
except Exception as e:
if f:
f.write(str(e))
else:
print (str(e))
finally:
if f:
f.close()
end
end
In gdb 8.1.1 this code in .gdbinit adds the required functionality:
python
import os
class Less(gdb.Command):
def __init__(self):
super().__init__("less", gdb.COMMAND_USER, gdb.COMPLETE_COMMAND)
def invoke(self, argstr, from_tty):
with os.popen("less","w") as pipe:
try:
pipe.write(gdb.execute(argstr, to_string=True))
except Exception as e:
pipe.write(str(e))
Less()
end
Usage
(gdb) less info breakpoints
(gdb) less backtrace
Information: Commands In Python.