bool
i386_frame_state (Dwfl_Frame_State *state)
{
- if (state->thread->process->core == NULL)
+ pid_t tid = state->thread->tid;
+ if (state->thread->process->core == NULL && tid)
{
#if !defined __i386__ && !defined __x86_64__
return false;
#else /* __i386__ || __x86_64__ */
- pid_t tid = state->thread->tid;
struct user_regs_struct user_regs;
if (ptrace (PTRACE_GETREGS, tid, NULL, &user_regs) != 0)
return false;
Dwfl_Frame_State_Process *process = thread->process;
Ebl *ebl = process->ebl;
Elf *core = process->core;
- if (core == NULL)
+ pid_t tid = thread->tid;
+ if (core == NULL && tid)
{
#ifndef __powerpc__
return false;
#else /* __powerpc__ */
- pid_t tid = thread->tid;
union
{
struct pt_regs r;
for CFI. */
#endif /* __powerpc__ */
}
- else /* core */
+ else if (core)
{
if (! core_get_pc (core, &state->pc,
ebl->class == ELFCLASS64 ? 0x170 : 0xc8))
Dwfl_Frame_State_Process *process = thread->process;
Ebl *ebl = process->ebl;
Elf *core = process->core;
- if (core == NULL)
+ pid_t tid = thread->tid;
+ if (core == NULL && tid)
{
#ifndef __s390__
return false;
#else /* __s390__ */
- pid_t tid = thread->tid;
struct user user_regs;
ptrace_area parea;
parea.process_addr = (uintptr_t) &user_regs;
state->pc_state = DWFL_FRAME_STATE_PC_SET;
#endif /* __s390__ */
}
- else /* core */
+ else if (core)
{
/* Fetch PSWA. */
if (! core_get_pc (core, &state->pc,
bool
x86_64_frame_state (Dwfl_Frame_State *state)
{
- if (state->thread->process->core == NULL)
+ pid_t tid = state->thread->tid;
+ if (state->thread->process->core == NULL && tid)
{
#ifndef __x86_64__
return false;
#else /* __x86_64__ */
- pid_t tid = state->thread->tid;
struct user_regs_struct user_regs;
if (ptrace (PTRACE_GETREGS, tid, NULL, &user_regs) != 0)
return false;
}
INTDEF (dwfl_frame_state_pid)
-/* Fetch inferior registers from a core file. */
-
Dwfl_Frame_State *
dwfl_frame_state_core (Dwfl *dwfl, const char *corefile)
{
}
INTDEF (dwfl_frame_state_core)
+Dwfl_Frame_State *
+dwfl_frame_state_data (Dwfl *dwfl, int pc_set, Dwarf_Addr pc, unsigned nregs,
+ const uint64_t *regs_set, const Dwarf_Addr *regs)
+{
+ Ebl *ebl = NULL;
+ for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
+ {
+ Dwfl_Error error = __libdwfl_module_getebl (mod);
+ if (error != DWFL_E_NOERROR)
+ continue;
+ ebl = mod->ebl;
+ }
+ if (ebl == NULL || nregs > ebl_frame_state_nregs (ebl))
+ {
+ __libdwfl_seterrno (DWFL_E_UNKNOWN_ERROR);
+ return NULL;
+ }
+ Dwfl_Frame_State_Process *process = process_alloc (dwfl);
+ if (process == NULL)
+ return NULL;
+ process->ebl = ebl;
+ Dwfl_Frame_State_Thread *thread = thread_alloc (process, 0);
+ if (thread == NULL)
+ {
+ process_free (process);
+ __libdwfl_seterrno (DWFL_E_UNKNOWN_ERROR);
+ return NULL;
+ }
+ Dwfl_Frame_State *state = thread->unwound;
+ state->pc_state = DWFL_FRAME_STATE_ERROR;
+ if (pc_set)
+ {
+ state->pc = pc;
+ state->pc_state = DWFL_FRAME_STATE_PC_SET;
+ }
+ for (unsigned regno = 0; regno < nregs; regno++)
+ if ((regs_set[regno / sizeof (*regs_set) / 8]
+ & (1U << (regno % (sizeof (*regs_set) * 8)))) != 0
+ && ! dwfl_frame_state_reg_set (state, regno, regs[regno]))
+ {
+ process_free (process);
+ __libdwfl_seterrno (DWFL_E_UNKNOWN_ERROR);
+ return NULL;
+ }
+ if (! ebl_frame_state (state) || ! state_fetch_pc (state))
+ {
+ process_free (process);
+ __libdwfl_seterrno (DWFL_E_UNKNOWN_ERROR);
+ return NULL;
+ }
+ return process->thread->unwound;
+}
+INTDEF (dwfl_frame_state_data)
+
Dwfl_Frame_State *
dwfl_frame_thread_next (Dwfl_Frame_State *state)
{
extern Dwfl_Frame_State *dwfl_frame_state_core (Dwfl *dwfl,
const char *corefile);
+/* Fetch inferior registers from a caller supplied storage. */
+extern Dwfl_Frame_State *dwfl_frame_state_data (Dwfl *dwfl, int pc_set,
+ Dwarf_Addr pc, unsigned nregs,
+ const uint64_t *regs_set,
+ const Dwarf_Addr *regs);
+
/* 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. */
/* 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. */
+ /* (1 << X) bitmask where 0 <= X < ebl_frame_state_nregs. */
uint64_t regs_set[3];
- /* REGS array size is ebl_frame_state_nregs (base->ebl). */
+ /* REGS array size is ebl_frame_state_nregs. */
Dwarf_Addr regs[];
};