Print this page
5688 ELF tools need to be more careful with dwarf data
*** 38,47 ****
--- 38,49 ----
/*
* Data from eh_frame section used by dump_cfi()
*/
typedef struct {
+ const char *file;
+ const char *sh_name;
Half e_machine; /* ehdr->e_machine */
uchar_t *e_ident; /* ehdr->e_ident */
uint64_t sh_addr; /* Address of eh_frame section */
int do_swap; /* True if object and system byte */
/* order differs */
*** 68,83 ****
* *ndx is incremented by the size of the extracted datum.
*
* The requested datum is extracted, byte swapped if necessary,
* and returned.
*/
! static uint64_t
! dwarf_extract_uint(uchar_t *data, uint64_t *ndx, int size, int do_swap)
{
switch (size) {
case 1:
! return (data[(*ndx)++]);
case 2:
{
Half r;
uchar_t *p = (uchar_t *)&r;
--- 70,91 ----
* *ndx is incremented by the size of the extracted datum.
*
* The requested datum is extracted, byte swapped if necessary,
* and returned.
*/
! static dwarf_error_t
! dwarf_extract_uint(uchar_t *data, size_t len, uint64_t *ndx, int size,
! int do_swap, uint64_t *ret)
{
+ if (((*ndx + size) > len) ||
+ ((*ndx + size) < *ndx))
+ return (DW_OVERFLOW);
+
switch (size) {
case 1:
! *ret = (data[(*ndx)++]);
! return (DW_SUCCESS);
case 2:
{
Half r;
uchar_t *p = (uchar_t *)&r;
*** 86,96 ****
UL_ASSIGN_BSWAP_HALF(p, data);
else
UL_ASSIGN_HALF(p, data);
(*ndx) += 2;
! return (r);
}
case 4:
{
Word r;
uchar_t *p = (uchar_t *)&r;
--- 94,105 ----
UL_ASSIGN_BSWAP_HALF(p, data);
else
UL_ASSIGN_HALF(p, data);
(*ndx) += 2;
! *ret = r;
! return (DW_SUCCESS);
}
case 4:
{
Word r;
uchar_t *p = (uchar_t *)&r;
*** 100,110 ****
UL_ASSIGN_BSWAP_WORD(p, data);
else
UL_ASSIGN_WORD(p, data);
(*ndx) += 4;
! return (r);
}
case 8:
{
uint64_t r;
--- 109,120 ----
UL_ASSIGN_BSWAP_WORD(p, data);
else
UL_ASSIGN_WORD(p, data);
(*ndx) += 4;
! *ret = r;
! return (DW_SUCCESS);
}
case 8:
{
uint64_t r;
*** 115,131 ****
UL_ASSIGN_BSWAP_LWORD(p, data);
else
UL_ASSIGN_LWORD(p, data);
(*ndx) += 8;
! return (r);
}
}
! /* If here, an invalid size was specified */
! assert(0);
! return (0);
}
/*
* Map a DWARF register constant to the machine register name it
* corresponds to, formatting the result into buf.
--- 125,142 ----
UL_ASSIGN_BSWAP_LWORD(p, data);
else
UL_ASSIGN_LWORD(p, data);
(*ndx) += 8;
! *ret = r;
! return (DW_SUCCESS);
}
+ default:
+ return (DW_BAD_ENCODING);
}
! /* NOTREACHED */
}
/*
* Map a DWARF register constant to the machine register name it
* corresponds to, formatting the result into buf.
*** 174,184 ****
*
* entry:
* data - Address of base of eh_frame section being processed
* off - Offset of current FDE within eh_frame
* ndx - Index of current position within current FDE
! * len - Length of eh_frame section
* state - Object, CIE, and FDE state for current request
* msg - Header message to issue before producing output.
* indent - # of indentation characters issued for each line of output.
*
* exit:
--- 185,195 ----
*
* entry:
* data - Address of base of eh_frame section being processed
* off - Offset of current FDE within eh_frame
* ndx - Index of current position within current FDE
! * len - Length of FDE
* state - Object, CIE, and FDE state for current request
* msg - Header message to issue before producing output.
* indent - # of indentation characters issued for each line of output.
*
* exit:
*** 261,274 ****
loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc));
loc_str = MSG_ORIG(MSG_STR_LOC);
continue;
case 0x2: /* v2: DW_CFA_offset, reg, offset */
! soper = uleb_extract(&data[off], ndx) *
! state->ciedalign;
dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
! REGNAME(LOW_OP(op), rbuf1), EC_SXWORD(soper));
continue;
case 0x3: /* v2: DW_CFA_restore, reg */
dbg_print(0, MSG_ORIG(MSG_CFA_REG), PREFIX,
REGNAME(LOW_OP(op), rbuf1));
--- 272,292 ----
loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc));
loc_str = MSG_ORIG(MSG_STR_LOC);
continue;
case 0x2: /* v2: DW_CFA_offset, reg, offset */
! if (uleb_extract(&data[off], ndx, len, &oper1) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
! oper1 *= state->ciedalign;
dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
! REGNAME(LOW_OP(op), rbuf1), EC_XWORD(oper1));
continue;
case 0x3: /* v2: DW_CFA_restore, reg */
dbg_print(0, MSG_ORIG(MSG_CFA_REG), PREFIX,
REGNAME(LOW_OP(op), rbuf1));
*** 299,311 ****
case 0x2d: /* GNU: DW_CFA_GNU_window_save */
dbg_print(0, MSG_ORIG(MSG_CFA_SIMPLE), PREFIX);
break;
case 0x01: /* v2: DW_CFA_set_loc, address */
! cur_pc = dwarf_ehe_extract(&data[off], ndx,
! state->cieRflag, state->e_ident, B_FALSE,
! state->sh_addr, off + *ndx, state->gotaddr);
dbg_print(0, MSG_ORIG(MSG_CFA_CFASET), PREFIX,
EC_XWORD(cur_pc));
break;
case 0x02: /* v2: DW_CFA_advance_loc_1, 1-byte delta */
--- 317,343 ----
case 0x2d: /* GNU: DW_CFA_GNU_window_save */
dbg_print(0, MSG_ORIG(MSG_CFA_SIMPLE), PREFIX);
break;
case 0x01: /* v2: DW_CFA_set_loc, address */
! switch (dwarf_ehe_extract(&data[off], len, ndx,
! &cur_pc, state->cieRflag, state->e_ident, B_FALSE,
! state->sh_addr, off + *ndx, state->gotaddr)) {
! case DW_OVERFLOW:
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! case DW_BAD_ENCODING:
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWBADENC),
! state->file, state->sh_name,
! state->cieRflag);
! return;
! case DW_SUCCESS:
! break;
! }
dbg_print(0, MSG_ORIG(MSG_CFA_CFASET), PREFIX,
EC_XWORD(cur_pc));
break;
case 0x02: /* v2: DW_CFA_advance_loc_1, 1-byte delta */
*** 315,447 ****
* Since the codes are contiguous, and the sizes are
* powers of 2, we can compute the word width from
* the code.
*/
i = 1 << (op - 0x02);
! oper1 = dwarf_extract_uint(data + off, ndx, i,
! state->do_swap) * state->ciecalign;
cur_pc += oper1;
dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC), PREFIX,
loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc));
loc_str = MSG_ORIG(MSG_STR_LOC);
break;
case 0x05: /* v2: DW_CFA_offset_extended,reg,off */
! oper1 = uleb_extract(&data[off], ndx);
! soper = uleb_extract(&data[off], ndx) *
! state->ciedalign;
dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
REGNAME(oper1, rbuf1), EC_SXWORD(soper));
break;
case 0x06: /* v2: DW_CFA_restore_extended, reg */
case 0x0d: /* v2: DW_CFA_def_cfa_register, reg */
case 0x08: /* v2: DW_CFA_same_value, reg */
case 0x07: /* v2: DW_CFA_undefined, reg */
! oper1 = uleb_extract(&data[off], ndx);
dbg_print(0, MSG_ORIG(MSG_CFA_REG), PREFIX,
REGNAME(oper1, rbuf1));
break;
case 0x09: /* v2: DW_CFA_register, reg, reg */
! oper1 = uleb_extract(&data[off], ndx);
! oper2 = uleb_extract(&data[off], ndx);
dbg_print(0, MSG_ORIG(MSG_CFA_REG_REG), PREFIX,
REGNAME(oper1, rbuf1), REGNAME(oper2, rbuf2));
break;
case 0x0c: /* v2: DW_CFA_def_cfa, reg, offset */
! oper1 = uleb_extract(&data[off], ndx);
! oper2 = uleb_extract(&data[off], ndx);
dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLU), PREFIX,
REGNAME(oper1, rbuf1), EC_XWORD(oper2));
break;
case 0x0e: /* v2: DW_CFA_def_cfa_offset, offset */
! oper1 = uleb_extract(&data[off], ndx);
dbg_print(0, MSG_ORIG(MSG_CFA_LLU), PREFIX,
EC_XWORD(oper1));
break;
case 0x0f: /* v3: DW_CFA_def_cfa_expression, blk */
! oper1 = uleb_extract(&data[off], ndx);
dbg_print(0, MSG_ORIG(MSG_CFA_EBLK), PREFIX,
EC_XWORD(oper1));
/* We currently do not decode the expression block */
*ndx += oper1;
break;
case 0x10: /* v3: DW_CFA_expression, reg, blk */
case 0x16: /* v3: DW_CFA_val_expression,reg,blk */
! oper1 = uleb_extract(&data[off], ndx);
! oper2 = uleb_extract(&data[off], ndx);
dbg_print(0, MSG_ORIG(MSG_CFA_REG_EBLK), PREFIX,
REGNAME(oper1, rbuf1), EC_XWORD(oper2));
/* We currently do not decode the expression block */
*ndx += oper2;
break;
case 0x11: /* v3: DW_CFA_offset_extended_sf, reg, off */
! oper1 = uleb_extract(&data[off], ndx);
! soper = sleb_extract(&data[off], ndx) *
! state->ciedalign;
dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
REGNAME(oper1, rbuf1), EC_SXWORD(soper));
break;
case 0x12: /* v3: DW_CFA_def_cfa_sf, reg, offset */
! oper1 = uleb_extract(&data[off], ndx);
! soper = sleb_extract(&data[off], ndx) *
! state->ciedalign;
dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX,
REGNAME(oper1, rbuf1), EC_SXWORD(soper));
break;
case 0x13: /* DW_CFA_def_cfa_offset_sf, offset */
! soper = sleb_extract(&data[off], ndx) *
! state->ciedalign;
dbg_print(0, MSG_ORIG(MSG_CFA_LLD), PREFIX,
EC_SXWORD(soper));
break;
case 0x14: /* v3: DW_CFA_val_offset, reg, offset */
! oper1 = uleb_extract(&data[off], ndx);
! soper = uleb_extract(&data[off], ndx) *
! state->ciedalign;
dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX,
REGNAME(oper1, rbuf1), EC_SXWORD(soper));
break;
case 0x15: /* v3: DW_CFA_val_offset_sf, reg, offset */
! oper1 = uleb_extract(&data[off], ndx);
! soper = sleb_extract(&data[off], ndx) *
! state->ciedalign;
dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX,
REGNAME(oper1, rbuf1), EC_SXWORD(soper));
break;
case 0x1d: /* GNU: DW_CFA_MIPS_advance_loc8, delta */
! oper1 = dwarf_extract_uint(data + off, ndx, i,
! state->do_swap) * state->ciecalign;
cur_pc += oper1;
dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC), PREFIX,
loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc));
loc_str = MSG_ORIG(MSG_STR_LOC);
break;
case 0x2e: /* GNU: DW_CFA_GNU_args_size, size */
! oper1 = uleb_extract(&data[off], ndx);
dbg_print(0, MSG_ORIG(MSG_CFA_LLU), PREFIX,
EC_XWORD(oper1));
break;
case 0x2f: /* GNU:DW_CFA_GNU_negative_offset_extended,reg,off */
! oper1 = uleb_extract(&data[off], ndx);
! soper = -uleb_extract(&data[off], ndx) *
! state->ciedalign;
dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
REGNAME(oper1, rbuf1), EC_SXWORD(soper));
break;
default:
--- 347,665 ----
* Since the codes are contiguous, and the sizes are
* powers of 2, we can compute the word width from
* the code.
*/
i = 1 << (op - 0x02);
! switch (dwarf_extract_uint(data + off, len,
! ndx, i, state->do_swap, &oper1)) {
! case DW_BAD_ENCODING:
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWBADENC),
! state->file, state->sh_name,
! i);
! return;
! case DW_OVERFLOW:
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! case DW_SUCCESS:
! break;
! }
! oper1 *= state->ciecalign;
cur_pc += oper1;
dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC), PREFIX,
loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc));
loc_str = MSG_ORIG(MSG_STR_LOC);
break;
case 0x05: /* v2: DW_CFA_offset_extended,reg,off */
! if (uleb_extract(&data[off], ndx, len, &oper1) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
! if (sleb_extract(&data[off], ndx, len, &soper) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
! soper *= state->ciedalign;
dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
REGNAME(oper1, rbuf1), EC_SXWORD(soper));
break;
case 0x06: /* v2: DW_CFA_restore_extended, reg */
case 0x0d: /* v2: DW_CFA_def_cfa_register, reg */
case 0x08: /* v2: DW_CFA_same_value, reg */
case 0x07: /* v2: DW_CFA_undefined, reg */
! if (uleb_extract(&data[off], ndx, len, &oper1) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
dbg_print(0, MSG_ORIG(MSG_CFA_REG), PREFIX,
REGNAME(oper1, rbuf1));
break;
case 0x09: /* v2: DW_CFA_register, reg, reg */
! if (uleb_extract(&data[off], ndx, len, &oper1) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
! if (uleb_extract(&data[off], ndx, len, &oper2) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
dbg_print(0, MSG_ORIG(MSG_CFA_REG_REG), PREFIX,
REGNAME(oper1, rbuf1), REGNAME(oper2, rbuf2));
break;
case 0x0c: /* v2: DW_CFA_def_cfa, reg, offset */
! if (uleb_extract(&data[off], ndx, len, &oper1) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
! if (uleb_extract(&data[off], ndx, len, &oper2) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLU), PREFIX,
REGNAME(oper1, rbuf1), EC_XWORD(oper2));
break;
case 0x0e: /* v2: DW_CFA_def_cfa_offset, offset */
! if (uleb_extract(&data[off], ndx, len, &oper1) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
dbg_print(0, MSG_ORIG(MSG_CFA_LLU), PREFIX,
EC_XWORD(oper1));
break;
case 0x0f: /* v3: DW_CFA_def_cfa_expression, blk */
! if (uleb_extract(&data[off], ndx, len, &oper1) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
dbg_print(0, MSG_ORIG(MSG_CFA_EBLK), PREFIX,
EC_XWORD(oper1));
/* We currently do not decode the expression block */
*ndx += oper1;
break;
case 0x10: /* v3: DW_CFA_expression, reg, blk */
case 0x16: /* v3: DW_CFA_val_expression,reg,blk */
! if (uleb_extract(&data[off], ndx, len, &oper1) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
! if (uleb_extract(&data[off], ndx, len, &oper2) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
dbg_print(0, MSG_ORIG(MSG_CFA_REG_EBLK), PREFIX,
REGNAME(oper1, rbuf1), EC_XWORD(oper2));
/* We currently do not decode the expression block */
*ndx += oper2;
break;
case 0x11: /* v3: DW_CFA_offset_extended_sf, reg, off */
! if (uleb_extract(&data[off], ndx, len, &oper1) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
! if (sleb_extract(&data[off], ndx, len, &soper) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
! soper *= state->ciedalign;
dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
REGNAME(oper1, rbuf1), EC_SXWORD(soper));
break;
case 0x12: /* v3: DW_CFA_def_cfa_sf, reg, offset */
! if (uleb_extract(&data[off], ndx, len, &oper1) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
! if (sleb_extract(&data[off], ndx, len, &soper) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
! soper *= state->ciedalign;
dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX,
REGNAME(oper1, rbuf1), EC_SXWORD(soper));
break;
case 0x13: /* DW_CFA_def_cfa_offset_sf, offset */
! if (sleb_extract(&data[off], ndx, len, &soper) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
! soper *= state->ciedalign;
dbg_print(0, MSG_ORIG(MSG_CFA_LLD), PREFIX,
EC_SXWORD(soper));
break;
case 0x14: /* v3: DW_CFA_val_offset, reg, offset */
! if (uleb_extract(&data[off], ndx, len, &oper1) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
! if (sleb_extract(&data[off], ndx, len, &soper) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
! soper *= state->ciedalign;
dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX,
REGNAME(oper1, rbuf1), EC_SXWORD(soper));
break;
case 0x15: /* v3: DW_CFA_val_offset_sf, reg, offset */
! if (uleb_extract(&data[off], ndx, len, &oper1) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
! if (sleb_extract(&data[off], ndx, len, &soper) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
! soper *= state->ciedalign;
dbg_print(0, MSG_ORIG(MSG_CFA_REG_OFFLLD), PREFIX,
REGNAME(oper1, rbuf1), EC_SXWORD(soper));
break;
case 0x1d: /* GNU: DW_CFA_MIPS_advance_loc8, delta */
! switch (dwarf_extract_uint(data + off, len,
! ndx, 8, state->do_swap, &oper1)) {
! case DW_BAD_ENCODING:
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWBADENC),
! state->file, state->sh_name,
! 8);
! return;
! case DW_OVERFLOW:
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! case DW_SUCCESS:
! break;
! }
! oper1 *= state->ciecalign;
cur_pc += oper1;
dbg_print(0, MSG_ORIG(MSG_CFA_ADV_LOC), PREFIX,
loc_str, EC_XWORD(oper1), EC_XWORD(cur_pc));
loc_str = MSG_ORIG(MSG_STR_LOC);
break;
case 0x2e: /* GNU: DW_CFA_GNU_args_size, size */
! if (uleb_extract(&data[off], ndx, len, &oper1) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
dbg_print(0, MSG_ORIG(MSG_CFA_LLU), PREFIX,
EC_XWORD(oper1));
break;
case 0x2f: /* GNU:DW_CFA_GNU_negative_offset_extended,reg,off */
! if (uleb_extract(&data[off], ndx, len, &oper1) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
!
! if (sleb_extract(&data[off], ndx, len, &soper) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! state->file, state->sh_name);
! return;
! }
! soper = -soper * state->ciedalign;
! soper *= state->ciedalign;
dbg_print(0, MSG_ORIG(MSG_CFA_CFAOFF), PREFIX,
REGNAME(oper1, rbuf1), EC_SXWORD(soper));
break;
default:
*** 463,483 ****
#undef REGNAME
#undef LOW_OP
}
void
! dump_eh_frame(uchar_t *data, size_t datasize, uint64_t sh_addr,
! Half e_machine, uchar_t *e_ident, uint64_t gotaddr)
{
Conv_dwarf_ehe_buf_t dwarf_ehe_buf;
dump_cfi_state_t cfi_state;
! uint64_t off, ndx;
uint_t cieid, cielength, cieversion, cieretaddr;
! int ciePflag, cieZflag, cieLflag, cieLflag_present;
! uint_t cieaugndx, length, id;
! char *cieaugstr;
cfi_state.e_machine = e_machine;
cfi_state.e_ident = e_ident;
cfi_state.sh_addr = sh_addr;
cfi_state.do_swap = _elf_sys_encoding() != e_ident[EI_DATA];
cfi_state.gotaddr = gotaddr;
--- 681,705 ----
#undef REGNAME
#undef LOW_OP
}
void
! dump_eh_frame(const char *file, char *sh_name, uchar_t *data, size_t datasize,
! uint64_t sh_addr, Half e_machine, uchar_t *e_ident, uint64_t gotaddr)
{
Conv_dwarf_ehe_buf_t dwarf_ehe_buf;
dump_cfi_state_t cfi_state;
! uint64_t off, ndx, length, id;
uint_t cieid, cielength, cieversion, cieretaddr;
! int ciePflag = 0, cieZflag = 0, cieLflag = 0;
! int cieLflag_present = 0;
! uint_t cieaugndx;
! char *cieaugstr = NULL;
! boolean_t have_cie = B_FALSE;
+ cfi_state.file = file;
+ cfi_state.sh_name = sh_name;
cfi_state.e_machine = e_machine;
cfi_state.e_ident = e_ident;
cfi_state.sh_addr = sh_addr;
cfi_state.do_swap = _elf_sys_encoding() != e_ident[EI_DATA];
cfi_state.gotaddr = gotaddr;
*** 494,525 ****
* remaining in this section. Note, ld(1) will terminate the
* processing of the .eh_frame contents for this file after a
* zero length CIE, thus any information that does follow is
* ignored by ld(1), and is therefore questionable.
*/
! length = (uint_t)dwarf_extract_uint(data + off, &ndx,
! 4, cfi_state.do_swap);
if (length == 0) {
dbg_print(0, MSG_ORIG(MSG_UNW_ZEROTERM));
off += 4;
continue;
}
/*
* extract CIE id in native format
*/
! id = (uint_t)dwarf_extract_uint(data + off, &ndx,
! 4, cfi_state.do_swap);
/*
* A CIE record has an id of '0', otherwise this is a
* FDE entry and the 'id' is the CIE pointer.
*/
if (id == 0) {
! uint64_t persVal, ndx_save;
! uint_t axsize;
cielength = length;
cieid = id;
ciePflag = cfi_state.cieRflag = cieZflag = 0;
cieLflag = cieLflag_present = 0;
--- 716,771 ----
* remaining in this section. Note, ld(1) will terminate the
* processing of the .eh_frame contents for this file after a
* zero length CIE, thus any information that does follow is
* ignored by ld(1), and is therefore questionable.
*/
! if (dwarf_extract_uint(data + off, datasize - off,
! &ndx, 4, cfi_state.do_swap, &length) == DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! file, sh_name);
! return;
! }
!
if (length == 0) {
dbg_print(0, MSG_ORIG(MSG_UNW_ZEROTERM));
off += 4;
continue;
}
+ if (length > (datasize - off)) {
+ (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADCIEFDELEN),
+ file, sh_name, EC_XWORD(length),
+ EC_XWORD(sh_addr + off));
+ /*
+ * If length is wrong, we have no means to find the
+ * next entry, just give up
+ */
+ return;
+ }
+
/*
* extract CIE id in native format
*/
! if (dwarf_extract_uint(data + off, datasize - off, &ndx,
! 4, cfi_state.do_swap, &id) == DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! file, sh_name);
! return;
! }
/*
* A CIE record has an id of '0', otherwise this is a
* FDE entry and the 'id' is the CIE pointer.
*/
if (id == 0) {
! uint64_t persVal, ndx_save = 0;
! uint64_t axsize;
!
+ have_cie = B_TRUE;
cielength = length;
cieid = id;
ciePflag = cfi_state.cieRflag = cieZflag = 0;
cieLflag = cieLflag_present = 0;
*** 534,545 ****
ndx += strlen(cieaugstr) + 1;
dbg_print(0, MSG_ORIG(MSG_UNW_CIEVERS),
cieversion, cieaugstr);
! cfi_state.ciecalign = uleb_extract(&data[off], &ndx);
! cfi_state.ciedalign = sleb_extract(&data[off], &ndx);
cieretaddr = data[off + ndx];
ndx += 1;
dbg_print(0, MSG_ORIG(MSG_UNW_CIECALGN),
EC_XWORD(cfi_state.ciecalign),
--- 780,804 ----
ndx += strlen(cieaugstr) + 1;
dbg_print(0, MSG_ORIG(MSG_UNW_CIEVERS),
cieversion, cieaugstr);
! if (uleb_extract(&data[off], &ndx, datasize - off,
! &cfi_state.ciecalign) == DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! file, sh_name);
! return;
! }
!
! if (sleb_extract(&data[off], &ndx, datasize - off,
! &cfi_state.ciedalign) == DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! file, sh_name);
! return;
! }
cieretaddr = data[off + ndx];
ndx += 1;
dbg_print(0, MSG_ORIG(MSG_UNW_CIECALGN),
EC_XWORD(cfi_state.ciecalign),
*** 549,561 ****
dbg_print(0, MSG_ORIG(MSG_UNW_CIEAXVAL));
for (cieaugndx = 0; cieaugstr[cieaugndx]; cieaugndx++) {
switch (cieaugstr[cieaugndx]) {
case 'z':
! axsize = uleb_extract(&data[off], &ndx);
dbg_print(0, MSG_ORIG(MSG_UNW_CIEAXSIZ),
! axsize);
cieZflag = 1;
/*
* The auxiliary section can contain
* unused padding bytes at the end, so
* save the current index. Along with
--- 808,828 ----
dbg_print(0, MSG_ORIG(MSG_UNW_CIEAXVAL));
for (cieaugndx = 0; cieaugstr[cieaugndx]; cieaugndx++) {
switch (cieaugstr[cieaugndx]) {
case 'z':
! if (uleb_extract(&data[off], &ndx,
! datasize - off, &axsize) ==
! DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! file, sh_name);
! return;
! }
!
dbg_print(0, MSG_ORIG(MSG_UNW_CIEAXSIZ),
! EC_XWORD(axsize));
cieZflag = 1;
/*
* The auxiliary section can contain
* unused padding bytes at the end, so
* save the current index. Along with
*** 567,579 ****
break;
case 'P':
ciePflag = data[off + ndx];
ndx += 1;
! persVal = dwarf_ehe_extract(&data[off],
! &ndx, ciePflag, e_ident, B_FALSE,
! sh_addr, off + ndx, gotaddr);
dbg_print(0,
MSG_ORIG(MSG_UNW_CIEAXPERS));
dbg_print(0,
MSG_ORIG(MSG_UNW_CIEAXPERSENC),
ciePflag, conv_dwarf_ehe(ciePflag,
--- 834,860 ----
break;
case 'P':
ciePflag = data[off + ndx];
ndx += 1;
! switch (dwarf_ehe_extract(&data[off],
! datasize - off, &ndx, &persVal,
! ciePflag, e_ident, B_FALSE, sh_addr,
! off + ndx, gotaddr)) {
! case DW_OVERFLOW:
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! file, sh_name);
! return;
! case DW_BAD_ENCODING:
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWBADENC),
! file, sh_name, ciePflag);
! return;
! case DW_SUCCESS:
! break;
! }
dbg_print(0,
MSG_ORIG(MSG_UNW_CIEAXPERS));
dbg_print(0,
MSG_ORIG(MSG_UNW_CIEAXPERSENC),
ciePflag, conv_dwarf_ehe(ciePflag,
*** 627,671 ****
} else {
uint_t fdelength = length;
int fdecieptr = id;
uint64_t fdeaddrrange;
dbg_print(0, MSG_ORIG(MSG_UNW_FDE),
EC_XWORD(sh_addr + off));
dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH),
fdelength, fdecieptr);
! cfi_state.fdeinitloc = dwarf_ehe_extract(&data[off],
! &ndx, cfi_state.cieRflag, e_ident, B_FALSE,
! sh_addr, off + ndx, gotaddr);
! fdeaddrrange = dwarf_ehe_extract(&data[off], &ndx,
! (cfi_state.cieRflag & ~DW_EH_PE_pcrel),
! e_ident, B_FALSE, sh_addr, off + ndx, gotaddr);
dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC),
EC_XWORD(cfi_state.fdeinitloc),
EC_XWORD(fdeaddrrange),
EC_XWORD(cfi_state.fdeinitloc + fdeaddrrange - 1));
! if (cieaugstr[0])
dbg_print(0, MSG_ORIG(MSG_UNW_FDEAXVAL));
if (cieZflag) {
uint64_t val;
uint64_t lndx;
! val = uleb_extract(&data[off], &ndx);
lndx = ndx;
ndx += val;
dbg_print(0, MSG_ORIG(MSG_UNW_FDEAXSIZE),
EC_XWORD(val));
if (val && cieLflag_present) {
uint64_t lsda;
! lsda = dwarf_ehe_extract(&data[off],
! &lndx, cieLflag, e_ident,
! B_FALSE, sh_addr, off + lndx,
! gotaddr);
dbg_print(0,
MSG_ORIG(MSG_UNW_FDEAXLSDA),
EC_XWORD(lsda));
}
}
--- 908,1003 ----
} else {
uint_t fdelength = length;
int fdecieptr = id;
uint64_t fdeaddrrange;
+ if (!have_cie) {
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_ERR_DWNOCIE), file, sh_name);
+ return;
+ }
+
dbg_print(0, MSG_ORIG(MSG_UNW_FDE),
EC_XWORD(sh_addr + off));
dbg_print(0, MSG_ORIG(MSG_UNW_FDELNGTH),
fdelength, fdecieptr);
! switch (dwarf_ehe_extract(&data[off], datasize - off,
! &ndx, &cfi_state.fdeinitloc, cfi_state.cieRflag,
! e_ident, B_FALSE, sh_addr, off + ndx, gotaddr)) {
! case DW_OVERFLOW:
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW), file, sh_name);
! return;
! case DW_BAD_ENCODING:
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWBADENC), file, sh_name,
! cfi_state.cieRflag);
! return;
! case DW_SUCCESS:
! break;
! }
!
! switch (dwarf_ehe_extract(&data[off], datasize - off,
! &ndx, &fdeaddrrange,
! (cfi_state.cieRflag & ~DW_EH_PE_pcrel), e_ident,
! B_FALSE, sh_addr, off + ndx, gotaddr)) {
! case DW_OVERFLOW:
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW), file, sh_name);
! return;
! case DW_BAD_ENCODING:
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWBADENC), file, sh_name,
! (cfi_state.cieRflag & ~DW_EH_PE_pcrel));
! return;
! case DW_SUCCESS:
! break;
! }
dbg_print(0, MSG_ORIG(MSG_UNW_FDEINITLOC),
EC_XWORD(cfi_state.fdeinitloc),
EC_XWORD(fdeaddrrange),
EC_XWORD(cfi_state.fdeinitloc + fdeaddrrange - 1));
! if ((cieaugstr != NULL) && (cieaugstr[0] != '\0'))
dbg_print(0, MSG_ORIG(MSG_UNW_FDEAXVAL));
if (cieZflag) {
uint64_t val;
uint64_t lndx;
! if (uleb_extract(&data[off], &ndx,
! datasize - off, &val) == DW_OVERFLOW) {
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! file, sh_name);
! return;
! }
lndx = ndx;
ndx += val;
dbg_print(0, MSG_ORIG(MSG_UNW_FDEAXSIZE),
EC_XWORD(val));
if (val && cieLflag_present) {
uint64_t lsda;
! switch (dwarf_ehe_extract(&data[off],
! datasize - off, &lndx, &lsda,
! cieLflag, e_ident, B_FALSE, sh_addr,
! off + lndx, gotaddr)) {
! case DW_OVERFLOW:
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWOVRFLW),
! file, sh_name);
! return;
! case DW_BAD_ENCODING:
! (void) fprintf(stderr,
! MSG_INTL(MSG_ERR_DWBADENC),
! file, sh_name, cieLflag);
! return;
! case DW_SUCCESS:
! break;
! }
dbg_print(0,
MSG_ORIG(MSG_UNW_FDEAXLSDA),
EC_XWORD(lsda));
}
}