| #include <u.h> |
| #include <libc.h> |
| #include <mach.h> |
| #include "elf.h" |
| #include "uregamd64.h" |
| |
| typedef struct Ureg Ureg; |
| |
| // See FreeBSD's sys/procfs.h. |
| |
| typedef struct Lreg Lreg; |
| typedef struct Status Status; |
| typedef struct Psinfo Psinfo; |
| |
| struct Lreg |
| { |
| u64int r15; |
| u64int r14; |
| u64int r13; |
| u64int r12; |
| u64int r11; |
| u64int r10; |
| u64int r9; |
| u64int r8; |
| u64int rdi; |
| u64int rsi; |
| u64int rbp; |
| u64int rbx; |
| u64int rdx; |
| u64int rcx; |
| u64int rax; |
| u32int trapno; |
| u16int fs; |
| u16int gs; |
| u32int err; |
| u16int es; |
| u16int ds; |
| u64int rip; |
| u64int cs; |
| u64int rflags; |
| u64int rsp; |
| u64int ss; |
| }; |
| |
| struct Status |
| { |
| u32int version; /* Version number of struct (1) */ |
| u64int statussz; /* sizeof(prstatus_t) (1) */ |
| u64int gregsetsz; /* sizeof(gregset_t) (1) */ |
| u64int fpregsetsz; /* sizeof(fpregset_t) (1) */ |
| u32int osreldate; /* Kernel version (1) */ |
| u32int cursig; /* Current signal (1) */ |
| u32int pid; /* Process ID (1) */ |
| Lreg reg; /* General purpose registers (1) */ |
| }; |
| |
| struct Psinfo |
| { |
| u32int version; |
| u64int size; |
| char name[17]; |
| char psargs[81]; |
| }; |
| |
| void |
| elfcorefreebsdamd64(Fhdr *fp, Elf *elf, ElfNote *note) |
| { |
| Status *s; |
| Lreg *l; |
| Ureg *u; |
| int i; |
| |
| switch(note->type) { |
| case ElfNotePrStatus: |
| if(note->descsz < sizeof(Status)){ |
| fprint(2, "warning: elf status note too small\n"); |
| break; |
| } |
| s = (Status*)note->desc; |
| if(s->version != 1){ |
| fprint(2, "warning: unknown elf note status version %ud\n", (uint)s->version); |
| break; |
| } |
| l = &s->reg; |
| u = malloc(sizeof(Ureg)); |
| |
| /* no byte order problems - just copying and rearranging */ |
| u->ax = l->rax; |
| u->bx = l->rbx; |
| u->cx = l->rcx; |
| u->dx = l->rdx; |
| u->si = l->rsi; |
| u->di = l->rdi; |
| u->bp = l->rbp; |
| u->r8 = l->r8; |
| u->r9 = l->r9; |
| u->r10 = l->r10; |
| u->r11 = l->r11; |
| u->r12 = l->r12; |
| u->r13 = l->r13; |
| u->r14 = l->r14; |
| u->r15 = l->r15; |
| |
| u->ds = l->ds; |
| u->es = l->es; |
| u->fs = l->fs; |
| u->gs = l->gs; |
| |
| u->type = l->trapno; |
| u->error = l->err; |
| u->ip = l->rip; |
| u->cs = l->cs; |
| u->flags = l->rflags; |
| u->sp = l->rsp; |
| u->ss = l->ss; |
| |
| if((fp->thread = realloc(fp->thread, (1+fp->nthread)*sizeof(fp->thread[0]))) == nil){ |
| fprint(2, "warning: out of memory saving thread info\n"); |
| return; |
| } |
| i = fp->nthread; |
| fp->thread[i].id = s->pid; |
| fp->thread[i].ureg = u; |
| fp->nthread++; |
| break; |
| } |
| } |
| |
| int |
| corecmdfreebsd386(Elf *elf, ElfNote *note, char **pp) |
| { |
| char *t; |
| Psinfo *p; |
| |
| *pp = nil; |
| if(note->descsz < sizeof(Psinfo)){ |
| werrstr("elf psinfo note too small"); |
| return -1; |
| } |
| p = (Psinfo*)note->desc; |
| /* print("elf name %s\nelf args %s\n", p->name, p->psargs); */ |
| t = malloc(80+1); |
| if(t == nil) |
| return -1; |
| memmove(t, p->psargs, 80); |
| t[80] = 0; |
| *pp = t; |
| return 0; |
| } |
| |