X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=binutils%2Fdwarf.c;h=598f8562abf2bee8b8a9240ec3cf118f6ba12fc2;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=130ba10be3eb6be7fbf22a3e4a2a4ea90ab7c9f3;hpb=b3adc24a0713411ab38a21dc894dd40dbc5c8f4f;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 130ba10be3..598f8562ab 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -32,6 +32,10 @@ #include "safe-ctype.h" #include +#ifdef HAVE_LIBDEBUGINFOD +#include +#endif + #undef MAX #undef MIN #define MAX(a, b) ((a) > (b) ? (a) : (b)) @@ -94,6 +98,7 @@ int do_debug_cu_index; int do_wide; int do_debug_links; int do_follow_links; +bfd_boolean do_checks; int dwarf_cutoff_level = -1; unsigned long dwarf_start_die; @@ -2004,7 +2009,7 @@ read_and_print_leb128 (unsigned char * data, int status; dwarf_vma val = read_leb128 (data, end, is_signed, bytes_read, &status); if (status != 0) - report_leb_status (status); + report_leb_status (status, __FILE__, __LINE__); else printf ("%s", dwarf_vmatoa (is_signed ? "d" : "u", val)); } @@ -3618,7 +3623,6 @@ read_debug_line_header (struct dwarf_section * section, { unsigned char *hdrptr; unsigned int initial_length_size; - unsigned char address_size, segment_selector_size; /* Extract information from the Line Number Program Header. (section 6.2.4 in the Dwarf3 doc). */ @@ -3675,15 +3679,15 @@ read_debug_line_header (struct dwarf_section * section, if (linfo->li_version >= 5) { - SAFE_BYTE_GET_AND_INC (address_size, hdrptr, 1, end); + SAFE_BYTE_GET_AND_INC (linfo->li_address_size, hdrptr, 1, end); - SAFE_BYTE_GET_AND_INC (segment_selector_size, hdrptr, 1, end); - if (segment_selector_size != 0) + SAFE_BYTE_GET_AND_INC (linfo->li_segment_size, hdrptr, 1, end); + if (linfo->li_segment_size != 0) { warn (_("The %s section contains " "unsupported segment selector size: %d.\n"), - section->name, segment_selector_size); - return 0; + section->name, linfo->li_segment_size); + return NULL; } } @@ -3733,8 +3737,13 @@ display_formatted_table (unsigned char * data, unsigned char *format_start, format_count, *format, formati; dwarf_vma data_count, datai; unsigned int namepass, last_entry = 0; - + const char * table_name = is_dir ? N_("Directory Table") : N_("File Name Table"); + SAFE_BYTE_GET_AND_INC (format_count, data, 1, end); + if (do_checks && format_count > 5) + warn (_("Unexpectedly large number of columns in the %s (%u)\n"), + table_name, format_count); + format_start = data; for (formati = 0; formati < format_count; formati++) { @@ -3742,39 +3751,34 @@ display_formatted_table (unsigned char * data, SKIP_ULEB (data, end); if (data == end) { - if (is_dir) - warn (_("Corrupt directory format table entry\n")); - else - warn (_("Corrupt file name format table entry\n")); + warn (_("%s: Corrupt format description entry\n"), table_name); return data; } } READ_ULEB (data_count, data, end); - if (data == end) + if (data_count == 0) { - if (is_dir) - warn (_("Corrupt directory list\n")); - else - warn (_("Corrupt file name list\n")); + printf (_("\n The %s is empty.\n"), table_name); return data; } - - if (data_count == 0) + else if (data == end) { - if (is_dir) - printf (_("\n The Directory Table is empty.\n")); - else - printf (_("\n The File Name Table is empty.\n")); + warn (_("%s: Corrupt entry count - expected %s but none found\n"), + table_name, dwarf_vmatoa ("x", data_count)); return data; } - if (is_dir) - printf (_("\n The Directory Table (offset 0x%lx):\n"), - (long) (data - start)); - else - printf (_("\n The File Name Table (offset 0x%lx):\n"), - (long) (data - start)); + else if (format_count == 0) + { + warn (_("%s: format count is zero, but the table is not empty\n"), + table_name); + return end; + } + + printf (_("\n The %s (offset 0x%lx, lines %s, columns %u):\n"), + table_name, (long) (data - start), dwarf_vmatoa ("u", data_count), + format_count); printf (_(" Entry")); /* Delay displaying name as the last entry for better screen layout. */ @@ -3802,7 +3806,7 @@ display_formatted_table (unsigned char * data, printf (_("\tSize")); break; case DW_LNCT_MD5: - printf (_("\tMD5")); + printf (_("\tMD5\t\t\t")); break; default: printf (_("\t(Unknown format content type %s)"), @@ -3836,12 +3840,10 @@ display_formatted_table (unsigned char * data, section, NULL, '\t', -1); } } - if (data == end) + + if (data == end && (datai < data_count - 1)) { - if (is_dir) - warn (_("Corrupt directory entries list\n")); - else - warn (_("Corrupt file name entries list\n")); + warn (_("\n%s: Corrupt entries list\n"), table_name); return data; } putchar ('\n'); @@ -3905,6 +3907,11 @@ display_debug_lines_raw (struct dwarf_section * section, printf (_(" Offset: 0x%lx\n"), (long)(data - start)); printf (_(" Length: %ld\n"), (long) linfo.li_length); printf (_(" DWARF Version: %d\n"), linfo.li_version); + if (linfo.li_version >= 5) + { + printf (_(" Address size (bytes): %d\n"), linfo.li_address_size); + printf (_(" Segment selector (bytes): %d\n"), linfo.li_segment_size); + } printf (_(" Prologue Length: %d\n"), (int) linfo.li_prologue_length); printf (_(" Minimum Instruction Length: %d\n"), linfo.li_min_insn_length); if (linfo.li_version >= 4) @@ -4342,6 +4349,9 @@ display_debug_lines_decoded (struct dwarf_section * section, /* Skip directories format. */ SAFE_BYTE_GET_AND_INC (format_count, data, 1, end); + if (do_checks && format_count > 1) + warn (_("Unexpectedly large number of columns in the directory name table (%u)\n"), + format_count); format_start = data; for (formati = 0; formati < format_count; formati++) { @@ -4356,8 +4366,11 @@ display_debug_lines_decoded (struct dwarf_section * section, break; } - directory_table = (unsigned char **) - xmalloc (n_directories * sizeof (unsigned char *)); + if (n_directories == 0) + directory_table = NULL; + else + directory_table = (unsigned char **) + xmalloc (n_directories * sizeof (unsigned char *)); for (entryi = 0; entryi < n_directories; entryi++) { @@ -4410,6 +4423,9 @@ display_debug_lines_decoded (struct dwarf_section * section, /* Skip files format. */ SAFE_BYTE_GET_AND_INC (format_count, data, 1, end); + if (do_checks && format_count > 5) + warn (_("Unexpectedly large number of columns in the file name table (%u)\n"), + format_count); format_start = data; for (formati = 0; formati < format_count; formati++) { @@ -4418,14 +4434,17 @@ display_debug_lines_decoded (struct dwarf_section * section, } READ_ULEB (n_files, data, end); - if (data == end) + if (data == end && n_files > 0) { warn (_("Corrupt file name list\n")); break; } - file_table = (File_Entry *) xcalloc (1, n_files - * sizeof (File_Entry)); + if (n_files == 0) + file_table = NULL; + else + file_table = (File_Entry *) xcalloc (1, n_files + * sizeof (File_Entry)); for (entryi = 0; entryi < n_files; entryi++) { @@ -4581,7 +4600,7 @@ display_debug_lines_decoded (struct dwarf_section * section, /* Print the Compilation Unit's name and a header. */ if (file_table == NULL) - ; + printf (_("CU: No directory table\n")); else if (directory_table == NULL) printf (_("CU: %s:\n"), file_table[0].name); else @@ -4609,7 +4628,10 @@ display_debug_lines_decoded (struct dwarf_section * section, printf ("%s:\n", file_table[0].name); } - printf (_("File name Line number Starting address View Stmt\n")); + if (n_files > 0) + printf (_("File name Line number Starting address View Stmt\n")); + else + printf (_("CU: Empty file name table\n")); saved_linfo = linfo; } @@ -4901,6 +4923,11 @@ display_debug_lines_decoded (struct dwarf_section * section, strncpy (newFileName, fileName + fileNameLength - MAX_FILENAME_LENGTH, MAX_FILENAME_LENGTH + 1); + /* FIXME: This is to pacify gcc-10 which can warn that the + strncpy above might leave a non-NUL terminated string + in newFileName. It won't, but gcc's analysis doesn't + quite go far enough to discover this. */ + newFileName[MAX_FILENAME_LENGTH] = 0; } else { @@ -6917,6 +6944,7 @@ display_debug_ranges (struct dwarf_section *section, int is_rnglists = strstr (section->name, "debug_rnglists") != NULL; /* Initialize it due to a false compiler warning. */ unsigned char address_size = 0; + dwarf_vma last_offset = 0; if (bytes == 0) { @@ -7072,6 +7100,15 @@ display_debug_ranges (struct dwarf_section *section, continue; } + /* If multiple DWARF entities reference the same range then we will + have multiple entries in the `range_entries' list for the same + offset. Thanks to the sort above these will all be consecutive in + the `range_entries' list, so we can easily ignore duplicates + here. */ + if (i > 0 && last_offset == offset) + continue; + last_offset = offset; + if (dwarf_check != 0 && i > 0) { if (start < next) @@ -7372,7 +7409,8 @@ regname_internal_riscv (unsigned int regno) document. */ switch (regno) { -#define DECLARE_CSR(NAME,VALUE) case VALUE + 4096: name = #NAME; break; +#define DECLARE_CSR(NAME,VALUE,CLASS,DEFINE_VER,ABORT_VER) \ + case VALUE + 4096: name = #NAME; break; #include "opcode/riscv-opc.h" #undef DECLARE_CSR @@ -7797,6 +7835,7 @@ display_debug_frames (struct dwarf_section *section, unsigned int offset_size; unsigned int initial_length_size; bfd_boolean all_nops; + static Frame_Chunk fde_fc; saved_start = start; @@ -7894,7 +7933,6 @@ display_debug_frames (struct dwarf_section *section, else { unsigned char *look_for; - static Frame_Chunk fde_fc; unsigned long segment_selector; if (is_eh) @@ -8701,6 +8739,17 @@ display_debug_frames (struct dwarf_section *section, if (do_debug_frames_interp && ! all_nops) frame_display_row (fc, &need_col_headers, &max_regs); + if (fde_fc.col_type != NULL) + { + free (fde_fc.col_type); + fde_fc.col_type = NULL; + } + if (fde_fc.col_offset != NULL) + { + free (fde_fc.col_offset); + fde_fc.col_offset = NULL; + } + start = block_end; eh_addr_size = saved_eh_addr_size; } @@ -10128,12 +10177,83 @@ add_separate_debug_file (const char * filename, void * handle) first_separate_info = i; } +#if HAVE_LIBDEBUGINFOD +/* Query debuginfod servers for the target debuglink or debugaltlink + file. If successful, store the path of the file in filename and + return TRUE, otherwise return FALSE. */ + +static bfd_boolean +debuginfod_fetch_separate_debug_info (struct dwarf_section * section, + char ** filename, + void * file) +{ + size_t build_id_len; + unsigned char * build_id; + + if (strcmp (section->uncompressed_name, ".gnu_debuglink") == 0) + { + /* Get the build-id of file. */ + build_id = get_build_id (file); + build_id_len = 0; + } + else if (strcmp (section->uncompressed_name, ".gnu_debugaltlink") == 0) + { + /* Get the build-id of the debugaltlink file. */ + unsigned int filelen; + + filelen = strnlen ((const char *)section->start, section->size); + if (filelen == section->size) + /* Corrupt debugaltlink. */ + return FALSE; + + build_id = section->start + filelen + 1; + build_id_len = section->size - (filelen + 1); + + if (build_id_len == 0) + return FALSE; + } + else + return FALSE; + + if (build_id) + { + int fd; + debuginfod_client * client; + + client = debuginfod_begin (); + if (client == NULL) + return FALSE; + + /* Query debuginfod servers for the target file. If found its path + will be stored in filename. */ + fd = debuginfod_find_debuginfo (client, build_id, build_id_len, filename); + debuginfod_end (client); + + /* Only free build_id if we allocated space for a hex string + in get_build_id (). */ + if (build_id_len == 0) + free (build_id); + + if (fd >= 0) + { + /* File successfully retrieved. Close fd since we want to + use open_debug_file () on filename instead. */ + close (fd); + return TRUE; + } + } + + return FALSE; +} +#endif + static void * load_separate_debug_info (const char * main_filename, struct dwarf_section * xlink, parse_func_type parse_func, check_func_type check_func, - void * func_data) + void * func_data, + void * file ATTRIBUTE_UNUSED) { const char * separate_filename; char * debug_filename; @@ -10235,6 +10355,23 @@ load_separate_debug_info (const char * main_filename, if (check_func (debug_filename, func_data)) goto found; +#if HAVE_LIBDEBUGINFOD + { + char * tmp_filename; + + if (debuginfod_fetch_separate_debug_info (xlink, + & tmp_filename, + file)) + { + /* File successfully downloaded from server, replace + debug_filename with the file's path. */ + free (debug_filename); + debug_filename = tmp_filename; + goto found; + } + } +#endif + /* Failed to find the file. */ warn (_("could not find separate debug file '%s'\n"), separate_filename); warn (_("tried: %s\n"), debug_filename); @@ -10264,6 +10401,16 @@ load_separate_debug_info (const char * main_filename, sprintf (debug_filename, "%s", separate_filename); warn (_("tried: %s\n"), debug_filename); +#if HAVE_LIBDEBUGINFOD + { + char *urls = getenv (DEBUGINFOD_URLS_ENV_VAR); + if (urls == NULL) + urls = ""; + + warn (_("tried: DEBUGINFOD_URLS=%s\n"), urls); + } +#endif + free (canon_dir); free (debug_filename); return NULL; @@ -10410,7 +10557,8 @@ load_separate_debug_files (void * file, const char * filename) & debug_displays[gnu_debugaltlink].section, parse_gnu_debugaltlink, check_gnu_debugaltlink, - & build_id_data); + & build_id_data, + file); } if (load_debug_section (gnu_debuglink, file)) @@ -10421,7 +10569,8 @@ load_separate_debug_files (void * file, const char * filename) & debug_displays[gnu_debuglink].section, parse_gnu_debuglink, check_gnu_debuglink, - & crc32); + & crc32, + file); } if (first_separate_info != NULL)