# include <sys/user.h>
# include <sys/ptrace.h>
#endif
-#include "../libdw/cfi.h"
+#include "libdwflP.h"
#define BACKEND i386_
#include "libebl_CPU.h"
bool
-i386_frame_state (Dwarf_Frame_State *state)
+i386_frame_state (Dwfl_Frame_State *state)
{
if (state->thread->process->core == NULL)
{
if (ptrace (PTRACE_GETREGS, tid, NULL, &user_regs) != 0)
return false;
# if defined __i386__
- dwarf_frame_state_reg_set (state, 0, user_regs.eax);
- dwarf_frame_state_reg_set (state, 1, user_regs.ecx);
- dwarf_frame_state_reg_set (state, 2, user_regs.edx);
- dwarf_frame_state_reg_set (state, 3, user_regs.ebx);
- dwarf_frame_state_reg_set (state, 4, user_regs.esp);
- dwarf_frame_state_reg_set (state, 5, user_regs.ebp);
- dwarf_frame_state_reg_set (state, 6, user_regs.esi);
- dwarf_frame_state_reg_set (state, 7, user_regs.edi);
- dwarf_frame_state_reg_set (state, 8, user_regs.eip);
+ dwfl_frame_state_reg_set (state, 0, user_regs.eax);
+ dwfl_frame_state_reg_set (state, 1, user_regs.ecx);
+ dwfl_frame_state_reg_set (state, 2, user_regs.edx);
+ dwfl_frame_state_reg_set (state, 3, user_regs.ebx);
+ dwfl_frame_state_reg_set (state, 4, user_regs.esp);
+ dwfl_frame_state_reg_set (state, 5, user_regs.ebp);
+ dwfl_frame_state_reg_set (state, 6, user_regs.esi);
+ dwfl_frame_state_reg_set (state, 7, user_regs.edi);
+ dwfl_frame_state_reg_set (state, 8, user_regs.eip);
# elif defined __x86_64__
- dwarf_frame_state_reg_set (state, 0, user_regs.rax);
- dwarf_frame_state_reg_set (state, 1, user_regs.rcx);
- dwarf_frame_state_reg_set (state, 2, user_regs.rdx);
- dwarf_frame_state_reg_set (state, 3, user_regs.rbx);
- dwarf_frame_state_reg_set (state, 4, user_regs.rsp);
- dwarf_frame_state_reg_set (state, 5, user_regs.rbp);
- dwarf_frame_state_reg_set (state, 6, user_regs.rsi);
- dwarf_frame_state_reg_set (state, 7, user_regs.rdi);
- dwarf_frame_state_reg_set (state, 8, user_regs.rip);
+ dwfl_frame_state_reg_set (state, 0, user_regs.rax);
+ dwfl_frame_state_reg_set (state, 1, user_regs.rcx);
+ dwfl_frame_state_reg_set (state, 2, user_regs.rdx);
+ dwfl_frame_state_reg_set (state, 3, user_regs.rbx);
+ dwfl_frame_state_reg_set (state, 4, user_regs.rsp);
+ dwfl_frame_state_reg_set (state, 5, user_regs.rbp);
+ dwfl_frame_state_reg_set (state, 6, user_regs.rsi);
+ dwfl_frame_state_reg_set (state, 7, user_regs.rdi);
+ dwfl_frame_state_reg_set (state, 8, user_regs.rip);
# else /* (__i386__ || __x86_64__) && (!__i386__ && !__x86_64__) */
# error
# endif /* (__i386__ || __x86_64__) && (!__i386__ && !__x86_64__) */
-/* Fetch live process Dwarf_Frame_State from PID.
+/* Fetch live process Dwfl_Frame_State from PID.
Copyright (C) 2012 Red Hat, Inc.
This file is part of elfutils.
# include <sys/user.h>
# include <sys/ptrace.h>
#endif
-#include "../libdw/cfi.h"
+#include "libdwflP.h"
#define BACKEND ppc_
#include "libebl_CPU.h"
__attribute__ ((alias ("ppc_frame_dwarf_to_regno")));
bool
-ppc_frame_state (Dwarf_Frame_State *state)
+ppc_frame_state (Dwfl_Frame_State *state)
{
- Dwarf_Frame_State_Thread *thread = state->thread;
- Dwarf_Frame_State_Process *process = thread->process;
+ Dwfl_Frame_State_Thread *thread = state->thread;
+ Dwfl_Frame_State_Process *process = thread->process;
Ebl *ebl = process->ebl;
Elf *core = process->core;
if (core == NULL)
}
for (unsigned gpr = 0;
gpr < sizeof (user_regs.r.gpr) / sizeof (*user_regs.r.gpr); gpr++)
- dwarf_frame_state_reg_set (state, gpr, user_regs.r.gpr[gpr]);
+ dwfl_frame_state_reg_set (state, gpr, user_regs.r.gpr[gpr]);
state->pc = user_regs.r.nip;
- state->pc_state = DWARF_FRAME_STATE_PC_SET;
- dwarf_frame_state_reg_set (state, 65, user_regs.r.link); // or 108
+ state->pc_state = DWFL_FRAME_STATE_PC_SET;
+ dwfl_frame_state_reg_set (state, 65, user_regs.r.link); // or 108
/* Registers like msr, ctr, xer, dar, dsisr etc. are probably irrelevant
for CFI. */
#endif /* __powerpc__ */
if (! core_get_pc (core, &state->pc,
ebl->class == ELFCLASS64 ? 0x170 : 0xc8))
return false;
- state->pc_state = DWARF_FRAME_STATE_PC_SET;
+ state->pc_state = DWFL_FRAME_STATE_PC_SET;
}
return true;
}
-/* Fetch live process Dwarf_Frame_State from PID.
+/* Fetch live process Dwfl_Frame_State from PID.
Copyright (C) 2012 Red Hat, Inc.
This file is part of elfutils.
# include <asm/ptrace.h>
# include <sys/ptrace.h>
#endif
-#include "../libdw/cfi.h"
+#include "libdwflP.h"
#define BACKEND s390_
#include "libebl_CPU.h"
#include "core-get-pc.c"
bool
-s390_frame_state (Dwarf_Frame_State *state)
+s390_frame_state (Dwfl_Frame_State *state)
{
- Dwarf_Frame_State_Thread *thread = state->thread;
- Dwarf_Frame_State_Process *process = thread->process;
+ Dwfl_Frame_State_Thread *thread = state->thread;
+ Dwfl_Frame_State_Process *process = thread->process;
Ebl *ebl = process->ebl;
Elf *core = process->core;
if (core == NULL)
*((const __typeof (*state->regs) *)
&user_regs.regs.fp_regs.fprs[u]));
state->pc = user_regs.regs.psw.addr;
- state->pc_state = DWARF_FRAME_STATE_PC_SET;
+ state->pc_state = DWFL_FRAME_STATE_PC_SET;
#endif /* __s390__ */
}
else /* core */
if (! core_get_pc (core, &state->pc,
ebl->class == ELFCLASS32 ? 0x4c : 0x78))
return false;
- state->pc_state = DWARF_FRAME_STATE_PC_SET;
+ state->pc_state = DWFL_FRAME_STATE_PC_SET;
}
return true;
}
void
s390_normalize_pc (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr *pc)
{
- if (ebl->class != ELFCLASS32)
- return;
+ assert (ebl->class == ELFCLASS32);
+
/* Clear S390 bit 31. */
*pc &= (1U << 31) - 1;
}
#endif
#include <stdlib.h>
-#include "../libdwfl/libdwfl.h"
#include <assert.h>
-#include "../libdw/cfi.h"
+#include "libdwflP.h"
#define BACKEND s390_
#include "libebl_CPU.h"
bool
-s390_frame_unwind (Ebl *ebl, Dwarf_Frame_State **statep, Dwarf_Addr pc,
- bool (*memory_read) (Dwarf_Frame_State_Process *process,
+s390_frame_unwind (Ebl *ebl, Dwfl_Frame_State **statep, Dwarf_Addr pc,
+ bool (*memory_read) (Dwfl_Frame_State_Process *process,
Dwarf_Addr addr, Dwarf_Addr *result))
{
- Dwarf_Frame_State *state = *statep;
- Dwarf_Frame_State_Process *process = state->thread->process;
+ Dwfl_Frame_State *state = *statep;
+ Dwfl_Frame_State_Process *process = state->thread->process;
assert (state->unwound == NULL);
/* Caller already assumed caller adjustment but S390 instructions are 4 bytes
long. Undo it. */
/* See GDB s390_sigtramp_frame_unwind_cache. */
# define S390_SP_REGNUM (0 + 15) /* S390_R15_REGNUM */
Dwarf_Addr this_sp;
- if (! dwarf_frame_state_reg_get (state, S390_SP_REGNUM, &this_sp))
+ if (! dwfl_frame_state_reg_get (state, S390_SP_REGNUM, &this_sp))
return false;
unsigned word_size = ebl->class == ELFCLASS64 ? 8 : 4;
Dwarf_Addr next_cfa = this_sp + 16 * word_size + 32;
return false;
sigreg_ptr += word_size;
size_t nregs = ebl->frame_state_nregs;
- Dwarf_Frame_State *unwound;
+ Dwfl_Frame_State *unwound;
unwound = malloc (sizeof (*unwound) + sizeof (*unwound->regs) * nregs);
state->unwound = unwound;
unwound->thread = state->thread;
unwound->unwound = NULL;
unwound->pc = val;
- unwound->pc_state = DWARF_FRAME_STATE_ERROR;
+ unwound->pc_state = DWFL_FRAME_STATE_ERROR;
memset (unwound->regs_set, 0, sizeof (unwound->regs_set));
unwound->signal_frame = true;
/* Then the GPRs. */
{
if (! memory_read (process, sigreg_ptr, &val))
return false;
- if (! dwarf_frame_state_reg_set (unwound, 0 + i, val))
+ if (! dwfl_frame_state_reg_set (unwound, 0 + i, val))
return false;
sigreg_ptr += word_size;
}
return false;
val = (val << 32) | val_low;
}
- if (! dwarf_frame_state_reg_set (unwound, 16 + i, val))
+ if (! dwfl_frame_state_reg_set (unwound, 16 + i, val))
return false;
sigreg_ptr += 8;
}
if (! memory_read (process, sigreg_ptr, &val))
return false;
Dwarf_Addr val_low;
- if (! dwarf_frame_state_reg_get (unwound, 0 + i, &val_low))
+ if (! dwfl_frame_state_reg_get (unwound, 0 + i, &val_low))
return false;
val = (val << 32) | val_low;
- if (! dwarf_frame_state_reg_set (unwound, 0 + i, val))
+ if (! dwfl_frame_state_reg_set (unwound, 0 + i, val))
return false;
sigreg_ptr += 4;
}
}
- unwound->pc_state = DWARF_FRAME_STATE_PC_SET;
+ unwound->pc_state = DWFL_FRAME_STATE_PC_SET;
*statep = unwound;
return true;
}
unwinding. */
eh->frame_state_nregs = 32;
HOOK (eh, frame_state);
- HOOK (eh, normalize_pc);
+ if (eh->class == ELFCLASS32)
+ HOOK (eh, normalize_pc);
HOOK (eh, frame_unwind);
/* Only the 64-bit format uses the incorrect hash table entry size. */
-/* Fetch live process Dwarf_Frame_State from PID.
+/* Fetch live process Dwfl_Frame_State from PID.
Copyright (C) 2012 Red Hat, Inc.
This file is part of elfutils.
# include <sys/user.h>
# include <sys/ptrace.h>
#endif
-#include "../libdw/cfi.h"
+#include "libdwflP.h"
#define BACKEND x86_64_
#include "libebl_CPU.h"
bool
-x86_64_frame_state (Dwarf_Frame_State *state)
+x86_64_frame_state (Dwfl_Frame_State *state)
{
if (state->thread->process->core == NULL)
{
struct user_regs_struct user_regs;
if (ptrace (PTRACE_GETREGS, tid, NULL, &user_regs) != 0)
return false;
- dwarf_frame_state_reg_set (state, 0, user_regs.rax);
- dwarf_frame_state_reg_set (state, 1, user_regs.rdx);
- dwarf_frame_state_reg_set (state, 2, user_regs.rcx);
- dwarf_frame_state_reg_set (state, 3, user_regs.rbx);
- dwarf_frame_state_reg_set (state, 4, user_regs.rsi);
- dwarf_frame_state_reg_set (state, 5, user_regs.rdi);
- dwarf_frame_state_reg_set (state, 6, user_regs.rbp);
- dwarf_frame_state_reg_set (state, 7, user_regs.rsp);
- dwarf_frame_state_reg_set (state, 8, user_regs.r8);
- dwarf_frame_state_reg_set (state, 9, user_regs.r9);
- dwarf_frame_state_reg_set (state, 10, user_regs.r10);
- dwarf_frame_state_reg_set (state, 11, user_regs.r11);
- dwarf_frame_state_reg_set (state, 12, user_regs.r12);
- dwarf_frame_state_reg_set (state, 13, user_regs.r13);
- dwarf_frame_state_reg_set (state, 14, user_regs.r14);
- dwarf_frame_state_reg_set (state, 15, user_regs.r15);
- dwarf_frame_state_reg_set (state, 16, user_regs.rip);
+ dwfl_frame_state_reg_set (state, 0, user_regs.rax);
+ dwfl_frame_state_reg_set (state, 1, user_regs.rdx);
+ dwfl_frame_state_reg_set (state, 2, user_regs.rcx);
+ dwfl_frame_state_reg_set (state, 3, user_regs.rbx);
+ dwfl_frame_state_reg_set (state, 4, user_regs.rsi);
+ dwfl_frame_state_reg_set (state, 5, user_regs.rdi);
+ dwfl_frame_state_reg_set (state, 6, user_regs.rbp);
+ dwfl_frame_state_reg_set (state, 7, user_regs.rsp);
+ dwfl_frame_state_reg_set (state, 8, user_regs.r8);
+ dwfl_frame_state_reg_set (state, 9, user_regs.r9);
+ dwfl_frame_state_reg_set (state, 10, user_regs.r10);
+ dwfl_frame_state_reg_set (state, 11, user_regs.r11);
+ dwfl_frame_state_reg_set (state, 12, user_regs.r12);
+ dwfl_frame_state_reg_set (state, 13, user_regs.r13);
+ dwfl_frame_state_reg_set (state, 14, user_regs.r14);
+ dwfl_frame_state_reg_set (state, 15, user_regs.r15);
+ dwfl_frame_state_reg_set (state, 16, user_regs.rip);
#endif /* __x86_64__ */
}
return true;
#include <stdbool.h>
#include <stdint.h>
-#include "../libebl/libebl.h"
+#include <libebl.h>
/* Opaque type for the assembler context descriptor. */
#include "libdwP.h"
#include "libelfP.h"
-#include "../libebl/libeblP.h"
struct ebl;
-#include <assert.h>
/* Cached CIE representation. */
struct dwarf_cie
struct dwarf_frame_register regs[];
};
-/* This holds information common for all the frames of one backtrace. */
-struct Dwarf_Frame_State_Process
-{
- Dwarf_Frame_State_Process *next;
- struct Dwfl *dwfl;
- struct ebl *ebl;
- /* If it is false we share EBL with one of DWFL's Dwfl_Module->ebl. */
- bool ebl_close : 1;
- /* If there is no core file both CORE is NULL and CORE_FD is -1. */
- Elf *core;
- int core_fd;
- Dwarf_Frame_State_Thread *thread;
-};
-
-struct Dwarf_Frame_State_Thread
-{
- Dwarf_Frame_State_Process *process;
- Dwarf_Frame_State_Thread *next;
- /* If there is no TID it is 0. */
- pid_t tid;
- bool tid_attached : 1;
- /* Bottom frame. */
- Dwarf_Frame_State *unwound;
-};
-
-/* This holds everything we know about the state of the frame at a particular
- PC location described by an FDE. */
-struct Dwarf_Frame_State
-{
- Dwarf_Frame_State_Thread *thread;
- /* Previous (outer) frame. */
- Dwarf_Frame_State *unwound;
- bool signal_frame : 1;
- enum
- {
- /* This structure is still being initialized or there was an error
- initializing it. */
- DWARF_FRAME_STATE_ERROR,
- /* PC field is valid. */
- DWARF_FRAME_STATE_PC_SET,
- /* PC field is undefined, this means the next (inner) frame was the
- outermost frame. */
- DWARF_FRAME_STATE_PC_UNDEFINED
- } pc_state;
- /* Either initialized from appropriate REGS element or on some archs
- initialized separately as the return address has no DWARF register. */
- Dwarf_Addr pc;
- /* (1 << X) bitmask where 0 <= X < NREGS. */
- uint64_t regs_set[3];
- /* REGS array size is ebl_frame_state_nregs (base->ebl). */
- Dwarf_Addr regs[];
-};
-
-/* Fetch value from Dwarf_Frame_State->regs indexed by DWARF REGNO.
- No error code is set if the function returns FALSE. */
-static inline bool
-dwarf_frame_state_reg_get (Dwarf_Frame_State *state, unsigned regno,
- Dwarf_Addr *val)
-{
- Ebl *ebl = state->thread->process->ebl;
- if (ebl->frame_dwarf_to_regno != NULL
- && ! ebl->frame_dwarf_to_regno (ebl, ®no))
- return false;
- if (regno >= ebl->frame_state_nregs)
- return false;
- if ((state->regs_set[regno / sizeof (*state->regs_set) / 8]
- & (1U << (regno % (sizeof (*state->regs_set) * 8)))) == 0)
- return false;
- if (val)
- *val = state->regs[regno];
- return true;
-}
-
-/* Store value to Dwarf_Frame_State->regs indexed by DWARF REGNO.
- No error code is set if the function returns FALSE. */
-static inline bool
-dwarf_frame_state_reg_set (Dwarf_Frame_State *state, unsigned regno,
- Dwarf_Addr val)
-{
- Ebl *ebl = state->thread->process->ebl;
- if (ebl->frame_dwarf_to_regno != NULL
- && ! ebl->frame_dwarf_to_regno (ebl, ®no))
- return false;
- if (regno >= ebl->frame_state_nregs)
- return false;
- /* For example i386 user_regs_struct has signed fields. */
- if (ebl->class == ELFCLASS32)
- val &= 0xffffffff;
- state->regs_set[regno / sizeof (*state->regs_set) / 8] |=
- (1U << (regno % (sizeof (*state->regs_set) * 8)));
- state->regs[regno] = val;
- return true;
-}
-
/* Clean up the data structure and all it points to. */
extern void __libdw_destroy_frame_cache (Dwarf_CFI *cache)
/* Opaque type representing a frame state described by CFI. */
typedef struct Dwarf_Frame_s Dwarf_Frame;
-typedef struct Dwarf_Frame_State_Process Dwarf_Frame_State_Process;
-typedef struct Dwarf_Frame_State_Thread Dwarf_Frame_State_Thread;
-typedef struct Dwarf_Frame_State Dwarf_Frame_State;
-
/* Opaque type representing a CFI section found in a DWARF or ELF file. */
typedef struct Dwarf_CFI_s Dwarf_CFI;
not, see <http://www.gnu.org/licenses/>. */
#include "libdwflP.h"
-#include "../libdw/cfi.h"
#include <unistd.h>
#include <sys/ptrace.h>
return;
/* FIXME: Unify with dwfl_frame_state.c. */
- Dwarf_Frame_State_Process *process = dwfl->framestatelist;
+ Dwfl_Frame_State_Process *process = dwfl->framestatelist;
while (process != NULL)
{
- Dwarf_Frame_State_Thread *thread = process->thread;
+ Dwfl_Frame_State_Thread *thread = process->thread;
while (thread != NULL)
{
if (thread->tid_attached)
ptrace (PTRACE_DETACH, thread->tid, NULL, NULL);
- Dwarf_Frame_State *state = thread->unwound;
+ Dwfl_Frame_State *state = thread->unwound;
while (state != NULL)
{
- Dwarf_Frame_State *dead = state;
+ Dwfl_Frame_State *dead = state;
state = state->unwound;
free (dead);
}
- Dwarf_Frame_State_Thread *dead = thread;
+ Dwfl_Frame_State_Thread *dead = thread;
thread = thread->next;
free (dead);
}
elf_end (process->core);
if (process->core_fd != -1)
close (process->core_fd);
- Dwarf_Frame_State_Process *dead = process;
+ Dwfl_Frame_State_Process *dead = process;
process = process->next;
free (dead);
}
not, see <http://www.gnu.org/licenses/>. */
#include "libdwflP.h"
-#include "../libdw/cfi.h"
#include <fcntl.h>
#include <unistd.h>
#include <sys/ptrace.h>
static bool
tid_is_attached (Dwfl *dwfl, pid_t tid)
{
- for (Dwarf_Frame_State_Process *process = dwfl->framestatelist; process;
+ for (Dwfl_Frame_State_Process *process = dwfl->framestatelist; process;
process = process->next)
- for (Dwarf_Frame_State_Thread *thread = process->thread; thread;
+ for (Dwfl_Frame_State_Thread *thread = process->thread; thread;
thread = thread->next)
if (thread->tid_attached && thread->tid == tid)
return true;
}
static bool
-state_fetch_pc (Dwarf_Frame_State *state)
+state_fetch_pc (Dwfl_Frame_State *state)
{
switch (state->pc_state)
{
- case DWARF_FRAME_STATE_PC_SET:
+ case DWFL_FRAME_STATE_PC_SET:
return true;
- case DWARF_FRAME_STATE_PC_UNDEFINED:
+ case DWFL_FRAME_STATE_PC_UNDEFINED:
abort ();
- case DWARF_FRAME_STATE_ERROR:;
+ case DWFL_FRAME_STATE_ERROR:;
Ebl *ebl = state->thread->process->ebl;
Dwarf_CIE abi_info;
if (ebl_abi_cfi (ebl, &abi_info) != 0)
return false;
}
state->pc = state->regs[ra];
- state->pc_state = DWARF_FRAME_STATE_PC_SET;
+ state->pc_state = DWFL_FRAME_STATE_PC_SET;
return true;
}
abort ();
/* Do not call it on your own, to be used by thread_* functions only. */
static void
-state_free (Dwarf_Frame_State *state)
+state_free (Dwfl_Frame_State *state)
{
- Dwarf_Frame_State_Thread *thread = state->thread;
+ Dwfl_Frame_State_Thread *thread = state->thread;
assert (thread->unwound == state);
thread->unwound = state->unwound;
free (state);
/* Do not call it on your own, to be used by thread_* functions only. */
-static Dwarf_Frame_State *
-state_alloc (Dwarf_Frame_State_Thread *thread)
+static Dwfl_Frame_State *
+state_alloc (Dwfl_Frame_State_Thread *thread)
{
assert (thread->unwound == NULL);
Ebl *ebl = thread->process->ebl;
size_t nregs = ebl_frame_state_nregs (ebl);
if (nregs == 0)
return NULL;
- assert (nregs < sizeof (((Dwarf_Frame_State *) NULL)->regs_set) * 8);
- Dwarf_Frame_State *state = malloc (sizeof (*state)
+ assert (nregs < sizeof (((Dwfl_Frame_State *) NULL)->regs_set) * 8);
+ Dwfl_Frame_State *state = malloc (sizeof (*state)
+ sizeof (*state->regs) * nregs);
if (state == NULL)
return NULL;
state->thread = thread;
state->signal_frame = false;
- state->pc_state = DWARF_FRAME_STATE_ERROR;
+ state->pc_state = DWFL_FRAME_STATE_ERROR;
memset (state->regs_set, 0, sizeof (state->regs_set));
thread->unwound = state;
state->unwound = NULL;
}
static void
-thread_free (Dwarf_Frame_State_Thread *thread)
+thread_free (Dwfl_Frame_State_Thread *thread)
{
while (thread->unwound)
state_free (thread->unwound);
if (thread->tid_attached)
ptrace (PTRACE_DETACH, thread->tid, NULL, NULL);
- Dwarf_Frame_State_Process *process = thread->process;
+ Dwfl_Frame_State_Process *process = thread->process;
assert (process->thread == thread);
process->thread = thread->next;
free (thread);
/* One state_alloc is called automatically. */
-static Dwarf_Frame_State_Thread *
-thread_alloc (Dwarf_Frame_State_Process *process, pid_t tid)
+static Dwfl_Frame_State_Thread *
+thread_alloc (Dwfl_Frame_State_Process *process, pid_t tid)
{
- Dwarf_Frame_State_Thread *thread = malloc (sizeof (*thread));
+ Dwfl_Frame_State_Thread *thread = malloc (sizeof (*thread));
if (thread == NULL)
return NULL;
thread->process = process;
}
static void
-process_free (Dwarf_Frame_State_Process *process)
+process_free (Dwfl_Frame_State_Process *process)
{
while (process->thread)
thread_free (process->thread);
free (process);
}
-static Dwarf_Frame_State_Process *
+static Dwfl_Frame_State_Process *
process_alloc (Dwfl *dwfl)
{
- Dwarf_Frame_State_Process *process = malloc (sizeof (*process));
+ Dwfl_Frame_State_Process *process = malloc (sizeof (*process));
if (process == NULL)
return NULL;
process->dwfl = dwfl;
return true;
}
-Dwarf_Frame_State *
+Dwfl_Frame_State *
dwfl_frame_state_pid (Dwfl *dwfl, pid_t pid)
{
char dirname[64];
int i = snprintf (dirname, sizeof (dirname), "/proc/%ld/task", (long) pid);
assert (i > 0 && i < (ssize_t) sizeof (dirname) - 1);
- Dwarf_Frame_State_Process *process = process_alloc (dwfl);
+ Dwfl_Frame_State_Process *process = process_alloc (dwfl);
if (process == NULL)
return NULL;
for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
__libdwfl_seterrno (DWFL_E_UNKNOWN_ERROR);
return NULL;
}
- Dwarf_Frame_State_Thread *thread = thread_alloc (process, tid);
+ Dwfl_Frame_State_Thread *thread = thread_alloc (process, tid);
if (thread == NULL)
{
process_free (process);
}
thread->tid_attached = true;
}
- Dwarf_Frame_State *state = thread->unwound;
+ Dwfl_Frame_State *state = thread->unwound;
if (! ebl_frame_state (state) || ! state_fetch_pc (state))
{
thread_free (thread);
/* Fetch inferior registers from a core file. */
-Dwarf_Frame_State *
+Dwfl_Frame_State *
dwfl_frame_state_core (Dwfl *dwfl, const char *corefile)
{
- Dwarf_Frame_State_Process *process = process_alloc (dwfl);
+ Dwfl_Frame_State_Process *process = process_alloc (dwfl);
if (process == NULL)
return NULL;
int core_fd = open64 (corefile, O_RDONLY);
__libdwfl_seterrno (DWFL_E_LIBELF);
return NULL;
}
- Dwarf_Frame_State_Thread *thread = NULL;
+ Dwfl_Frame_State_Thread *thread = NULL;
for (size_t cnt = 0; cnt < phnum; ++cnt)
{
GElf_Phdr phdr_mem, *phdr = gelf_getphdr (core, cnt, &phdr_mem);
{
/* Delay initialization of THREAD till all notes for it have
been read in. */
- Dwarf_Frame_State *state = thread->unwound;
+ Dwfl_Frame_State *state = thread->unwound;
if (! ebl_frame_state (state) || ! state_fetch_pc (state))
{
thread_free (thread);
/* Ignore notes before first PR_NTSTATUS. */
continue;
}
- Dwarf_Frame_State *state = thread->unwound;
+ Dwfl_Frame_State *state = thread->unwound;
desc += regs_offset;
for (size_t regloci = 0; regloci < nregloc; regloci++)
{
CFI which clashes with register 108 (LR) we need.
LR (108) is provided earlier (in NT_PRSTATUS) than the # 65.
FIXME: It depends now on their order in core notes. */
- if (dwarf_frame_state_reg_get (state, regno, NULL))
+ if (dwfl_frame_state_reg_get (state, regno, NULL))
continue;
Dwarf_Addr val;
switch (regloc->bits)
return NULL;
}
/* Registers not valid for CFI are just ignored. */
- dwarf_frame_state_reg_set (state, regno, val);
+ dwfl_frame_state_reg_set (state, regno, val);
reg_desc += regloc->pad;
}
}
{
/* Delay initialization of THREAD till all notes for it have been read
in. */
- Dwarf_Frame_State *state = thread->unwound;
+ Dwfl_Frame_State *state = thread->unwound;
if (! ebl_frame_state (state) || ! state_fetch_pc (state))
thread_free (thread);
}
}
INTDEF (dwfl_frame_state_core)
-Dwarf_Frame_State *
-dwfl_frame_thread_next (Dwarf_Frame_State *state)
+Dwfl_Frame_State *
+dwfl_frame_thread_next (Dwfl_Frame_State *state)
{
- Dwarf_Frame_State_Thread *thread_next = state->thread->next;
+ Dwfl_Frame_State_Thread *thread_next = state->thread->next;
return thread_next ? thread_next->unwound : NULL;
}
INTDEF (dwfl_frame_thread_next)
pid_t
-dwfl_frame_tid_get (Dwarf_Frame_State *state)
+dwfl_frame_tid_get (Dwfl_Frame_State *state)
{
return state->thread->tid;
}
# include <config.h>
#endif
-#include "../libdw/cfi.h"
-#include "../libebl/libebl.h"
#include "libdwflP.h"
bool
-dwfl_frame_state_pc (Dwarf_Frame_State *state, Dwarf_Addr *pc, bool *minusone)
+dwfl_frame_state_pc (Dwfl_Frame_State *state, Dwarf_Addr *pc, bool *minusone)
{
- assert (state->pc_state == DWARF_FRAME_STATE_PC_SET);
+ assert (state->pc_state == DWFL_FRAME_STATE_PC_SET);
*pc = state->pc;
ebl_normalize_pc (state->thread->process->ebl, pc);
if (minusone)
}
static bool
-state_get_reg (Dwarf_Frame_State *state, unsigned regno, Dwarf_Addr *val)
+state_get_reg (Dwfl_Frame_State *state, unsigned regno, Dwarf_Addr *val)
{
- if (! dwarf_frame_state_reg_get (state, regno, val))
+ if (! dwfl_frame_state_reg_get (state, regno, val))
{
__libdwfl_seterrno (DWFL_E_UNKNOWN_ERROR);
return false;
}
static bool
-memory_read (Dwarf_Frame_State_Process *process, Dwarf_Addr addr,
+memory_read (Dwfl_Frame_State_Process *process, Dwarf_Addr addr,
Dwarf_Addr *result)
{
if (process->core == NULL)
/* FIXME: Handle bytecode deadlocks and overflows. */
static bool
-expr_eval (Dwarf_Frame_State *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
+expr_eval (Dwfl_Frame_State *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
size_t nops, Dwarf_Addr *result)
{
if (nops == 0)
(and call __libdwfl_seterrno) otherwise. */
static bool
-have_unwound (Dwarf_Frame_State **statep)
+have_unwound (Dwfl_Frame_State **statep)
{
- Dwarf_Frame_State *state = *statep, *unwound = state->unwound;
+ Dwfl_Frame_State *state = *statep, *unwound = state->unwound;
switch (unwound->pc_state)
{
- case DWARF_FRAME_STATE_ERROR:
+ case DWFL_FRAME_STATE_ERROR:
__libdwfl_seterrno (DWFL_E_UNKNOWN_ERROR);
*statep = NULL;
return false;
- case DWARF_FRAME_STATE_PC_SET:
+ case DWFL_FRAME_STATE_PC_SET:
*statep = unwound;
return true;
- case DWARF_FRAME_STATE_PC_UNDEFINED:
+ case DWFL_FRAME_STATE_PC_UNDEFINED:
*statep = NULL;
return true;
}
an undefined PC register (due to an error unwinding it). */
static bool
-handle_cfi (Dwarf_Frame_State **statep, Dwarf_Addr pc, Dwfl_Module *mod,
+handle_cfi (Dwfl_Frame_State **statep, Dwarf_Addr pc, Dwfl_Module *mod,
Dwarf_CFI *cfi, Dwarf_Addr bias)
{
- Dwarf_Frame_State *state = *statep;
+ Dwfl_Frame_State *state = *statep;
Dwarf_Frame *frame;
if (INTUSE(dwarf_cfi_addrframe) (cfi, pc - bias, &frame) != 0)
{
int dw_errno = dwarf_errno ();
- if (dw_errno == DWARF_E_NO_MATCH)
+ if (dw_errno == DWFL_E_NO_MATCH)
{
if (! no_fde (pc, mod, bias))
return false;
__libdwfl_seterrno (DWFL_E_LIBDW);
return false;
}
- Dwarf_Frame_State_Thread *thread = state->thread;
- Dwarf_Frame_State_Process *process = thread->process;
+ Dwfl_Frame_State_Thread *thread = state->thread;
+ Dwfl_Frame_State_Process *process = thread->process;
Ebl *ebl = process->ebl;
size_t nregs = ebl_frame_state_nregs (ebl);
- Dwarf_Frame_State *unwound;
+ Dwfl_Frame_State *unwound;
unwound = malloc (sizeof (*unwound) + sizeof (*unwound->regs) * nregs);
state->unwound = unwound;
unwound->thread = thread;
unwound->unwound = NULL;
unwound->signal_frame = frame->fde->cie->signal_frame;
- unwound->pc_state = DWARF_FRAME_STATE_ERROR;
+ unwound->pc_state = DWFL_FRAME_STATE_ERROR;
memset (unwound->regs_set, 0, sizeof (unwound->regs_set));
for (unsigned regno = 0; regno < nregs; regno++)
{
/* REGNO is undefined. */
unsigned ra = frame->fde->cie->return_address_register;
if (ebl_frame_dwarf_to_regno (ebl, &ra) && regno == ra)
- unwound->pc_state = DWARF_FRAME_STATE_PC_UNDEFINED;
+ unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
continue;
}
else if (reg_ops == NULL)
But PPC32 does not use such registers. */
continue;
}
- if (! dwarf_frame_state_reg_set (unwound, regno, regval))
+ if (! dwfl_frame_state_reg_set (unwound, regno, regval))
{
__libdwfl_seterrno (DWFL_E_UNKNOWN_ERROR);
continue;
}
}
- if (unwound->pc_state == DWARF_FRAME_STATE_ERROR
- && dwarf_frame_state_reg_get (unwound,
- frame->fde->cie->return_address_register,
- &unwound->pc))
+ if (unwound->pc_state == DWFL_FRAME_STATE_ERROR
+ && dwfl_frame_state_reg_get (unwound,
+ frame->fde->cie->return_address_register,
+ &unwound->pc))
{
/* PPC32 __libc_start_main properly CFI-unwinds PC as zero. Currently
none of the archs supported for unwinding have zero as a valid PC. */
if (unwound->pc == 0)
- unwound->pc_state = DWARF_FRAME_STATE_PC_UNDEFINED;
+ unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
else
- unwound->pc_state = DWARF_FRAME_STATE_PC_SET;
+ unwound->pc_state = DWFL_FRAME_STATE_PC_SET;
}
return have_unwound (statep);
}
bool
-dwfl_frame_unwind (Dwarf_Frame_State **statep)
+dwfl_frame_unwind (Dwfl_Frame_State **statep)
{
- Dwarf_Frame_State *state = *statep;
+ Dwfl_Frame_State *state = *statep;
if (state->unwound)
return have_unwound (statep);
Dwarf_Addr pc;
return true;
if (state->unwound)
{
- assert (state->unwound->pc_state == DWARF_FRAME_STATE_ERROR);
+ assert (state->unwound->pc_state == DWFL_FRAME_STATE_ERROR);
return false;
}
}
return true;
if (state->unwound)
{
- assert (state->unwound->pc_state == DWARF_FRAME_STATE_ERROR);
+ assert (state->unwound->pc_state == DWFL_FRAME_STATE_ERROR);
return false;
}
}
return true;
if (state->unwound)
{
- assert (state->unwound->pc_state == DWARF_FRAME_STATE_ERROR);
+ assert (state->unwound->pc_state == DWFL_FRAME_STATE_ERROR);
return false;
}
__libdwfl_seterrno (DWFL_E_NO_DWARF);
/* Handle describing a line record. */
typedef struct Dwfl_Line Dwfl_Line;
+/* This holds everything we know about the state of the frame at a particular
+ PC location described by an FDE. */
+typedef struct Dwfl_Frame_State Dwfl_Frame_State;
+
/* Callbacks. */
typedef struct
{
/* Get innermost frame of first thread of live process PID. Returns NULL on
failure. */
-extern Dwarf_Frame_State *dwfl_frame_state_pid (Dwfl *dwfl, pid_t pid);
+extern Dwfl_Frame_State *dwfl_frame_state_pid (Dwfl *dwfl, pid_t pid);
/* Get innermost frame of first thread of core file COREFILE. Returns NULL on
failure. */
-extern Dwarf_Frame_State *dwfl_frame_state_core (Dwfl *dwfl,
- const char *corefile);
+extern Dwfl_Frame_State *dwfl_frame_state_core (Dwfl *dwfl,
+ const char *corefile);
/* Return TRUE and update *STATEP for the unwound frame for successful unwind.
Return TRUE and set *STATEP to NULL for the outermost frame. Return FALSE
(and call __libdwfl_seterrno) otherwise. */
-extern bool dwfl_frame_unwind (Dwarf_Frame_State **statep);
+extern bool dwfl_frame_unwind (Dwfl_Frame_State **statep);
/* Get return address register value for frame. Return TRUE if *PC set and
optionally *MINUSONE is also set, if MINUSONE is not NULL. Return FALSE
(and call __libdw_seterrno) otherwise. *MINUSONE is TRUE for normal calls
where *PC should be decremented by one to get the call instruction, it is
FALSE if this frame was interrupted by a signal handler. */
-extern bool dwfl_frame_state_pc (Dwarf_Frame_State *state, Dwarf_Addr *pc,
+extern bool dwfl_frame_state_pc (Dwfl_Frame_State *state, Dwarf_Addr *pc,
bool *minusone);
/* Get innermost frame of the next thread from STATE. STATE can be any frame
of (the previous) thread. */
-extern Dwarf_Frame_State *dwfl_frame_thread_next (Dwarf_Frame_State *state);
+extern Dwfl_Frame_State *dwfl_frame_thread_next (Dwfl_Frame_State *state);
/* Get Task ID of the thread of STATE. This is PID for the thread started by
function main and gettid () for the other threads. */
-extern pid_t dwfl_frame_tid_get (Dwarf_Frame_State *state);
+extern pid_t dwfl_frame_tid_get (Dwfl_Frame_State *state);
#ifdef __cplusplus
}
#include <string.h>
#include "../libdw/libdwP.h" /* We need its INTDECLs. */
+#include "../libebl/libeblP.h"
+
+typedef struct Dwfl_Frame_State_Process Dwfl_Frame_State_Process;
+typedef struct Dwfl_Frame_State_Thread Dwfl_Frame_State_Thread;
/* gettext helper macros. */
#define _(Str) dgettext ("elfutils", Str)
Dwfl_Module *modulelist; /* List in order used by full traversals. */
- Dwarf_Frame_State_Process *framestatelist;
+ Dwfl_Frame_State_Process *framestatelist;
GElf_Addr offline_next_address;
bool gc; /* Mark/sweep flag. */
};
+/* This holds information common for all the threads/tasks/TIDs of one process
+ for backtraces. */
+
+struct Dwfl_Frame_State_Process
+{
+ Dwfl_Frame_State_Process *next;
+ struct Dwfl *dwfl;
+ struct ebl *ebl;
+ /* If it is false we share EBL with one of DWFL's Dwfl_Module->ebl. */
+ bool ebl_close : 1;
+ /* If there is no core file both CORE is NULL and CORE_FD is -1. */
+ Elf *core;
+ int core_fd;
+ Dwfl_Frame_State_Thread *thread;
+};
+
+/* This holds information common for all the frames of one backtrace for
+ a partical thread/task/TID. */
+
+struct Dwfl_Frame_State_Thread
+{
+ Dwfl_Frame_State_Process *process;
+ Dwfl_Frame_State_Thread *next;
+ /* If there is no TID it is 0. */
+ pid_t tid;
+ bool tid_attached : 1;
+ /* Bottom frame. */
+ Dwfl_Frame_State *unwound;
+};
+
+/* See its typedef in libdwfl.h. */
+
+struct Dwfl_Frame_State
+{
+ Dwfl_Frame_State_Thread *thread;
+ /* Previous (outer) frame. */
+ Dwfl_Frame_State *unwound;
+ bool signal_frame : 1;
+ enum
+ {
+ /* This structure is still being initialized or there was an error
+ initializing it. */
+ DWFL_FRAME_STATE_ERROR,
+ /* PC field is valid. */
+ DWFL_FRAME_STATE_PC_SET,
+ /* PC field is undefined, this means the next (inner) frame was the
+ outermost frame. */
+ DWFL_FRAME_STATE_PC_UNDEFINED
+ } pc_state;
+ /* Either initialized from appropriate REGS element or on some archs
+ initialized separately as the return address has no DWARF register. */
+ Dwarf_Addr pc;
+ /* (1 << X) bitmask where 0 <= X < NREGS. */
+ uint64_t regs_set[3];
+ /* REGS array size is ebl_frame_state_nregs (base->ebl). */
+ Dwarf_Addr regs[];
+};
+
+/* Fetch value from Dwfl_Frame_State->regs indexed by DWARF REGNO.
+ No error code is set if the function returns FALSE. */
+
+static inline bool
+dwfl_frame_state_reg_get (Dwfl_Frame_State *state, unsigned regno,
+ Dwarf_Addr *val)
+{
+ Ebl *ebl = state->thread->process->ebl;
+ if (ebl->frame_dwarf_to_regno != NULL
+ && ! ebl->frame_dwarf_to_regno (ebl, ®no))
+ return false;
+ if (regno >= ebl->frame_state_nregs)
+ return false;
+ if ((state->regs_set[regno / sizeof (*state->regs_set) / 8]
+ & (1U << (regno % (sizeof (*state->regs_set) * 8)))) == 0)
+ return false;
+ if (val)
+ *val = state->regs[regno];
+ return true;
+}
+
+/* Store value to Dwfl_Frame_State->regs indexed by DWARF REGNO.
+ No error code is set if the function returns FALSE. */
+static inline bool
+dwfl_frame_state_reg_set (Dwfl_Frame_State *state, unsigned regno,
+ Dwarf_Addr val)
+{
+ Ebl *ebl = state->thread->process->ebl;
+ if (ebl->frame_dwarf_to_regno != NULL
+ && ! ebl->frame_dwarf_to_regno (ebl, ®no))
+ return false;
+ if (regno >= ebl->frame_state_nregs)
+ return false;
+ /* For example i386 user_regs_struct has signed fields. */
+ if (ebl->class == ELFCLASS32)
+ val &= 0xffffffff;
+ state->regs_set[regno / sizeof (*state->regs_set) / 8] |=
+ (1U << (regno % (sizeof (*state->regs_set) * 8)));
+ state->regs[regno] = val;
+ return true;
+}
/* Information cached about each CU in Dwfl_Module.dw. */
struct dwfl_cu
##
include $(top_srcdir)/config/eu.am
AM_CFLAGS += -fpic
-INCLUDES += -I$(srcdir)/../libelf -I$(srcdir)/../libdw -I$(srcdir)/../libasm
+INCLUDES += -I$(srcdir)/../libelf -I$(srcdir)/../libdw -I$(srcdir)/../libasm \
+ -I$(srcdir)/../libdwfl
VERSION = 1
LIBEBL_SUBDIR = @LIBEBL_SUBDIR@
GElf_Sym *sym);
/* Fetch process data from STATE->base->pid or STATE->base->core. */
-bool EBLHOOK(frame_state) (Dwarf_Frame_State *state);
+bool EBLHOOK(frame_state) (struct Dwfl_Frame_State *state);
/* Number of Dwarf_Frame_State->regs entries to allocate for frame_state
above. */
/* See dwfl_frame_unwind. */
bool
- EBLHOOK(frame_unwind) (Ebl *ebl, Dwarf_Frame_State **statep, Dwarf_Addr pc,
- bool
- (*memory_read) (Dwarf_Frame_State_Process *process,
- Dwarf_Addr addr,
- Dwarf_Addr *result));
+ EBLHOOK(frame_unwind) (Ebl *ebl, struct Dwfl_Frame_State **statep,
+ Dwarf_Addr pc,
+ bool (*memory_read) (
+ struct Dwfl_Frame_State_Process *process,
+ Dwarf_Addr addr,
+ Dwarf_Addr *result));
/* Destructor for ELF backend handle. */
void EBLHOOK(destr) (struct ebl *);
-/* Fetch live process Dwarf_Frame_State from PID.
+/* Fetch live process Dwfl_Frame_State from PID.
Copyright (C) 2012 Red Hat, Inc.
This file is part of elfutils.
#endif
#include <libeblP.h>
-#include "../libdw/cfi.h"
#include <assert.h>
+#include "libdwflP.h"
bool
-ebl_frame_state (Dwarf_Frame_State *state)
+ebl_frame_state (Dwfl_Frame_State *state)
{
- Dwarf_Frame_State_Process *process = state->thread->process;
+ Dwfl_Frame_State_Process *process = state->thread->process;
Ebl *ebl = process->ebl;
/* Otherwise caller could not allocate STATE of proper size. If FRAME_STATE
is unsupported then FRAME_STATE_NREGS is zero. */
#include <libeblP.h>
bool
-ebl_frame_unwind (Ebl *ebl, Dwarf_Frame_State **statep, Dwarf_Addr pc,
- bool (*memory_read) (Dwarf_Frame_State_Process *process,
+ebl_frame_unwind (Ebl *ebl, Dwfl_Frame_State **statep, Dwarf_Addr pc,
+ bool (*memory_read) (struct Dwfl_Frame_State_Process *process,
Dwarf_Addr addr, Dwarf_Addr *result))
{
if (ebl == NULL || ebl->frame_unwind == NULL)
__nonnull_attribute__ (1, 2, 3);
/* Fetch process data from STATE->base->pid or STATE->base->core. */
-extern bool ebl_frame_state (Dwarf_Frame_State *state)
+struct Dwfl_Frame_State;
+extern bool ebl_frame_state (struct Dwfl_Frame_State *state)
__nonnull_attribute__ (1);
/* Number of registers to allocate for STATE of ebl_frame_state. */
__nonnull_attribute__ (1, 2);
/* Get previous frame state for an existing frame state. */
+struct Dwfl_Frame_State_Process;
extern bool
- ebl_frame_unwind (Ebl *ebl, Dwarf_Frame_State **statep, Dwarf_Addr pc,
- bool (*memory_read) (Dwarf_Frame_State_Process *process,
- Dwarf_Addr addr, Dwarf_Addr *result))
+ ebl_frame_unwind (Ebl *ebl, struct Dwfl_Frame_State **statep, Dwarf_Addr pc,
+ bool
+ (*memory_read) (struct Dwfl_Frame_State_Process *process,
+ Dwarf_Addr addr, Dwarf_Addr *result))
__nonnull_attribute__ (1, 2, 4);
/* Convert *REGNO as is in DWARF to a lower range. */
{
if (pid)
report_pid (dwfl, pid);
- Dwarf_Frame_State *state;
+ Dwfl_Frame_State *state;
if (pid)
state = dwfl_frame_state_pid (dwfl, pid);
else if (corefile)
error (2, 0, "dwfl_frame_state: %s", dwfl_errmsg (-1));
do
{
- Dwarf_Frame_State *thread = state;
+ Dwfl_Frame_State *thread = state;
pid_t tid = dwfl_frame_tid_get (thread);
printf ("TID %ld:\n", (long) tid);
unsigned frameno;
void *data)
{
Dwfl *dwfl;
- Dwarf_Frame_State *state;
+ Dwfl_Frame_State *state;
if (pid && !corefile)
{
dwfl = dwfl_pid (pid);
int err = 0;
do
{
- Dwarf_Frame_State *thread = state;
+ Dwfl_Frame_State *thread = state;
pid_t tid = dwfl_frame_tid_get (thread);
printf ("TID %ld:\n", (long) tid);
unsigned frameno;