5 changed files with 299 additions and 0 deletions
@ -1,2 +1,7 @@
|
||||
#source ~/config/gdb/peda/peda.py |
||||
#source ~/config/gdb/gdb-dashboard/.gdbinit |
||||
#source ~/config/gdb/gdb_gef/gef.py |
||||
|
||||
source ~/config/gdb/commands.py |
||||
source ~/config/gdb/commands2.py |
||||
|
||||
|
@ -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) |
@ -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() |
Loading…
Reference in new issue