/* The size of the circular list of strings may be set and reset as desired. Returns the previous size of the list. If the list is shortened excess error entries are simply dropped. If the reallocation fails the list size is left unchanged. Do not make this a long list! Remember the maxcount we record is 1 > the user count, so we adjust it so it looks like the user count. */ unsigned dwarf_set_harmless_error_list_size(Dwarf_Debug dbg, unsigned maxcount ) { struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors; unsigned prevcount = dhp->dh_maxcount; if (maxcount != 0) { ++maxcount; if (maxcount != dhp->dh_maxcount) { /* Assign transfers 'ownership' of the malloc areas to oldarray. */ struct Dwarf_Harmless_s oldarray = *dhp; /* Do not double increment the max, the init() func increments it too. */ dwarf_harmless_init(dhp,maxcount-1); if (oldarray.dh_next_to_use != oldarray.dh_first) { unsigned i = 0; for (i = oldarray.dh_first; i != oldarray.dh_next_to_use; i = (i+1)%oldarray.dh_maxcount) { dwarf_insert_harmless_error(dbg,oldarray.dh_errors[i]); } if (oldarray.dh_errs_count > dhp->dh_errs_count) { dhp->dh_errs_count = oldarray.dh_errs_count; } } dwarf_harmless_cleanout(&oldarray); } } return prevcount-1; }
/* Common code for two user-visible routines to share. Errors here result in memory leaks, but errors here are serious (making aranges unusable) so we assume callers will not repeat the error often or mind the leaks. */ static int dwarf_get_aranges_list(Dwarf_Debug dbg, Dwarf_Chain * chain_out, Dwarf_Signed * chain_count_out, Dwarf_Error * error) { /* Sweeps through the arange. */ Dwarf_Small *arange_ptr = 0; Dwarf_Small *arange_ptr_start = 0; /* Start of arange header. Used for rounding offset of arange_ptr to twice the tuple size. Libdwarf requirement. */ Dwarf_Small *header_ptr = 0; /* Version of .debug_aranges header. */ Dwarf_Half version = 0; /* Offset of current set of aranges into .debug_info. */ Dwarf_Off info_offset = 0; /* Size in bytes of addresses in target. */ Dwarf_Small address_size = 0; /* Size in bytes of segment offsets in target. */ Dwarf_Small segment_size = 0; /* Count of total number of aranges. */ Dwarf_Unsigned arange_count = 0; Dwarf_Arange arange = 0; /* Used to chain Dwarf_Aranges structs. */ Dwarf_Chain curr_chain = NULL; Dwarf_Chain prev_chain = NULL; Dwarf_Chain head_chain = NULL; if (!dbg->de_debug_aranges.dss_size) { return (DW_DLV_NO_ENTRY); } arange_ptr = dbg->de_debug_aranges.dss_data; arange_ptr_start = arange_ptr; do { /* Length of current set of aranges. */ Dwarf_Unsigned length = 0; Dwarf_Small remainder = 0; Dwarf_Small *arange_ptr_past_end = 0; Dwarf_Unsigned range_entry_size = 0; int local_length_size; /*REFERENCED*/ /* Not used in this instance of the macro */ int local_extension_size = 0; header_ptr = arange_ptr; /* READ_AREA_LENGTH updates arange_ptr for consumed bytes */ READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned, arange_ptr, local_length_size, local_extension_size); arange_ptr_past_end = arange_ptr + length; READ_UNALIGNED(dbg, version, Dwarf_Half, arange_ptr, sizeof(Dwarf_Half)); arange_ptr += sizeof(Dwarf_Half); length = length - sizeof(Dwarf_Half); if (version != CURRENT_VERSION_STAMP) { _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR); return (DW_DLV_ERROR); } READ_UNALIGNED(dbg, info_offset, Dwarf_Off, arange_ptr, local_length_size); arange_ptr += local_length_size; length = length - local_length_size; /* This applies to debug_info only, not to debug_types. */ if (info_offset >= dbg->de_debug_info.dss_size) { FIX_UP_OFFSET_IRIX_BUG(dbg, info_offset, "arange info offset.a"); if (info_offset >= dbg->de_debug_info.dss_size) { _dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD); return (DW_DLV_ERROR); } } address_size = *(Dwarf_Small *) arange_ptr; if(address_size > sizeof(Dwarf_Addr)) { _dwarf_error(dbg, error, DW_DLE_ADDRESS_SIZE_ERROR); return DW_DLV_ERROR; } if(address_size == 0) { _dwarf_error(dbg, error, DW_DLE_ADDRESS_SIZE_ERROR); return DW_DLV_ERROR; } /* It is not an error if the sizes differ. Unusual, but not an error. */ arange_ptr = arange_ptr + sizeof(Dwarf_Small); length = length - sizeof(Dwarf_Small); /* Even DWARF2 had a segment_size field here, meaning size in bytes of a segment descriptor on the target system. */ segment_size = *(Dwarf_Small *) arange_ptr; if(segment_size > sizeof(Dwarf_Addr)) { _dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD); return (DW_DLV_ERROR); } arange_ptr = arange_ptr + sizeof(Dwarf_Small); length = length - sizeof(Dwarf_Small); range_entry_size = 2*address_size + segment_size; /* Round arange_ptr offset to next multiple of address_size. */ remainder = (Dwarf_Unsigned) (arange_ptr - header_ptr) % (range_entry_size); if (remainder != 0) { arange_ptr = arange_ptr + (2 * address_size) - remainder; length = length - ((2 * address_size) - remainder); } do { Dwarf_Addr range_address = 0; Dwarf_Unsigned segment_selector = 0; Dwarf_Unsigned range_length = 0; /* For segmented address spaces, the first field to read is a segment selector (new in DWARF4). Surprising since the segment_size was always there in the table header! */ if(version == 4 && segment_size != 0) { READ_UNALIGNED(dbg, segment_selector, Dwarf_Unsigned, arange_ptr, segment_size); arange_ptr += address_size; length = length - address_size; } READ_UNALIGNED(dbg, range_address, Dwarf_Addr, arange_ptr, address_size); arange_ptr += address_size; length = length - address_size; READ_UNALIGNED(dbg, range_length, Dwarf_Unsigned, arange_ptr, address_size); arange_ptr += address_size; length = length - address_size; { /* We used to suppress all-zero entries, but now we return all aranges entries so we show the entire content. March 31, 2010. */ arange = (Dwarf_Arange) _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1); if (arange == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } arange->ar_segment_selector = segment_selector; arange->ar_segment_selector_size = segment_size; arange->ar_address = range_address; arange->ar_length = range_length; arange->ar_info_offset = info_offset; arange->ar_dbg = dbg; arange_count++; 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); } curr_chain->ch_item = arange; if (head_chain == NULL) head_chain = prev_chain = curr_chain; else { prev_chain->ch_next = curr_chain; prev_chain = curr_chain; } } /* The current set of ranges is terminated by range_address 0 and range_length 0, but that does not necessarily terminate the ranges for this CU! There can be multiple sets in that DWARF does not explicitly forbid multiple sets. DWARF2,3,4 section 7.20 We stop short to avoid overrun of the end of the CU. */ } while (arange_ptr_past_end >= (arange_ptr + range_entry_size)); /* A compiler could emit some padding bytes here. dwarf2/3 (dwarf4 sec 7.20) does not clearly make extra padding bytes illegal. */ if (arange_ptr_past_end < arange_ptr) { char buf[200]; Dwarf_Unsigned pad_count = arange_ptr - arange_ptr_past_end; Dwarf_Unsigned offset = arange_ptr - arange_ptr_start; snprintf(buf,sizeof(buf),"DW_DLE_ARANGE_LENGTH_BAD." " 0x%" DW_PR_XZEROS DW_PR_DUx " pad bytes at offset 0x%" DW_PR_XZEROS DW_PR_DUx " in .debug_aranges", pad_count, offset); dwarf_insert_harmless_error(dbg,buf); } /* For most compilers, arange_ptr == arange_ptr_past_end at this point. But not if there were padding bytes */ arange_ptr = arange_ptr_past_end; } while (arange_ptr < dbg->de_debug_aranges.dss_data + dbg->de_debug_aranges.dss_size); if (arange_ptr != dbg->de_debug_aranges.dss_data + dbg->de_debug_aranges.dss_size) { _dwarf_error(dbg, error, DW_DLE_ARANGE_DECODE_ERROR); return (DW_DLV_ERROR); } *chain_out = head_chain; *chain_count_out = arange_count; return DW_DLV_OK; }
static int dwarf_next_cu_header_internal(Dwarf_Debug dbg, Dwarf_Bool is_info, Dwarf_Unsigned * cu_header_length, Dwarf_Half * version_stamp, Dwarf_Unsigned * abbrev_offset, Dwarf_Half * address_size, Dwarf_Half * offset_size, Dwarf_Half * extension_size, Dwarf_Sig8 * signature, Dwarf_Unsigned *typeoffset, Dwarf_Unsigned * next_cu_offset, Dwarf_Error * error) { /* Offset for current and new CU. */ Dwarf_Unsigned new_offset = 0; /* CU Context for current CU. */ Dwarf_CU_Context cu_context = 0; Dwarf_Debug_InfoTypes dis = 0; Dwarf_Unsigned section_size = 0; /* ***** BEGIN CODE ***** */ if (dbg == NULL) { _dwarf_error(NULL, error, DW_DLE_DBG_NULL); return (DW_DLV_ERROR); } dis = is_info? &dbg->de_info_reading: &dbg->de_types_reading; /* Get offset into .debug_info of next CU. If dbg has no context, this has to be the first one. */ if (dis->de_cu_context == NULL) { new_offset = 0; Dwarf_Small *dataptr = is_info? dbg->de_debug_info.dss_data: dbg->de_debug_types.dss_data; if (!dataptr) { Dwarf_Error err2= 0; int res = is_info?_dwarf_load_debug_info(dbg, &err2): _dwarf_load_debug_types(dbg,&err2); if (res != DW_DLV_OK) { if(reloc_incomplete(err2)) { /* We will assume all is ok, though it is not. Relocation errors need not be fatal. */ char msg_buf[200]; snprintf(msg_buf,sizeof(msg_buf), "Relocations did not complete successfully, but we are " " ignoring error: %s",dwarf_errmsg(err2)); dwarf_insert_harmless_error(dbg,msg_buf); res = DW_DLV_OK; } else { if( error) { *error = err2; } return res; } } } } else { new_offset = dis->de_cu_context->cc_debug_offset + dis->de_cu_context->cc_length + dis->de_cu_context->cc_length_size + dis->de_cu_context->cc_extension_size; } /* Check that there is room in .debug_info beyond the new offset for at least a new cu header. If not, return 0 to indicate end of debug_info section, and reset de_cu_debug_info_offset to enable looping back through the cu's. */ section_size = is_info? dbg->de_debug_info.dss_size: dbg->de_debug_types.dss_size; if ((new_offset + _dwarf_length_of_cu_header_simple(dbg,is_info)) >= section_size) { dis->de_cu_context = NULL; return (DW_DLV_NO_ENTRY); } /* Check if this CU has been read before. */ cu_context = _dwarf_find_CU_Context(dbg, new_offset,is_info); /* If not, make CU Context for it. */ if (cu_context == NULL) { cu_context = _dwarf_make_CU_Context(dbg, new_offset,is_info, error); if (cu_context == NULL) { /* Error if CU Context could not be made. Since _dwarf_make_CU_Context has already registered an error we do not do that here: we let the lower error pass thru. */ return (DW_DLV_ERROR); } } dis->de_cu_context = cu_context; if (cu_header_length != NULL) { *cu_header_length = cu_context->cc_length; } if (version_stamp != NULL) { *version_stamp = cu_context->cc_version_stamp; } if (abbrev_offset != NULL) { *abbrev_offset = cu_context->cc_abbrev_offset; } if (address_size != NULL) { *address_size = cu_context->cc_address_size; } if (offset_size != NULL) { *offset_size = cu_context->cc_length_size; } if (extension_size != NULL) { *extension_size = cu_context->cc_extension_size; } if(!is_info) { if(signature) { *signature = cu_context->cc_signature; } if(typeoffset) { *typeoffset = cu_context->cc_typeoffset; } } new_offset = new_offset + cu_context->cc_length + cu_context->cc_length_size + cu_context->cc_extension_size; *next_cu_offset = new_offset; return (DW_DLV_OK); }