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 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 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 83 thread_free_all_states (Dwfl_Thread *thread) 84 { 85 while (thread->unwound) 86 state_free (thread->unwound); 87 } 88 89 static Dwfl_Frame * 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 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 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 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 } 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 } 232 INTDEF(dwfl_pid) 233 234 Dwfl * 235 dwfl_thread_dwfl (Dwfl_Thread *thread) 236 { 237 return thread->process->dwfl; 238 } 239 INTDEF(dwfl_thread_dwfl) 240 241 pid_t 242 dwfl_thread_tid (Dwfl_Thread *thread) 243 { 244 return thread->tid; 245 } 246 INTDEF(dwfl_thread_tid) 247 248 Dwfl_Thread * 249 dwfl_frame_thread (Dwfl_Frame *state) 250 { 251 return state->thread; 252 } 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 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 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 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 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 } 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