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)); } }