commit 1cc215aaf92a6cf3cea436f2c215a84839fd59bc from: rsc date: Sat Dec 25 22:03:28 2004 UTC better unwinding for 386. command-line extraction from core files on linux and freebsd. move linux ureg into ureg386.h (used in many places). commit - cdf1805191ba4ab5b8fbb1697a95fe0d32e25ee6 commit + 1cc215aaf92a6cf3cea436f2c215a84839fd59bc blob - 12b0f9b8001beaab242e039df8d44cd04621f0fa blob + def8925e1547fcd098a64a4e6dafe0676c6d5927 --- src/libmach/Linux.c +++ src/libmach/Linux.c @@ -18,10 +18,12 @@ #include #include #include +#include #include #include #include #include +#include #include "ureg386.h" Mach *machcpu = &mach386; @@ -34,42 +36,27 @@ struct PtraceRegs int pid; }; -static int ptracerw(Map*, Seg*, ulong, void*, uint, int); +static int ptracesegrw(Map*, Seg*, ulong, void*, uint, int); static int ptraceregrw(Regs*, char*, ulong*, int); static int attachedpids[1000]; static int nattached; -void -unmapproc(Map *map) -{ - int i; - - if(map == nil) - return; - for(i=0; inseg; i++) - while(inseg && map->seg[i].pid){ - map->nseg--; - memmove(&map->seg[i], &map->seg[i+1], - (map->nseg-i)*sizeof(map->seg[0])); - } -} - int -mapproc(int pid, Map *map, Regs **rp) +ptraceattach(int pid) { int i; - Seg s; - PtraceRegs *r; + /* if(nattached==1 && attachedpids[0] == pid) goto already; if(nattached) detachproc(attachedpids[0]); - + */ + for(i=0; inseg; i++) + while(inseg && map->seg[i].pid){ + map->nseg--; + memmove(&map->seg[i], &map->seg[i+1], + (map->nseg-i)*sizeof(map->seg[0])); + } +} + + + +int +mapproc(int pid, Map *map, Regs **rp) +{ + Seg s; + PtraceRegs *r; + + if(ptraceattach(pid) < 0) + return -1; + memset(&s, 0, sizeof s); s.base = 0; s.size = 0xFFFFFFFF; s.offset = 0; s.name = "data"; s.file = nil; - s.rw = ptracerw; + s.rw = ptracesegrw; s.pid = pid; if(addseg(map, s) < 0){ fprint(2, "addseg: %r\n"); @@ -126,17 +140,16 @@ detachproc(int pid) } static int -ptracerw(Map *map, Seg *seg, ulong addr, void *v, uint n, int isr) +ptracerw(int type, int xtype, int isr, int pid, ulong addr, void *v, uint n) { int i; u32int u; uchar buf[4]; - addr += seg->base; for(i=0; ipid, addr+i, 0); + u = ptrace(type, pid, addr+i, 0); if(errno) goto ptraceerr; if(n-i >= 4) @@ -150,14 +163,14 @@ ptracerw(Map *map, Seg *seg, ulong addr, void *v, uint u = *(u32int*)((char*)v+i); else{ errno = 0; - u = ptrace(PTRACE_PEEKDATA, seg->pid, addr+i, 0); + u = ptrace(xtype, pid, addr+i, 0); if(errno) return -1; *(u32int*)buf = u; memmove(buf, (char*)v+i, n-i); u = *(u32int*)buf; } - if(ptrace(PTRACE_POKEDATA, seg->pid, addr+i, &u) < 0) + if(ptrace(type, pid, addr+i, &u) < 0) goto ptraceerr; } } @@ -166,6 +179,14 @@ ptracerw(Map *map, Seg *seg, ulong addr, void *v, uint ptraceerr: werrstr("ptrace: %r"); return -1; +} + +static int +ptracesegrw(Map *map, Seg *seg, ulong addr, void *v, uint n, int isr) +{ + addr += seg->base; + return ptracerw(isr ? PTRACE_PEEKDATA : PTRACE_POKEDATA, PTRACE_PEEKDATA, + isr, seg->pid, addr, v, n); } static char* linuxregs[] = { @@ -482,4 +503,192 @@ 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 - eb99947d39856eeb2615a1ab24598b12ef15ab1a blob + f0f84230d5f12fe9079992ccb13f695fc7c84196 --- src/libmach/crackelf.c +++ src/libmach/crackelf.c @@ -40,11 +40,18 @@ static struct uint mtype; uint atype; int (*coreregs)(Elf*, ElfNote*, uchar**); + int (*corecmd)(Elf*, ElfNote*, char**); } ctab[] = { /* Font Tab 4 */ - M386, ALINUX, coreregslinux386, - M386, ANONE, coreregslinux386, /* [sic] */ - M386, AFREEBSD, coreregsfreebsd386, + M386, ALINUX, + coreregslinux386, + corecmdlinux386, + M386, ANONE, + coreregslinux386, /* [sic] */ + corecmdlinux386, /* [sic] */ + M386, AFREEBSD, + coreregsfreebsd386, + corecmdfreebsd386, }; int blob - 6ed239bc2ce4ba9d2d6ccdfa51a296832423182d blob + d4b459e1cc431dae80736d89c347d0f7f7c3084c --- src/libmach/elf.h +++ src/libmach/elf.h @@ -218,6 +218,7 @@ struct Elf ElfSect *dynsym; ElfSect *dynstr; ElfSect *bss; + ulong dynamic; /* offset to elf dynamic crap */ int (*coreregs)(Elf*, ElfNote*, uchar**); }; @@ -227,7 +228,10 @@ Elf* elfinit(int); ElfSect *elfsection(Elf*, char*); void elfclose(Elf*); 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**); blob - 2ff746dee42843fa39c6604fb527172662975961 blob + 84f6c0fd18e153e34f3f95a99b4e4621baaf33dd --- src/libmach/elfcorefreebsd386.c +++ src/libmach/elfcorefreebsd386.c @@ -6,6 +6,7 @@ typedef struct Lreg Lreg; typedef struct Status Status; +typedef struct Psinfo Psinfo; struct Lreg { @@ -32,16 +33,24 @@ struct Lreg struct Status { - u32int version; /* Version number of struct (1) */ - u32int statussz; /* sizeof(prstatus_t) (1) */ - u32int gregsetsz; /* sizeof(gregset_t) (1) */ - u32int 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) */ + u32int version; /* Version number of struct (1) */ + u32int statussz; /* sizeof(prstatus_t) (1) */ + u32int gregsetsz; /* sizeof(gregset_t) (1) */ + u32int 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; + u32int size; + char name[17]; + char psargs[81]; +}; + int coreregsfreebsd386(Elf *elf, ElfNote *note, uchar **up) { @@ -87,3 +96,25 @@ coreregsfreebsd386(Elf *elf, ElfNote *note, uchar **up return sizeof(Ureg); } +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; +} + blob - f6a0234c64263db6aa4e2d6497d4b503a8a4c91b blob + 18f8bdfec0bb7e3f6e11501f90762e15325ba039 --- src/libmach/elfcorelinux386.c +++ src/libmach/elfcorelinux386.c @@ -6,30 +6,10 @@ typedef struct Lreg Lreg; typedef struct Status Status; +typedef struct Psinfo Psinfo; -struct Lreg -{ - u32int ebx; - u32int ecx; - u32int edx; - u32int esi; - u32int edi; - u32int ebp; - u32int eax; - u32int ds; - u32int es; - u32int fs; - u32int gs; - u32int origeax; - u32int eip; - u32int cs; - u32int eflags; - u32int esp; - u32int ss; -}; - /* - * Lreg is 64-bit aligned within status, so we shouldn't + * UregLinux386 is 64-bit aligned within status, so we shouldn't * have any packing problems. */ struct Status @@ -48,15 +28,32 @@ struct Status u32int stime[2]; u32int cutime[2]; u32int cstime[2]; - Lreg reg; + UregLinux386 reg; u32int fpvalid; }; +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]; +}; + int coreregslinux386(Elf *elf, ElfNote *note, uchar **up) { Status *s; - Lreg *l; + UregLinux386 *l; Ureg *u; if(note->descsz < sizeof(Status)){ @@ -65,31 +62,31 @@ coreregslinux386(Elf *elf, ElfNote *note, uchar **up) } s = (Status*)note->desc; l = &s->reg; - u = malloc(sizeof(Ureg)); - if(u == nil) + if((u = _linux2ureg386(l)) == nil) return -1; - - /* no byte order problems - just copying and rearranging */ - 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->gs; - u->fs = l->fs; - u->es = l->es; - u->ds = l->ds; - u->trap = ~0; // l->trapno; - u->ecode = ~0; // l->err; - u->pc = l->eip; - u->cs = l->cs; - u->flags = l->eflags; - u->sp = l->esp; - u->ss = l->ss; *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; +} + blob - 6e4485190b3a7eb03a4f5101a7c7870ce00dc7cc blob + 035c6a5233802ed23e254628f3811337d85dc95f --- src/libmach/frame.c +++ src/libmach/frame.c @@ -79,7 +79,7 @@ stacktrace(Map *map, Regs *regs, Tracer trace) lr.oldregs = regs; lr.val = cur; lr.map = map; - if((i = unwindframe(map, &lr.r, next)) >= 0) + if((i = unwindframe(map, &lr.r, next, sp)) >= 0) nextpc = next[ipc]; else nextpc = ~(ulong)0; blob - 4b43683e654654cae5f0c6e4031d535d6413faee blob + b47fcd554adae8f174a0ea4fe6a211fbb3d42be5 --- src/libmach/mach386.c +++ src/libmach/mach386.c @@ -29,7 +29,7 @@ static int i386hexinst(Map*, ulong, char*, int); static int i386das(Map*, ulong, char, char*, int); static int i386instlen(Map*, ulong); static char *i386windregs[]; -static int i386unwind(Map*, Regs*, ulong*); +static int i386unwind(Map*, Regs*, ulong*, Symbol*); static Regdesc i386reglist[] = { {"DI", REGOFF(di), RINT, 'X'}, @@ -128,14 +128,37 @@ static char *i386windregs[] = { 0, }; +/* + * The wrapper code around Linux system calls + * saves AX on the stack before calling some calls + * (at least, __libc_nanosleep), when running in + * threaded programs. + */ +static void +syscallhack(Map *map, Regs *regs, int *spoff) +{ + ulong pc; + char buf[60]; + + rget(regs, "PC", &pc); + if(i386das(map, pc-2, 0, buf, sizeof buf) != 2 || strncmp(buf, "INTB\t$", 6) != 0) + return; + if(i386das(map, pc, 0, buf, sizeof buf) != 2 || strcmp(buf, "MOVL\tDX,BX") != 0) + return; + if(i386das(map, pc+2, 0, buf, sizeof buf) != 3 || strcmp(buf, "XCHGL\tAX,0(SP)") != 0) + return; + *spoff += 4; +} + static int -i386unwind(Map *map, Regs *regs, ulong *next) +i386unwind(Map *map, Regs *regs, ulong *next, Symbol *sym) { - int isp, ipc, ibp; - ulong bp; + int i, isp, ipc, ibp, havebp, n, spoff, off[9]; + ulong pc; u32int v; + char buf[60], *p; - /* No symbol information, use frame pointer and do the best we can. */ +//print("i386unwind %s\n", sym ? sym->name : nil); isp = windindex("SP"); ipc = windindex("PC"); ibp = windindex("BP"); @@ -144,19 +167,85 @@ i386unwind(Map *map, Regs *regs, ulong *next) return -1; } - bp = next[ibp]; + /* + * Disassemble entry to figure out + * where values have been saved. + * Perhaps should disassemble exit path + * instead -- a random walk on the code + * should suffice to get us to a RET. + */ + if(sym){ + pc = sym->loc.addr; +//print("startpc %lux\n", pc); + memset(off, 0xff, sizeof off); + spoff = 0; + havebp = 0; + for(;;){ + if((n = i386das(map, pc, 0, buf, sizeof buf)) < 0) + break; +//print("%s\n", buf); + pc += n; + if(strncmp(buf, "PUSHL\t", 6) == 0){ + spoff += 4; + if((i = windindex(buf+6)) >= 0) + off[i] = spoff; + }else if(strcmp(buf, "MOVL\tSP,BP") == 0 && spoff == 4 && off[ibp] == 4){ + havebp = 1; + }else if(strncmp(buf, "SUBL\t$", 6) == 0){ + if((p = strrchr(buf, ',')) && strcmp(p, ",SP") == 0){ +//print("spoff %s\n", buf+6); + spoff += strtol(buf+6, 0, 16); + } + break; + }else if(strncmp(buf, "XORL\t", 5) == 0 || strncmp(buf, "MOVL\t", 5) == 0){ + /* + * Hope these are rescheduled non-prologue instructions + * like XORL AX, AX or MOVL $0x3, AX and thus ignorable. + */ + }else + break; + } - if(get4(map, bp, &v) < 0) - return -1; - next[ibp] = v; + syscallhack(map, regs, &spoff); - next[isp] = bp+4; + if(havebp){ +//print("havebp\n"); + rget(regs, "BP", &next[isp]); + get4(map, next[isp], &v); + next[ibp] = v; + next[isp] += 4; + }else{ + rget(regs, "SP", &next[isp]); +//print("old sp %lux + %d\n", next[isp], spoff); + next[isp] += spoff; + } + for(i=0; i %lux\n", next[isp], v); + next[ipc] = v; + next[isp] += 4; + return 0; + } + + /* + * Rely on bp chaining + */ + if(rget(regs, "BP", &next[isp]) < 0 + || get4(map, next[isp], &v) < 0) return -1; + next[ibp] = v; + next[isp] += 4; + if(get4(map, next[isp], &v) < 0) + return -1; next[ipc] = v; - - return 0; + next[isp] += 4; + return 0; } //static char STARTSYM[] = "_main"; @@ -1766,8 +1855,10 @@ pea(Instr *ip) else { if (ip->base < 0) immediate(ip, ip->disp); - else + else { + bprint(ip, "%lux", ip->disp); bprint(ip,"(%s%s)", ANAME(ip), reg[(uchar)ip->base]); + } } if (ip->index >= 0) bprint(ip,"(%s%s*%d)", ANAME(ip), reg[(uchar)ip->index], 1<ss); blob - c704be7f1d96b1af9bc13f437eab5d2c8fc51a45 blob + 6191721639fbfad9683a44d0560f4ed7b2e7e8e4 --- src/libmach/machpower.c +++ src/libmach/machpower.c @@ -1337,7 +1337,7 @@ static char *powerwindregs[] = }; static int -powerunwind(Map *map, Regs *regs, ulong *next) +powerunwind(Map *map, Regs *regs, ulong *next, Symbol *sym) { /* * This is tremendously hard. The best we're going to blob - 77426436b9b0feb7b5961250416458ffaba7cdef blob + 8ebe03744e10597c62416a480943723755fe956e --- src/libmach/mkfile +++ src/libmach/mkfile @@ -4,6 +4,7 @@ LIB=libmach.a OFILES=\ $SYSNAME.$O\ + cmdline.$O\ crack.$O\ crackelf.$O\ crackmacho.$O\ @@ -17,6 +18,7 @@ OFILES=\ dwarfpc.$O\ dwarfpubnames.$O\ elf.$O\ + elfdl386.$O\ elfcorefreebsd386.$O\ elfcorelinux386.$O\ frame.$O\ @@ -57,6 +59,13 @@ dwarfdump: dwarfdump.o $LIBDIR/$LIB nm: nm.o $LIBDIR/$LIB $LD -o $target $prereq -l9 +t: t.o $LIBDIR/$LIB + $LD -o $target $prereq -l9 -lthread_db + +elfnm: elfnm.o $LIBDIR/$LIB + $LD -o $target $prereq -l9 + + SunOS.$O: nosys.c Darwin.$O: nosys.c OpenBSD.$O: nosys.c blob - b734957f39c3d05b35e9336e1106f95565a06b9d blob + a5cf0314116b2122a7f5b1a30e1c65f27824f14a --- src/libmach/sym.c +++ src/libmach/sym.c @@ -50,6 +50,23 @@ _delhdr(Fhdr *h) h->next = nil; } +Fhdr* +findhdr(char *name) +{ + int len, plen; + Fhdr *p; + + len = strlen(name); + for(p=fhdrlist; p; p=p->next){ + plen = strlen(p->filename); + if(plen >= len) + if(strcmp(p->filename+plen-len, name) == 0) + if(plen == len || p->filename[plen-len-1] == '/') + return p; + } + return nil; +} + int pc2file(ulong pc, char *file, uint nfile, ulong *line) { @@ -354,14 +371,14 @@ findlsym(Symbol *s1, Loc loc, Symbol *s2) } int -unwindframe(Map *map, Regs *regs, ulong *next) +unwindframe(Map *map, Regs *regs, ulong *next, Symbol *sym) { Fhdr *p; for(p=fhdrlist; p; p=p->next) - if(p->unwind && p->unwind(p, map, regs, next) >= 0) + if(p->unwind && p->unwind(p, map, regs, next, sym) >= 0) return 0; - if(mach->unwind && mach->unwind(map, regs, next) >= 0) + if(mach->unwind && mach->unwind(map, regs, next, sym) >= 0) return 0; return -1; } blob - eeafa8dccb8bc755aac55f482ffa3ab7242e896b blob + 3ac1257759627739c2cfeedab87f45bd82d4fb02 --- src/libmach/symdwarf.c +++ src/libmach/symdwarf.c @@ -13,7 +13,7 @@ static int dwarfindexlsym(Fhdr*, Symbol*, uint, Symbol static int dwarffindlsym(Fhdr*, Symbol*, Loc, Symbol*); static void dwarfsyminit(Fhdr*); static int dwarftosym(Fhdr*, Dwarf*, DwarfSym*, Symbol*, int); -static int _dwarfunwind(Fhdr *fhdr, Map *map, Regs *regs, ulong *next); +static int _dwarfunwind(Fhdr *fhdr, Map *map, Regs *regs, ulong *next, Symbol*); int symdwarf(Fhdr *hdr) @@ -396,7 +396,7 @@ dwarfexprfmt(Fmt *fmt) #endif static int -_dwarfunwind(Fhdr *fhdr, Map *map, Regs *regs, ulong *next) +_dwarfunwind(Fhdr *fhdr, Map *map, Regs *regs, ulong *next, Symbol *sym) { char *name; int i, j; blob - 7babbd496997724635fa29c7c29951b6a8e26eb5 blob + 0b9f410e1c85e7817f709ed5c0731b115a93b8f0 --- src/libmach/symelf.c +++ src/libmach/symelf.c @@ -53,6 +53,7 @@ elfsyminit(Fhdr *fp) p = &elf->prog[i]; if(p->type != ElfProgDynamic) continue; + elf->dynamic = p->vaddr; memset(&sym, 0, sizeof sym); sym.name = "_DYNAMIC"; sym.loc = locaddr(p->vaddr); @@ -65,6 +66,23 @@ elfsyminit(Fhdr *fp) } int +elfsymlookup(Elf *elf, char *name, ulong *addr) +{ + int i; + ElfSym esym; + + for(i=0; elfsym(elf, i, &esym) >= 0; i++){ + if(esym.name == nil) + continue; + if(strcmp(esym.name, name) == 0){ + *addr = esym.value; + return 0; + } + } + return -1; +} + +int symelf(Fhdr *fhdr) { int ret; blob - 961ef6d093d7b18d1c04e721dfdfbde3294a6c72 blob + f5f9a474adf261869b609e0e1013ebc71ddd3c10 --- src/libmach/ureg386.h +++ src/libmach/ureg386.h @@ -29,6 +29,7 @@ struct UregLinux386 ulong ecx; ulong edx; ulong esi; + ulong edi; ulong ebp; ulong eax; ulong xds; @@ -43,3 +44,5 @@ struct UregLinux386 ulong xss; }; +Ureg *_linux2ureg386(UregLinux386*); +