tt.c - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tt.c (5664B)
       ---
            1 #include <u.h>
            2 #include <thread_db.h>
            3 #include <sys/ptrace.h>
            4 #include <errno.h>
            5 #include <sys/procfs.h>        /* psaddr_t */
            6 #include <libc.h>
            7 #include <mach.h>
            8 #include "ureg386.h"
            9 
           10 int td_get_allthreads(td_thragent_t *ta, td_thrhandle_t **pall);
           11 
           12 static char *tderrstr[] =
           13 {
           14 [TD_OK]                        "no error",
           15 [TD_ERR]                "some error",
           16 [TD_NOTHR]                "no matching thread found",
           17 [TD_NOSV]                "no matching synchronization handle found",
           18 [TD_NOLWP]                "no matching light-weight process found",
           19 [TD_BADPH]                "invalid process handle",
           20 [TD_BADTH]                "invalid thread handle",
           21 [TD_BADSH]                "invalid synchronization handle",
           22 [TD_BADTA]                "invalid thread agent",
           23 [TD_BADKEY]                "invalid key",
           24 [TD_NOMSG]                "no event available",
           25 [TD_NOFPREGS]        "no floating-point register content available",
           26 [TD_NOLIBTHREAD]        "application not linked with thread library",
           27 [TD_NOEVENT]        "requested event is not supported",
           28 [TD_NOEVENT]        "requested event is not supported",
           29 [TD_NOCAPAB]        "capability not available",
           30 [TD_DBERR]                "internal debug library error",
           31 [TD_NOAPLIC]        "operation is not applicable",
           32 [TD_NOTSD]                "no thread-specific data available",
           33 [TD_MALLOC]                "out of memory",
           34 [TD_PARTIALREG]        "not entire register set was read or written",
           35 [TD_NOXREGS]        "X register set not available for given threads",
           36 [TD_TLSDEFER]        "thread has not yet allocated TLS for given module",
           37 [TD_VERSION]        "version mismatch twixt libpthread and libthread_db",
           38 [TD_NOTLS]                "there is no TLS segment in the given module",
           39 };
           40 
           41 static char*
           42 terr(int e)
           43 {
           44         static char buf[50];
           45 
           46         if(e < 0 || e >= nelem(tderrstr) || tderrstr[e] == nil){
           47                 snprint(buf, sizeof buf, "thread err %d", e);
           48                 return buf;
           49         }
           50         return tderrstr[e];
           51 }
           52 
           53 void
           54 usage(void)
           55 {
           56         fprint(2, "usage: t pid\n");
           57         exits("usage");
           58 }
           59 
           60 #define        STRINGSZ        128
           61 
           62 /*
           63  *        print the value of dot as file:line
           64  */
           65 void
           66 printsource(long dot)
           67 {
           68         char str[STRINGSZ];
           69 
           70         if (fileline(dot, str, STRINGSZ) >= 0)
           71                 print("%s", str);
           72 }
           73 
           74 void
           75 printlocals(Symbol *fn, Regs *regs)
           76 {
           77         int i;
           78         u32int v;
           79         Symbol s;
           80 
           81         for (i = 0; indexlsym(fn, i, &s)>=0; i++) {
           82                 if (s.class != CAUTO)
           83                         continue;
           84                 if(lget4(cormap, regs, s.loc, &v) >= 0)
           85                         print("\t%s.%s/\t%#lux\n", fn->name, s.name, v);
           86                 else
           87                         print("\t%s.%s/\t?\n", fn->name, s.name);
           88         }
           89 }
           90 
           91 void
           92 printparams(Symbol *fn, Regs *regs)
           93 {
           94         int i;
           95         Symbol s;
           96         u32int v;
           97         int first = 0;
           98         ulong pc, sp, bp;
           99 
          100         if(0) print("pc=%lux sp=%lux bp=%lux ",
          101                 (rget(regs, "PC", &pc), pc),
          102                 (rget(regs, "SP", &sp), sp),
          103                 (rget(regs, "BP", &bp), bp));
          104         for (i = 0; indexlsym(fn, i, &s)>=0; i++) {
          105                 if (s.class != CPARAM)
          106                         continue;
          107                 if (first++)
          108                         print(", ");
          109                 if(0) print("(%d.%s.%ux.%x)", s.loc.type, s.loc.reg, s.loc.addr, s.loc.offset);
          110                 if(lget4(cormap, regs, s.loc, &v) >= 0)
          111                         print("%s=%#lux", s.name, v);
          112                 else
          113                         print("%s=?", s.name);
          114         }
          115 }
          116 
          117 /*
          118  *        callback on stack trace
          119  */
          120 static int
          121 xtrace(Map *map, Regs *regs, ulong pc, ulong nextpc, Symbol *sym, int depth)
          122 {
          123         char buf[512];
          124 
          125         USED(map);
          126         print("\t");
          127         if(sym){
          128                 print("%s(", sym->name);
          129                 printparams(sym, regs);
          130                 print(")+0x%ux ", pc-sym->loc.addr);
          131         }else
          132                 print("%#lux ", pc);
          133         printsource(pc);
          134 
          135         print(" called from ");
          136         symoff(buf, 512, nextpc, CTEXT);
          137         print("%s ", buf);
          138 /*        printsource(nextpc); */
          139         print("\n");
          140         if(sym)
          141                 printlocals(sym, regs);
          142         return depth<40;
          143 }
          144 
          145 void
          146 main(int argc, char **argv)
          147 {
          148         struct ps_prochandle p;
          149         prgregset_t regs;
          150         int e;
          151         td_thragent_t *ta;
          152         td_thrhandle_t *ts;
          153         td_thrinfo_t info;
          154         int i, n;
          155         Ureg *u;
          156         UregRegs r;
          157 
          158         ARGBEGIN{
          159         default:
          160                 usage();
          161         }ARGEND
          162 
          163         attachargs(argc, argv, OREAD);
          164         attachdynamic();
          165 
          166 /*        if(!corpid && !corhdr) */
          167 /*                sysfatal("could not attach to process"); */
          168 /* */
          169         p.pid = corpid;
          170         if((e = td_ta_new(&p, &ta)) != TD_OK)
          171                 sysfatal("td_ta_new: %s", terr(e));
          172         if((e = td_ta_get_nthreads(ta, &n)) != TD_OK)
          173                 sysfatal("td_ta_get_nthreads: %s", terr(e));
          174         print("%d threads\n", n);
          175 
          176         if((n = td_get_allthreads(ta, &ts)) < 0)
          177                 sysfatal("td_get_allthreads: %r");
          178         print("%d threads - regs = %p\n", n, regs);
          179         for(i=0; i<n; i++){
          180                 if((e = td_thr_get_info(&ts[i], &info)) != TD_OK)
          181                         sysfatal("td_thr_get_info: %s", terr(e));
          182                 print("%d: startfunc=%lux stkbase=%lux pc=%lux sp=%lux lid=%d\n",
          183                         i, info.ti_startfunc, info.ti_stkbase, info.ti_pc, info.ti_sp, info.ti_lid);
          184                 if((e = td_thr_getgregs(&ts[i], regs)) != TD_OK)
          185                         sysfatal("td_thr_getregs: %s", terr(e));
          186                 print("%d: pc=%lux sp=%lux gs=%lux\n", i, regs[12], regs[15], regs[10]);
          187                 if((u = _linux2ureg386((UregLinux386*)regs)) == nil)
          188                         sysfatal("%r");
          189                 r.r.rw = _uregrw;
          190                 r.ureg = (uchar*)u;
          191                 stacktrace(cormap, &r.r, xtrace);
          192         }
          193         exits(0);
          194 }
          195 
          196 typedef struct AllThread AllThread;
          197 struct AllThread
          198 {
          199         td_thrhandle_t *a;
          200         int n;
          201         int err;
          202 };
          203 
          204 static int
          205 thritercb(const td_thrhandle_t *th, void *cb)
          206 {
          207         td_thrhandle_t **p;
          208         AllThread *a;
          209         int n;
          210 
          211         a = cb;
          212         if((a->n&(a->n-1)) == 0){
          213                 if(a->n == 0)
          214                         n = 1;
          215                 else
          216                         n = a->n<<1;
          217                 if((p = realloc(a->a, n*sizeof a->a[0])) == 0){
          218                         a->err = -1;
          219                         return -1;        /* stop iteration */
          220                 }
          221                 a->a = p;
          222         }
          223         a->a[a->n++] = *th;
          224         return 0;
          225 }
          226 
          227 int
          228 td_get_allthreads(td_thragent_t *ta, td_thrhandle_t **pall)
          229 {
          230         int e;
          231         AllThread a;
          232 
          233         a.a = nil;
          234         a.n = 0;
          235         a.err = 0;
          236         if((e = td_ta_thr_iter(ta, thritercb, &a,
          237                 TD_THR_ANY_STATE,
          238                 TD_THR_LOWEST_PRIORITY,
          239                 TD_SIGNO_MASK,
          240                 TD_THR_ANY_USER_FLAGS)) != TD_OK){
          241                 werrstr("%s", terr(e));
          242                 return -1;
          243         }
          244 
          245         if(a.err){
          246                 free(a.a);
          247                 return -1;
          248         }
          249 
          250         *pall = a.a;
          251         return a.n;
          252 }
          253 
          254 /*
          255 td_err_e td_ta_map_id2thr(const td_thragent_t *ta_p, thread_t tid,td_thrhandle_t *th_p);
          256 */
          257 
          258 /*
          259 int
          260 threadregs(int tid, Regs **rp)
          261 {
          262         check pid
          263         look up tid (td_ta_map_id2thr)
          264         create Regs with thr handle inside
          265         rw function calls thr_getregs and then
          266                 pulls out the desired register
          267 }
          268 
          269 */