diff --git a/dev-debug/peda/files/peda-1.2-gdb_logging.patch b/dev-debug/peda/files/peda-1.2-gdb_logging.patch new file mode 100644 index 0000000000000..8abee7df38a4c --- /dev/null +++ b/dev-debug/peda/files/peda-1.2-gdb_logging.patch @@ -0,0 +1,48 @@ +From baaecddc58db23db1b0d85651090b743ddf7899a Mon Sep 17 00:00:00 2001 +From: Nikolaos Chatzikonstantinou +Date: Thu, 8 Feb 2024 03:51:51 -0500 +Subject: [PATCH] remove deprecated notice +Upstream: https://github.com/longld/peda/pull/176 + +From GDB 12.1+, `set logging on|off` is deprecated, and a notice is +given. See +. +This patch fixes the issue for the newer gdb versions. +--- a/peda.py ++++ b/peda.py +@@ -108,22 +108,22 @@ def execute_redirect(self, gdb_command, silent=False): + else: + logfd = tmpfile() + logname = logfd.name +- gdb.execute('set logging off') # prevent nested call ++ gdb.execute('set logging enabled off') # prevent nested call + gdb.execute('set height 0') # disable paging + gdb.execute('set logging file %s' % logname) + gdb.execute('set logging overwrite on') + gdb.execute('set logging redirect on') +- gdb.execute('set logging on') ++ gdb.execute('set logging enabled on') + try: + gdb.execute(gdb_command) + gdb.flush() +- gdb.execute('set logging off') ++ gdb.execute('set logging enabled off') + if not silent: + logfd.flush() + result = logfd.read() + logfd.close() + except Exception as e: +- gdb.execute('set logging off') #to be sure ++ gdb.execute('set logging enabled off') #to be sure + if config.Option.get("debug") == "on": + msg('Exception (%s): %s' % (gdb_command, e), "red") + traceback.print_exc() +@@ -6112,7 +6112,7 @@ def complete(self, text, word): + # handle SIGINT / Ctrl-C + def sigint_handler(signal, frame): + warning_msg("Got Ctrl+C / SIGINT!") +- gdb.execute("set logging off") ++ gdb.execute("set logging enabled off") + peda.restore_user_command("all") + raise KeyboardInterrupt + signal.signal(signal.SIGINT, sigint_handler) diff --git a/dev-debug/peda/files/peda-1.2-python3_14.patch b/dev-debug/peda/files/peda-1.2-python3_14.patch new file mode 100644 index 0000000000000..5c1b6a9c2d9ef --- /dev/null +++ b/dev-debug/peda/files/peda-1.2-python3_14.patch @@ -0,0 +1,438 @@ +From 8a7985f971b255931ea38ea83bbe736ec07f2e45 Mon Sep 17 00:00:00 2001 +From: punixcorn +Date: Thu, 4 Jul 2024 04:05:44 +0000 +Subject: [PATCH 1/6] SyntaxWarning: invalid escape sequence #177 fixed +Upstream: https://github.com/longld/peda/pull/179 + +--- a/peda.py ++++ b/peda.py +@@ -18,7 +18,6 @@ + import signal + import traceback + import codecs +- + # point to absolute path of peda.py + PEDAFILE = os.path.abspath(os.path.expanduser(__file__)) + if os.path.islink(PEDAFILE): +@@ -26,7 +25,7 @@ + sys.path.insert(0, os.path.dirname(PEDAFILE) + "/lib/") + + # Use six library to provide Python 2/3 compatibility +-import six ++#import six + from six.moves import range + from six.moves import input + try: +@@ -35,7 +34,6 @@ + import pickle + + +- + from skeleton import * + from shellcode import * + from utils import * +@@ -148,10 +146,10 @@ def parse_and_eval(self, exp): + if "$"+r not in exp and "e"+r not in exp and "r"+r not in exp: + exp = exp.replace(r, "$%s" % r) + +- p = re.compile("(.*)\[(.*)\]") # DWORD PTR [esi+eax*1] ++ p = re.compile(r"(.*)\[(.*)\]") # DWORD PTR [esi+eax*1] + matches = p.search(exp) + if not matches: +- p = re.compile("(.*).s:(0x.*)") # DWORD PTR ds:0xdeadbeef ++ p = re.compile(r"(.*).s:(0x.*)") # DWORD PTR ds:0xdeadbeef + matches = p.search(exp) + + if matches: +@@ -370,12 +368,12 @@ def getfile(self): + result = None + out = self.execute_redirect('info files') + if out and '"' in out: +- p = re.compile(".*exec file:\s*`(.*)'") ++ p = re.compile(r".*exec file:\s*`(.*)'") + m = p.search(out) + if m: + result = m.group(1) + else: # stripped file, get symbol file +- p = re.compile("Symbols from \"([^\"]*)") ++ p = re.compile(r"Symbols from \"([^\"]*)") + m = p.search(out) + if m: + result = m.group(1) +@@ -547,11 +545,11 @@ def get_breakpoint(self, num): + + lines = out.splitlines()[1:] + # breakpoint regex +- p = re.compile("^(\d*)\s*(.*breakpoint)\s*(keep|del)\s*(y|n)\s*(0x[^ ]*)\s*(.*)") ++ p = re.compile(r"^(\d*)\s*(.*breakpoint)\s*(keep|del)\s*(y|n)\s*(0x[^ ]*)\s*(.*)") + m = p.match(lines[0]) + if not m: + # catchpoint/watchpoint regex +- p = re.compile("^(\d*)\s*(.*point)\s*(keep|del)\s*(y|n)\s*(.*)") ++ p = re.compile(r"^(\d*)\s*(.*point)\s*(keep|del)\s*(y|n)\s*(.*)") + m = p.match(lines[0]) + if not m: + return None +@@ -564,7 +562,7 @@ def get_breakpoint(self, num): + disp = True if disp == "keep" else False + enb = True if enb == "y" else False + addr = to_int(addr) +- m = re.match("in.*at(.*:\d*)", what) ++ m = re.match(r"in.*at(.*:\d*)", what) + if m: + what = m.group(1) + else: +@@ -593,7 +591,7 @@ def get_breakpoints(self): + + bplist = [] + for line in out.splitlines(): +- m = re.match("^(\d*).*", line) ++ m = re.match(r"^(\d*).*", line) + if m and to_int(m.group(1)): + bplist += [to_int(m.group(1))] + +@@ -625,7 +623,7 @@ def save_breakpoints(self, filename): + try: + fd = open(filename, "w") + for (num, type, disp, enb, addr, what, commands) in bplist: +- m = re.match("(.*)point", type) ++ m = re.match(r"(.*)point", type) + if m: + cmd = m.group(1).split()[-1] + else: +@@ -786,7 +784,7 @@ def prev_inst(self, address, count=1): + if len(lines) > count and "(bad)" not in " ".join(lines): + for line in lines[-count-1:-1]: + (addr, code) = line.split(":", 1) +- addr = re.search("(0x[^ ]*)", addr).group(1) ++ addr = re.search(r"(0x[^ ]*)", addr).group(1) + result += [(to_int(addr), code)] + return result + return None +@@ -807,7 +805,7 @@ def current_inst(self, address): + return None + + (addr, code) = out.split(":", 1) +- addr = re.search("(0x[^ ]*)", addr).group(1) ++ addr = re.search(r"(0x[^ ]*)", addr).group(1) + addr = to_int(addr) + code = code.strip() + +@@ -833,7 +831,7 @@ def next_inst(self, address, count=1): + lines = code.strip().splitlines() + for i in range(1, count+1): + (addr, code) = lines[i].split(":", 1) +- addr = re.search("(0x[^ ]*)", addr).group(1) ++ addr = re.search(r"(0x[^ ]*)", addr).group(1) + result += [(to_int(addr), code)] + return result + +@@ -913,9 +911,9 @@ def xrefs(self, search="", filename=None): + out = self.execute_redirect("x/i 0x%x" % addr) + if out: + line = out +- p = re.compile("\s*(0x[^ ]*).*?:\s*([^ ]*)\s*(.*)") ++ p = re.compile(r"\s*(0x[^ ]*).*?:\s*([^ ]*)\s*(.*)") + else: +- p = re.compile("(.*?)\s*<.*?>\s*([^ ]*)\s*(.*)") ++ p = re.compile(r"(.*?)\s*<.*?>\s*([^ ]*)\s*(.*)") + + m = p.search(line) + if m: +@@ -934,7 +932,7 @@ def _get_function_args_32(self, code, argc=None): + """ + if not argc: + argc = 0 +- p = re.compile(".*mov.*\[esp(.*)\],") ++ p = re.compile(r".*mov.*\[esp(.*)\],") + matches = p.findall(code) + if matches: + l = len(matches) +@@ -966,11 +964,11 @@ def _get_function_args_64(self, code, argc=None): + + # just retrieve max 6 args + arg_order = ["rdi", "rsi", "rdx", "rcx", "r8", "r9"] +- p = re.compile(":\s*([^ ]*)\s*(.*),") ++ p = re.compile(r":\s*([^ ]*)\s*(.*),") + matches = p.findall(code) + regs = [r for (_, r) in matches] + p = re.compile(("di|si|dx|cx|r8|r9")) +- m = p.findall(" ".join(regs)) ++ m = p.findall(r" ".join(regs)) + m = list(set(m)) # uniqify + argc = 0 + if "si" in m and "di" not in m: # dirty fix +@@ -1106,14 +1104,14 @@ def stepuntil(self, inst, mapname=None, depth=None): + current_instruction = "End of execution" + break + +- p = re.compile(".*?(0x[^ :]*)") ++ p = re.compile(r".*?(0x[^ :]*)") + addr = p.search(current_instruction).group(1) + addr = to_int(addr) + if addr is None: + break + +- #p = re.compile(".*?:\s*([^ ]*)") +- p = re.compile(".*?:\s*(.*)") ++ #p = re.compile(r".*?:\s*([^ ]*)") ++ p = re.compile(r".*?:\s*(.*)") + code = p.match(current_instruction).group(1) + found = 0 + for i in inst.replace(",", " ").split(): +@@ -1220,10 +1218,10 @@ def eval_target(self, inst): + inst = inst.strip() + opcode = inst.split(":\t")[-1].split()[0] + # this regex includes x86_64 RIP relateive address reference +- p = re.compile(".*?:\s*[^ ]*\s*(.* PTR ).*(0x[^ ]*)") ++ p = re.compile(r".*?:\s*[^ ]*\s*(.* PTR ).*(0x[^ ]*)") + m = p.search(inst) + if not m: +- p = re.compile(".*?:\s.*\s(0x[^ ]*|\w+)") ++ p = re.compile(r".*?:\s.*\s(0x[^ ]*|\w+)") + m = p.search(inst) + if m: + target = m.group(1) +@@ -1232,7 +1230,7 @@ def eval_target(self, inst): + target = None + else: + if "]" in m.group(2): # e.g DWORD PTR [ebx+0xc] +- p = re.compile(".*?:\s*[^ ]*\s*(.* PTR ).*\[(.*)\]") ++ p = re.compile(r".*?:\s*[^ ]*\s*(.* PTR ).*\[(.*)\]") + m = p.search(inst) + target = self.parse_and_eval("%s[%s]" % (m.group(1), m.group(2).strip())) + +@@ -1427,7 +1425,7 @@ def _get_offline_maps(): + def _get_allmaps_osx(pid, remote=False): + maps = [] + #_DATA 00007fff77975000-00007fff77976000 [ 4K] rw-/rw- SM=COW /usr/lib/system/libremovefile.dylib +- pattern = re.compile("([^\n]*)\s* ([0-9a-f][^-\s]*)-([^\s]*) \[.*\]\s([^/]*).* (.*)") ++ pattern = re.compile(r"([^\n]*)\s* ([0-9a-f][^-\s]*)-([^\s]*) \[.*\]\s([^/]*).* (.*)") + + if remote: # remote target, not yet supported + return maps +@@ -1452,7 +1450,7 @@ def _get_allmaps_freebsd(pid, remote=False): + maps = [] + mpath = "/proc/%s/map" % pid + # 0x8048000 0x8049000 1 0 0xc36afdd0 r-x 1 0 0x1000 COW NC vnode /path/to/file NCH -1 +- pattern = re.compile("0x([0-9a-f]*) 0x([0-9a-f]*)(?: [^ ]*){3} ([rwx-]*)(?: [^ ]*){6} ([^ ]*)") ++ pattern = re.compile(r"0x([0-9a-f]*) 0x([0-9a-f]*)(?: [^ ]*){3} ([rwx-]*)(?: [^ ]*){6} ([^ ]*)") + + if remote: # remote target, not yet supported + return maps +@@ -1479,7 +1477,7 @@ def _get_allmaps_linux(pid, remote=False): + maps = [] + mpath = "/proc/%s/maps" % pid + #00400000-0040b000 r-xp 00000000 08:02 538840 /path/to/file +- pattern = re.compile("([0-9a-f]*)-([0-9a-f]*) ([rwxps-]*)(?: [^ ]*){3} *(.*)") ++ pattern = re.compile(r"([0-9a-f]*)-([0-9a-f]*) ([rwxps-]*)(?: [^ ]*){3} *(.*)") + + if remote: # remote target + tmp = tmpfile() +@@ -2093,7 +2091,7 @@ def examine_data(value, bits=32): + if value >= start and value < end: + if type == "code": + out = self.get_disasm(value) +- p = re.compile(".*?0x[^ ]*?\s(.*)") ++ p = re.compile(r".*?0x[^ ]*?\s(.*)") + m = p.search(out) + result = (to_hex(value), "code", m.group(1)) + else: # rodata address +@@ -2111,7 +2109,7 @@ def examine_data(value, bits=32): + out = examine_data(value, bits) + result = (to_hex(value), "rodata", out.split(":", 1)[1].strip()) + else: +- p = re.compile(".*?0x[^ ]*?\s(.*)") ++ p = re.compile(r".*?0x[^ ]*?\s(.*)") + m = p.search(out) + result = (to_hex(value), "code", m.group(1)) + +@@ -2211,7 +2209,7 @@ def elfentry(self): + - entry address (Int) + """ + out = self.execute_redirect("info files") +- p = re.compile("Entry point: ([^\s]*)") ++ p = re.compile(r"Entry point: ([^\s]*)") + if out: + m = p.search(out) + if m: +@@ -2239,7 +2237,7 @@ def elfheader(self, name=None): + if not out: + return {} + +- p = re.compile("\s*(0x[^-]*)->(0x[^ ]*) at (0x[^:]*):\s*([^ ]*)\s*(.*)") ++ p = re.compile(r"\s*(0x[^-]*)->(0x[^ ]*) at (0x[^:]*):\s*([^ ]*)\s*(.*)") + matches = p.findall(out) + + for (start, end, offset, hname, attr) in matches: +@@ -2313,7 +2311,7 @@ def elfsymbols(self, pattern=None): + symname += "@plt" + out = self.execute_redirect("info functions %s" % symname) + if not out: continue +- m = re.findall(".*(0x[^ ]*)\s*%s" % re.escape(symname), out) ++ m = re.findall(r".*(0x[^ ]*)\s*%s" % re.escape(symname), out) + for addr in m: + addr = to_int(addr) + if self.is_address(addr, binmap): +@@ -2390,7 +2388,7 @@ def main_entry(self): + if refs: + inst = self.prev_inst(refs[0][0]) + if inst: +- addr = re.search(".*(0x.*)", inst[0][1]) ++ addr = re.search(r".*(0x.*)", inst[0][1]) + if addr: + return to_int(addr.group(1)) + return None +@@ -2413,7 +2411,7 @@ def readelf_header(self, filename, name=None): + out = execute_external_command("%s -W -S %s" % (config.READELF, filename)) + if not out: + return {} +- p = re.compile(".*\[.*\] (\.[^ ]*) [^0-9]* ([^ ]*) [^ ]* ([^ ]*)(.*)") ++ p = re.compile(r".*\[.*\] (\.[^ ]*) [^0-9]* ([^ ]*) [^ ]* ([^ ]*)(.*)") + matches = p.findall(out) + if not matches: + return result +@@ -2471,7 +2469,7 @@ def _elfheader_solib_all(): + if not out: + return None + +- p = re.compile("[^\n]*\s*(0x[^ ]*) - (0x[^ ]*) is (\.[^ ]*) in (.*)") ++ p = re.compile(r"[^\n]*\s*(0x[^ ]*) - (0x[^ ]*) is (\.[^ ]*) in (.*)") + soheaders = p.findall(out) + + result = [] +@@ -2678,7 +2676,7 @@ def decode_hex_escape(str_): + blen = gadget[-1][0] - gadget[0][0] + 1 + bytes = v[:2*blen] + asmcode_rs = "; ".join([c for _, c in gadget]) +- if re.search(re.escape(asmcode).replace("\ ",".*").replace("\?",".*"), asmcode_rs)\ ++ if re.search(re.escape(asmcode).replace(r"\ ",".*").replace(r"\?",".*"), asmcode_rs)\ + and a not in result: + result[a] = (bytes, asmcode_rs) + result = list(result.items()) +@@ -2688,7 +2686,7 @@ def decode_hex_escape(str_): + asmcode = self.execute_redirect("disassemble 0x%x, 0x%x" % (a, a+(len(v)//2))) + if asmcode: + asmcode = "\n".join(asmcode.splitlines()[1:-1]) +- matches = re.findall(".*:([^\n]*)", asmcode) ++ matches = re.findall(r".*:([^\n]*)", asmcode) + result += [(a, (v, ";".join(matches).strip()))] + + return result +@@ -2829,7 +2827,7 @@ def search_jmpcall(self, start, end, regname=None): + if regname is None: + regname = "" + regname = regname.lower() +- pattern = re.compile(b'|'.join(JMPCALL).replace(b' ', b'\ ')) ++ pattern = re.compile(r'|'.join(JMPCALL).replace(r' ', r'\ ')) + mem = self.dumpmem(start, end) + found = pattern.finditer(mem) + (arch, bits) = self.getarch() +@@ -3411,7 +3409,7 @@ def xprint(self, *arg): + """ + text = "" + exp = " ".join(list(arg)) +- m = re.search(".*\[(.*)\]|.*?s:(0x[^ ]*)", exp) ++ m = re.search(r".*\[(.*)\]|.*?s:(0x[^ ]*)", exp) + if m: + addr = peda.parse_and_eval(m.group(1)) + if to_int(addr): +@@ -3516,7 +3514,7 @@ def procinfo(self, *arg): + fdlist = os.listdir("/proc/%d/fd" % pid) + for fd in fdlist: + rpath = os.readlink("/proc/%d/fd/%s" % (pid, fd)) +- sock = re.search("socket:\[(.*)\]", rpath) ++ sock = re.search(r"socket:\[(.*)\]", rpath) + if sock: + spath = execute_external_command("netstat -aen | grep %s" % sock.group(1)) + if spath: +@@ -3526,11 +3524,11 @@ def procinfo(self, *arg): + # uid/gid, pid, ppid + info["pid"] = pid + status = open("/proc/%d/status" % pid).read() +- ppid = re.search("PPid:\s*([^\s]*)", status).group(1) ++ ppid = re.search(r"PPid:\s*([^\s]*)", status).group(1) + info["ppid"] = to_int(ppid) if ppid else -1 +- uid = re.search("Uid:\s*([^\n]*)", status).group(1) ++ uid = re.search(r"Uid:\s*([^\n]*)", status).group(1) + info["uid"] = [to_int(id) for id in uid.split()] +- gid = re.search("Gid:\s*([^\n]*)", status).group(1) ++ gid = re.search(r"Gid:\s*([^\n]*)", status).group(1) + info["gid"] = [to_int(id) for id in gid.split()] + + for opt in options: +@@ -4122,7 +4120,7 @@ def traceinst(self, *arg): + prev_depth = peda.backtrace_depth(peda.getreg("sp")) + logfd = open(logname, "w") + +- p = re.compile(".*?:\s*[^ ]*\s*([^,]*),(.*)") ++ p = re.compile(r".*?:\s*[^ ]*\s*([^,]*),(.*)") + while count: + result = peda.stepuntil(",".join(instlist), mapname, prev_depth) + if result is None: +@@ -4134,7 +4132,7 @@ def traceinst(self, *arg): + + # special case for JUMP inst + prev_code = "" +- if re.search("j[^m]", code.split(":\t")[-1].split()[0]): ++ if re.search(r"j[^m]", code.split(":\t")[-1].split()[0]): + prev_insts = peda.prev_inst(peda.getreg("pc")) + if prev_insts: + prev_code = "0x%x:%s" % prev_insts[0] +@@ -4143,7 +4141,7 @@ def traceinst(self, *arg): + text = "%s%s%s" % (" "*(prev_depth-1), " dep:%02d " % (prev_depth-1), code.strip()) + msg(text, teefd=logfd) + +- if re.search("call", code.split(":\t")[-1].split()[0]): ++ if re.search(r"call", code.split(":\t")[-1].split()[0]): + args = peda.get_function_args() + if args: + for (i, a) in enumerate(args): + +From 6b185589187a4ca7271be518780cfddbabb36b27 Mon Sep 17 00:00:00 2001 +From: potato <103060805+punixcorn@users.noreply.github.com> +Date: Sun, 7 Jul 2024 16:34:42 +0000 +Subject: [PATCH 5/6] fix invalid escape sequence errors + +in lib/utils.py and lib/nasm.py +--- a/lib/nasm.py ++++ b/lib/nasm.py +@@ -82,7 +82,7 @@ def nasm2shellcode(asmcode): + return "" + + shellcode = [] +- pattern = re.compile("([0-9A-F]{8})\s*([^\s]*)\s*(.*)") ++ pattern = re.compile(r"([0-9A-F]{8})\s*([^\s]*)\s*(.*)") + + matches = pattern.findall(asmcode) + for line in asmcode.splitlines(): +--- a/lib/utils.py ++++ b/lib/utils.py +@@ -523,7 +523,7 @@ def format_disasm_code(code, nearby=None): + result += line + "\n" + else: + color = style = None +- m = re.search(".*(0x[^ ]*).*:\s*([^ ]*)", line) ++ m = re.search(r".*(0x[^ ]*).*:\s*([^ ]*)", line) + if not m: # failed to parse + result += line + "\n" + continue +@@ -540,7 +540,7 @@ def format_disasm_code(code, nearby=None): + break + + prefix = line.split(":\t")[0] +- addr = re.search("(0x[^\s]*)", prefix) ++ addr = re.search(r"(0x[^\s]*)", prefix) + if addr: + addr = to_int(addr.group(1)) + else: +@@ -589,7 +589,7 @@ def cyclic_pattern_charset(charset_type=None): + charset[2] = "sn()" + charset[2] + + if charset_type == 2: # maximum type +- charset += ['!"#$%&\()*+,-./:;<=>?@[]^_{|}~'] # string.punctuation ++ charset += [r'!"#$%&\()*+,-./:;<=>?@[]^_{|}~'] # string.punctuation + + mixed_charset = mixed = '' + k = 0 + diff --git a/dev-debug/peda/peda-1.2.ebuild b/dev-debug/peda/peda-1.2-r1.ebuild similarity index 71% rename from dev-debug/peda/peda-1.2.ebuild rename to dev-debug/peda/peda-1.2-r1.ebuild index bf78cc2e99b04..9e175be19fa88 100644 --- a/dev-debug/peda/peda-1.2.ebuild +++ b/dev-debug/peda/peda-1.2-r1.ebuild @@ -1,9 +1,9 @@ -# Copyright 1999-2025 Gentoo Authors +# Copyright 1999-2026 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 EAPI=8 -PYTHON_COMPAT=( python3_{10..13} ) +PYTHON_COMPAT=( python3_{11..14} ) inherit python-single-r1 wrapper @@ -31,6 +31,19 @@ RDEPEND=" ') " +PATCHES=( + "${FILESDIR}/${P}-gdb_logging.patch" + "${FILESDIR}/${P}-python3_14.patch" +) + +src_prepare() { + default + + # File was remove in upstream patch ${P}-python3_14.patch. To keep the + # patch file size low, we remove this file directly instead via the patch. + rm lib/six.py || die +} + src_install() { insinto /usr/share/${PN} doins -r lib/ *.py