+2022-07-28 Di Chen <dichen@redhat.com>
+
+ * NEWS: Add dwfl_frame_reg.
+
2022-07-13 Mark Wielaard <mark@klomp.org>
* NEWS: Add dwfl_get_debuginfod_client.
debuginfod: Add --disable-source-scan option.
libdwfl: Add new function dwfl_get_debuginfod_client.
+ Add new function dwfl_frame_reg.
Version 0.187
+2022-07-28 Di Chen <dichen@redhat.com>
+
+ * libdw.map (ELFUTILS_0.188): Add dwfl_frame_reg.
+
2022-07-13 Mark Wielaard <mark@klomp.org>
* libdw.map (ELFUTILS_0.187): Renamed to...
ELFUTILS_0.188 {
global:
dwfl_get_debuginfod_client;
+ dwfl_frame_reg;
} ELFUTILS_0.186;
+2022-07-28 Di Chen <dichen@redhat.com>
+
+ * libdwfl.h (dwfl_frame_reg): New function.
+ * libdwflP.h (DWFL_E_REGISTER_VAL_UNKNOWN): New error code.
+ (__libdwfl_frame_reg_get): Return an int.
+ (dwfl_frame_reg): INTDECL.
+ * dwfl_frame_regs.c (dwfl_frame_reg): New function.
+ * frame_unwind.c (__libdwfl_frame_reg_get): Return an int.
+ (state_get_reg): Removed.
+ (expr_eval): Use INTUSE (dwfl_frame_reg) instead of state_get_reg.
+ (handle_cfi): Likewise.
+ (getfunc): Likewise.
+ * linux-core-attach.c (core_set_initial_registers): Check
+ __libdwfl_frame_reg_get returns zero.
+
2022-07-28 Mark Wielaard <mark@klomp.org>
* core-file.c (elf_begin_rand): Replace struct ar_hdr h with
state->pc_state = DWFL_FRAME_STATE_PC_SET;
}
INTDEF(dwfl_thread_state_register_pc)
+
+int
+dwfl_frame_reg (Dwfl_Frame *state, unsigned regno, Dwarf_Word *val)
+{
+ int res = __libdwfl_frame_reg_get (state, regno, val);
+ if (res == -1)
+ __libdwfl_seterrno (DWFL_E_INVALID_REGISTER);
+ else if (res == 1)
+ __libdwfl_seterrno (DWFL_E_REGISTER_VAL_UNKNOWN);
+ return res;
+}
+INTDEF(dwfl_frame_reg)
error. */
#define DWARF_EXPR_STEPS_MAX 0x1000
-bool
+int
internal_function
__libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val)
{
Ebl *ebl = state->thread->process->ebl;
if (! ebl_dwarf_to_regno (ebl, ®no))
- return false;
+ return -1;
if (regno >= ebl_frame_nregs (ebl))
- return false;
+ return -1;
if ((state->regs_set[regno / sizeof (*state->regs_set) / 8]
& ((uint64_t) 1U << (regno % (sizeof (*state->regs_set) * 8)))) == 0)
- return false;
+ return 1;
if (val)
*val = state->regs[regno];
- return true;
+ return 0;
}
bool
return true;
}
-static bool
-state_get_reg (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val)
-{
- if (! __libdwfl_frame_reg_get (state, regno, val))
- {
- __libdwfl_seterrno (DWFL_E_INVALID_REGISTER);
- return false;
- }
- return true;
-}
-
static int
bra_compar (const void *key_voidp, const void *elem_voidp)
{
}
break;
case DW_OP_reg0 ... DW_OP_reg31:
- if (! state_get_reg (state, op->atom - DW_OP_reg0, &val1)
+ if (INTUSE (dwfl_frame_reg) (state, op->atom - DW_OP_reg0, &val1) != 0
|| ! push (val1))
{
free (stack.addrs);
}
break;
case DW_OP_regx:
- if (! state_get_reg (state, op->number, &val1) || ! push (val1))
+ if (INTUSE (dwfl_frame_reg) (state, op->number, &val1) != 0 || ! push (val1))
{
free (stack.addrs);
return false;
}
break;
case DW_OP_breg0 ... DW_OP_breg31:
- if (! state_get_reg (state, op->atom - DW_OP_breg0, &val1))
+ if (INTUSE (dwfl_frame_reg) (state, op->atom - DW_OP_breg0, &val1) != 0)
{
free (stack.addrs);
return false;
}
break;
case DW_OP_bregx:
- if (! state_get_reg (state, op->number, &val1))
+ if (INTUSE (dwfl_frame_reg) (state, op->number, &val1) != 0)
{
free (stack.addrs);
return false;
else if (reg_ops == NULL)
{
/* REGNO is same-value. */
- if (! state_get_reg (state, regno, ®val))
+ if (INTUSE (dwfl_frame_reg) (state, regno, ®val) != 0)
continue;
}
else
}
if (unwound->pc_state == DWFL_FRAME_STATE_ERROR)
{
- if (__libdwfl_frame_reg_get (unwound,
- frame->fde->cie->return_address_register,
- &unwound->pc))
+ int res = INTUSE (dwfl_frame_reg) (unwound,
+ frame->fde->cie->return_address_register,
+ &unwound->pc);
+ if (res == 0)
{
/* PPC32 __libc_start_main properly CFI-unwinds PC as zero.
Currently none of the archs supported for unwinding have
Dwfl_Frame *state = arg;
assert (firstreg >= 0);
while (nregs--)
- if (! __libdwfl_frame_reg_get (state, firstreg++, regs++))
+ if (INTUSE (dwfl_frame_reg) (state, firstreg++, regs++) != 0)
return false;
return true;
}
bool dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation)
__nonnull_attribute__ (1, 2);
+/* Get the value of the DWARF register number in the given frame.
+ Returns zero on success, -1 on error (invalid DWARF register
+ number) or 1 if the value of the register in the frame is unknown. */
+int dwfl_frame_reg (Dwfl_Frame *state, unsigned regno, Dwarf_Word *val)
+ __nonnull_attribute__ (1);
+
/* Return the internal debuginfod-client connection handle for the DWFL session.
When the client connection has not yet been initialized, it will be done on the
first call to this function. If elfutils is compiled without support for debuginfod,
DWFL_ERROR (LIBEBL_BAD, N_("Internal error due to ebl")) \
DWFL_ERROR (CORE_MISSING, N_("Missing data in core file")) \
DWFL_ERROR (INVALID_REGISTER, N_("Invalid register")) \
+ DWFL_ERROR (REGISTER_VAL_UNKNOWN, N_("Unknown register value")) \
DWFL_ERROR (PROCESS_MEMORY_READ, N_("Error reading process memory")) \
DWFL_ERROR (PROCESS_NO_ARCH, N_("Couldn't find architecture of any ELF")) \
DWFL_ERROR (PARSE_PROC, N_("Error parsing /proc filesystem")) \
Dwarf_Addr regs[];
};
-/* Fetch value from Dwfl_Frame->regs indexed by DWARF REGNO.
- No error code is set if the function returns FALSE. */
-bool __libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno,
+/* Fetch value from Dwfl_Frame->regs indexed by DWARF REGNO. The
+ function returns 0 on success, -1 on error (invalid DWARF register
+ number), 1 if the value of the register in the frame is unknown.
+ Even on error, no error code is set. */
+int __libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno,
Dwarf_Addr *val)
internal_function;
INTDECL (dwfl_getthreads)
INTDECL (dwfl_thread_getframes)
INTDECL (dwfl_frame_pc)
+INTDECL (dwfl_frame_reg)
INTDECL (dwfl_get_debuginfod_client)
/* Leading arguments standard to callbacks passed a Dwfl_Module. */
FIXME: It depends now on their order in core notes.
FIXME: It uses private function. */
if (regno < nregs
- && __libdwfl_frame_reg_get (thread->unwound, regno, NULL))
+ && __libdwfl_frame_reg_get (thread->unwound, regno, NULL) == 0)
continue;
Dwarf_Word val;
switch (regloc->bits)