/* We encapsulate the macro use so we can free local malloc resources that would otherwise leak. See the call points below. */ static int read_unaligned_addr_check(Dwarf_Debug dbg, Dwarf_Addr *addr_out, Dwarf_Small *rangeptr, unsigned address_size, Dwarf_Error *error, Dwarf_Small *section_end) { Dwarf_Addr a = 0; READ_UNALIGNED_CK(dbg,a, Dwarf_Addr, rangeptr, address_size, error,section_end); *addr_out = a; return DW_DLV_OK; }
/* Sweeps the complete section. */ int _dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg, Dwarf_Small * section_data_ptr, Dwarf_Unsigned section_length, Dwarf_Global ** globals, Dwarf_Signed * return_count, Dwarf_Error * error, int context_code, int global_code, int length_err_num, int version_err_num) { Dwarf_Small *pubnames_like_ptr = 0; Dwarf_Small *section_end_ptr = section_data_ptr +section_length; /* Points to the context for the current set of global names, and contains information to identify the compilation-unit that the set refers to. */ Dwarf_Global_Context pubnames_context = 0; Dwarf_Half version = 0; /* Offset from the start of compilation-unit for the current global. */ Dwarf_Off die_offset_in_cu = 0; Dwarf_Unsigned global_count = 0; /* Points to the current global read. */ Dwarf_Global global = 0; /* Used to chain the Dwarf_Global_s structs for creating contiguous list of pointers to the structs. */ Dwarf_Chain curr_chain = 0; Dwarf_Chain prev_chain = 0; Dwarf_Chain head_chain = 0; /* Points to contiguous block of Dwarf_Global's to be returned. */ Dwarf_Global *ret_globals = 0; /* Temporary counter. */ Dwarf_Unsigned i = 0; if (dbg == NULL) { _dwarf_error(NULL, error, DW_DLE_DBG_NULL); return (DW_DLV_ERROR); } /* We will eventually need the .debug_info data. Load it now. */ if (!dbg->de_debug_info.dss_data) { int res = _dwarf_load_debug_info(dbg, error); if (res != DW_DLV_OK) { return res; } } if (section_data_ptr == NULL) { return (DW_DLV_NO_ENTRY); } pubnames_like_ptr = section_data_ptr; do { Dwarf_Unsigned length = 0; int local_extension_size = 0; int local_length_size = 0; /* Some compilers emit padding at the end of each cu's area. pubnames_ptr_past_end_cu records the true area end for the pubnames(like) content of a cu. Essentially the length in the header and the 0 terminator of the data are redundant information. The dwarf2/3 spec does not mention what to do if the length is past the 0 terminator. So we take any bytes left after the 0 as padding and ignore them. */ Dwarf_Small *pubnames_ptr_past_end_cu = 0; pubnames_context = (Dwarf_Global_Context) _dwarf_get_alloc(dbg, context_code, 1); if (pubnames_context == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } /* READ_AREA_LENGTH updates pubnames_like_ptr for consumed bytes. */ READ_AREA_LENGTH_CK(dbg, length, Dwarf_Unsigned, pubnames_like_ptr, local_length_size, local_extension_size,error,section_length,section_end_ptr); pubnames_context->pu_length_size = local_length_size; pubnames_context->pu_extension_size = local_extension_size; pubnames_context->pu_dbg = dbg; pubnames_ptr_past_end_cu = pubnames_like_ptr + length; READ_UNALIGNED_CK(dbg, version, Dwarf_Half, pubnames_like_ptr, DWARF_HALF_SIZE, error,section_end_ptr); pubnames_like_ptr += DWARF_HALF_SIZE; /* ASSERT: DW_PUBNAMES_VERSION2 == DW_PUBTYPES_VERSION2 */ if (version != DW_PUBNAMES_VERSION2) { _dwarf_error(dbg, error, version_err_num); return (DW_DLV_ERROR); } /* Offset of CU header in debug section. */ READ_UNALIGNED_CK(dbg, pubnames_context->pu_offset_of_cu_header, Dwarf_Off, pubnames_like_ptr, pubnames_context->pu_length_size, error,section_end_ptr); pubnames_like_ptr += pubnames_context->pu_length_size; FIX_UP_OFFSET_IRIX_BUG(dbg, pubnames_context->pu_offset_of_cu_header, "pubnames cu header offset"); READ_UNALIGNED_CK(dbg, pubnames_context->pu_info_length, Dwarf_Unsigned, pubnames_like_ptr, pubnames_context->pu_length_size, error,section_end_ptr); pubnames_like_ptr += pubnames_context->pu_length_size; if (pubnames_like_ptr > (section_data_ptr + section_length)) { _dwarf_error(dbg, error, length_err_num); return (DW_DLV_ERROR); } /* Read initial offset (of DIE within CU) of a pubname, final entry is not a pair, just a zero offset. */ READ_UNALIGNED_CK(dbg, die_offset_in_cu, Dwarf_Off, pubnames_like_ptr, pubnames_context->pu_length_size, error,section_end_ptr); pubnames_like_ptr += pubnames_context->pu_length_size; FIX_UP_OFFSET_IRIX_BUG(dbg, die_offset_in_cu, "offset of die in cu"); /* Loop thru pairs. DIE off with CU followed by string. */ while (die_offset_in_cu != 0) { int res; /* Already read offset, pubnames_like_ptr now points to the string. */ global = (Dwarf_Global) _dwarf_get_alloc(dbg, global_code, 1); if (global == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } global_count++; global->gl_context = pubnames_context; global->gl_named_die_offset_within_cu = die_offset_in_cu; global->gl_name = pubnames_like_ptr; res = _dwarf_check_string_valid(dbg,section_data_ptr, pubnames_like_ptr,section_end_ptr, DW_DLE_STRING_OFF_END_PUBNAMES_LIKE,error); if (res != DW_DLV_OK) { return res; } pubnames_like_ptr = pubnames_like_ptr + strlen((char *) pubnames_like_ptr) + 1; /* Finish off current entry chain */ curr_chain = (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); if (curr_chain == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } /* Put current global on singly_linked list. */ curr_chain->ch_item = (Dwarf_Global) global; if (head_chain == NULL) head_chain = prev_chain = curr_chain; else { prev_chain->ch_next = curr_chain; prev_chain = curr_chain; } /* Fead offset for the *next* entry */ READ_UNALIGNED_CK(dbg, die_offset_in_cu, Dwarf_Off, pubnames_like_ptr, pubnames_context->pu_length_size, error,section_end_ptr); pubnames_like_ptr += pubnames_context->pu_length_size; FIX_UP_OFFSET_IRIX_BUG(dbg, die_offset_in_cu, "offset of next die in cu"); if (pubnames_like_ptr > (section_data_ptr + section_length)) { _dwarf_error(dbg, error, length_err_num); return (DW_DLV_ERROR); } } /* ASSERT: die_offset_in_cu == 0 */ if (pubnames_like_ptr > pubnames_ptr_past_end_cu) { /* This is some kind of error. This simply cannot happen. The encoding is wrong or the length in the header for this cu's contribution is wrong. */ _dwarf_error(dbg, error, length_err_num); return (DW_DLV_ERROR); } /* If there is some kind of padding at the end of the section, as emitted by some compilers, skip over that padding and simply ignore the bytes thus passed-over. With most compilers, pubnames_like_ptr == pubnames_ptr_past_end_cu at this point */ pubnames_like_ptr = pubnames_ptr_past_end_cu; } while (pubnames_like_ptr < (section_data_ptr + section_length)); /* Points to contiguous block of Dwarf_Global's. */ ret_globals = (Dwarf_Global *) _dwarf_get_alloc(dbg, DW_DLA_LIST, global_count); if (ret_globals == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } /* Store pointers to Dwarf_Global_s structs in contiguous block, and deallocate the chain. */ curr_chain = head_chain; for (i = 0; i < global_count; i++) { *(ret_globals + i) = curr_chain->ch_item; prev_chain = curr_chain; curr_chain = curr_chain->ch_next; dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); } *globals = ret_globals; *return_count = (Dwarf_Signed) global_count; return DW_DLV_OK; }
int dwarf_get_xu_index_header(Dwarf_Debug dbg, /* Pass in section_type "tu" or "cu" */ const char * section_type, Dwarf_Xu_Index_Header * xuptr, Dwarf_Unsigned * version, Dwarf_Unsigned * number_of_columns, /* L */ Dwarf_Unsigned * number_of_CUs, /* N */ Dwarf_Unsigned * number_of_slots, /* M */ const char ** section_name, Dwarf_Error * error) { Dwarf_Xu_Index_Header indexptr = 0; int res = DW_DLV_ERROR; struct Dwarf_Section_s *sect = 0; Dwarf_Unsigned local_version = 0; Dwarf_Unsigned num_col = 0; Dwarf_Unsigned num_CUs = 0; Dwarf_Unsigned num_slots = 0; Dwarf_Small *data = 0; Dwarf_Unsigned tables_end_offset = 0; Dwarf_Unsigned hash_tab_offset = 0; Dwarf_Unsigned indexes_tab_offset = 0; Dwarf_Unsigned section_offsets_tab_offset = 0; Dwarf_Unsigned section_sizes_tab_offset = 0; unsigned datalen32 = LEN32BIT; Dwarf_Small *section_end = 0; if (!strcmp(section_type,"cu") ) { sect = &dbg->de_debug_cu_index; } else if (!strcmp(section_type,"tu") ) { sect = &dbg->de_debug_tu_index; } else { _dwarf_error(dbg, error, DW_DLE_XU_TYPE_ARG_ERROR); return DW_DLV_ERROR; } if (!sect->dss_size) { return DW_DLV_NO_ENTRY; } if (!sect->dss_data) { res = _dwarf_load_section(dbg, sect,error); if (res != DW_DLV_OK) { return res; } } data = sect->dss_data; section_end = data + sect->dss_size; if (sect->dss_size < (4*datalen32) ) { _dwarf_error(dbg, error, DW_DLE_ERRONEOUS_XU_INDEX_SECTION); return (DW_DLV_ERROR); } READ_UNALIGNED_CK(dbg,local_version, Dwarf_Unsigned, data,datalen32, error,section_end); data += datalen32; READ_UNALIGNED_CK(dbg,num_col, Dwarf_Unsigned, data,datalen32, error,section_end); data += datalen32; READ_UNALIGNED_CK(dbg,num_CUs, Dwarf_Unsigned, data,datalen32, error,section_end); data += datalen32; READ_UNALIGNED_CK(dbg,num_slots, Dwarf_Unsigned, data,datalen32, error,section_end); data += datalen32; hash_tab_offset = datalen32*4; indexes_tab_offset = hash_tab_offset + (num_slots * HASHSIGNATURELEN); /* Look for corrupt section data. */ if (num_slots > sect->dss_size) { _dwarf_error(dbg, error, DW_DLE_ERRONEOUS_XU_INDEX_SECTION); return (DW_DLV_ERROR); } if ( (4*num_slots) > sect->dss_size) { _dwarf_error(dbg, error, DW_DLE_ERRONEOUS_XU_INDEX_SECTION); return (DW_DLV_ERROR); } section_offsets_tab_offset = indexes_tab_offset + (num_slots *datalen32); if ( num_col > sect->dss_size) { /* Something is badly wrong here. */ _dwarf_error(dbg, error, DW_DLE_ERRONEOUS_XU_INDEX_SECTION); return (DW_DLV_ERROR); } if ( (4*num_col) > sect->dss_size) { /* Something is badly wrong here. */ _dwarf_error(dbg, error, DW_DLE_ERRONEOUS_XU_INDEX_SECTION); return (DW_DLV_ERROR); } section_sizes_tab_offset = section_offsets_tab_offset + ((num_CUs +1) *num_col* datalen32) ; tables_end_offset = section_sizes_tab_offset + ((num_CUs ) *num_col* datalen32); if ( tables_end_offset > sect->dss_size) { /* Something is badly wrong here. */ _dwarf_error(dbg, error, DW_DLE_ERRONEOUS_XU_INDEX_SECTION); return (DW_DLV_ERROR); } indexptr = (Dwarf_Xu_Index_Header)_dwarf_get_alloc(dbg,DW_DLA_XU_INDEX,1); if (indexptr == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } strcpy(indexptr->gx_type,section_type); indexptr->gx_dbg = dbg; indexptr->gx_section_length = sect->dss_size; indexptr->gx_section_data = sect->dss_data; indexptr->gx_section_name = sect->dss_name; indexptr->gx_version = local_version; indexptr->gx_column_count_sections = num_col; indexptr->gx_units_in_index = num_CUs; indexptr->gx_slots_in_hash = num_slots; indexptr->gx_hash_table_offset = hash_tab_offset; indexptr->gx_index_table_offset = indexes_tab_offset; indexptr->gx_section_offsets_offset = section_offsets_tab_offset; indexptr->gx_section_sizes_offset = section_sizes_tab_offset; *xuptr = indexptr; *version = indexptr->gx_version; *number_of_columns = indexptr->gx_column_count_sections; *number_of_CUs = indexptr->gx_units_in_index; *number_of_slots = indexptr->gx_slots_in_hash; *section_name = indexptr->gx_section_name; return DW_DLV_OK; }
static int _dwarf_read_loc_section_dwo(Dwarf_Debug dbg, Dwarf_Block_c * return_block, Dwarf_Addr * lowpc, Dwarf_Addr * highpc, Dwarf_Bool *at_end, Dwarf_Half * lle_op, Dwarf_Off sec_offset, Dwarf_Half address_size, Dwarf_Error * error) { Dwarf_Small *beg = dbg->de_debug_loc.dss_data + sec_offset; Dwarf_Small *locptr = 0; Dwarf_Small llecode = 0; Dwarf_Word leb128_length = 0; Dwarf_Unsigned expr_offset = sec_offset; Dwarf_Byte_Ptr section_end = dbg->de_debug_loc.dss_data + dbg->de_debug_loc.dss_size; if (sec_offset >= dbg->de_debug_loc.dss_size) { /* We're at the end. No more present. */ return DW_DLV_NO_ENTRY; } memset(return_block,0,sizeof(*return_block)); /* not the same as non-split loclist, but still a list. */ return_block->bl_from_loclist = 2; return_block->bl_locdesc_offset = sec_offset; llecode = *beg; locptr = beg +1; expr_offset++; switch(llecode) { case DW_LLE_end_of_list_entry: *at_end = TRUE; return_block->bl_section_offset = expr_offset; expr_offset++; break; case DW_LLE_base_address_selection_entry: { Dwarf_Unsigned addr_index = 0; DECODE_LEB128_UWORD_CK(locptr,addr_index, dbg,error,section_end); return_block->bl_section_offset = expr_offset; /* So this behaves much like non-dwo loclist */ *lowpc=MAX_ADDR; *highpc=addr_index; } break; case DW_LLE_start_end_entry: { Dwarf_Unsigned addr_indexs = 0; Dwarf_Unsigned addr_indexe= 0; Dwarf_Half exprlen = 0; DECODE_LEB128_UWORD_CK(locptr,addr_indexs, dbg,error,section_end); expr_offset += leb128_length; DECODE_LEB128_UWORD_CK(locptr,addr_indexe, dbg,error,section_end); expr_offset +=leb128_length; *lowpc=addr_indexs; *highpc=addr_indexe; READ_UNALIGNED_CK(dbg, exprlen, Dwarf_Half, locptr, sizeof(exprlen), error,section_end); locptr += sizeof(exprlen); expr_offset += sizeof(exprlen); return_block->bl_len = exprlen; return_block->bl_data = locptr; return_block->bl_section_offset = expr_offset; expr_offset += exprlen; if (expr_offset > dbg->de_debug_loc.dss_size) { _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT); return DW_DLV_ERROR; } } break; case DW_LLE_start_length_entry: { Dwarf_Unsigned addr_index = 0; Dwarf_ufixed range_length = 0; Dwarf_Half exprlen = 0; DECODE_LEB128_UWORD_CK(locptr,addr_index, dbg,error,section_end); expr_offset +=leb128_length; READ_UNALIGNED_CK(dbg, range_length, Dwarf_ufixed, locptr, sizeof(range_length), error,section_end); locptr += sizeof(range_length); expr_offset += sizeof(range_length); READ_UNALIGNED_CK(dbg, exprlen, Dwarf_Half, locptr, sizeof(exprlen), error,section_end); locptr += sizeof(exprlen); expr_offset += sizeof(exprlen); *lowpc = addr_index; *highpc = range_length; return_block->bl_len = exprlen; return_block->bl_data = locptr; return_block->bl_section_offset = expr_offset; /* exprblock_size can be zero, means no expression */ expr_offset += exprlen; if (expr_offset > dbg->de_debug_loc.dss_size) { _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT); return DW_DLV_ERROR; } } break; case DW_LLE_offset_pair_entry: { Dwarf_ufixed startoffset = 0; Dwarf_ufixed endoffset = 0; Dwarf_Half exprlen = 0; READ_UNALIGNED_CK(dbg, startoffset, Dwarf_ufixed, locptr, sizeof(startoffset), error,section_end); locptr += sizeof(startoffset); expr_offset += sizeof(startoffset); READ_UNALIGNED_CK(dbg, endoffset, Dwarf_ufixed, locptr, sizeof(endoffset), error,section_end); locptr += sizeof(endoffset); expr_offset += sizeof(endoffset); *lowpc= startoffset; *highpc = endoffset; READ_UNALIGNED_CK(dbg, exprlen, Dwarf_Half, locptr, sizeof(exprlen), error,section_end); locptr += sizeof(exprlen); expr_offset += sizeof(exprlen); return_block->bl_len = exprlen; return_block->bl_data = locptr; return_block->bl_section_offset = expr_offset; expr_offset += exprlen; if (expr_offset > dbg->de_debug_loc.dss_size) { _dwarf_error(NULL, error, DW_DLE_DEBUG_LOC_SECTION_SHORT); return DW_DLV_ERROR; } } break; default: _dwarf_error(dbg,error,DW_DLE_LLE_CODE_UNKNOWN); return DW_DLV_ERROR; } *lle_op = llecode; return DW_DLV_OK; }