diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/guest-diag/memprobe.py | 224 | ||||
| -rw-r--r-- | tools/guest-diag/peek.c | 67 | ||||
| -rw-r--r-- | tools/guest-diag/scan.c | 105 | ||||
| -rw-r--r-- | tools/guest-diag/scan2.c | 88 | ||||
| -rw-r--r-- | tools/guest-diag/scan3.c | 77 | ||||
| -rw-r--r-- | tools/guest-diag/trkinfo.py | 49 |
6 files changed, 600 insertions, 10 deletions
diff --git a/tools/guest-diag/memprobe.py b/tools/guest-diag/memprobe.py new file mode 100644 index 0000000..4fe000b --- /dev/null +++ b/tools/guest-diag/memprobe.py @@ -0,0 +1,224 @@ +#!/usr/bin/env python3 +# memprobe.py - read/write another process's memory through /proc/<pid>/mem +# (root only, no gdb/ptrace attach needed). +# +# scan PID [--min 0x204800000 --max 0x204c0000] [--limit 8] +# find tracker objects: qwords inside [min,max) (the client's sem VAs), +# then objects whose +0x10 points at them (sem objects), then objects +# whose +0x9430 points at those (the libcuda tracker at p+0x9410). +# dump PID 0xP +# dump the tracker at 0xP (fields sem/mirror/completed, sem value, +# progress object at p+0x48 and its indexed slots). +# poke PID 0xADDR=0xVAL,... +# watch PID 0xADDR,... [--ms 2] [--secs 20] +import sys, os, time, array, struct + +WS = 8 + +def rd(fd, addr, n): + try: + return os.pread(fd, n, addr) + except OSError: + return None + +def wr(fd, addr, data): + return os.pwrite(fd, data, addr) + +def r32(buf, off=0): + return struct.unpack_from("<I", buf, off)[0] +def r64(buf, off=0): + return struct.unpack_from("<Q", buf, off)[0] + +def regions(pid, writable=True): + out = [] + with open("/proc/%d/maps" % pid) as f: + for line in f: + p = line.split() + try: + lo, hi = [int(x, 16) for x in p[0].split("-")] + except Exception: + continue + perm = p[1] + if writable and "w" not in perm: + continue + out.append((lo, hi, perm, " ".join(p[5:]))) + return out + +def scan_qwords(pid, fd, lo, hi, needle_lo=None, needle_hi=None, needle_set=None, chunk=1 << 20): + hits = [] + for rlo, rhi, perm, name in regions(pid): + a = max(rlo, 0) + while a < min(rhi, 1 << 47): + n = min(chunk, rhi - a) + buf = rd(fd, a, n) + if not buf: + a += n + continue + buf = buf[:n - (n % WS)] + arr = array.array("Q") + arr.frombytes(buf) + if needle_set is not None: + for i, v in enumerate(arr): + if v in needle_set: + hits.append((a + i * WS, v)) + else: + for i, v in enumerate(arr): + if needle_lo is not None and v < needle_lo: + continue + if needle_hi is not None and v >= needle_hi: + continue + hits.append((a + i * WS, v)) + a += n + return hits + +def sem_objs(pid, fd, lo, hi): + # qword in [lo,hi) at address A -> a sem object holds it at +0x10 + first = scan_qwords(pid, fd, None, None, needle_lo=lo, needle_hi=hi) + out = {} + for addr, val in first: + so = addr - 0x10 + out.setdefault(val, set()).add(so) + return out + +def find_trackers(pid, fd, lo, hi, limit=8): + sems = sem_objs(pid, fd, lo, hi) + print("sem VAs found: %d" % len(sems)) + for va, sos in sorted(sems.items())[:8]: + print(" va=0x%x -> %d sem-obj candidate(s)" % (va, len(sos))) + needles = set() + for sos in sems.values(): + needles |= sos + if not needles: + return [] + hits = scan_qwords(pid, fd, None, None, needle_set=needles) + pset = set() + for addr, val in hits: + cand = addr - 0x9430 + if cand >= 0: + pset.add(cand) + print("tracker candidates: %d" % len(pset)) + res = [] + for p in sorted(pset): + buf = rd(fd, p + 0x9410, 0x40) + if not buf or len(buf) < 0x40: + continue + sub = r64(buf, 0x08); last = r64(buf, 0x10); cur = r64(buf, 0x18); sem = r64(buf, 0x20) + if sem not in needles: + continue + mem = None + sob = rd(fd, sem, 0x40) + if sob: + mem = r64(sob, 0x10) + res.append((p, sub, last, cur, sem, mem)) + if len(res) >= limit: + break + return res + +def dump_tracker(pid, fd, p): + t = p + 0x9410 + buf = rd(fd, t, 0x40) + if not buf: + print("tracker unreadable at 0x%x" % t); return + print("TRK=0x%x sub=0x%x last=0x%x cur=0x%x sem_obj=0x%x" + % (t, r64(buf, 8), r64(buf, 0x10), r64(buf, 0x18), r64(buf, 0x20))) + sem = r64(buf, 0x20) + sob = rd(fd, sem, 0x40) + if sob: + print(" sem_obj[0:0x40]=%s" % sob.hex()) + mem = r64(sob, 0x10) + mvb = rd(fd, mem & ~0xfff, 0x40) + print(" sem_mem=0x%x val@+0x%x=0x%x" % (mem, mem & 0xfff, r32(mvb, mem & 0xfff) if mvb else -1)) + q = r64(rd(fd, p + 0x48, 8) or b"\0" * 8) + print(" prog_obj=0x%x next=0x%x cblist=0x%x idx95bc=0x%x p34=0x%x" + % (q, r64(rd(fd, p + 0x9470, 8) or b"\0" * 8), + r64(rd(fd, p + 0x9458, 8) or b"\0" * 8), + r32(rd(fd, p + 0x95bc, 4) or b"\0" * 4), + r32(rd(fd, p + 0x34, 4) or b"\0" * 4))) + if q: + qb = rd(fd, q, 0x50) + if qb: + size = r32(qb, 8); idx = r32(qb, 0x48); cur = r32(qb, 0x4c); arr = r64(qb, 0x40) + print(" size=%d idx=0x%x cursor=0x%x arr=0x%x" % (size, idx, cur, arr)) + for s in (idx, cur): + slot = arr + (s % size if size else s) * 0x38 + sb = rd(fd, slot, 0x38) + print(" slot[%d]@0x%x=%s" % (s, slot, sb.hex() if sb else "unreadable")) + +def main(): + if len(sys.argv) < 3: + print(__doc__); return 1 + mode = sys.argv[1] + pid = int(sys.argv[2]) + fd = os.open("/proc/%d/mem" % pid, os.O_RDWR) + try: + if mode == "scan": + lo, hi = 0x204800000, 0x204c0000 + limit = 8 + for i, a in enumerate(sys.argv[3:]): + if a == "--min": lo = int(sys.argv[4 + i], 16) + if a == "--max": hi = int(sys.argv[5 + i], 16) + if a == "--limit": limit = int(sys.argv[4 + i]) + res = find_trackers(pid, fd, lo, hi, limit) + for p, sub, last, cur, sem, mem in res: + print("P=0x%x sub=0x%x last=0x%x cur=0x%x sem_obj=0x%x sem_mem=0x%x" % + (p, sub, last, cur, sem, mem or 0)) + dump_tracker(pid, fd, p) + elif mode == "dump": + dump_tracker(pid, fd, int(sys.argv[3], 16)) + elif mode == "hex": + a = int(sys.argv[3], 16) + n = int(sys.argv[4], 16) if len(sys.argv) > 4 else 0x100 + d = rd(fd, a, n) or b"" + for off in range(0, len(d), 16): + c = d[off:off + 16] + q = [int.from_bytes(c[i:i + 8], "little") for i in (0, 8)] + print("0x%x: %s %s" % (a + off, c.hex(), " ".join("0x%x" % x for x in q))) + elif mode == "ctx": + ctx = int(sys.argv[3], 16) + count = r32(rd(fd, ctx + 0x10, 4) or b"\0" * 4) + ent = r64(rd(fd, ctx + 0x18, 8) or b"\0" * 8) + print("waitobj ctx=0x%x count=%d entries=0x%x" % (ctx, count, ent)) + for i in range(min(count, 48)): + e = ent + i * 0x28 + eb = rd(fd, e, 0x28) + if not eb: + print(" e%d unreadable" % i); continue + typ = r32(eb, 0); p = r64(eb, 8); v = r64(eb, 0x10) + x18 = r64(eb, 0x18); x20 = r64(eb, 0x20) + print(" e%d type=0x%x p=0x%x v=0x%x x18=0x%x x20=0x%x" % (i, typ, p, v, x18, x20)) + if typ == 1 and p: + dump_tracker(pid, fd, p) + elif mode == "poke": + for spec in sys.argv[3].split(","): + a, v = spec.split("=") + a = int(a, 16); v = int(v, 16) + n = wr(fd, a, v.to_bytes(8, "little")) + print("poke 0x%x <- 0x%x (%s)" % (a, v, "ok" if n == 8 else "FAIL")) + elif mode == "watch": + addrs = [int(x, 16) for x in sys.argv[3].split(",")] + ms = 2; secs = 20 + for i in range(4, len(sys.argv)): + if sys.argv[i] == "--ms" and i + 1 < len(sys.argv): + ms = int(sys.argv[i + 1]) + if sys.argv[i] == "--secs" and i + 1 < len(sys.argv): + secs = int(sys.argv[i + 1]) + last = {} + t0 = time.time() + while time.time() - t0 < secs: + for a in addrs: + b = rd(fd, a, 8) + if not b: + continue + v = r64(b) + if last.get(a) != v: + print("%.3f 0x%x = 0x%x" % (time.time() - t0, a, v)) + last[a] = v + time.sleep(ms / 1000.0) + else: + print(__doc__); return 1 + finally: + os.close(fd) + return 0 + +if __name__ == "__main__": + sys.exit(main())
\ No newline at end of file diff --git a/tools/guest-diag/peek.c b/tools/guest-diag/peek.c new file mode 100644 index 0000000..857afd0 --- /dev/null +++ b/tools/guest-diag/peek.c @@ -0,0 +1,67 @@ +/* peek.c - print RIP/RBX/RSP/RDI of every thread of a process (root). + usage: peek PID [lo_off hi_off] (offsets from the libcuda r-xp base) + Flags threads whose RIP is inside [base+lo, base+hi) with SPIN. */ +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <sys/ptrace.h> +#include <sys/wait.h> +#include <sys/user.h> +#include <sys/uio.h> +#include <unistd.h> + +int main(int argc, char **argv) +{ + if (argc < 2) { fprintf(stderr, "usage: peek PID [lo_off hi_off]\n"); return 1; } + int pid = atoi(argv[1]); + unsigned long lo = 0x23f700, hi = 0x23fd10; + if (argc >= 4) { lo = strtoul(argv[2], 0, 16); hi = strtoul(argv[3], 0, 16); } + + char path[256]; + snprintf(path, sizeof path, "/proc/%d/maps", pid); + FILE *f = fopen(path, "r"); + if (!f) { perror("maps"); return 1; } + unsigned long base = 0; + char line[512]; + while (fgets(line, sizeof line, f)) { + if (strstr(line, "libcuda") && strstr(line, "r-xp")) { + unsigned long a, b, off; char perms[8], dev[16], name[256]; unsigned long ino; + if (sscanf(line, "%lx-%lx %7s %lx %15s %lu %255s", + &a, &b, perms, &off, dev, &ino, name) >= 6) { + base = a - off; + break; + } + } + } + fclose(f); + printf("libcuda base=0x%lx\n", base); + + snprintf(path, sizeof path, "/proc/%d/task", pid); + DIR *d = opendir(path); + if (!d) { perror("task"); return 1; } + struct dirent *e; + while ((e = readdir(d))) { + if (e->d_name[0] == '.') continue; + int tid = atoi(e->d_name); + if (ptrace(PTRACE_ATTACH, tid, 0, 0)) { printf("tid %d attach fail\n", tid); continue; } + int st; + waitpid(tid, &st, 0); + struct user_regs_struct r; + struct iovec io = { &r, sizeof r }; + if (ptrace(PTRACE_GETREGSET, tid, (void *)1, &io)) { + printf("tid %d getregs fail\n", tid); + ptrace(PTRACE_DETACH, tid, 0, 0); + continue; + } + printf("tid %d rip=0x%llx rsp=0x%llx rbx=0x%llx rdi=0x%llx%s\n", + tid, + (unsigned long long)r.rip, (unsigned long long)r.rsp, + (unsigned long long)r.rbx, (unsigned long long)r.rdi, + (r.rip >= base + lo && r.rip < base + hi) ? " SPIN" : ""); + ptrace(PTRACE_DETACH, tid, 0, 0); + } + closedir(d); + return 0; +}
\ No newline at end of file diff --git a/tools/guest-diag/scan.c b/tools/guest-diag/scan.c new file mode 100644 index 0000000..d229dc8 --- /dev/null +++ b/tools/guest-diag/scan.c @@ -0,0 +1,105 @@ +/* scan.c - find the libcuda tracker objects in a process without ptrace. + Tracker layout (object p): p+0x9418 submitted, p+0x9420 completed, + p+0x9428 mirror, p+0x9430 sem object; sem object +0x10 -> sem VA (a + /dev/nvidia* mapping) whose u32 is small. + + usage: scan PID (prints candidate p and its fields) */ +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/stat.h> + +#define MAXR 4096 +static struct { uint64_t lo, hi; } wr[MAXR], nv[MAXR]; +static int nwr, nnv; + +static int in_nv(uint64_t a) +{ + for (int i = 0; i < nnv; i++) + if (a >= nv[i].lo && a < nv[i].hi) return 1; + return 0; +} + +static int in_wr(uint64_t a) +{ + for (int i = 0; i < nwr; i++) + if (a >= wr[i].lo && a < wr[i].hi) return 1; + return 0; +} + +static void load_maps(int pid) +{ + char path[64], line[1024]; + snprintf(path, sizeof path, "/proc/%d/maps", pid); + FILE *f = fopen(path, "r"); + if (!f) { perror("maps"); exit(1); } + while (fgets(line, sizeof line, f)) { + uint64_t lo, hi; + char perms[16], rest[768]; + if (sscanf(line, "%lx-%lx %15s %*s %*s %*s %767[^\n]", &lo, &hi, perms, rest) < 3) + continue; + if (strchr(perms, 'w') && nwr < MAXR) { wr[nwr].lo = lo; wr[nwr].hi = hi; nwr++; } + if (strstr(line, "nvidia") && nnv < MAXR) { nv[nnv].lo = lo; nv[nnv].hi = hi; nnv++; } + } + fclose(f); +} + +int main(int argc, char **argv) +{ + if (argc < 2) { fprintf(stderr, "usage: scan PID\n"); return 1; } + int pid = atoi(argv[1]); + load_maps(pid); + printf("writable regions=%d nvidia regions=%d\n", nwr, nnv); + + char mp[64]; + snprintf(mp, sizeof mp, "/proc/%d/mem", pid); + int fd = open(mp, O_RDONLY); + if (fd < 0) { perror("mem"); return 1; } + + size_t CH = 4 << 20; + static uint8_t *buf; + buf = malloc(CH + 64); + int hits = 0; + for (int r = 0; r < nwr; r++) { + uint64_t a = wr[r].lo; + while (a < wr[r].hi) { + size_t n = (size_t)((wr[r].hi - a) < CH ? (wr[r].hi - a) : CH); + ssize_t got = pread(fd, buf, n, (off_t)a); + if (got <= 0) { /* try smaller granularity */ + size_t n2 = 256 << 10; + if (n > n2) { n = n2; continue; } + a += 4096; continue; + } + if ((size_t)got < n) { + /* partial read: scan what we got, then continue */ + n = got; + } + n -= n % 8; + uint64_t *w = (uint64_t *)buf; + for (size_t i = 0; i + 4 <= n / 8; i++) { + uint64_t sub = w[i], last = w[i + 1], cur = w[i + 2], sem = w[i + 3]; + if (sub == 0 || sub > 1000) continue; + if (last == 0 || last > 1000) continue; + if (cur > 0x200000000ULL) continue; + if (sem < 0x10000 || sem > 0x100000000ULL) continue; + uint64_t vaptr = 0; + if (pread(fd, &vaptr, 8, (off_t)(sem + 0x10)) != 8) continue; + if (!in_nv(vaptr)) continue; + uint32_t val = 0; + if (pread(fd, &val, 4, (off_t)vaptr) != 4) continue; + if (val > 1000) continue; + uint64_t p = a + i * 8 - 0x9418; + printf("P=0x%lx sub=%lu last=%lu cur=0x%lx sem_obj=0x%lx sem_va=0x%lx sem_val=%u\n", + p, sub, last, cur, sem, vaptr, val); + hits++; + } + a += n; + } + } + printf("hits=%d\n", hits); + return 0; +}
\ No newline at end of file diff --git a/tools/guest-diag/scan2.c b/tools/guest-diag/scan2.c new file mode 100644 index 0000000..6220038 --- /dev/null +++ b/tools/guest-diag/scan2.c @@ -0,0 +1,88 @@ +/* scan2.c - find qwords whose value points into a /dev/nvidia* mapping of + the target process, and report the u32 stored there (semaphore hunt). + usage: scan2 PID [max_print] */ +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <fcntl.h> +#include <unistd.h> + +#define MAXR 4096 +static struct { uint64_t lo, hi; char name[64]; } nv[MAXR], wr[MAXR]; +static int nnv, nwr; + +static int in_nv(uint64_t a, int *idx) +{ + for (int i = 0; i < nnv; i++) + if (a >= nv[i].lo && a < nv[i].hi) { if (idx) *idx = i; return 1; } + return 0; +} + +static void load_maps(int pid) +{ + char path[64], line[1024]; + snprintf(path, sizeof path, "/proc/%d/maps", pid); + FILE *f = fopen(path, "r"); + if (!f) { perror("maps"); exit(1); } + while (fgets(line, sizeof line, f)) { + uint64_t lo, hi; + char perms[16], name[128] = ""; + if (sscanf(line, "%lx-%lx %15s %*s %*s %*s %127[^\n]", &lo, &hi, perms, name) < 3) + continue; + if (strchr(perms, 'w') && nwr < MAXR) { wr[nwr].lo = lo; wr[nwr].hi = hi; nwr++; } + if (strstr(line, "nvidia") && nnv < MAXR) { + nv[nnv].lo = lo; nv[nnv].hi = hi; + snprintf(nv[nnv].name, sizeof nv[nnv].name, "%s", name); + nnv++; + } + } + fclose(f); +} + +int main(int argc, char **argv) +{ + if (argc < 2) { fprintf(stderr, "usage: scan2 PID [max_print]\n"); return 1; } + int pid = atoi(argv[1]); + int maxp = argc > 2 ? atoi(argv[2]) : 200; + load_maps(pid); + printf("writable=%d nvidia=%d\n", nwr, nnv); + + char mp[64]; + snprintf(mp, sizeof mp, "/proc/%d/mem", pid); + int fd = open(mp, O_RDONLY); + if (fd < 0) { perror("mem"); return 1; } + + size_t CH = 4 << 20; + uint8_t *buf = malloc(CH + 64); + int printed = 0, scanned = 0; + for (int r = 0; r < nwr; r++) { + uint64_t a = wr[r].lo; + while (a < wr[r].hi) { + size_t n = (size_t)((wr[r].hi - a) < CH ? (wr[r].hi - a) : CH); + ssize_t got = pread(fd, buf, n, (off_t)a); + if (got <= 0) { + if (n > (256u << 10)) { n = 256u << 10; continue; } + a += 4096; continue; + } + if ((size_t)got < n) n = got; + n -= n % 8; + uint64_t *w = (uint64_t *)buf; + for (size_t i = 0; i < n / 8; i++, scanned++) { + uint64_t v = w[i]; + int idx; + if (!in_nv(v, &idx)) continue; + uint32_t val = 0; + if (pread(fd, &val, 4, (off_t)v) != 4) continue; + if (val > 0x100000) continue; + if (printed < maxp) + printf("at 0x%lx -> 0x%lx (%s) val=%u\n", a + i * 8, v, nv[idx].name, val); + printed++; + } + a += n; + } + } + printf("scanned=%d printed=%d\n", scanned, printed); + return 0; +}
\ No newline at end of file diff --git a/tools/guest-diag/scan3.c b/tools/guest-diag/scan3.c new file mode 100644 index 0000000..94f6a42 --- /dev/null +++ b/tools/guest-diag/scan3.c @@ -0,0 +1,77 @@ +/* scan3.c - scan all writable memory of a process for qwords equal to any + of the given 64-bit needles; print every hit address. + usage: scan3 PID 0xNEEDLE [0xNEEDLE ...] */ +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <fcntl.h> +#include <unistd.h> + +#define MAXR 4096 +#define MAXN 64 +static struct { uint64_t lo, hi; } wr[MAXR]; +static int nwr; +static uint64_t needle[MAXN]; +static int nn; + +static void load_maps(int pid) +{ + char path[64], line[1024]; + snprintf(path, sizeof path, "/proc/%d/maps", pid); + FILE *f = fopen(path, "r"); + if (!f) { perror("maps"); exit(1); } + while (fgets(line, sizeof line, f)) { + uint64_t lo, hi; + char perms[16]; + if (sscanf(line, "%lx-%lx %15s", &lo, &hi, perms) < 3) continue; + if (strchr(perms, 'w') && nwr < MAXR) { wr[nwr].lo = lo; wr[nwr].hi = hi; nwr++; } + } + fclose(f); +} + +int main(int argc, char **argv) +{ + if (argc < 3) { fprintf(stderr, "usage: scan3 PID 0xNEEDLE [...]\n"); return 1; } + int pid = atoi(argv[1]); + for (int i = 2; i < argc && nn < MAXN; i++) + needle[nn++] = strtoull(argv[i], 0, 16); + load_maps(pid); + printf("writable=%d needles=%d\n", nwr, nn); + + char mp[64]; + snprintf(mp, sizeof mp, "/proc/%d/mem", pid); + int fd = open(mp, O_RDONLY); + if (fd < 0) { perror("mem"); return 1; } + + size_t CH = 4 << 20; + uint8_t *buf = malloc(CH + 64); + int hits = 0; + for (int r = 0; r < nwr; r++) { + uint64_t a = wr[r].lo; + while (a < wr[r].hi) { + size_t n = (size_t)((wr[r].hi - a) < CH ? (wr[r].hi - a) : CH); + ssize_t got = pread(fd, buf, n, (off_t)a); + if (got <= 0) { + if (n > (256u << 10)) { n = 256u << 10; continue; } + a += 4096; continue; + } + if ((size_t)got < n) n = got; + n -= n % 8; + uint64_t *w = (uint64_t *)buf; + for (size_t i = 0; i < n / 8; i++) { + uint64_t v = w[i]; + for (int k = 0; k < nn; k++) { + if (v == needle[k]) { + printf("hit 0x%lx = 0x%lx\n", a + i * 8, v); + hits++; + } + } + } + a += n; + } + } + printf("hits=%d\n", hits); + return 0; +}
\ No newline at end of file diff --git a/tools/guest-diag/trkinfo.py b/tools/guest-diag/trkinfo.py index 46b6a69..0d6d629 100644 --- a/tools/guest-diag/trkinfo.py +++ b/tools/guest-diag/trkinfo.py @@ -1,9 +1,9 @@ #!/usr/bin/env python3 # gdb script (run with: sudo gdb -p <pid> -batch -x /tmp/trkinfo.py) -# Drills into the libcuda tracker the client spins on (the wait loop around -# libcuda+0x23f700): dumps the tracker object at p+0x9410, the semaphore -# object it references at +0x20, and the u32 semaphore memory that object -# points at (+0x10), plus the VMA that memory lives in. +# Drills into the libcuda tracker wait: dumps every wait entry, the tracker +# objects they reference (channel/context layout at p+0x9410 with the sem +# object at +0x9430), and the progress object at p+0x48 (size/idx/cursor and +# the 0x38-byte slots it indexes). import gdb def r32(a): @@ -66,18 +66,25 @@ if not found: raise SystemExit tid, pc, ctx = found -print("SPINNER tid=%s pc=0x%x ctx=0x%x" % (tid, pc, ctx)) +print("SPINNER tid=%s pc=0x%x ctx=0x%x libbase=0x%x" % (tid, pc, ctx, base)) count = r32(ctx + 0x10) ent = r64(ctx + 0x18) print("count=%d entries=0x%x" % (count, ent)) -n = min(count, 32) +n = min(count, 48) for i in range(n): e = ent + i * 0x28 typ = r32(e) p = r64(e + 8) - v = r32(e + 0x10) + v = r64(e + 0x10) + x18 = r64(e + 0x18) + x20 = r64(e + 0x20) if typ != 1: - print("e%d type=%d p=0x%x v=0x%x (skip)" % (i, typ, p, v)) + print("e%d type=0x%x p=0x%x v=0x%x x18=0x%x x20=0x%x" % (i, typ, p, v, x18, x20)) + if p: + try: + print(" obj[0:0x28]=%s" % rmem(p, 0x28).hex()) + except Exception: + pass continue t = p + 0x9410 try: @@ -85,11 +92,12 @@ for i in range(n): except Exception as ex: print("e%d tracker unreadable: %s" % (i, ex)) continue + sub = int.from_bytes(trk[0x08:0x10], "little") last = int.from_bytes(trk[0x10:0x18], "little") cur = int.from_bytes(trk[0x18:0x20], "little") sem = int.from_bytes(trk[0x20:0x28], "little") - print("e%d p=0x%x v=0x%x TRK=0x%x last=0x%x cur=0x%x sem_obj=0x%x" - % (i, p, v, t, last, cur, sem)) + print("e%d p=0x%x v=0x%x TRK=0x%x sub=0x%x last=0x%x cur=0x%x sem_obj=0x%x" + % (i, p, v, t, sub, last, cur, sem)) try: so = rmem(sem, 0x40) print(" sem_obj[0:0x40]=%s" % so.hex()) @@ -102,4 +110,25 @@ for i in range(n): print(" sem_page unreadable: %s" % ex) except Exception as ex: print(" sem_obj unreadable: %s" % ex) + try: + q = r64(p + 0x48) + print(" prog_obj=0x%x next=0x%x cblist=0x%x idx_u32=0x%x flags95bc=0x%x" + % (q, r64(p + 0x9470), r64(p + 0x9458), r32(p + 0x34), r32(p + 0x95bc))) + if q: + size = r32(q + 8) + idx = r32(q + 0x48) + cur2 = r32(q + 0x4c) + arr = r64(q + 0x40) + print(" q+8=size=%d idx=0x%x cursor=0x%x arr=0x%x" % (size, idx, cur2, arr)) + for s in (idx, cur2): + if size: + slot = arr + (s % size) * 0x38 + else: + slot = arr + s * 0x38 + try: + print(" slot[%d]@0x%x=%s" % (s, slot, rmem(slot, 0x38).hex())) + except Exception as ex: + print(" slot[%d] unreadable: %s" % (s, ex)) + except Exception as ex: + print(" prog unreadable: %s" % ex) print("DONE_TRK")
\ No newline at end of file |
