/* Calculate the number of abbreviations for the current CU and set up a basic abbreviations array info, storing the number of attributes per abbreviation. */ void get_abbrev_array_info(Dwarf_Debug dbg, Dwarf_Unsigned offset_in) { Dwarf_Unsigned offset = offset_in; if (check_abbreviations) { Dwarf_Abbrev ab; Dwarf_Unsigned length = 0; Dwarf_Unsigned abbrev_entry_count = 0; Dwarf_Unsigned abbrev_code; int abres = DW_DLV_OK; Dwarf_Error err; Dwarf_Bool bMore = TRUE; CU_abbrev_count = 0; if (abbrev_array == NULL) { /* Allocate initial abbreviation array info */ abbrev_array = (Dwarf_Signed *) calloc(ABBREV_ARRAY_INITIAL_SIZE+1,sizeof(Dwarf_Signed)); abbrev_array_size = ABBREV_ARRAY_INITIAL_SIZE; } else { /* Clear out values from previous CU */ memset((void *)abbrev_array,0, (abbrev_array_size+1) * sizeof(Dwarf_Signed)); } while (bMore && (abres = dwarf_get_abbrev(dbg, offset, &ab, &length, &abbrev_entry_count, &err)) == DW_DLV_OK) { dwarf_get_abbrev_code(ab,&abbrev_code,&err); if (abbrev_code == 0) { /* End of abbreviation table for this CU */ ++offset; /* Skip abbreviation code */ bMore = FALSE; } else { /* Valid abbreviation code */ if (abbrev_code > 0) { if (abbrev_code > abbrev_array_size) { /* Resize abbreviation array */ abbrev_array_size *= 2; abbrev_array = (Dwarf_Signed *) realloc(abbrev_array, (abbrev_array_size+1) * sizeof(Dwarf_Signed)); } abbrev_array[abbrev_code] = abbrev_entry_count; ++CU_abbrev_count; offset += length; } else { /* Invalid abbreviation code */ print_error(dbg, "get_abbrev_array_info", abres, err); } } dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); } } }
/* Print data in .debug_abbrev This is inherently unsafe as it assumes there are no byte sequences in .debug_abbrev other than legal abbrev sequences. But the Dwarf spec does not promise that. The spec only promises that any bytes at an offset referred to from .debug_info are legal sequences. */ extern void print_abbrevs(Dwarf_Debug dbg) { Dwarf_Abbrev ab; Dwarf_Unsigned offset = 0; Dwarf_Unsigned length = 0; Dwarf_Unsigned abbrev_entry_count = 0; /* Maximum defined tag is 0xffff, DW_TAG_hi_user. */ Dwarf_Half tag = 0; Dwarf_Half attr = 0; Dwarf_Signed form = 0; Dwarf_Off off = 0; Dwarf_Unsigned i = 0; const char * child_name = 0; Dwarf_Unsigned abbrev_num = 1; Dwarf_Signed child_flag = 0; int abres = 0; int tres = 0; int acres = 0; Dwarf_Unsigned abbrev_code = 0; current_section_id = DEBUG_ABBREV; if (do_print_dwarf) { printf("\n.debug_abbrev\n"); } while ((abres = dwarf_get_abbrev(dbg, offset, &ab, &length, &abbrev_entry_count, &err)) == DW_DLV_OK) { if (abbrev_entry_count == 0) { /* Simple innocuous zero : null abbrev entry */ if (dense) { printf("<%" DW_PR_DUu "><0x%" DW_PR_XZEROS DW_PR_DUx "><%" DW_PR_DSd "><%s>\n", abbrev_num, offset, (Dwarf_Signed) /* abbrev_code */ 0, "null .debug_abbrev entry"); } else { printf("<%5" DW_PR_DUu "><0x%" DW_PR_XZEROS DW_PR_DUx "><code: %3" DW_PR_DSd "> %-20s\n", abbrev_num, offset, (Dwarf_Signed) /* abbrev_code */ 0, "null .debug_abbrev entry"); } offset += length; ++abbrev_num; dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); continue; } tres = dwarf_get_abbrev_tag(ab, &tag, &err); if (tres != DW_DLV_OK) { dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); print_error(dbg, "dwarf_get_abbrev_tag", tres, err); } tres = dwarf_get_abbrev_code(ab, &abbrev_code, &err); if (tres != DW_DLV_OK) { dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); print_error(dbg, "dwarf_get_abbrev_code", tres, err); } if (dense) { printf("<%" DW_PR_DUu "><0x%" DW_PR_XZEROS DW_PR_DUx "><%" DW_PR_DSd "><%s>", abbrev_num, offset, abbrev_code, get_TAG_name(tag,dwarf_names_print_on_error)); } else { printf("<%5" DW_PR_DUu "><0x%" DW_PR_XZEROS DW_PR_DUx "><code: %3" DW_PR_DSd "> %-20s", abbrev_num, offset, abbrev_code, get_TAG_name(tag,dwarf_names_print_on_error)); } /* Process specific TAGs specially. */ tag_specific_checks_setup(tag,0); ++abbrev_num; acres = dwarf_get_abbrev_children_flag(ab, &child_flag, &err); if (acres == DW_DLV_ERROR) { dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); print_error(dbg, "dwarf_get_abbrev_children_flag", acres, err); } if (acres == DW_DLV_NO_ENTRY) { child_flag = 0; } child_name = get_children_name(child_flag, dwarf_names_print_on_error); if (dense) printf(" %s", child_name); else printf(" %s\n", child_name); /* Abbrev just contains the format of a die, which debug_info then points to with the real data. So here we just print the given format. */ for (i = 0; i < abbrev_entry_count; i++) { int aeres = 0; aeres = dwarf_get_abbrev_entry(ab, i, &attr, &form, &off, &err); if (aeres == DW_DLV_ERROR) { dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); print_error(dbg, "dwarf_get_abbrev_entry", aeres, err); } if (aeres == DW_DLV_NO_ENTRY) { attr = -1LL; form = -1LL; } if (dense) { printf(" <%ld>%s<%s>", (unsigned long) off, get_AT_name(attr,dwarf_names_print_on_error), get_FORM_name((Dwarf_Half) form, dwarf_names_print_on_error)); } else { printf(" <0x%08lx> %-28s%s\n", (unsigned long) off, get_AT_name(attr, dwarf_names_print_on_error), get_FORM_name((Dwarf_Half) form, dwarf_names_print_on_error)); } } dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); offset += length; if (dense) { printf("\n"); } } if (abres == DW_DLV_ERROR) { print_error(dbg, "dwarf_get_abbrev", abres, err); } }
/* Print data in .debug_abbrev This is inherently unsafe as it assumes there are no byte sequences in .debug_abbrev other than legal abbrev sequences. But the Dwarf spec does not promise that. The spec only promises that any bytes at an offset referred to from .debug_info are legal sequences. */ extern void print_abbrevs(Dwarf_Debug dbg) { Dwarf_Abbrev ab; Dwarf_Unsigned offset = 0; Dwarf_Unsigned length = 0; Dwarf_Unsigned abbrev_entry_count = 0; /* Maximum defined tag is 0xffff, DW_TAG_hi_user. */ Dwarf_Half tag = 0; Dwarf_Half attr = 0; Dwarf_Signed form = 0; Dwarf_Off off = 0; Dwarf_Unsigned i = 0; Dwarf_Unsigned abbrev_num = 1; Dwarf_Signed child_flag = 0; int abres = 0; int tres = 0; int acres = 0; Dwarf_Unsigned abbrev_code = 0; Dwarf_Error paerr = 0; current_section_id = DEBUG_ABBREV; if (do_print_dwarf) { printf("\n.debug_abbrev\n"); } while ((abres = dwarf_get_abbrev(dbg, offset, &ab, &length, &abbrev_entry_count, &paerr)) == DW_DLV_OK) { const char *tagname = ""; /* Here offset is the global offset in .debug_abbrev. The abbrev_num is a relatively worthless counter of all abbreviations. */ tres = dwarf_get_abbrev_tag(ab, &tag, &paerr); if (tres != DW_DLV_OK) { dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); print_error(dbg, "dwarf_get_abbrev_tag", tres, paerr); } tres = dwarf_get_abbrev_code(ab, &abbrev_code, &paerr); if (tres != DW_DLV_OK) { dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); print_error(dbg, "dwarf_get_abbrev_code", tres, paerr); } tagname = get_TAG_name(tag,dwarf_names_print_on_error); if (!tag) { tagname = "Abbrev 0: null abbrev entry"; } if (dense) { printf("<%" DW_PR_DUu "><0x%" DW_PR_XZEROS DW_PR_DUx "><code: %" DW_PR_DUu ">", abbrev_num, offset,abbrev_code); if (verbose) { printf("<length: 0x%" DW_PR_XZEROS DW_PR_DUx ">", length); } printf(" %s", tagname); } else { printf("<%5" DW_PR_DUu "><0x%" DW_PR_XZEROS DW_PR_DUx "><code: %3" DW_PR_DUu ">", abbrev_num, offset, abbrev_code); if (verbose) { printf("<length: 0x%" DW_PR_XZEROS DW_PR_DUx ">", length); } printf(" %-27s", tagname); } /* Process specific TAGs specially. */ tag_specific_checks_setup(tag,0); ++abbrev_num; acres = dwarf_get_abbrev_children_flag(ab, &child_flag, &paerr); if (acres == DW_DLV_ERROR) { dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); print_error(dbg, "dwarf_get_abbrev_children_flag", acres, paerr); } if (acres == DW_DLV_NO_ENTRY) { child_flag = 0; } /* If tag is zero, it is a null byte, not a real abbreviation, so there is no 'children' flag to print. */ if (tag) { const char * child_name = 0; child_name = get_children_name(child_flag, dwarf_names_print_on_error); printf(" %s", child_name); } if(!dense) { printf("\n"); } /* Abbrev just contains the format of a die, which debug_info then points to with the real data. So here we just print the given format. */ for (i = 0; i < abbrev_entry_count; i++) { int aeres = 0; aeres = dwarf_get_abbrev_entry(ab, i, &attr, &form, &off, &paerr); if (aeres == DW_DLV_ERROR) { dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); print_error(dbg, "dwarf_get_abbrev_entry", aeres, paerr); } if (aeres == DW_DLV_NO_ENTRY) { attr = -1LL; form = -1LL; } if (dense) { printf(" <%ld>%s<%s>", (unsigned long) off, get_AT_name(attr,dwarf_names_print_on_error), get_FORM_name((Dwarf_Half) form, dwarf_names_print_on_error)); } else { printf(" <0x%08lx> %-28s%s\n", (unsigned long) off, get_AT_name(attr, dwarf_names_print_on_error), get_FORM_name((Dwarf_Half) form, dwarf_names_print_on_error)); } } dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); offset += length; if (dense) { printf("\n"); } } if (abres == DW_DLV_ERROR) { print_error(dbg, "dwarf_get_abbrev", abres, paerr); } }
/* Calculate the number of abbreviations for the current CU and set up basic abbreviations array info, storing the number of attributes per abbreviation */ void get_abbrev_array_info(Dwarf_Debug dbg, Dwarf_Unsigned offset_in) { Dwarf_Unsigned offset = offset_in; if (check_abbreviations) { Dwarf_Abbrev ab = 0; Dwarf_Unsigned length = 0; Dwarf_Unsigned abbrev_entry_count = 0; Dwarf_Unsigned abbrev_code; int abres = DW_DLV_OK; Dwarf_Error aberr = 0; Dwarf_Unsigned last_abbrev_code = 0; Dwarf_Bool bMore = TRUE; Dwarf_Unsigned CU_abbrev_count = 0; if (abbrev_array == NULL) { /* Allocate initial abbreviation array info */ abbrev_array_size = ABBREV_ARRAY_INITIAL_SIZE; abbrev_array = (Dwarf_Unsigned *) calloc(abbrev_array_size,sizeof(Dwarf_Unsigned)); } else { /* Clear out values from previous CU */ memset((void *)abbrev_array,0, (abbrev_array_size) * sizeof(Dwarf_Unsigned)); } while (bMore && (abres = dwarf_get_abbrev(dbg, offset, &ab, &length, &abbrev_entry_count, &aberr)) == DW_DLV_OK) { dwarf_get_abbrev_code(ab,&abbrev_code,&aberr); if (abbrev_code == 0) { /* End of abbreviation table for this CU */ ++offset; /* Skip abbreviation code */ bMore = FALSE; } else { /* Valid abbreviation code. We hope. */ if (abbrev_code > 0) { check_abbrev_num_sequence(abbrev_code,last_abbrev_code, abbrev_array_size,abbrev_entry_count,CU_abbrev_count); while (abbrev_code >= abbrev_array_size) { Dwarf_Unsigned old_size = abbrev_array_size; size_t addl_size_bytes = old_size * sizeof(Dwarf_Unsigned); /* Resize abbreviation array. Only a bogus abbreviation number will iterate more than once, and it will be caught later. Or we will run out of memory! */ abbrev_array_size *= 2; abbrev_array = (Dwarf_Unsigned *) realloc(abbrev_array, abbrev_array_size * sizeof(Dwarf_Unsigned)); /* Zero out the new bytes. */ memset(abbrev_array + old_size,0,addl_size_bytes); } check_reused_code(abbrev_code, abbrev_entry_count); abbrev_array[abbrev_code] = abbrev_entry_count; ++CU_abbrev_count; offset += length; } else { /* Invalid abbreviation code */ print_error(dbg, "get_abbrev_array_info", abres, aberr); } last_abbrev_code = abbrev_code; } dwarf_dealloc(dbg, ab, DW_DLA_ABBREV); } } }