Blob


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>
9 typedef struct Ptprog Ptprog;
10 struct Pprog
11 {
12 Pthread *t;
13 uint nt;
14 };
16 typedef struct Pthread Pthread;
17 struct Pthread
18 {
19 td_thrhandle_t handle;
20 };
22 void
23 pthreadattach(int pid)
24 {
26 }
28 void pthreadattach()
29 set up mapping
31 Regs *pthreadregs()
32 int npthread();
36 static int td_get_allthreads(td_thragent_t*, td_thrhandle_t**);
37 static int terr(int);
40 Regs*
41 threadregs()
42 {
44 }
48 typedef struct AllThread AllThread;
49 struct AllThread
50 {
51 td_thrhandle_t *a;
52 int n;
53 int err;
54 };
56 static int
57 thritercb(const td_thrhandle_t *th, void *cb)
58 {
59 td_thrhandle_t **p;
60 AllThread *a;
61 int n;
63 a = cb;
64 if((a->n&(a->n-1)) == 0){
65 if(a->n == 0)
66 n = 1;
67 else
68 n = a->n<<1;
69 if((p = realloc(a->a, n*sizeof a->a[0])) == 0){
70 a->err = -1;
71 return -1; /* stop iteration */
72 }
73 a->a = p;
74 }
75 a->a[a->n++] = *th;
76 return 0;
77 }
79 int
80 td_get_allthreads(td_thragent_t *ta, td_thrhandle_t **pall)
81 {
82 int e;
83 AllThread a;
85 a.a = nil;
86 a.n = 0;
87 a.err = 0;
88 if((e = td_ta_thr_iter(ta, thritercb, &a,
89 TD_THR_ANY_STATE,
90 TD_THR_LOWEST_PRIORITY,
91 TD_SIGNO_MASK,
92 TD_THR_ANY_USER_FLAGS)) != TD_OK){
93 werrstr("%s", terr(e));
94 return -1;
95 }
97 if(a.err){
98 free(a.a);
99 return -1;
102 *pall = a.a;
103 return a.n;
106 static char *tderrstr[] =
108 [TD_OK] "no error",
109 [TD_ERR] "some error",
110 [TD_NOTHR] "no matching thread found",
111 [TD_NOSV] "no matching synchronization handle found",
112 [TD_NOLWP] "no matching light-weight process found",
113 [TD_BADPH] "invalid process handle",
114 [TD_BADTH] "invalid thread handle",
115 [TD_BADSH] "invalid synchronization handle",
116 [TD_BADTA] "invalid thread agent",
117 [TD_BADKEY] "invalid key",
118 [TD_NOMSG] "no event available",
119 [TD_NOFPREGS] "no floating-point register content available",
120 [TD_NOLIBTHREAD] "application not linked with thread library",
121 [TD_NOEVENT] "requested event is not supported",
122 [TD_NOEVENT] "requested event is not supported",
123 [TD_NOCAPAB] "capability not available",
124 [TD_DBERR] "internal debug library error",
125 [TD_NOAPLIC] "operation is not applicable",
126 [TD_NOTSD] "no thread-specific data available",
127 [TD_MALLOC] "out of memory",
128 [TD_PARTIALREG] "not entire register set was read or written",
129 [TD_NOXREGS] "X register set not available for given threads",
130 [TD_TLSDEFER] "thread has not yet allocated TLS for given module",
131 [TD_VERSION] "version mismatch twixt libpthread and libthread_db",
132 [TD_NOTLS] "there is no TLS segment in the given module",
133 };
135 static char*
136 terr(int e)
138 static char buf[50];
140 if(e < 0 || e >= nelem(tderrstr) || tderrstr[e] == nil){
141 snprint(buf, sizeof buf, "thread err %d", e);
142 return buf;
144 return tderrstr[e];
147 /*
148 * bottom-end functions for libthread_db to call
149 */
150 enum
152 PS_OK,
153 PS_ERR,
154 PS_BADPID,
155 PS_BADLWPID,
156 PS_BADADDR,
157 PS_NOSYM,
158 PS_NOFPREGS,
159 };
161 pid_t
162 ps_getpid(struct ps_prochandle *ph)
164 return ph->pid;
167 int
168 ps_pstop(const struct ps_prochandle *ph)
170 return PS_ERR;
173 int
174 ps_pcontinue(const struct ps_prochandle *ph)
176 return PS_ERR;
179 int
180 ps_lstop(const struct ps_prochandle *ph)
182 return PS_ERR;
185 int
186 ps_lcontinue(const struct ps_prochandle *ph)
188 return PS_ERR;
191 /* read/write data or text memory */
192 int
193 ps_pdread(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz)
195 if(get1(ph->map, addr, v, sz) < 0)
196 return PS_ERR;
197 return PS_OK;
200 int
201 ps_pdwrite(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz)
203 if(put1(ph->map, addr, v, sz) < 0)
204 return PS_ERR;
205 return PS_OK;
208 int
209 ps_ptread(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz)
211 return ps_pdread(ph, addr, v, sz);
214 int
215 ps_ptwrite(struct ps_prochandle *ph, psaddr_t addr, void *v, size_t sz)
217 return ps_pdwrite(ph, addr, v, sz);
220 int
221 ps_lgetregs(struct ps_prochandle *ph, lwpid_t lwp, prgregset_t regs)
223 int i;
225 USED(ph);
226 if(corhdr == nil)
227 return sys_ps_lgetregs(ph, lwp, regs);
228 for(i=0; i<corhdr->nthread; i++){
229 if(corhdr->thread[i].id == lwp){
230 ureg2prgregset(corhdr->thread[i].ureg, regs);
231 return PS_OK;
234 return PS_ERR;
237 int
238 ps_lsetregs(struct ps_prochandle *ph, lwpid_t lwp, prgregset_t regs)
240 if(corhdr == nil)
241 return sys_ps_lsetregs(ph, lwp, regs);
242 return PS_ERR;
245 int
246 ps_lgetfpregs(struct ps_prochandle *ph, lwpid_t lwp, prfpregset_t *fpregs)
248 if(corhdr == nil)
249 return sys_ps_lgetfpregs(ph, lwp, fpregs);
250 /* BUG - Look in core dump. */
251 return PS_ERR:
254 int
255 ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t lwp, prfpregset_t *fpregs)
257 if(corhdr == nil)
258 return sys_ps_lsetfpregs(ph, lwp, fpregs);
259 return PS_ERR;
262 /* Fetch the special per-thread address associated with the given LWP.
263 This call is only used on a few platforms (most use a normal register).
264 The meaning of the `int' parameter is machine-dependent. */
265 int
266 ps_get_thread_area(struct ps_prochandle *ph, lwpid_t lwp, int xxx, psaddr_t *addr)
268 return sys_ps_get_thread_area(ph, lwp, xxx, addr);
271 int
272 ps_pglobal_lookup(struct ps_prochandle *ph, char *object_name, char *sym_name, psaddr_t *sym_addr)
274 Fhdr *fp;
275 ulong addr;
277 if((fp = findhdr(object_name)) == nil){
278 print("libmach pthread: lookup %d %s %s => no such hdr\n", ph->pid, object_name, sym_name);
279 return PS_NOSYM;
281 if(elfsymlookup(fp->elf, sym_name, &addr) < 0){
282 print("libmach pthread: lookup %d %s %s => name not found\n", ph->pid, object_name, sym_name);
283 return PS_NOSYM;
285 /* print("libmach pthread: lookup %d %s %s => 0x%lux\n", ph->pid, object_name, sym_name, addr); */
286 *sym_addr = (void*)(addr+fp->base);
287 return PS_OK;