In recent versions of GDB, setting a breakpoint on a library function call results in multiple actual breakpoints:
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.
To skip a breakpoint a certain number of times, we use the ignore command. The ignore command takes two arguments: the breakpoint number to skip, and the number of times to skip it. (gdb) ignore 2 5 Will ignore next 5 crossings of breakpoint 2.
The PLT is the procedure linkage table, one of the structures which makes dynamic loading and linking easier to use.
Setting breakpoints A breakpoint is like a stop sign in your code -- whenever gdb gets to a breakpoint it halts execution of your program and allows you to examine it. To set breakpoints, type "break [filename]:[linenumber]". For example, if you wanted to set a breakpoint at line 55 of main.
The global offset table converts position-independent address calculations to absolute locations. Similarly the procedure linkage table converts position-independent function calls to absolute locations.
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:
So, this will place breakpoints on all the functions including PLT.
Now type:
This will save a list of all breakpoints in a file called as filename.
or
sed 's/@plt//g' filename > newfilename
Now type command:
or
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With