Blame


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