// nvkmstrace.c - LD_PRELOAD shim: log NVKMS_IOCTL_IOWR commands #define _GNU_SOURCE #include #include #include #include #include #include struct nvkms_ioctl_params { uint32_t cmd; uint32_t size; uint64_t address; }; #define NVKMS_REQ 0xC0106D00UL static int (*real_ioctl)(int, unsigned long, ...); int ioctl(int fd, unsigned long req, ...) { va_list ap; void *arg; va_start(ap, req); arg = va_arg(ap, void *); va_end(ap); if (!real_ioctl) real_ioctl = dlsym(RTLD_NEXT, "ioctl"); if (req == NVKMS_REQ && arg) { struct nvkms_ioctl_params *p = arg; int rc; rc = real_ioctl(fd, req, arg); fprintf(stderr, "NVKMS_IOCTL cmd=%u size=%u addr=%p rc=%d\n", p->cmd, p->size, (void *)(uintptr_t)p->address, rc); if (p->address && p->size) { unsigned char *q = (unsigned char *)(uintptr_t)p->address; unsigned n = p->size < 64 ? p->size : 64, i; fprintf(stderr, " data:"); for (i = 0; i < n; i++) fprintf(stderr, " %02x", q[i]); fprintf(stderr, "\n"); if (p->size >= 700) { /* reply.status candidates: request = 32 + 4 + * 4*1 (NvBool=NvU8) + 16*(32+4) = 616 bytes */ unsigned o; for (o = 600; o <= 700; o += 4) { unsigned v; memcpy(&v, q + o, 4); if (v <= 16) fprintf(stderr, " small@%u=%u\n", o, v); } } } return rc; } return real_ioctl(fd, req, arg); }