/* 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; }
/* This function returns DW_DLV_OK if it succeeds and DW_DLV_ERR or DW_DLV_OK otherwise. count is set to the number of addresses in the .debug_aranges section. For each address, the corresponding element in an array is set to the address itself(aranges) and the section offset (offsets). Must be identical in most aspects to dwarf_get_aranges! */ int _dwarf_get_aranges_addr_offsets(Dwarf_Debug dbg, Dwarf_Addr ** addrs, Dwarf_Off ** offsets, Dwarf_Signed * count, Dwarf_Error * error) { /* Sweeps the .debug_aranges section. */ Dwarf_Small *arange_ptr = 0; Dwarf_Small *arange_start_ptr = 0; /* Start of arange header. Used for rounding offset of arange_ptr to twice the tuple size. Libdwarf requirement. */ Dwarf_Small *header_ptr = 0; /* Length of current set of aranges. */ Dwarf_Unsigned length = 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; Dwarf_Small remainder = 0; /* Count of total number of aranges. */ Dwarf_Unsigned arange_count = 0; /* Start address of arange. */ Dwarf_Addr range_address = 0; /* Length of arange. */ Dwarf_Unsigned range_length = 0; Dwarf_Arange arange = 0; Dwarf_Unsigned i = 0; /* Used to chain Dwarf_Aranges structs. */ Dwarf_Chain curr_chain = NULL; Dwarf_Chain prev_chain = NULL; Dwarf_Chain head_chain = NULL; Dwarf_Addr *arange_addrs = 0; Dwarf_Off *arange_offsets = 0; int res = DW_DLV_ERROR; /* ***** BEGIN CODE ***** */ if (error != NULL) *error = NULL; if (dbg == NULL) { _dwarf_error(NULL, error, DW_DLE_DBG_NULL); return (DW_DLV_ERROR); } res = _dwarf_load_section(dbg, &dbg->de_debug_aranges,error); if (res != DW_DLV_OK) { return res; } arange_ptr = dbg->de_debug_aranges.dss_data; do { int local_length_size = 0; /*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); 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; if (info_offset >= dbg->de_debug_info.dss_size) { FIX_UP_OFFSET_IRIX_BUG(dbg, info_offset, "arange info offset.b"); 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; arange_ptr = arange_ptr + sizeof(Dwarf_Small); length = length - sizeof(Dwarf_Small); segment_size = *(Dwarf_Small *) arange_ptr; arange_ptr = arange_ptr + sizeof(Dwarf_Small); length = length - sizeof(Dwarf_Small); if (segment_size != 0) { _dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD); return (DW_DLV_ERROR); } /* Round arange_ptr offset to next multiple of address_size. */ remainder = (Dwarf_Unsigned) (arange_ptr - header_ptr) % (2 * address_size); if (remainder != 0) { arange_ptr = arange_ptr + (2 * address_size) - remainder; length = length - ((2 * address_size) - remainder); } do { arange_start_ptr = arange_ptr; READ_UNALIGNED(dbg, range_address, Dwarf_Addr, arange_ptr, dbg->de_pointer_size); arange_ptr += dbg->de_pointer_size; length = length - dbg->de_pointer_size; READ_UNALIGNED(dbg, range_length, Dwarf_Unsigned, arange_ptr, local_length_size); arange_ptr += local_length_size; length = length - local_length_size; if (range_address != 0 || range_length != 0) { 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_address = range_address; arange->ar_length = range_length; arange->ar_info_offset = arange_start_ptr - dbg->de_debug_aranges.dss_data; 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; } } } while (range_address != 0 || range_length != 0); if (length != 0) { _dwarf_error(dbg, error, DW_DLE_ARANGE_LENGTH_BAD); return (DW_DLV_ERROR); } } 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); } arange_addrs = (Dwarf_Addr *) _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count); if (arange_addrs == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } arange_offsets = (Dwarf_Off *) _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count); if (arange_offsets == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } curr_chain = head_chain; for (i = 0; i < arange_count; i++) { Dwarf_Arange ar = curr_chain->ch_item; arange_addrs[i] = ar->ar_address; arange_offsets[i] = ar->ar_info_offset; prev_chain = curr_chain; curr_chain = curr_chain->ch_next; dwarf_dealloc(dbg, ar, DW_DLA_ARANGE); dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); } *count = arange_count; *offsets = arange_offsets; *addrs = arange_addrs; return (DW_DLV_OK); }
/* This function returns the count of the number of aranges in the .debug_aranges section. It sets aranges to point to a block of Dwarf_Arange's describing the arange's. It returns DW_DLV_ERROR on error. Must be identical in most aspects to dwarf_get_aranges_addr_offsets! */ int dwarf_get_aranges(Dwarf_Debug dbg, Dwarf_Arange ** aranges, Dwarf_Signed * returned_count, Dwarf_Error * error) { /* Sweeps the .debug_aranges section. */ Dwarf_Small *arange_ptr = 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; Dwarf_Small remainder = 0; /* Count of total number of aranges. */ Dwarf_Unsigned arange_count = 0; /* Start address of arange. */ Dwarf_Addr range_address = 0; /* Length of arange. */ Dwarf_Unsigned range_length = 0; Dwarf_Arange arange, *arange_block = 0; Dwarf_Unsigned i = 0; /* Used to chain Dwarf_Aranges structs. */ Dwarf_Chain curr_chain = NULL; Dwarf_Chain prev_chain = NULL; Dwarf_Chain head_chain = NULL; int res = DW_DLV_ERROR; /* ***** BEGIN CODE ***** */ if (dbg == NULL) { _dwarf_error(NULL, error, DW_DLE_DBG_NULL); return (DW_DLV_ERROR); } res = _dwarf_load_section(dbg, &dbg->de_debug_aranges, error); if (res != DW_DLV_OK) { return res; } arange_ptr = dbg->de_debug_aranges.dss_data; do { /* Length of current set of aranges. */ Dwarf_Unsigned length; Dwarf_Small *arange_ptr_past_end = 0; int local_length_size; /*REFERENCED*/ /* Not used in this instance of the macro */ int local_extension_size; 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; 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; #ifdef notdef /* It is not an error if the sizes differ. Unusual, but not an error. */ if (address_size != dbg->de_pointer_size) { /* Internal error of some kind */ _dwarf_error(dbg, error, DW_DLE_BADBITC); return (DW_DLV_ERROR); } #endif arange_ptr = arange_ptr + sizeof(Dwarf_Small); length = length - sizeof(Dwarf_Small); segment_size = *(Dwarf_Small *) arange_ptr; arange_ptr = arange_ptr + sizeof(Dwarf_Small); length = length - sizeof(Dwarf_Small); if (segment_size != 0) { _dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD); return (DW_DLV_ERROR); } /* Round arange_ptr offset to next multiple of address_size. */ remainder = (Dwarf_Unsigned) (arange_ptr - header_ptr) % (2 * address_size); if (remainder != 0) { arange_ptr = arange_ptr + (2 * address_size) - remainder; length = length - ((2 * address_size) - remainder); } do { 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; if (range_address != 0 || range_length != 0) { 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_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; } } } while (range_address != 0 || range_length != 0); /* A compiler could emit some padding bytes here. dwarf2/3 (dwarf3 draft8 sec 7.20) does not clearly make extra padding bytes illegal. */ if (arange_ptr_past_end < arange_ptr) { _dwarf_error(dbg, error, DW_DLE_ARANGE_LENGTH_BAD); return (DW_DLV_ERROR); } /* 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); } arange_block = (Dwarf_Arange *) _dwarf_get_alloc(dbg, DW_DLA_LIST, arange_count); if (arange_block == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } curr_chain = head_chain; for (i = 0; i < arange_count; i++) { *(arange_block + i) = curr_chain->ch_item; prev_chain = curr_chain; curr_chain = curr_chain->ch_next; dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); } *aranges = arange_block; *returned_count = (arange_count); 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; }