简体   繁体   English

防止 GDB 中的 PLT(过程链接表)断点

[英]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:在最新版本的 GDB 中,在库函数调用上设置断点会导致多个实际断点:

  1. Call into the procedure linkage table (PLT)调用过程链接表 (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.在以前的 GDB 版本中,只会创建 #2,因此您只能休息一次。

So the question is: can one can create a library function call breakpoint without the corresponding PLT breakpoint?那么问题来了:能不能在没有对应的PLT断点的情况下创建库函数调用断点呢? I am aware that you can create a regular breakpoint and then explicitly disable the PLT one, but this is really tedious.我知道您可以创建一个常规断点,然后显式禁用 PLT 断点,但这真的很乏味。

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). break 的语法,但不是指定十六进制地址,而是给出函数的名称(计算结果为函数的地址)。 Something like就像是

break *myfunction

That sets a breakpoint only on the main function, and not any of the PLT versions.这仅在主函数上设置断点,而不是任何 PLT 版本。

add these lines to your ~/.gdbinit file and call disaplts to disable all @plt breakpoints:将这些行添加到您的~/.gdbinit文件并调用disaplts以禁用所有@plt断点:

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.注意:注意python代码中的间距。 I recommend you use cat to paste the content.我建议您使用cat粘贴内容。 EDIT: added "execute on library load" per @WallStProg编辑:根据@WallStProg 添加“在库加载时执行”

Yup, it can be done.是的,它可以做到。

To simply place breakpoints on all functions, use command:要简单地在所有函数上放置断点,请使用命令:

  1. rbreak .* rbreak .*

So, this will place breakpoints on all the functions including PLT.因此,这将在包括 PLT 在内的所有函数上放置断点。

Now type:现在输入:

  1. save breakpoints filename保存断点文件名

This will save a list of all breakpoints in a file called as filename .这将在名为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.现在在像gedit这样的普通文本编辑器中打开文件,并删除文件末尾给出的所有PLT行。 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:使用以下命令从函数名称中删除所有@plt

sed 's/@plt//g' filename > newfilename sed 's/@plt//g' 文件名 > 新文件名

  1. After this, exit gdb (to unlink gdb from useless PLT breakpoints, added before) and execute gdb again .在此之后,退出 gdb (将 gdb 与无用的 PLT 断点断开,之前添加)并再次执行 gdb

Now type command:现在输入命令:

  1. source filename源文件名

or或者

  1. source newfilename (in case you used sed command)源新文件名(如果您使用了 sed 命令)

At this point, gdb will put breakpoints only on the functions mentioned in the file called as " filename " or " newfilename " (if used sed).此时,gdb 将仅在名为“ filename ”或“ newfilename ”(如果使用 sed)的文件中提到的函数上放置断点。

Note: To filter functions more in the file "filename" , one can use grep also according to the requirements.注意:要过滤更多文件“filename”中的函数,也可以根据需要使用grep。 :) :)

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.这是一个命令rdelete ,它就像delete一样, rbreak就像break一样 - 它根据正则表达式参数删除断点。

$ 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM