| #include <u.h> |
| #include <libc.h> |
| #include <mach.h> |
| #include "elf.h" |
| #include "ureg386.h" |
| |
| #undef errno |
| #define errno uregerrno |
| |
| typedef struct Lreg Lreg; |
| typedef struct Status Status; |
| typedef struct Psinfo Psinfo; |
| |
| /* |
| * UregLinux386 is 64-bit aligned within status, so we shouldn't |
| * have any packing problems. |
| */ |
| struct Status |
| { |
| u32int signo; |
| u32int code; |
| u32int errno; |
| u32int cursig; |
| u32int sigpend; |
| u32int sighold; |
| u32int pid; |
| u32int ppid; |
| u32int pgrp; |
| u32int sid; |
| u32int utime[2]; |
| u32int stime[2]; |
| u32int cutime[2]; |
| u32int cstime[2]; |
| UregLinux386 reg; |
| u32int fpvalid; |
| }; |
| enum |
| { |
| StatusSize = sizeof(Status) |
| }; |
| |
| struct Psinfo |
| { |
| char state; |
| char sname; |
| char zomb; |
| char nice; |
| u32int flag; |
| u16int uid; |
| u16int gid; |
| u32int pid; |
| u32int ppid; |
| u32int pgrp; |
| u32int sid; |
| char fname[16]; |
| char psargs[80]; |
| }; |
| enum |
| { |
| PsinfoSize = sizeof(Psinfo) |
| }; |
| |
| int |
| coreregslinux386(Elf *elf, ElfNote *note, uchar **up) |
| { |
| Status *s; |
| UregLinux386 *l; |
| Ureg *u; |
| |
| if(note->descsz < sizeof(Status)){ |
| werrstr("elf status note too small"); |
| return -1; |
| } |
| s = (Status*)note->desc; |
| l = &s->reg; |
| if((u = malloc(sizeof *u)) == nil) |
| return -1; |
| linux2ureg386(l, u); |
| *up = (uchar*)u; |
| return sizeof(Ureg); |
| } |
| |
| int |
| corecmdlinux386(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->fname, p->psargs); */ |
| t = malloc(80+1); |
| if(t == nil) |
| return -1; |
| memmove(t, p->psargs, 80); |
| t[80] = 0; |
| *pp = t; |
| return 0; |
| } |
| |
| #define dprint if(0)print |
| |
| void |
| elfcorelinux386(Fhdr *fp, Elf *elf, ElfNote *note) |
| { |
| int i; |
| Psinfo *ps; |
| Status *st; |
| Mach *m; |
| Ureg *u; |
| |
| m = fp->mach; |
| dprint("%s ", note->name); |
| switch(note->type){ |
| case ElfNotePrPsinfo: |
| ps = (Psinfo*)note->desc; |
| dprint("note info\n"); |
| dprint("state=%d sname=%d zomb=%d nice=%d\n", |
| ps->state, ps->sname, ps->zomb, ps->nice); |
| dprint("flag=0x%ux uid=%ud gid=%ud pid=%ud ppid=%ud pgrp=%ud sid=%ud\n", |
| (uint)m->swap4(ps->flag), |
| (uint)m->swap2(ps->uid), |
| (uint)m->swap2(ps->gid), |
| (uint)m->swap4(ps->pid), |
| (uint)m->swap4(ps->ppid), |
| (uint)m->swap4(ps->pgrp), |
| (uint)m->swap4(ps->sid)); |
| dprint("fname=%s psargs=%s\n", ps->fname, ps->psargs); |
| fp->pid = m->swap4(ps->pid); |
| if((fp->prog = strdup(ps->fname)) == nil) |
| fprint(2, "warning: out of memory saving core program name\n"); |
| if((fp->cmdline = strdup(ps->psargs)) == nil) |
| fprint(2, "warning: out of memory saving core command line\n"); |
| break; |
| case ElfNotePrTaskstruct: |
| dprint("note taskstruct\n"); |
| break; |
| case ElfNotePrAuxv: |
| dprint("note auxv\n"); |
| break; |
| case ElfNotePrStatus: |
| dprint("note status\n"); |
| if(note->descsz < StatusSize){ |
| dprint("too small\n"); |
| break; |
| } |
| st = (Status*)note->desc; |
| dprint("sig=%ud code=%ud errno=%ud cursig=%ud sigpend=0x%ux sighold=0x%ux\n", |
| (uint)m->swap4(st->signo), |
| (uint)m->swap4(st->code), |
| (uint)m->swap4(st->errno), |
| (uint)m->swap4(st->cursig), |
| (uint)m->swap4(st->sigpend), |
| (uint)m->swap4(st->sighold)); |
| dprint("pid=%ud ppid=%ud pgrp=%ud sid=%ud\n", |
| (uint)m->swap4(st->pid), |
| (uint)m->swap4(st->ppid), |
| (uint)m->swap4(st->pgrp), |
| (uint)m->swap4(st->sid)); |
| dprint("utime=%ud.%06ud stime=%ud.%06ud cutime=%ud.%06ud cstime=%ud.%06ud\n", |
| (uint)m->swap4(st->utime[0]), |
| (uint)m->swap4(st->utime[1]), |
| (uint)m->swap4(st->stime[0]), |
| (uint)m->swap4(st->stime[1]), |
| (uint)m->swap4(st->cutime[0]), |
| (uint)m->swap4(st->cutime[1]), |
| (uint)m->swap4(st->cstime[0]), |
| (uint)m->swap4(st->cstime[1])); |
| dprint("fpvalid=%ud\n", |
| (uint)m->swap4(st->fpvalid)); |
| 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 = m->swap4(st->pid); |
| u = malloc(sizeof *u); |
| if(u == nil){ |
| fprint(2, "warning: out of memory saving thread info\n"); |
| return; |
| } |
| fp->thread[i].ureg = u; |
| linux2ureg386(&st->reg, u); |
| fp->nthread++; |
| break; |
| case ElfNotePrFpreg: |
| dprint("note fpreg\n"); |
| /* XXX maybe record floating-point registers eventually */ |
| break; |
| case ElfNotePrXfpreg: |
| dprint("note xfpreg\n"); |
| /* XXX maybe record floating-point registers eventually */ |
| break; |
| default: |
| dprint("note %d\n", note->type); |
| } |
| } |
| |