Add more gdb modules and tools
This commit is contained in:
parent
01fe1ff04a
commit
28ce478821
5
.gdbinit
5
.gdbinit
@ -1,2 +1,7 @@
|
|||||||
#source ~/config/gdb/peda/peda.py
|
#source ~/config/gdb/peda/peda.py
|
||||||
#source ~/config/gdb/gdb-dashboard/.gdbinit
|
#source ~/config/gdb/gdb-dashboard/.gdbinit
|
||||||
|
#source ~/config/gdb/gdb_gef/gef.py
|
||||||
|
|
||||||
|
source ~/config/gdb/commands.py
|
||||||
|
source ~/config/gdb/commands2.py
|
||||||
|
|
||||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -13,3 +13,6 @@
|
|||||||
[submodule "gdb/gdbundle"]
|
[submodule "gdb/gdbundle"]
|
||||||
path = gdb/gdbundle
|
path = gdb/gdbundle
|
||||||
url = https://github.com/memfault/gdbundle
|
url = https://github.com/memfault/gdbundle
|
||||||
|
[submodule "gdb/gdb_gef"]
|
||||||
|
path = gdb/gdb_gef
|
||||||
|
url = https://github.com/hugsy/gef
|
||||||
|
268
gdb/commands.py
Normal file
268
gdb/commands.py
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
#from https://www.pythonsheets.com/appendix/python-gdb.html
|
||||||
|
# try help user-defined from gdb for desc
|
||||||
|
|
||||||
|
import gdb
|
||||||
|
import time
|
||||||
|
import re
|
||||||
|
import json
|
||||||
|
|
||||||
|
class DumpMemory(gdb.Command):
|
||||||
|
"""Dump memory info into a file."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("dm", gdb.COMMAND_USER)
|
||||||
|
|
||||||
|
def get_addr(self, p, tty):
|
||||||
|
"""Get memory addresses."""
|
||||||
|
cmd = "info proc mappings"
|
||||||
|
out = gdb.execute(cmd, tty, True)
|
||||||
|
addrs = []
|
||||||
|
for l in out.split("\n"):
|
||||||
|
if re.match(f".*{p}*", l):
|
||||||
|
s, e, *_ = l.split()
|
||||||
|
addrs.append((s, e))
|
||||||
|
return addrs
|
||||||
|
|
||||||
|
def dump(self, addrs):
|
||||||
|
"""Dump memory result."""
|
||||||
|
if not addrs:
|
||||||
|
return
|
||||||
|
|
||||||
|
for s, e in addrs:
|
||||||
|
f = int(time.time() * 1000)
|
||||||
|
gdb.execute(f"dump memory {f}.bin {s} {e}")
|
||||||
|
|
||||||
|
def invoke(self, args, tty):
|
||||||
|
try:
|
||||||
|
# cat /proc/self/maps
|
||||||
|
addrs = self.get_addr(args, tty)
|
||||||
|
# dump memory
|
||||||
|
self.dump(addrs)
|
||||||
|
except Exception as e:
|
||||||
|
print("Usage: dm [pattern]\n\twhith pattern : heap, stack or any value in /proc/self/maps")
|
||||||
|
|
||||||
|
DumpMemory()
|
||||||
|
|
||||||
|
class DumpJson(gdb.Command):
|
||||||
|
"""Dump std::string as a styled JSON."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("dj", gdb.COMMAND_USER)
|
||||||
|
|
||||||
|
def get_json(self, args):
|
||||||
|
"""Parse std::string to JSON string."""
|
||||||
|
ret = gdb.parse_and_eval(args)
|
||||||
|
typ = str(ret.type)
|
||||||
|
if re.match("^std::.*::string", typ):
|
||||||
|
return json.loads(str(ret))
|
||||||
|
return None
|
||||||
|
|
||||||
|
def invoke(self, args, tty):
|
||||||
|
try:
|
||||||
|
# string to json string
|
||||||
|
s = self.get_json(args)
|
||||||
|
# json string to object
|
||||||
|
o = json.loads(s)
|
||||||
|
print(json.dumps(o, indent=2))
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Parse json error! {args}")
|
||||||
|
|
||||||
|
DumpJson()
|
||||||
|
|
||||||
|
tp = {}
|
||||||
|
|
||||||
|
class Tracepoint(gdb.Breakpoint):
|
||||||
|
def __init__(self, *args):
|
||||||
|
super().__init__(*args)
|
||||||
|
self.silent = True
|
||||||
|
self.count = 0
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.count += 1
|
||||||
|
frame = gdb.newest_frame()
|
||||||
|
block = frame.block()
|
||||||
|
sym_and_line = frame.find_sal()
|
||||||
|
framename = frame.name()
|
||||||
|
filename = sym_and_line.symtab.filename
|
||||||
|
line = sym_and_line.line
|
||||||
|
# show tracepoint info
|
||||||
|
print(f"{framename} @ {filename}:{line}")
|
||||||
|
# show args and vars
|
||||||
|
for s in block:
|
||||||
|
if not s.is_argument and not s.is_variable:
|
||||||
|
continue
|
||||||
|
typ = s.type
|
||||||
|
val = s.value(frame)
|
||||||
|
size = typ.sizeof
|
||||||
|
name = s.name
|
||||||
|
print(f"\t{name}({typ}: {val}) [{size}]")
|
||||||
|
# do not stop at tracepoint
|
||||||
|
return False
|
||||||
|
|
||||||
|
class SetTracepoint(gdb.Command):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("tp", gdb.COMMAND_USER)
|
||||||
|
|
||||||
|
def invoke(self, args, tty):
|
||||||
|
try:
|
||||||
|
global tp
|
||||||
|
tp[args] = Tracepoint(args)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
def finish(event):
|
||||||
|
for t, p in tp.items():
|
||||||
|
c = p.count
|
||||||
|
print(f"Tracepoint '{t}' Count: {c}")
|
||||||
|
|
||||||
|
gdb.events.exited.connect(finish)
|
||||||
|
SetTracepoint()
|
||||||
|
|
||||||
|
|
||||||
|
class EndPoint(gdb.FinishBreakpoint):
|
||||||
|
def __init__(self, breakpoint, *a, **kw):
|
||||||
|
super().__init__(*a, **kw)
|
||||||
|
self.silent = True
|
||||||
|
self.breakpoint = breakpoint
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
# normal finish
|
||||||
|
end = time.time()
|
||||||
|
start, out = self.breakpoint.stack.pop()
|
||||||
|
diff = end - start
|
||||||
|
print(out.strip())
|
||||||
|
print(f"\tCost: {diff}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
class StartPoint(gdb.Breakpoint):
|
||||||
|
def __init__(self, *a, **kw):
|
||||||
|
super().__init__(*a, **kw)
|
||||||
|
self.silent = True
|
||||||
|
self.stack = []
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
start = time.time()
|
||||||
|
# start, end, diff
|
||||||
|
frame = gdb.newest_frame()
|
||||||
|
sym_and_line = frame.find_sal()
|
||||||
|
func = frame.function().name
|
||||||
|
filename = sym_and_line.symtab.filename
|
||||||
|
line = sym_and_line.line
|
||||||
|
block = frame.block()
|
||||||
|
|
||||||
|
args = []
|
||||||
|
for s in block:
|
||||||
|
if not s.is_argument:
|
||||||
|
continue
|
||||||
|
name = s.name
|
||||||
|
typ = s.type
|
||||||
|
val = s.value(frame)
|
||||||
|
args.append(f"{name}: {val} [{typ}]")
|
||||||
|
|
||||||
|
# format
|
||||||
|
out = ""
|
||||||
|
out += f"{func} @ {filename}:{line}\n"
|
||||||
|
for a in args:
|
||||||
|
out += f"\t{a}\n"
|
||||||
|
|
||||||
|
# append current status to a breakpoint stack
|
||||||
|
self.stack.append((start, out))
|
||||||
|
EndPoint(self, internal=True)
|
||||||
|
return False
|
||||||
|
|
||||||
|
class Profile(gdb.Command):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("prof", gdb.COMMAND_USER)
|
||||||
|
|
||||||
|
def invoke(self, args, tty):
|
||||||
|
try:
|
||||||
|
StartPoint(args)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
Profile()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import pwd
|
||||||
|
import grp
|
||||||
|
import stat
|
||||||
|
import time
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class StatPrint:
|
||||||
|
def __init__(self, val):
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def get_filetype(self, st_mode):
|
||||||
|
if stat.S_ISDIR(st_mode):
|
||||||
|
return "directory"
|
||||||
|
if stat.S_ISCHR(st_mode):
|
||||||
|
return "character device"
|
||||||
|
if stat.S_ISBLK(st_mode):
|
||||||
|
return "block device"
|
||||||
|
if stat.S_ISREG:
|
||||||
|
return "regular file"
|
||||||
|
if stat.S_ISFIFO(st_mode):
|
||||||
|
return "FIFO"
|
||||||
|
if stat.S_ISLNK(st_mode):
|
||||||
|
return "symbolic link"
|
||||||
|
if stat.S_ISSOCK(st_mode):
|
||||||
|
return "socket"
|
||||||
|
return "unknown"
|
||||||
|
|
||||||
|
def get_access(self, st_mode):
|
||||||
|
out = "-"
|
||||||
|
info = ("r", "w", "x")
|
||||||
|
perm = [
|
||||||
|
(stat.S_IRUSR, stat.S_IWUSR, stat.S_IXUSR),
|
||||||
|
(stat.S_IRGRP, stat.S_IRWXG, stat.S_IXGRP),
|
||||||
|
(stat.S_IROTH, stat.S_IWOTH, stat.S_IXOTH),
|
||||||
|
]
|
||||||
|
for pm in perm:
|
||||||
|
for c, p in zip(pm, info):
|
||||||
|
out += p if st_mode & c else "-"
|
||||||
|
return out
|
||||||
|
|
||||||
|
def get_time(self, st_time):
|
||||||
|
tv_sec = int(st_time["tv_sec"])
|
||||||
|
return datetime.fromtimestamp(tv_sec).isoformat()
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
st = self.val
|
||||||
|
st_ino = int(st["st_ino"])
|
||||||
|
st_mode = int(st["st_mode"])
|
||||||
|
st_uid = int(st["st_uid"])
|
||||||
|
st_gid = int(st["st_gid"])
|
||||||
|
st_size = int(st["st_size"])
|
||||||
|
st_blksize = int(st["st_blksize"])
|
||||||
|
st_blocks = int(st["st_blocks"])
|
||||||
|
st_atim = st["st_atim"]
|
||||||
|
st_mtim = st["st_mtim"]
|
||||||
|
st_ctim = st["st_ctim"]
|
||||||
|
|
||||||
|
out = "{\n"
|
||||||
|
out += f"Size: {st_size}\n"
|
||||||
|
out += f"Blocks: {st_blocks}\n"
|
||||||
|
out += f"IO Block: {st_blksize}\n"
|
||||||
|
out += f"Inode: {st_ino}\n"
|
||||||
|
out += f"Access: {self.get_access(st_mode)}\n"
|
||||||
|
out += f"File Type: {self.get_filetype(st_mode)}\n"
|
||||||
|
out += f"Uid: ({st_uid}/{pwd.getpwuid(st_uid).pw_name})\n"
|
||||||
|
out += f"Gid: ({st_gid}/{grp.getgrgid(st_gid).gr_name})\n"
|
||||||
|
out += f"Access: {self.get_time(st_atim)}\n"
|
||||||
|
out += f"Modify: {self.get_time(st_mtim)}\n"
|
||||||
|
out += f"Change: {self.get_time(st_ctim)}\n"
|
||||||
|
out += "}"
|
||||||
|
return out
|
||||||
|
# Could be disabled at runtime with:
|
||||||
|
# disable pretty-print global sp
|
||||||
|
# then check "info pretty-print"
|
||||||
|
p = gdb.printing.RegexpCollectionPrettyPrinter("sp")
|
||||||
|
p.add_printer("stat", "^stat$", StatPrint)
|
||||||
|
|
||||||
|
o = gdb.current_objfile()
|
||||||
|
gdb.printing.register_pretty_printer(o, p)
|
22
gdb/commands2.py
Normal file
22
gdb/commands2.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import gdb
|
||||||
|
|
||||||
|
from pygments import highlight
|
||||||
|
from pygments.lexers import CLexer
|
||||||
|
from pygments.formatters import TerminalFormatter
|
||||||
|
|
||||||
|
class PrettyList(gdb.Command):
|
||||||
|
"""Print source code with color."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("pl", gdb.COMMAND_USER)
|
||||||
|
self.lex = CLexer()
|
||||||
|
self.fmt = TerminalFormatter()
|
||||||
|
|
||||||
|
def invoke(self, args, tty):
|
||||||
|
try:
|
||||||
|
out = gdb.execute(f"l {args}", tty, True)
|
||||||
|
print(highlight(out, self.lex, self.fmt))
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
PrettyList()
|
1
gdb/gdb_gef
Submodule
1
gdb/gdb_gef
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 5d5efae0732c4f74919f22ba6acc833c4d474adf
|
Loading…
Reference in New Issue
Block a user