Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent PLT (procedure linkage table) breakpoints in GDB

In recent versions of GDB, setting a breakpoint on a library function call results in multiple actual breakpoints:

  1. Call into the procedure linkage table (PLT)
  2. 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.

like image 758
istarus Avatar asked Jan 30 '15 19:01

istarus


People also ask

How do I skip breakpoints in gdb?

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.

What is PLT in gdb?

The PLT is the procedure linkage table, one of the structures which makes dynamic loading and linking easier to use.

How do you set breakpoints in gdb C?

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.

What is the procedure linkage table?

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.


4 Answers

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.

like image 102
SCFrench Avatar answered Oct 13 '22 02:10

SCFrench


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

like image 42
Felipe Lema Avatar answered Oct 13 '22 01:10

Felipe Lema


Yup, it can be done.

To simply place breakpoints on all functions, use command:

  1. rbreak .*

So, this will place breakpoints on all the functions including PLT.

Now type:

  1. save breakpoints filename

This will save a list of all breakpoints in a file called as filename.

  1. 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

  1. Remove all the @plt from the function names using the command:

sed 's/@plt//g' filename > newfilename

  1. After this, exit gdb (to unlink gdb from useless PLT breakpoints, added before) and execute gdb again.

Now type command:

  1. source filename

or

  1. 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. :)

like image 37
RuchirArya Avatar answered Oct 13 '22 01:10

RuchirArya


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
like image 37
Mark Plotnick Avatar answered Oct 13 '22 02:10

Mark Plotnick