Skip to content

Instantly share code, notes, and snippets.

@maliubiao
Last active December 22, 2015 03:19
Show Gist options
  • Save maliubiao/6409557 to your computer and use it in GitHub Desktop.
Save maliubiao/6409557 to your computer and use it in GitHub Desktop.
break a c function in python, usage: source break.py, see: help pycbreak in gdb.
#! /usr/bin/env python
try:
import gdb
except:
print("gdb only")
exit(0)
def version_error():
print("python 2.7.3 only")
exit(0)
import sys
for m, n in zip((2, 7, 3), sys.version_info):
if m != n:
version_error()
parse_and_eval = gdb.parse_and_eval
class CFunctionBreak(gdb.Breakpoint):
def __init__(self, name):
super(CFunctionBreak, self).__init__(
spec = "PyCFunction_Call",
type = gdb.WP_READ,
wp_class = gdb.BP_READ_WATCHPOINT
)
self.functionname = name
self.flags = {
0x0000: "METH_OLDARGS",
0x0001: "METH_VARARGS",
0x0002: "METH_KEYWORDS",
0x0004: "METH_NOARGS",
0x0008: "METH_O"
}
self.query = "((PyCFunctionObject *)func)->m_ml"
def stop(self):
function = parse_and_eval(self.query)
info = ("name: ", str(function['ml_name']),
", function: ", str(function['ml_meth']),
", doc: ", str(function['ml_doc']),
", flags: ", self.translate_flags(int(function['ml_flags'])),
"\n")
if self.functionname == str(function['ml_name']):
print("".join(info))
return False
def translate_flags(self, functionflag):
flaglist = []
for flag in self.flags.keys():
if functionflag & flag:
flaglist.append(self.flags[flag])
return "|".join(flaglist)
class CFunctionCmd(gdb.Command):
'''pycbreak {add, rm, enable, disable} function'''
def __init__(self):
super(CFunctionCmd, self).__init__(
name="pycbreak",
command_class = gdb.COMMAND_BREAKPOINTS,
completer_class = gdb.COMPLETE_SYMBOL,
)
self.breaklist = {}
def invoke(self, argument, from_tty):
args = gdb.string_to_argv(argument)
if len(args) < 2:
raise gdb.GdbError("require more arguments, see: help pycbreak")
if args[0] == 'add':
self.breaklist[args[1]] = CFunctionBreak(args[1])
elif args[0] == 'rm':
try:
self.breaklist[args[1]].delete()
except:
raise gdb.GdbError("There is no breakpoint: %s" % args[1])
elif args[0] == "enable":
try:
self.breaklist[args[1]].enabled = True
except:
raise gdb.GdbError("There is no breakpoint: %s" % args[1])
elif args[0] == "disable":
try:
self.breaklist[args[1]].enabled = False
except:
raise gdb.GdbError("There is no breakpoint: %s" % args[1])
else:
raise gdb.GdbError("unknown command %s" % args[0])
CFunctionCmd()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment