summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/peek.c
blob: 7c959ec17cab6f4efc685283ff6bd638f679f5f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/* SPDX-License-Identifier: BSD-3-Clause */
/* Copyright (c) 2026 Open-IOV contributors */
/* 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;
}