# gdb script: dump FUN_003e35f0 args at the call from FUN_00e0e970 (file # 0xd0e970 -> call site 0xd0eb65, caller return 0xd0eb6a). # # bpz12 named the failing call: FUN_00e0e970 -> FUN_003e35f0 returned # nonzero (forced to status 1). FUN_003e35f0 is a clock/step calculator # whose first early returns are: # if (param_5 < 1) return 1; (param_5 = dev+0xf5c) # if ((int)param_2[2] < 1) return 1; ... param_2[6], param_2[8], param_2[10] # This script prints all args + which condition fires. # # Run: sudo gdb -p -batch -x /tmp/bpz13.py import gdb import time out = gdb.execute("info proc mappings", to_string=True) base = None for line in out.splitlines(): if "libcuda" in line and "r-xp" in line: f = line.split() base = int(f[0], 16) - int(f[3], 16) break print("BASE=0x%x" % (base or 0)) if base is None: raise SystemExit gdb.execute("set pagination off") gdb.execute("set confirm off") ENTRY = base + 0x2e35f0 CALLER_RET = base + 0xd0eb6a gdb.execute("break *0x%x" % ENTRY) def rd(addr, size, fmt="unsigned int"): try: return int(gdb.parse_and_eval("*(%s*)0x%x" % (fmt, addr))) except Exception: return None t0 = time.time() for hit in range(200): try: gdb.execute("continue") except gdb.error as e: print("CONTINUE_END %s" % e) break ret = rd(int(gdb.parse_and_eval("$rsp")), 8, "unsigned long") if ret != CALLER_RET: print("skip FUN_003e35f0 call from 0x%x (not our caller)" % (ret or 0)) continue rdi = int(gdb.parse_and_eval("$rdi")) & 0xffffffffffffffff rsi = int(gdb.parse_and_eval("$rsi")) & 0xffffffffffffffff rdx = int(gdb.parse_and_eval("$rdx")) & 0xffffffffffffffff rcx = int(gdb.parse_and_eval("$rcx")) & 0xffffffffffffffff r8 = int(gdb.parse_and_eval("$r8d")) & 0xffffffff r9 = int(gdb.parse_and_eval("$r9")) & 0xffffffffffffffff print("CALL t=%.3f rdi=0x%x rsi=0x%x rdx=0x%x rcx=0x%x param_5(r8d)=0x%x r9=0x%x" % (time.time() - t0, rdi, rsi, rdx, rcx, r8, r9)) print("param_1 dwords:", [rd(rdi + 4 * i, 4) for i in range(8)]) p2 = [rd(rsi + 4 * i, 4) for i in range(16)] print("param_2 dwords[0..15]:", p2) print("param_2 qwords at +0x20,+0x28: 0x%x 0x%x" % (rd(rsi + 0x20, 8, "unsigned long") or 0xdead, rd(rsi + 0x28, 8, "unsigned long") or 0xdead)) print("param_3 dwords[0..3]:", [rd(rdx + 4 * i, 4) for i in range(4)]) print("param_4 dwords[0..3]:", [rd(rcx + 4 * i, 4) for i in range(4)]) conds = [] if r8 < 1: conds.append("param_5<1") if (p2[2] or 0) & 0x80000000 or (p2[2] or 0) < 1: conds.append("(int)param_2[2]<1") if (p2[3] or 0) & 0x80000000 or (p2[3] or 0) < 1: conds.append("(int)param_2[3]<1") if (p2[4] or 0) & 0x80000000 or (p2[4] or 0) < 1: conds.append("(int)param_2[4]<1") if (p2[5] or 0) & 0x80000000 or (p2[5] or 0) < 1: conds.append("(int)param_2[5]<1") if (p2[6] or 0) & 0x80000000 or (p2[6] or 0) < 1: conds.append("(int)param_2[6]<1") if (rd(rsi + 0x20, 8, "unsigned long") or 0) == 0: conds.append("param_2[+0x20]==0") if (rd(rsi + 0x28, 8, "unsigned long") or 0) == 0: conds.append("param_2[+0x28]==0") if (p2[0xc] or 0) & 0x80000000 or (p2[0xc] or 0) < 1: conds.append("(int)param_2[0xc]<1") p3 = rd(rdx, 4) if p3 is None or p3 < 1: conds.append("param_3[0]<1") if (rd(rdx + 4, 4) or 0) < 0: conds.append("param_3[1]<0") print("EARLY-RETURN-1 CONDITIONS:", conds or "none") try: print(gdb.execute("bt 4", to_string=True)) except Exception: pass break try: gdb.execute("detach") except Exception: pass