commit e8a7b9699925f3f650593d07eb382155e9374ae6 from: rsc date: Mon Dec 27 17:01:23 2004 UTC more features commit - 2189e55cde473b2a81492759526f824b0ecd227e commit + e8a7b9699925f3f650593d07eb382155e9374ae6 blob - /dev/null blob + 3d0753543811002fc671ba0427fd1b71be186f69 (mode 644) --- /dev/null +++ src/libmach/cmdline.c @@ -0,0 +1,187 @@ +#include +#include +#include + +Fhdr *symhdr; +Fhdr *corhdr; +char *symfil; +char *corfil; +int corpid; +Regs *correg; +Map *symmap; +Map *cormap; + +int +alldigs(char *s) +{ + while(*s){ + if(*s<'0' || '9'<*s) + return 0; + s++; + } + return 1; +} + +/* + * attach to arguments in argc, argv + */ +int +attachargs(int argc, char **argv, int omode) +{ + int i; + Fhdr *hdr; + char *s; + + symhdr = nil; + corhdr = nil; + symfil = nil; + corfil = nil; + corpid = 0; + correg = nil; + + for(i=0; ianame, hdr->mname, hdr->fname); + if(hdr->ftype == FCORE){ + if(corpid){ + fprint(2, "already have corpid %d; ignoring core %s\n", corpid, argv[i]); + uncrackhdr(hdr); + continue; + } + if(corhdr){ + fprint(2, "already have core %s; ignoring core %s\n", corfil, argv[i]); + uncrackhdr(hdr); + continue; + } + corhdr = hdr; + corfil = argv[i]; + }else{ + if(symhdr){ + fprint(2, "already have text %s; ignoring text %s\n", symfil, argv[i]); + uncrackhdr(hdr); + continue; + } + symhdr = hdr; + symfil = argv[i]; + } + } + + if(symhdr == nil){ + symfil = "a.out"; /* default */ + if(corpid){ /* try from corpid */ + if((s = proctextfile(corpid)) != nil){ + fprint(2, "corpid %d: text %s\n", corpid, s); + 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((symhdr = crackhdr(symfil, omode)) == nil){ + fprint(2, "crackhdr %s: %r\n", symfil); + symfil = nil; + } + } + + if(symhdr) + syminit(symhdr); + + if(!mach) + mach = machcpu; + + /* + * Set up maps + */ + symmap = allocmap(); + cormap = allocmap(); + if(symmap == nil || cormap == nil) + sysfatal("allocating maps: %r"); + + if(symhdr){ + if(mapfile(symhdr, 0, symmap, nil) < 0) + fprint(2, "mapfile %s: %r\n", symfil); + mapfile(symhdr, 0, cormap, nil); + } + + if(corpid) + attachproc(corpid); + + if(corhdr) + attachcore(corhdr); + + return 0; +} + +static int thecorpid; +static Fhdr *thecorhdr; + +static void +unattach(void) +{ + unmapproc(cormap); + unmapfile(corhdr, cormap); + free(correg); + correg = nil; + thecorpid = 0; + thecorhdr = nil; + corpid = 0; + corhdr = nil; + corfil = nil; +} + +int +attachproc(int pid) +{ + unattach(); + if(pid == 0) + return 0; + if(mapproc(pid, cormap, &correg) < 0){ + fprint(2, "attachproc %d: %r\n", pid); + return -1; + } + thecorpid = pid; + corpid = pid; + return 0; +} + +int +attachcore(Fhdr *hdr) +{ + unattach(); + if(corhdr == nil) + return 0; + if(mapfile(hdr, 0, cormap, &correg) < 0){ + fprint(2, "attachcore %s: %r\n", hdr->filename); + return -1; + } + thecorhdr = hdr; + corhdr = hdr; + corfil = hdr->filename; + return 0; +} + +int +attachdynamic(void) +{ + elfdl386mapdl(); + return 0; +} + blob - /dev/null blob + 104e5a95c36d4464e940ad2ae56cfd03f7ff47f5 (mode 644) --- /dev/null +++ src/libmach/elfdl386.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include "elf.h" + +/* +aggr Linkdebug +{ + 'X' 0 version; + 'X' 4 map; +}; + +aggr Linkmap +{ + 'X' 0 addr; + 'X' 4 name; + 'X' 8 dynsect; + 'X' 12 next; + 'X' 16 prev; +}; +*/ +enum +{ + DT_NULL = 0, + DT_NEEDED, + DT_PLTRRELSZ, + DT_PLTGOT, + DT_HASH, + DT_STRTAB, + DT_SYMTAB, + DT_RELA, + DT_RELASZ = 8, + DT_RELAENT, + DT_STSZ, + DT_SYMENT, + DT_INIT, + DT_FINI, + DT_SONAME, + DT_RPATH, + DT_SYMBOLIC = 16, + DT_REL, + DT_RELSZ, + DT_RELENT, + DT_PLTREL, + DT_DEBUG, + DT_TEXTREL, + DT_JMPREL, +}; + +static int +getstr(Map *map, ulong addr, char *buf, uint nbuf) +{ + int i; + + for(i=0; ielf)->dynamic) == 0){ + fprint(2, "no hdr/dynamic %p\n", hdr); + return 0; + } + addr += hdr->base; + + while(addr != 0){ + if(get4(cormap, addr, &u) < 0) + return 0; + if(u == x){ + if(get4(cormap, addr+4, &u) < 0) + return 0; + return u; + } + addr += 8; + } + return 0; +} + +void +elfdl386mapdl(void) +{ + 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; + } + if(get4(cormap, linkdebug+4, &linkmap) < 0){ + fprint(2, "get4 linkdebug+4 (0x%lux) failed\n", linkdebug); + return; + } + + for(i=0; i<100 && linkmap != 0; i++){ + if(get4(cormap, linkmap, &addr) < 0 + || get4(cormap, linkmap+4, &name) < 0 + || 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(syminit(hdr) < 0) + fprint(2, "syminit %s: %\r", buf); + } + } + } +} + blob - /dev/null blob + 9e6d1eac0ed0f14293567084831f6ec5f9ef4e23 (mode 644) --- /dev/null +++ src/libmach/elfnm.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +void +usage(void) +{ + fprint(2, "usage: elfnm file...\n"); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + ElfSym esym; + Fhdr *fp; + int i, j; + + ARGBEGIN{ + default: + usage(); + }ARGEND + + if(argc == 0) + usage(); + + for(i=0; ielf, j, &esym)>=0; j++) + print("%s 0x%lux\n", esym.name, esym.value); + uncrackhdr(fp); + } + exits(0); +} blob - /dev/null blob + 46eca4f2ed36b7aa59538df7d291b64614b3fbe9 (mode 644) --- /dev/null +++ src/libmach/pthread.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include /* psaddr_t */ +#include +#include + +static char *tderrstr[] = +{ +[TD_OK] "no error", +[TD_ERR] "some error", +[TD_NOTHR] "no matching thread found", +[TD_NOSV] "no matching synchronization handle found", +[TD_NOLWP] "no matching light-weight process found", +[TD_BADPH] "invalid process handle", +[TD_BADTH] "invalid thread handle", +[TD_BADSH] "invalid synchronization handle", +[TD_BADTA] "invalid thread agent", +[TD_BADKEY] "invalid key", +[TD_NOMSG] "no event available", +[TD_NOFPREGS] "no floating-point register content available", +[TD_NOLIBTHREAD] "application not linked with thread library", +[TD_NOEVENT] "requested event is not supported", +[TD_NOEVENT] "requested event is not supported", +[TD_NOCAPAB] "capability not available", +[TD_DBERR] "internal debug library error", +[TD_NOAPLIC] "operation is not applicable", +[TD_NOTSD] "no thread-specific data available", +[TD_MALLOC] "out of memory", +[TD_PARTIALREG] "not entire register set was read or written", +[TD_NOXREGS] "X register set not available for given threads", +[TD_TLSDEFER] "thread has not yet allocated TLS for given module", +[TD_VERSION] "version mismatch twixt libpthread and libthread_db", +[TD_NOTLS] "there is no TLS segment in the given module", +}; + +static char* +terr(int e) +{ + static char buf[50]; + + if(e < 0 || e >= nelem(tderrstr) || tderrstr[e] == nil){ + snprint(buf, sizeof buf, "thread err %d", e); + return buf; + } + return tderrstr[e]; +} + blob - /dev/null blob + d11cb7dda39229692e949dace288c200ec1a4dfb (mode 644) --- /dev/null +++ src/libmach/t.c @@ -0,0 +1,269 @@ +#include +#include +#include +#include +#include /* psaddr_t */ +#include +#include +#include "ureg386.h" + +int td_get_allthreads(td_thragent_t *ta, td_thrhandle_t **pall); + +static char *tderrstr[] = +{ +[TD_OK] "no error", +[TD_ERR] "some error", +[TD_NOTHR] "no matching thread found", +[TD_NOSV] "no matching synchronization handle found", +[TD_NOLWP] "no matching light-weight process found", +[TD_BADPH] "invalid process handle", +[TD_BADTH] "invalid thread handle", +[TD_BADSH] "invalid synchronization handle", +[TD_BADTA] "invalid thread agent", +[TD_BADKEY] "invalid key", +[TD_NOMSG] "no event available", +[TD_NOFPREGS] "no floating-point register content available", +[TD_NOLIBTHREAD] "application not linked with thread library", +[TD_NOEVENT] "requested event is not supported", +[TD_NOEVENT] "requested event is not supported", +[TD_NOCAPAB] "capability not available", +[TD_DBERR] "internal debug library error", +[TD_NOAPLIC] "operation is not applicable", +[TD_NOTSD] "no thread-specific data available", +[TD_MALLOC] "out of memory", +[TD_PARTIALREG] "not entire register set was read or written", +[TD_NOXREGS] "X register set not available for given threads", +[TD_TLSDEFER] "thread has not yet allocated TLS for given module", +[TD_VERSION] "version mismatch twixt libpthread and libthread_db", +[TD_NOTLS] "there is no TLS segment in the given module", +}; + +static char* +terr(int e) +{ + static char buf[50]; + + if(e < 0 || e >= nelem(tderrstr) || tderrstr[e] == nil){ + snprint(buf, sizeof buf, "thread err %d", e); + return buf; + } + return tderrstr[e]; +} + +void +usage(void) +{ + fprint(2, "usage: t pid\n"); + exits("usage"); +} + +#define STRINGSZ 128 + +/* + * print the value of dot as file:line + */ +void +printsource(long dot) +{ + char str[STRINGSZ]; + + if (fileline(dot, str, STRINGSZ) >= 0) + print("%s", str); +} + +void +printlocals(Symbol *fn, Regs *regs) +{ + int i; + u32int v; + Symbol s; + + for (i = 0; indexlsym(fn, i, &s)>=0; i++) { + if (s.class != CAUTO) + continue; + if(lget4(cormap, regs, s.loc, &v) >= 0) + print("\t%s.%s/\t%#lux\n", fn->name, s.name, v); + else + print("\t%s.%s/\t?\n", fn->name, s.name); + } +} + +void +printparams(Symbol *fn, Regs *regs) +{ + int i; + Symbol s; + u32int v; + int first = 0; + ulong pc, sp, bp; + + if(0) print("pc=%lux sp=%lux bp=%lux ", + (rget(regs, "PC", &pc), pc), + (rget(regs, "SP", &sp), sp), + (rget(regs, "BP", &bp), bp)); + for (i = 0; indexlsym(fn, i, &s)>=0; i++) { + if (s.class != CPARAM) + continue; + if (first++) + print(", "); + if(0) print("(%d.%s.%ux.%x)", s.loc.type, s.loc.reg, s.loc.addr, s.loc.offset); + if(lget4(cormap, regs, s.loc, &v) >= 0) + print("%s=%#lux", s.name, v); + else + print("%s=?", s.name); + } +} + +/* + * callback on stack trace + */ +static int +xtrace(Map *map, Regs *regs, ulong pc, ulong nextpc, Symbol *sym, int depth) +{ + char buf[512]; + + USED(map); + print("\t"); + if(sym){ + print("%s(", sym->name); + printparams(sym, regs); + print(")+0x%ux ", pc-sym->loc.addr); + }else + print("%#lux ", pc); + printsource(pc); + + print(" called from "); + symoff(buf, 512, nextpc, CTEXT); + print("%s ", buf); +/* printsource(nextpc); */ + print("\n"); + if(sym) + printlocals(sym, regs); + return depth<40; +} + +void +main(int argc, char **argv) +{ + struct ps_prochandle p; + prgregset_t regs; + int e; + td_thragent_t *ta; + td_thrhandle_t *ts; + td_thrinfo_t info; + int i, n; + Ureg *u; + UregRegs r; + + ARGBEGIN{ + default: + usage(); + }ARGEND + + attachargs(argc, argv, OREAD); + attachdynamic(); + + if(!corpid && !corhdr) + sysfatal("could not attach to process"); + + p.pid = corpid; + if((e = td_ta_new(&p, &ta)) != TD_OK) + sysfatal("td_ta_new: %s", terr(e)); + if((e = td_ta_get_nthreads(ta, &n)) != TD_OK) + sysfatal("td_ta_get_nthreads: %s", terr(e)); + print("%d threads\n", n); + + if((n = td_get_allthreads(ta, &ts)) < 0) + sysfatal("td_get_allthreads: %r"); + print("%d threads - regs = %p\n", n, regs); + for(i=0; in&(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; +} + +/* +td_err_e td_ta_map_id2thr(const td_thragent_t *ta_p, thread_t tid,td_thrhandle_t *th_p); +*/ + +/* +int +threadregs(int tid, Regs **rp) +{ + check pid + look up tid (td_ta_map_id2thr) + create Regs with thr handle inside + rw function calls thr_getregs and then + pulls out the desired register +} + +*/