The DCMD_PROC_GETGREG and DCMD_PROC_GETFPREG commands

Updated: October 26, 2022

The DCMD_PROC_GETGREG and DCMD_PROC_GETFPREG commands are used to fetch the current general registers and floating-point registers for the thread.

This will, of course, be architecture-specific. For simplicity, I've shown the x86_64 version, and just the general registers.

The data structure is (slightly edited for clarity):

typedef union _debug_gregs {
  ARM_CPU_REGISTERS       arm;
  X86_64_CPU_REGISTERS    x86_64;
  AARCH64_CPU_REGISTERS   aarch64;
  uint64_t                padding [1024];
} debug_greg_t;

The x86_64 version, (the x86_64 member), is as follows (from <x86_64/context.h>):

typedef struct x86_64_cpu_registers {
        uint64_t        rdi,
                        rsi,
                        rdx,
                        r10,
                        r8,
                        r9,
                        rax,
                        rbx,
                        rbp,
                        rcx,
                        r11,
                        r12,
                        r13,
                        r14,
                        r15;
        uint64_t        rip;
        uint32_t        cs;
        uint32_t        rsvd1;
        uint64_t        rflags;
        uint64_t        rsp;
        uint32_t        ss;
        uint32_t        rsvd2;
} X86_64_CPU_REGISTERS;

To get the information, a simple devctl() is issued:

static void
dump_procfs_greg (int fd, int tid)
{
  procfs_greg   g;
  int           sts;

  // set the current thread first!
  if ((sts = devctl (fd, DCMD_PROC_CURTHREAD, &tid,
                     sizeof (tid), NULL)) != EOK) {
    fprintf (stderr, "%s:  CURTHREAD for tid %d, error %d (%s)\n",
             progname, tid, sts, strerror (sts));
    exit (EXIT_FAILURE);
  }

  // fetch information about the registers for this pid/tid
  if ((sts = devctl (fd, DCMD_PROC_GETGREG, &g,
                     sizeof (g), NULL)) != EOK) {
    fprintf (stderr, "%s:  GETGREG information, error %d (%s)\n",
             progname, sts, strerror (sts));
    exit (EXIT_FAILURE);
  }

  // print information here...
}
Note: This call, unlike the other calls mentioned so far, requires you to call devctl() with DCMD_PROC_CURTHREAD to set the current thread. Otherwise, you'll get an EINVAL return code from the devctl().

Here is some sample output:

Info from DCMD_PROC_GETGREG
  cs  0x0000001D   eip  0xF000EF9C
  ss  0x00000099   esp  0xEFFF7C14
  eax 0x00000002   ebx  0xEFFFEB00
  ecx 0xEFFF7C14   edx  0xF000EF9E
  edi 0x00000000   esi  0x00000000
  ebp 0xEFFF77C0   exx  0xEFFFEBEC
  efl 0x00001006