commit dd944ec72a26d0b380ba2af5f6c00310f2f1651e from: rsc date: Sun Jan 23 22:33:04 2005 UTC Start working through proper handling of pthreads when debugging Linux core dumps. Pthreads for active processes is still not supported, nor are other systems. commit - a0e8d02d093e01fdadf8a16bc86fe18b0c4e82c3 commit + dd944ec72a26d0b380ba2af5f6c00310f2f1651e blob - 9127434fd9f8a6784339095e008085fbde469ac5 blob + ff727409faa4cbaaa4e846f320d3a9a7bb9ddaba --- src/libmach/Linux.c +++ src/libmach/Linux.c @@ -168,7 +168,7 @@ ptracerw(int type, int xtype, int isr, int pid, ulong memmove(buf, (char*)v+i, n-i); u = *(u32int*)buf; } - if(ptrace(type, pid, addr+i, &u) < 0) + if(ptrace(type, pid, addr+i, u) < 0) goto ptraceerr; } } @@ -501,192 +501,3 @@ proctextfile(int pid) } Bterm(b); #endif - -/* - * bottom-end functions for libthread_db to call - */ -enum -{ - PS_OK, - PS_ERR, - PS_BADPID, - PS_BADLWPID, - PS_BADADDR, - PS_NOSYM, - PS_NOFPREGS, -}; - -pid_t -ps_getpid(struct ps_prochandle *ph) -{ - return ph->pid; -} - -int -ps_pstop(const struct ps_prochandle *ph) -{ - return PS_ERR; -} - -int -ps_pcontinue(const struct ps_prochandle *ph) -{ - return PS_ERR; -} - -int -ps_lstop(const struct ps_prochandle *ph) -{ - return PS_ERR; -} - -int -ps_lcontinue(const struct ps_prochandle *ph) -{ - return PS_ERR; -} - -/* read/write data or text memory */ -int -ps_pdread(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz) -{ -//print("read %d %p %d\n", ph->pid, addr, sz); - if(ptracerw(PTRACE_PEEKDATA, 0, 1, ph->pid, (ulong)addr, v, sz) < 0) - return PS_ERR; -//print(" => 0x%lux\n", *(ulong*)v); - return PS_OK; -} - -int -ps_pdwrite(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz) -{ -//print("write %d %p\n", ph->pid, addr); - if(ptracerw(PTRACE_POKEDATA, PTRACE_PEEKDATA, 0, ph->pid, (ulong)addr, v, sz) < 0) - return PS_ERR; - return PS_OK; -} - -int -ps_ptread(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz) -{ -//print("read %d %p\n", ph->pid, addr); - if(ptracerw(PTRACE_PEEKTEXT, 0, 1, ph->pid, (ulong)addr, v, sz) < 0) - return PS_ERR; - return PS_OK; -} - -int -ps_ptwrite(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz) -{ -//print("write %d %p\n", ph->pid, addr); - if(ptracerw(PTRACE_POKETEXT, PTRACE_PEEKTEXT, 0, ph->pid, (ulong)addr, v, sz) < 0) - return PS_ERR; - return PS_OK; -} - -int -ps_lgetregs(struct ps_prochandle *ph, lwpid_t lwp, prgregset_t regs) -{ - if(lwp == 0){ - memset(regs, 0xfe, sizeof(regs[0])*nelem(linuxregs)); - return PS_OK; - } -//print("getregs %d %p (%d)\n", lwp, regs, sizeof(regs[0])*nelem(linuxregs)); - - if(ptraceattach(lwp) < 0){ - fprint(2, "ptrace attach: %r\n"); - return PS_ERR; - } - - if(ptracerw(PTRACE_PEEKUSER, 0, 1, lwp, 0, regs, sizeof(regs[0])*nelem(linuxregs)) < 0){ - fprint(2, "ptrace: %r\n"); - return PS_ERR; - } - return PS_OK; -} - -int -ps_lsetregs(struct ps_prochandle *ph, lwpid_t lwp, prgregset_t regs) -{ -print("setregs %d\n", lwp); - if(ptracerw(PTRACE_POKEUSER, PTRACE_PEEKUSER, 1, lwp, 0, regs, sizeof(regs[0])*nelem(linuxregs)) < 0) - return PS_ERR; - return PS_OK; -} - -int -ps_lgetfpregs(struct ps_prochandle *ph, lwpid_t lwp, prfpregset_t *fpregs) -{ - if(ptracerw(PTRACE_PEEKUSER, 0, 1, lwp, 18*4, fpregs, sizeof *fpregs) < 0) - return PS_ERR; - return PS_OK; -} - -int -ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t lwp, prfpregset_t *fpregs) -{ - if(ptracerw(PTRACE_POKEUSER, PTRACE_PEEKUSER, 1, lwp, 18*4, fpregs, sizeof *fpregs) < 0) - return PS_ERR; - return PS_OK; -} - -/* Fetch the special per-thread address associated with the given LWP. - This call is only used on a few platforms (most use a normal register). - The meaning of the `int' parameter is machine-dependent. */ -int -ps_get_thread_area(struct ps_prochandle *ph, lwpid_t lwp, int xxx, psaddr_t *addr) -{ - return PS_NOSYM; -} - -/* Look up the named symbol in the named DSO in the symbol tables - associated with the process being debugged, filling in *SYM_ADDR - with the corresponding run-time address. */ -int -ps_pglobal_lookup(struct ps_prochandle *ph, char *object_name, char *sym_name, psaddr_t *sym_addr) -{ - Fhdr *fp; - ulong addr; - - if((fp = findhdr(object_name)) == nil){ -print("lookup %d %s %s => no such hdr\n", ph->pid, object_name, sym_name); - return PS_NOSYM; - } - if(elfsymlookup(fp->elf, sym_name, &addr) < 0){ -print("lookup %d %s %s => name not found\n", ph->pid, object_name, sym_name); - return PS_NOSYM; - } -print("lookup %d %s %s => 0x%lux\n", ph->pid, object_name, sym_name, addr); - *sym_addr = (void*)(addr+fp->base); - return PS_OK; -} - -Ureg* -_linux2ureg386(UregLinux386 *l) -{ - Ureg *u; - - u = malloc(sizeof(Ureg)); - if(u == nil) - return nil; - u->di = l->edi; - u->si = l->esi; - u->bp = l->ebp; - u->nsp = l->esp; - u->bx = l->ebx; - u->dx = l->edx; - u->cx = l->ecx; - u->ax = l->eax; - u->gs = l->xgs; - u->fs = l->xfs; - u->es = l->xes; - u->ds = l->xds; - u->trap = ~0; // l->trapno; - u->ecode = ~0; // l->err; - u->pc = l->eip; - u->cs = l->xcs; - u->flags = l->eflags; - u->sp = l->esp; - u->ss = l->xss; - return u; -} blob - 4da38d9efc33df574f4021696d9f318148a179a1 blob + 568bc017048b45d719656d168a58735f4a24d490 --- src/libmach/cmdline.c +++ src/libmach/cmdline.c @@ -26,11 +26,11 @@ alldigs(char *s) * attach to arguments in argc, argv */ int -attachargs(int argc, char **argv, int omode) +attachargs(int argc, char **argv, int omode, int verbose) { int i; Fhdr *hdr; - char *s; + char *s, *t; symhdr = nil; corhdr = nil; @@ -56,9 +56,9 @@ attachargs(int argc, char **argv, int omode) fprint(2, "crackhdr %s: %r\n", argv[i]); continue; } - fprint(2, "%s: %s %s %s\n", argv[i], hdr->aname, hdr->mname, hdr->fname); + if(verbose) + fprint(2, "%s: %s %s %s\n", argv[i], hdr->aname, hdr->mname, hdr->fname); if(hdr->ftype == FCORE){ - fprint(2, "core cmd: %s\n", hdr->cmd); if(corpid){ fprint(2, "already have corpid %d; ignoring core %s\n", corpid, argv[i]); uncrackhdr(hdr); @@ -90,10 +90,21 @@ attachargs(int argc, char **argv, int omode) symfil = s; } } - if(corhdr){ /* try from core */ - if(corhdr->txtfil != nil){ - fprint(2, "core %s: text %s\n", corfil, corhdr->txtfil); - symfil = corhdr->txtfil; + if(corhdr && corhdr->cmdline){ /* try from core */ + /* + * prog gives only the basename of the command, + * so try the command line for a path. + */ + if((s = strdup(corhdr->cmdline)) != nil){ + t = strchr(s, ' '); + if(t) + *t = 0; + if((t = searchpath(s)) != nil){ + if(verbose) + fprint(2, "core: text %s\n", t); + symfil = t; + } + free(s); } } if((symhdr = crackhdr(symfil, omode)) == nil){ @@ -124,10 +135,10 @@ attachargs(int argc, char **argv, int omode) if(corpid) attachproc(corpid); - if(corhdr) attachcore(corhdr); + attachdynamic(verbose); return 0; } @@ -167,7 +178,7 @@ int attachcore(Fhdr *hdr) { unattach(); - if(corhdr == nil) + if(hdr == nil) return 0; if(mapfile(hdr, 0, cormap, &correg) < 0){ fprint(2, "attachcore %s: %r\n", hdr->filename); @@ -180,10 +191,12 @@ attachcore(Fhdr *hdr) } int -attachdynamic(void) +attachdynamic(int verbose) { -extern void elfdl386mapdl(void); - elfdl386mapdl(); + extern void elfdl386mapdl(int); + + if(mach && mach->type == M386 && symhdr && symhdr->elf) + elfdl386mapdl(verbose); return 0; } blob - ffc3b06c7e5ecd6af56dd74605cf69ad0d005d36 blob + c186456a661331990ed2d731012b3e4b617471bf --- src/libmach/crack.c +++ src/libmach/crack.c @@ -2,6 +2,7 @@ #include #include #include +#include "elf.h" static struct { @@ -50,9 +51,18 @@ crackhdr(char *name, int mode) void uncrackhdr(Fhdr *hdr) { - close(hdr->fd); - _delhdr(hdr); - free(hdr->cmd); + int i; + + symclose(hdr); + if(hdr->elf) + elfclose(hdr->elf); + if(hdr->fd >= 0) + close(hdr->fd); + free(hdr->cmdline); + free(hdr->prog); + for(i=0; inthread; i++) + free(hdr->thread[i].ureg); + free(hdr->thread); free(hdr); } @@ -71,6 +81,8 @@ mapfile(Fhdr *fp, ulong base, Map *map, Regs **regs) werrstr("cannot load map for this file type"); return -1; } + if(regs) + *regs = nil; return fp->map(fp, base, map, regs); } @@ -90,3 +102,23 @@ unmapfile(Fhdr *fp, Map *map) } } } + +Regs* +coreregs(Fhdr *fp, uint id) +{ + UregRegs *r; + int i; + + for(i=0; inthread; i++){ + if(fp->thread[i].id == id){ + if((r = mallocz(sizeof *r, 1)) == nil) + return nil; + r->r.rw = _uregrw; + r->ureg = fp->thread[i].ureg; + return &r->r; + } + } + werrstr("thread not found"); + return nil; +} + blob - 682d9a72cbd429752be7a510f6be92e4b6c2979e blob + e80d9ec3a7ee61dbf7524d2d20ffdf676c2341bd --- src/libmach/crackelf.c +++ src/libmach/crackelf.c @@ -5,8 +5,7 @@ #include "dwarf.h" static int mapelf(Fhdr *fp, ulong base, Map *map, Regs**); -static int mapcoreregs(Fhdr *fp, Map *map, Regs**); -static char *getcorecmd(Fhdr *fp); +static int unpacknote(Elf *elf, uchar *a, uchar *ea, ElfNote *note, uchar **pa); static struct { @@ -40,28 +39,24 @@ static struct { uint mtype; uint atype; - int (*coreregs)(Elf*, ElfNote*, uchar**); - int (*corecmd)(Elf*, ElfNote*, char**); + void (*elfcore)(Fhdr*, Elf*, ElfNote*); } ctab[] = { /* Font Tab 4 */ - M386, ALINUX, - coreregslinux386, - corecmdlinux386, - M386, ANONE, - coreregslinux386, /* [sic] */ - corecmdlinux386, /* [sic] */ - M386, AFREEBSD, - coreregsfreebsd386, - corecmdfreebsd386, + M386, ALINUX, elfcorelinux386, + M386, ANONE, elfcorelinux386, /* [sic] */ +/* M386, AFREEBSD, elfcorefreebsd386, */ }; int crackelf(int fd, Fhdr *fp) { - int i, havetext, havedata; + uchar *a, *sa, *ea; + int i, havetext, havedata, n; Elf *elf; + ElfNote note; ElfProg *p; ElfSect *s1, *s2; + void (*elfcore)(Fhdr*, Elf*, ElfNote*); if((elf = elfinit(fd)) == nil) return -1; @@ -133,16 +128,37 @@ crackelf(int fd, Fhdr *fp) fp->map = mapelf; if(fp->ftype == FCORE){ + elfcore = nil; for(i=0; iatype || ctab[i].mtype != fp->mtype) continue; - elf->coreregs = ctab[i].coreregs; - elf->corecmd = ctab[i].corecmd; + elfcore = ctab[i].elfcore; break; } - if((fp->cmd = getcorecmd(fp)) == nil) - fprint(2, "warning: reading core command: %r"); + if(elfcore) + for(i=0; inprog; i++){ + p = &elf->prog[i]; + if(p->type != ElfProgNote) + continue; + n = p->filesz; + a = malloc(n); + if(a == nil) + goto err; + if(seek(fp->fd, p->offset, 0) < 0 || readn(fp->fd, a, n) != n){ + free(a); + continue; + } + sa = a; + ea = a+n; + while(a < ea){ + note.offset = (a-sa) + p->offset; + if(unpacknote(elf, a, ea, ¬e, &a) < 0) + break; + elfcore(fp, elf, ¬e); + } + free(sa); + } return 0; } @@ -258,10 +274,8 @@ mapelf(Fhdr *fp, ulong base, Map *map, Regs **regs) } } - if(fp->ftype == FCORE){ - if(mapcoreregs(fp, map, regs) < 0) - fprint(2, "warning: reading core regs: %r"); - } + if(fp->nthread && regs) + *regs = coreregs(fp, fp->thread[0].id); return 0; } @@ -286,126 +300,3 @@ unpacknote(Elf *elf, uchar *a, uchar *ea, ElfNote *not return 0; } -static int -mapcoreregs(Fhdr *fp, Map *map, Regs **rp) -{ - int i; - uchar *a, *sa, *ea, *uregs; - uint n; - ElfNote note; - ElfProg *p; - Elf *elf; - UregRegs *r; - - elf = fp->elf; - if(elf->coreregs == 0){ - werrstr("cannot parse %s %s cores", fp->mname, fp->aname); - return -1; - } - - for(i=0; inprog; i++){ - p = &elf->prog[i]; - if(p->type != ElfProgNote) - continue; - n = p->filesz; - a = malloc(n); - if(a == nil) - return -1; - if(seek(fp->fd, p->offset, 0) < 0 || readn(fp->fd, a, n) != n){ - free(a); - continue; - } - sa = a; - ea = a+n; - while(a < ea){ - note.offset = (a-sa) + p->offset; - if(unpacknote(elf, a, ea, ¬e, &a) < 0) - break; - switch(note.type){ - case ElfNotePrStatus: - if((n = (*elf->coreregs)(elf, ¬e, &uregs)) < 0){ - free(sa); - return -1; - } - free(sa); - if((r = mallocz(sizeof(*r), 1)) == nil){ - free(uregs); - return -1; - } - r->r.rw = _uregrw; - r->ureg = uregs; - *rp = &r->r; - return 0; - case ElfNotePrFpreg: - case ElfNotePrPsinfo: - case ElfNotePrTaskstruct: - case ElfNotePrAuxv: - case ElfNotePrXfpreg: - break; - } - // fprint(2, "0x%lux note %s/%lud %p\n", note.offset, note.name, note.type, note.desc); - } - free(sa); - } - fprint(2, "could not find registers in core file\n"); - return -1; -} - -static char* -getcorecmd(Fhdr *fp) -{ - int i; - uchar *a, *sa, *ea; - char *cmd; - uint n; - ElfNote note; - ElfProg *p; - Elf *elf; - - elf = fp->elf; - if(elf->corecmd == 0){ - werrstr("cannot parse %s %s cores", fp->mname, fp->aname); - return nil; - } - - for(i=0; inprog; i++){ - p = &elf->prog[i]; - if(p->type != ElfProgNote) - continue; - n = p->filesz; - a = malloc(n); - if(a == nil) - return nil; - if(seek(fp->fd, p->offset, 0) < 0 || readn(fp->fd, a, n) != n){ - free(a); - continue; - } - sa = a; - ea = a+n; - while(a < ea){ - note.offset = (a-sa) + p->offset; - if(unpacknote(elf, a, ea, ¬e, &a) < 0) - break; - switch(note.type){ - case ElfNotePrPsinfo: - if((n = elf->corecmd(elf, ¬e, &cmd)) < 0){ - free(sa); - return nil; - } - free(sa); - return cmd; - case ElfNotePrStatus: - case ElfNotePrFpreg: - case ElfNotePrTaskstruct: - case ElfNotePrAuxv: - case ElfNotePrXfpreg: - break; - } - // fprint(2, "0x%lux note %s/%lud %p\n", note.offset, note.name, note.type, note.desc); - } - free(sa); - } - fprint(2, "could not find registers in core file\n"); - return nil; -} - blob - 6b65cfc86b856817731a86e9c83e1fb6fad0c125 blob + f52450997363bafa1d6692c425816801babbe6c2 --- src/libmach/elf.h +++ src/libmach/elf.h @@ -232,8 +232,6 @@ int elfsym(Elf*, int, ElfSym*); int elfsymlookup(Elf*, char*, ulong*); int elfmap(Elf*, ElfSect*); -int coreregslinux386(Elf*, ElfNote*, uchar**); -int coreregsfreebsd386(Elf*, ElfNote*, uchar**); -int corecmdlinux386(Elf*, ElfNote*, char**); -int corecmdfreebsd386(Elf*, ElfNote*, char**); -void elfdl386mapdl(void); +struct Fhdr; +void elfcorelinux386(struct Fhdr*, Elf*, ElfNote*); +void elfdl386mapdl(int); blob - 9e8d0aa9794d1b79f2634a6eb3e640b5b472b996 blob + 4c4aabc44e13cdaf16e7bc5885d24cbd9ac8dd41 --- src/libmach/elfcorelinux386.c +++ src/libmach/elfcorelinux386.c @@ -34,6 +34,10 @@ struct Status UregLinux386 reg; u32int fpvalid; }; +enum +{ + StatusSize = sizeof(Status), +}; struct Psinfo { @@ -51,6 +55,10 @@ struct Psinfo char fname[16]; char psargs[80]; }; +enum +{ + PsinfoSize = sizeof(Psinfo), +}; int coreregslinux386(Elf *elf, ElfNote *note, uchar **up) @@ -65,8 +73,9 @@ coreregslinux386(Elf *elf, ElfNote *note, uchar **up) } s = (Status*)note->desc; l = &s->reg; - if((u = _linux2ureg386(l)) == nil) + if((u = malloc(sizeof *u)) == nil) return -1; + linux2ureg386(l, u); *up = (uchar*)u; return sizeof(Ureg); } @@ -93,3 +102,101 @@ corecmdlinux386(Elf *elf, ElfNote *note, char **pp) 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); + } +} + blob - a2439158f4025c31f6b0d7452fd2207f6f8313f2 blob + 5386f1b64ff567594b7d1c28797fd50a19a66c46 --- src/libmach/elfdl386.c +++ src/libmach/elfdl386.c @@ -86,14 +86,13 @@ dyninfo(Fhdr *hdr, int x) } void -elfdl386mapdl(void) +elfdl386mapdl(int verbose) { int i; Fhdr *hdr; u32int linkdebug, linkmap, name, addr; char buf[1024]; -print("elfdl386mapdl\n"); if((linkdebug = dyninfo(symhdr, DT_DEBUG)) == 0){ fprint(2, "no dt_debug section\n"); return; @@ -109,25 +108,27 @@ print("elfdl386mapdl\n"); || get4(cormap, linkmap+12, &linkmap) < 0) break; - if(name - && getstr(cormap, name, buf, sizeof buf) >= 0 - && buf[0] - && access(buf, AEXIST) >= 0){ - if((hdr = crackhdr(buf, OREAD)) == nil) - fprint(2, "crackhdr %s: %r\n", buf); - else{ - fprint(2, "%s: %s %s %s\n", buf, hdr->aname, hdr->mname, hdr->fname); - hdr->base = addr; - if(mapfile(hdr, addr, symmap, nil) < 0) - fprint(2, "mapfile %s: %r\n", buf); - if(corhdr){ - unmapfile(corhdr, cormap); - mapfile(hdr, addr, cormap, nil); - } - if(symopen(hdr) < 0) - fprint(2, "syminit %s: %\r", buf); - } - } + if(name == 0 || getstr(cormap, name, buf, sizeof buf) < 0 || buf[0] == 0) + continue; + if((hdr = crackhdr(buf, OREAD)) == nil){ + fprint(2, "crackhdr %s: %r\n", buf); + continue; + } + hdr->base = addr; + if(verbose) + fprint(2, "%s: %s %s %s\n", buf, hdr->aname, hdr->mname, hdr->fname); + if(mapfile(hdr, addr, symmap, nil) < 0) + fprint(2, "mapping %s: %r\n", buf); + if(corhdr){ + /* + * Need to map the text file under the core file. + */ + unmapfile(corhdr, cormap); + mapfile(hdr, addr, cormap, nil); + mapfile(corhdr, 0, cormap, nil); + } + if(symopen(hdr) < 0) + fprint(2, "syminit %s: %r\n", buf); } } blob - 035c6a5233802ed23e254628f3811337d85dc95f blob + 7d03f3b4c070026d3c615122f948e18ed810b1fe --- src/libmach/frame.c +++ src/libmach/frame.c @@ -87,8 +87,12 @@ stacktrace(Map *map, Regs *regs, Tracer trace) break; if(i < 0) break; - if(sp && strcmp(sp->name, "main") == 0) - break; + if(sp){ + if(strcmp(sp->name, "main") == 0 + || strcmp(sp->name, "procscheduler") == 0 + || strcmp(sp->name, "threadstart") == 0) + break; + } pc = nextpc; memmove(cur, next, mach->nwindreg*sizeof(cur[0])); } blob - bfb5f722813acb01c7712bf157a4344fa7440cbd blob + b20bd8738b98d54940bb9fb333195d0bfe49e500 --- src/libmach/map.c +++ src/libmach/map.c @@ -31,7 +31,7 @@ addseg(Map *map, Seg seg) { Seg *ss; - if(map == 0){ + if(map == nil){ werrstr("invalid map"); return -1; } @@ -57,7 +57,7 @@ findseg(Map *map, char *name, char *file) { int i; - if(map == 0) + if(map == nil) return -1; for(i=0; inseg; i++){ if(name && (!map->seg[i].name || strcmp(map->seg[i].name, name) != 0)) blob - 53d1af99e49643bc1192684b64acedd445efdbbf blob + a6d6507e2ca4c6e73e26ebecbd6141558485793e --- src/libmach/mkfile +++ src/libmach/mkfile @@ -43,7 +43,7 @@ OFILES=\ symstabs.$O\ ureg386.$O\ -HFILES=mach.h +HFILES=$PLAN9/include/mach.h <$PLAN9/src/mksyslib CFLAGS=$CFLAGS -I. blob - 46eca4f2ed36b7aa59538df7d291b64614b3fbe9 blob + 8a2b60a989069685e0cb23c48469981d24e44973 --- src/libmach/pthread.c +++ src/libmach/pthread.c @@ -6,6 +6,103 @@ #include #include +typedef struct Ptprog Ptprog; +struct Pprog +{ + Pthread *t; + uint nt; +}; + +typedef struct Pthread Pthread; +struct Pthread +{ + td_thrhandle_t handle; +}; + +void +pthreadattach(int pid) +{ + +} + +void pthreadattach() + set up mapping + +Regs *pthreadregs() +int npthread(); + + + +static int td_get_allthreads(td_thragent_t*, td_thrhandle_t**); +static int terr(int); + + +Regs* +threadregs() +{ + +} + + + +typedef struct AllThread AllThread; +struct AllThread +{ + td_thrhandle_t *a; + int n; + int err; +}; + +static int +thritercb(const td_thrhandle_t *th, void *cb) +{ + td_thrhandle_t **p; + AllThread *a; + int n; + + a = cb; + if((a->n&(a->n-1)) == 0){ + if(a->n == 0) + n = 1; + else + n = a->n<<1; + if((p = realloc(a->a, n*sizeof a->a[0])) == 0){ + a->err = -1; + return -1; /* stop iteration */ + } + a->a = p; + } + a->a[a->n++] = *th; + return 0; +} + +int +td_get_allthreads(td_thragent_t *ta, td_thrhandle_t **pall) +{ + int e; + AllThread a; + + a.a = nil; + a.n = 0; + a.err = 0; + if((e = td_ta_thr_iter(ta, thritercb, &a, + TD_THR_ANY_STATE, + TD_THR_LOWEST_PRIORITY, + TD_SIGNO_MASK, + TD_THR_ANY_USER_FLAGS)) != TD_OK){ + werrstr("%s", terr(e)); + return -1; + } + + if(a.err){ + free(a.a); + return -1; + } + + *pall = a.a; + return a.n; +} + static char *tderrstr[] = { [TD_OK] "no error", @@ -47,3 +144,146 @@ terr(int e) return tderrstr[e]; } +/* + * bottom-end functions for libthread_db to call + */ +enum +{ + PS_OK, + PS_ERR, + PS_BADPID, + PS_BADLWPID, + PS_BADADDR, + PS_NOSYM, + PS_NOFPREGS, +}; + +pid_t +ps_getpid(struct ps_prochandle *ph) +{ + return ph->pid; +} + +int +ps_pstop(const struct ps_prochandle *ph) +{ + return PS_ERR; +} + +int +ps_pcontinue(const struct ps_prochandle *ph) +{ + return PS_ERR; +} + +int +ps_lstop(const struct ps_prochandle *ph) +{ + return PS_ERR; +} + +int +ps_lcontinue(const struct ps_prochandle *ph) +{ + return PS_ERR; +} + +/* read/write data or text memory */ +int +ps_pdread(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz) +{ + if(get1(ph->map, addr, v, sz) < 0) + return PS_ERR; + return PS_OK; +} + +int +ps_pdwrite(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz) +{ + if(put1(ph->map, addr, v, sz) < 0) + return PS_ERR; + return PS_OK; +} + +int +ps_ptread(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz) +{ + return ps_pdread(ph, addr, v, sz); +} + +int +ps_ptwrite(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz) +{ + return ps_pdwrite(ph, addr, v, sz); +} + +int +ps_lgetregs(struct ps_prochandle *ph, lwpid_t lwp, prgregset_t regs) +{ + int i; + + USED(ph); + if(corhdr == nil) + return sys_ps_lgetregs(ph, lwp, regs); + for(i=0; inthread; i++){ + if(corhdr->thread[i].id == lwp){ + ureg2prgregset(corhdr->thread[i].ureg, regs); + return PS_OK; + } + } + return PS_ERR; +} + +int +ps_lsetregs(struct ps_prochandle *ph, lwpid_t lwp, prgregset_t regs) +{ + if(corhdr == nil) + return sys_ps_lsetregs(ph, lwp, regs); + return PS_ERR; +} + +int +ps_lgetfpregs(struct ps_prochandle *ph, lwpid_t lwp, prfpregset_t *fpregs) +{ + if(corhdr == nil) + return sys_ps_lgetfpregs(ph, lwp, fpregs); + /* BUG - Look in core dump. */ + return PS_ERR: +} + +int +ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t lwp, prfpregset_t *fpregs) +{ + if(corhdr == nil) + return sys_ps_lsetfpregs(ph, lwp, fpregs); + return PS_ERR; +} + +/* Fetch the special per-thread address associated with the given LWP. + This call is only used on a few platforms (most use a normal register). + The meaning of the `int' parameter is machine-dependent. */ +int +ps_get_thread_area(struct ps_prochandle *ph, lwpid_t lwp, int xxx, psaddr_t *addr) +{ + return sys_ps_get_thread_area(ph, lwp, xxx, addr); +} + +int +ps_pglobal_lookup(struct ps_prochandle *ph, char *object_name, char *sym_name, psaddr_t *sym_addr) +{ + Fhdr *fp; + ulong addr; + + if((fp = findhdr(object_name)) == nil){ + print("libmach pthread: lookup %d %s %s => no such hdr\n", ph->pid, object_name, sym_name); + return PS_NOSYM; + } + if(elfsymlookup(fp->elf, sym_name, &addr) < 0){ + print("libmach pthread: lookup %d %s %s => name not found\n", ph->pid, object_name, sym_name); + return PS_NOSYM; + } + /* print("libmach pthread: lookup %d %s %s => 0x%lux\n", ph->pid, object_name, sym_name, addr); */ + *sym_addr = (void*)(addr+fp->base); + return PS_OK; +} + blob - b5d3eacf5df903294e3686ac5b9d8f673de7ef0f blob + 3b5c5ec4360c379efdff4560cac3d7daeae0274e --- src/libmach/sym.c +++ src/libmach/sym.c @@ -42,10 +42,11 @@ _delhdr(Fhdr *h) else{ for(p=fhdrlist; p && p->next!=h; p=p->next) ; - if(p) + if(p){ p->next = h->next; - if(p->next == nil) - last = p; + if(p->next == nil) + last = p; + } } h->next = nil; } blob - 09ef095db2596e94e60cb9a99823761810e4d6bd blob + 76945030fe746f6365382228d42f630808c24096 --- src/libmach/ureg386.c +++ src/libmach/ureg386.c @@ -1,18 +1,11 @@ #include #include #include -#include #include "ureg386.h" - -Ureg* -_linux2ureg386(UregLinux386 *l) +void +linux2ureg386(UregLinux386 *l, Ureg *u) { - Ureg *u; - - u = malloc(sizeof(Ureg)); - if(u == nil) - return nil; u->di = l->edi; u->si = l->esi; u->bp = l->ebp; @@ -32,5 +25,27 @@ _linux2ureg386(UregLinux386 *l) u->flags = l->eflags; u->sp = l->esp; u->ss = l->xss; - return u; } + +void +ureg2linux386(Ureg *u, UregLinux386 *l) +{ + l->edi = u->di; + l->esi = u->si; + l->ebp = u->bp; + l->esp = u->nsp; + l->ebx = u->bx; + l->edx = u->dx; + l->ecx = u->cx; + l->eax = u->ax; + l->xgs = u->gs; + l->xfs = u->fs; + l->xes = u->es; + l->xds = u->ds; + l->eip = u->pc; + l->xcs = u->cs; + l->eflags = u->flags; + l->esp = u->sp; + l->xss = u->ss; +} + blob - f5f9a474adf261869b609e0e1013ebc71ddd3c10 blob + 9c4853d6822c027055fa9bd6ebf843d964cabb6f --- src/libmach/ureg386.h +++ src/libmach/ureg386.h @@ -25,24 +25,24 @@ struct Ureg typedef struct UregLinux386 UregLinux386; struct UregLinux386 { - ulong ebx; - ulong ecx; - ulong edx; - ulong esi; - ulong edi; - ulong ebp; - ulong eax; - ulong xds; - ulong xes; - ulong xfs; - ulong xgs; - ulong origeax; - ulong eip; - ulong xcs; - ulong eflags; - ulong esp; - ulong xss; + u32int ebx; + u32int ecx; + u32int edx; + u32int esi; + u32int edi; + u32int ebp; + u32int eax; + u32int xds; + u32int xes; + u32int xfs; + u32int xgs; + u32int origeax; + u32int eip; + u32int xcs; + u32int eflags; + u32int esp; + u32int xss; }; -Ureg *_linux2ureg386(UregLinux386*); - +void linux2ureg386(UregLinux386*, Ureg*); +void ureg2linux386(Ureg*, UregLinux386*);