1 /* Get Dwarf Frame state for target PID or core file.
2 Copyright (C) 2013, 2014 Red Hat, Inc.
3 This file is part of elfutils.
4
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
7
8 * the GNU Lesser General Public License as published by the Free
9 Software Foundation; either version 3 of the License, or (at
10 your option) any later version
11
12 or
13
14 * the GNU General Public License as published by the Free
15 Software Foundation; either version 2 of the License, or (at
16 your option) any later version
17
18 or both in parallel, as here.
19
20 elfutils is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received copies of the GNU General Public License and
26 the GNU Lesser General Public License along with this program. If
27 not, see <http://www.gnu.org/licenses/>. */
28
29 #ifdef HAVE_CONFIG_H
30 # include <config.h>
31 #endif
32
33 #include "libdwflP.h"
34 #include <unistd.h>
35
36 /* Set STATE->pc_set from STATE->regs according to the backend. Return true on
37 success, false on error. */
38 static bool
state_fetch_pc(Dwfl_Frame * state)39 state_fetch_pc (Dwfl_Frame *state)
40 {
41 switch (state->pc_state)
42 {
43 case DWFL_FRAME_STATE_PC_SET:
44 return true;
45 case DWFL_FRAME_STATE_PC_UNDEFINED:
46 abort ();
47 case DWFL_FRAME_STATE_ERROR:
48 {
49 Ebl *ebl = state->thread->process->ebl;
50 Dwarf_CIE abi_info;
51 if (ebl_abi_cfi (ebl, &abi_info) != 0)
52 {
53 __libdwfl_seterrno (DWFL_E_LIBEBL);
54 return false;
55 }
56 unsigned ra = abi_info.return_address_register;
57 /* dwarf_frame_state_reg_is_set is not applied here. */
58 if (ra >= ebl_frame_nregs (ebl))
59 {
60 __libdwfl_seterrno (DWFL_E_LIBEBL_BAD);
61 return false;
62 }
63 state->pc = state->regs[ra] + ebl_ra_offset (ebl);
64 state->pc_state = DWFL_FRAME_STATE_PC_SET;
65 }
66 return true;
67 }
68 abort ();
69 }
70
71 /* Do not call it on your own, to be used by thread_* functions only. */
72
73 static void
state_free(Dwfl_Frame * state)74 state_free (Dwfl_Frame *state)
75 {
76 Dwfl_Thread *thread = state->thread;
77 assert (thread->unwound == state);
78 thread->unwound = state->unwound;
79 free (state);
80 }
81
82 static void
thread_free_all_states(Dwfl_Thread * thread)83 thread_free_all_states (Dwfl_Thread *thread)
84 {
85 while (thread->unwound)
86 state_free (thread->unwound);
87 }
88
89 static Dwfl_Frame *
state_alloc(Dwfl_Thread * thread)90 state_alloc (Dwfl_Thread *thread)
91 {
92 assert (thread->unwound == NULL);
93 Ebl *ebl = thread->process->ebl;
94 size_t nregs = ebl_frame_nregs (ebl);
95 if (nregs == 0)
96 return NULL;
97 assert (nregs < sizeof (((Dwfl_Frame *) NULL)->regs_set) * 8);
98 Dwfl_Frame *state = malloc (sizeof (*state) + sizeof (*state->regs) * nregs);
99 if (state == NULL)
100 return NULL;
101 state->thread = thread;
102 state->signal_frame = false;
103 state->initial_frame = true;
104 state->pc_state = DWFL_FRAME_STATE_ERROR;
105 memset (state->regs_set, 0, sizeof (state->regs_set));
106 thread->unwound = state;
107 state->unwound = NULL;
108 return state;
109 }
110
111 void
112 internal_function
__libdwfl_process_free(Dwfl_Process * process)113 __libdwfl_process_free (Dwfl_Process *process)
114 {
115 Dwfl *dwfl = process->dwfl;
116 if (process->callbacks->detach != NULL)
117 process->callbacks->detach (dwfl, process->callbacks_arg);
118 assert (dwfl->process == process);
119 dwfl->process = NULL;
120 if (process->ebl_close)
121 ebl_closebackend (process->ebl);
122 free (process);
123 dwfl->attacherr = DWFL_E_NOERROR;
124 }
125
126 /* Allocate new Dwfl_Process for DWFL. */
127 static void
process_alloc(Dwfl * dwfl)128 process_alloc (Dwfl *dwfl)
129 {
130 Dwfl_Process *process = malloc (sizeof (*process));
131 if (process == NULL)
132 return;
133 process->dwfl = dwfl;
134 dwfl->process = process;
135 }
136
137 bool
dwfl_attach_state(Dwfl * dwfl,Elf * elf,pid_t pid,const Dwfl_Thread_Callbacks * thread_callbacks,void * arg)138 dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid,
139 const Dwfl_Thread_Callbacks *thread_callbacks, void *arg)
140 {
141 if (dwfl->process != NULL)
142 {
143 __libdwfl_seterrno (DWFL_E_ATTACH_STATE_CONFLICT);
144 return false;
145 }
146
147 /* Reset any previous error, we are just going to try again. */
148 dwfl->attacherr = DWFL_E_NOERROR;
149 /* thread_callbacks is declared NN */
150 if (thread_callbacks->next_thread == NULL
151 || thread_callbacks->set_initial_registers == NULL)
152 {
153 dwfl->attacherr = DWFL_E_INVALID_ARGUMENT;
154 fail:
155 dwfl->attacherr = __libdwfl_canon_error (dwfl->attacherr);
156 __libdwfl_seterrno (dwfl->attacherr);
157 return false;
158 }
159
160 Ebl *ebl;
161 bool ebl_close;
162 if (elf != NULL)
163 {
164 ebl = ebl_openbackend (elf);
165 ebl_close = true;
166 }
167 else
168 {
169 ebl = NULL;
170 for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
171 {
172 /* Reading of the vDSO or (deleted) modules may fail as
173 /proc/PID/mem is unreadable without PTRACE_ATTACH and
174 we may not be PTRACE_ATTACH-ed now. MOD would not be
175 re-read later to unwind it when we are already
176 PTRACE_ATTACH-ed to PID. This happens when this function
177 is called from dwfl_linux_proc_attach with elf == NULL.
178 __libdwfl_module_getebl will call __libdwfl_getelf which
179 will call the find_elf callback. */
180 if (strncmp (mod->name, "[vdso: ", 7) == 0
181 || strcmp (strrchr (mod->name, ' ') ?: "",
182 " (deleted)") == 0)
183 continue;
184 Dwfl_Error error = __libdwfl_module_getebl (mod);
185 if (error != DWFL_E_NOERROR)
186 continue;
187 ebl = mod->ebl;
188 break;
189 }
190 ebl_close = false;
191 }
192 if (ebl == NULL)
193 {
194 /* Not identified EBL from any of the modules. */
195 dwfl->attacherr = DWFL_E_PROCESS_NO_ARCH;
196 goto fail;
197 }
198 process_alloc (dwfl);
199 Dwfl_Process *process = dwfl->process;
200 if (process == NULL)
201 {
202 if (ebl_close)
203 ebl_closebackend (ebl);
204 dwfl->attacherr = DWFL_E_NOMEM;
205 goto fail;
206 }
207 process->ebl = ebl;
208 process->ebl_close = ebl_close;
209 process->pid = pid;
210 process->callbacks = thread_callbacks;
211 process->callbacks_arg = arg;
212 return true;
213 }
INTDEF(dwfl_attach_state)214 INTDEF(dwfl_attach_state)
215
216 pid_t
217 dwfl_pid (Dwfl *dwfl)
218 {
219 if (dwfl->attacherr != DWFL_E_NOERROR)
220 {
221 __libdwfl_seterrno (dwfl->attacherr);
222 return -1;
223 }
224
225 if (dwfl->process == NULL)
226 {
227 __libdwfl_seterrno (DWFL_E_NO_ATTACH_STATE);
228 return -1;
229 }
230 return dwfl->process->pid;
231 }
INTDEF(dwfl_pid)232 INTDEF(dwfl_pid)
233
234 Dwfl *
235 dwfl_thread_dwfl (Dwfl_Thread *thread)
236 {
237 return thread->process->dwfl;
238 }
INTDEF(dwfl_thread_dwfl)239 INTDEF(dwfl_thread_dwfl)
240
241 pid_t
242 dwfl_thread_tid (Dwfl_Thread *thread)
243 {
244 return thread->tid;
245 }
INTDEF(dwfl_thread_tid)246 INTDEF(dwfl_thread_tid)
247
248 Dwfl_Thread *
249 dwfl_frame_thread (Dwfl_Frame *state)
250 {
251 return state->thread;
252 }
INTDEF(dwfl_frame_thread)253 INTDEF(dwfl_frame_thread)
254
255 int
256 dwfl_getthreads (Dwfl *dwfl, int (*callback) (Dwfl_Thread *thread, void *arg),
257 void *arg)
258 {
259 if (dwfl->attacherr != DWFL_E_NOERROR)
260 {
261 __libdwfl_seterrno (dwfl->attacherr);
262 return -1;
263 }
264
265 Dwfl_Process *process = dwfl->process;
266 if (process == NULL)
267 {
268 __libdwfl_seterrno (DWFL_E_NO_ATTACH_STATE);
269 return -1;
270 }
271
272 Dwfl_Thread thread;
273 thread.process = process;
274 thread.unwound = NULL;
275 thread.callbacks_arg = NULL;
276 for (;;)
277 {
278 thread.tid = process->callbacks->next_thread (dwfl,
279 process->callbacks_arg,
280 &thread.callbacks_arg);
281 if (thread.tid < 0)
282 {
283 Dwfl_Error saved_errno = dwfl_errno ();
284 thread_free_all_states (&thread);
285 __libdwfl_seterrno (saved_errno);
286 return -1;
287 }
288 if (thread.tid == 0)
289 {
290 thread_free_all_states (&thread);
291 __libdwfl_seterrno (DWFL_E_NOERROR);
292 return 0;
293 }
294 int err = callback (&thread, arg);
295 if (err != DWARF_CB_OK)
296 {
297 thread_free_all_states (&thread);
298 return err;
299 }
300 assert (thread.unwound == NULL);
301 }
302 /* NOTREACHED */
303 }
304 INTDEF(dwfl_getthreads)
305
306 struct one_arg
307 {
308 pid_t tid;
309 bool seen;
310 int (*callback) (Dwfl_Thread *thread, void *arg);
311 void *arg;
312 int ret;
313 };
314
315 static int
get_one_thread_cb(Dwfl_Thread * thread,void * arg)316 get_one_thread_cb (Dwfl_Thread *thread, void *arg)
317 {
318 struct one_arg *oa = (struct one_arg *) arg;
319 if (! oa->seen && INTUSE(dwfl_thread_tid) (thread) == oa->tid)
320 {
321 oa->seen = true;
322 oa->ret = oa->callback (thread, oa->arg);
323 return DWARF_CB_ABORT;
324 }
325
326 return DWARF_CB_OK;
327 }
328
329 /* Note not currently exported, will be when there are more Dwfl_Thread
330 properties to query. Use dwfl_getthread_frames for now directly. */
331 static int
getthread(Dwfl * dwfl,pid_t tid,int (* callback)(Dwfl_Thread * thread,void * arg),void * arg)332 getthread (Dwfl *dwfl, pid_t tid,
333 int (*callback) (Dwfl_Thread *thread, void *arg),
334 void *arg)
335 {
336 if (dwfl->attacherr != DWFL_E_NOERROR)
337 {
338 __libdwfl_seterrno (dwfl->attacherr);
339 return -1;
340 }
341
342 Dwfl_Process *process = dwfl->process;
343 if (process == NULL)
344 {
345 __libdwfl_seterrno (DWFL_E_NO_ATTACH_STATE);
346 return -1;
347 }
348
349 if (process->callbacks->get_thread != NULL)
350 {
351 Dwfl_Thread thread;
352 thread.process = process;
353 thread.unwound = NULL;
354 thread.callbacks_arg = NULL;
355
356 if (process->callbacks->get_thread (dwfl, tid, process->callbacks_arg,
357 &thread.callbacks_arg))
358 {
359 int err;
360 thread.tid = tid;
361 err = callback (&thread, arg);
362 thread_free_all_states (&thread);
363 return err;
364 }
365
366 return -1;
367 }
368
369 struct one_arg oa = { .tid = tid, .callback = callback,
370 .arg = arg, .seen = false };
371 int err = INTUSE(dwfl_getthreads) (dwfl, get_one_thread_cb, &oa);
372
373 if (err == DWARF_CB_ABORT && oa.seen)
374 return oa.ret;
375
376 if (err == DWARF_CB_OK && ! oa.seen)
377 {
378 errno = ESRCH;
379 __libdwfl_seterrno (DWFL_E_ERRNO);
380 return -1;
381 }
382
383 return err;
384 }
385
386 struct one_thread
387 {
388 int (*callback) (Dwfl_Frame *frame, void *arg);
389 void *arg;
390 };
391
392 static int
get_one_thread_frames_cb(Dwfl_Thread * thread,void * arg)393 get_one_thread_frames_cb (Dwfl_Thread *thread, void *arg)
394 {
395 struct one_thread *ot = (struct one_thread *) arg;
396 return INTUSE(dwfl_thread_getframes) (thread, ot->callback, ot->arg);
397 }
398
399 int
dwfl_getthread_frames(Dwfl * dwfl,pid_t tid,int (* callback)(Dwfl_Frame * frame,void * arg),void * arg)400 dwfl_getthread_frames (Dwfl *dwfl, pid_t tid,
401 int (*callback) (Dwfl_Frame *frame, void *arg),
402 void *arg)
403 {
404 struct one_thread ot = { .callback = callback, .arg = arg };
405 return getthread (dwfl, tid, get_one_thread_frames_cb, &ot);
406 }
INTDEF(dwfl_getthread_frames)407 INTDEF(dwfl_getthread_frames)
408
409 int
410 dwfl_thread_getframes (Dwfl_Thread *thread,
411 int (*callback) (Dwfl_Frame *state, void *arg),
412 void *arg)
413 {
414 if (thread->unwound != NULL)
415 {
416 /* We had to be called from inside CALLBACK. */
417 __libdwfl_seterrno (DWFL_E_ATTACH_STATE_CONFLICT);
418 return -1;
419 }
420 Ebl *ebl = thread->process->ebl;
421 if (ebl_frame_nregs (ebl) == 0)
422 {
423 __libdwfl_seterrno (DWFL_E_NO_UNWIND);
424 return -1;
425 }
426 if (state_alloc (thread) == NULL)
427 {
428 __libdwfl_seterrno (DWFL_E_NOMEM);
429 return -1;
430 }
431 Dwfl_Process *process = thread->process;
432 if (! process->callbacks->set_initial_registers (thread,
433 thread->callbacks_arg))
434 {
435 thread_free_all_states (thread);
436 return -1;
437 }
438 if (! state_fetch_pc (thread->unwound))
439 {
440 if (process->callbacks->thread_detach)
441 process->callbacks->thread_detach (thread, thread->callbacks_arg);
442 thread_free_all_states (thread);
443 return -1;
444 }
445
446 Dwfl_Frame *state;
447 do
448 {
449 state = thread->unwound;
450 int err = callback (state, arg);
451 if (err != DWARF_CB_OK)
452 {
453 if (process->callbacks->thread_detach)
454 process->callbacks->thread_detach (thread, thread->callbacks_arg);
455 thread_free_all_states (thread);
456 return err;
457 }
458 __libdwfl_frame_unwind (state);
459 /* The old frame is no longer needed. */
460 state_free (thread->unwound);
461 state = thread->unwound;
462 }
463 while (state && state->pc_state == DWFL_FRAME_STATE_PC_SET);
464
465 Dwfl_Error err = dwfl_errno ();
466 if (process->callbacks->thread_detach)
467 process->callbacks->thread_detach (thread, thread->callbacks_arg);
468 if (state == NULL || state->pc_state == DWFL_FRAME_STATE_ERROR)
469 {
470 thread_free_all_states (thread);
471 __libdwfl_seterrno (err);
472 return -1;
473 }
474 assert (state->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED);
475 thread_free_all_states (thread);
476 return 0;
477 }
478 INTDEF(dwfl_thread_getframes)
479