/* Because we do not know what DIE is involved, if the object being printed has different address sizes in different compilation units this will not work properly: anything could happen. */ extern void print_ranges(Dwarf_Debug dbg) { Dwarf_Unsigned off = 0; int group_number = 0; int wasdense = 0; current_section_id = DEBUG_RANGES; if (!do_print_dwarf) { return; } printf("\n.debug_ranges\n"); /* Turn off dense, we do not want print_ranges_list_to_extra to use dense form here. */ wasdense = dense; dense = 0; for(;;) { Dwarf_Ranges *rangeset = 0; Dwarf_Signed rangecount = 0; Dwarf_Unsigned bytecount = 0; /* We do not know what DIE is involved, we use the older call here. */ int rres = dwarf_get_ranges(dbg,off,&rangeset, &rangecount,&bytecount,&err); if(rres == DW_DLV_OK) { char *val = 0; printf(" Ranges group %d:\n",group_number); esb_empty_string(&esb_string); print_ranges_list_to_extra(dbg,off, rangeset,rangecount,bytecount, &esb_string); dwarf_ranges_dealloc(dbg,rangeset,rangecount); val = esb_get_string(&esb_string); printf("%s",val); ++group_number; } else if (rres == DW_DLV_NO_ENTRY) { printf("End of .debug_ranges.\n"); break; } else { /* ERROR, which does not quite mean a real error, as we might just be misaligned reading things without a DW_AT_ranges offset.*/ printf("End of .debug_ranges..\n"); break; } off += bytecount; } dense = wasdense; }
/* Extracted this from print_range_attribute() to isolate the check of the range list. */ static void check_ranges_list(Dwarf_Debug dbg, Dwarf_Off die_off, Dwarf_Die cu_die, Dwarf_Unsigned original_off, Dwarf_Ranges *rangeset, Dwarf_Signed rangecount, Dwarf_Unsigned bytecount) { Dwarf_Unsigned off = original_off; Dwarf_Signed index = 0; Dwarf_Addr base_address = CU_base_address; Dwarf_Addr lopc = 0; Dwarf_Addr hipc = 0; Dwarf_Bool bError = FALSE; static boolean do_print = TRUE; #if 0 { /* START -> Just for debugging */ struct esb_s rangesstr; esb_constructor(&rangesstr); printf("\n**** START ****\n"); printf("\tGLB_OFF: (0x%" DW_PR_XZEROS DW_PR_DUx ") ",die_off); printf("\tRGN_OFF: (0x%" DW_PR_XZEROS DW_PR_DUx ")\n",original_off); print_ranges_list_to_extra(dbg,original_off, rangeset,rangecount,bytecount, &rangesstr); printf("%s\n", esb_get_string(&rangesstr)); printf("**** END ****\n"); /* END <- Just for debugging */ } #endif /* 0 */ /* Ignore last entry, is the end-of-list */ for (index = 0; index < rangecount - 1; index++) { Dwarf_Ranges *r = rangeset + index; if (r->dwr_addr1 == elf_max_address) { /* (0xffffffff,addr), use specific address (current PU address) */ base_address = r->dwr_addr2; } else { /* (offset,offset), update using CU address */ lopc = r->dwr_addr1 + base_address; hipc = r->dwr_addr2 + base_address; DWARF_CHECK_COUNT(ranges_result,1); /* Check the low_pc and high_pc are within a valid range in the .text section */ if (IsValidInBucketGroup(pRangesInfo,lopc) && IsValidInBucketGroup(pRangesInfo,hipc)) { /* Valid values; do nothing */ } else { /* At this point may be we are dealing with a linkonce symbol */ if (IsValidInLinkonce(pLinkonceInfo, PU_name,lopc,hipc)) { /* Valid values; do nothing */ } else { bError = TRUE; DWARF_CHECK_ERROR(ranges_result, ".debug_ranges: Address outside a " "valid .text range"); if (check_verbose_mode && do_print) { /* Update DIEs offset just for printing */ int res = dwarf_die_offsets(cu_die, &DIE_overall_offset,&DIE_offset,&err); if (res != DW_DLV_OK) { print_error(dbg, "dwarf_die_offsets",res,err); } printf( "Offset = 0x%" DW_PR_XZEROS DW_PR_DUx ", Base = 0x%" DW_PR_XZEROS DW_PR_DUx ", " "Low = 0x%" DW_PR_XZEROS DW_PR_DUx " (0x%" DW_PR_XZEROS DW_PR_DUx "), High = 0x%" DW_PR_XZEROS DW_PR_DUx " (0x%" DW_PR_XZEROS DW_PR_DUx ")\n", off,base_address,lopc, r->dwr_addr1,hipc, r->dwr_addr2); } } } } /* Each entry holds 2 addresses (offsets) */ off += elf_address_size * 2; } /* In the case of errors, we have to print the range records that caused the error. */ if (bError && check_verbose_mode && do_print) { struct esb_s rangesstr; esb_constructor(&rangesstr); printf("\n"); print_ranges_list_to_extra(dbg,original_off, rangeset,rangecount,bytecount, &rangesstr); printf("%s\n", esb_get_string(&rangesstr)); } /* In the case of printing unique errors, stop the printing of any subsequent errors, which have the same text. */ if (bError && check_verbose_mode && print_unique_errors) { do_print = FALSE; } }