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