From: Nick Clifton Date: Fri, 17 Apr 2026 11:17:27 +0000 (+0100) Subject: Add --debug-dir option to readelf and objdumo. Load separate debug info files when... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bfd118583ed69db365265915d1a48eb719e997f5;p=thirdparty%2Fbinutils-gdb.git Add --debug-dir option to readelf and objdumo. Load separate debug info files when disassemblng. --- diff --git a/binutils/NEWS b/binutils/NEWS index 1a3c25d1fe7..5ac0e8b7811 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -1,5 +1,8 @@ -*- text -*- +* Objdump and readelf now have a --debug-dir= option which can be used to + tell them where to find separate debug info files. + * Add --map-global-vars option to objdump which displays the location and type of global variables in object files. This feature was developed by Guillaume Vacherias . diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index 8025458b2fa..59ffe548543 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -2350,6 +2350,7 @@ objdump [@option{-a}|@option{--archive-headers}] [@option{-WN}|@option{--dwarf=no-follow-links}] [@option{-WD}|@option{--dwarf=use-debuginfod}] [@option{-WE}|@option{--dwarf=do-not-use-debuginfod}] + [@option{--debug-dir=@file{dir}}] [@option{--map-global-vars}] [@option{-L}|@option{--process-links}] [@option{--ctf=}@var{section}] @@ -2999,6 +3000,9 @@ The @option{off} argument disables colored disassembly. @item --dwarf-check Enable additional checks for consistency of Dwarf information. +@item --debug-dir=@file{dir} +Search @file{dir} when looking for separate debug info files. + @include ctf.options.texi @include sframe.options.texi @@ -5172,6 +5176,7 @@ readelf [@option{-a}|@option{--all}] [@option{-wN}|@option{--debug-dump=no-follow-links}] [@option{-wD}|@option{--debug-dump=use-debuginfod}] [@option{-wE}|@option{--debug-dump=do-not-use-debuginfod}] + [@option{--debug-dir=@file{dir}}] [@option{-P}|@option{--process-links}] [@option{--dwarf-depth=@var{n}}] [@option{--dwarf-start=@var{n}}] @@ -5477,6 +5482,9 @@ command to @command{ar}, but without using the BFD library. @xref{ar}. @itemx --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=str-offsets,=loc,=Ranges,=pubtypes,=trace_info,=trace_abbrev,=trace_aranges,=gdb_index,=addr,=cu_index,=links,=follow-links] @include debug.options.texi +@item --debug-dir=@file{dir} +Search @file{dir} when looking for separate debug info files. + @item -P @itemx --process-links Display the contents of non-debug sections found in separate debuginfo diff --git a/binutils/dwarf.c b/binutils/dwarf.c index fa8dce25d44..42386154b49 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -125,6 +125,8 @@ separate_info * first_separate_info = NULL; unsigned int eh_addr_size; +const char * separate_debug_info_dir = NULL; + int do_debug_info; int do_debug_abbrevs; int do_debug_lines; @@ -13379,17 +13381,22 @@ load_separate_debug_info (const char * main_filename, #define EXTRA_DEBUG_ROOT2 "/usr/lib/debug/usr" #endif - debug_filename = (char *) malloc (strlen (DEBUGDIR) + 1 - + canon_dirlen - + strlen (".debug/") + unsigned long len = strlen (DEBUGDIR) + 1 + + canon_dirlen + + strlen (".debug/") #ifdef EXTRA_DEBUG_ROOT1 - + strlen (EXTRA_DEBUG_ROOT1) + + strlen (EXTRA_DEBUG_ROOT1) #endif #ifdef EXTRA_DEBUG_ROOT2 - + strlen (EXTRA_DEBUG_ROOT2) + + strlen (EXTRA_DEBUG_ROOT2) #endif - + strlen (separate_filename) - + 1); + + strlen (separate_filename) + + 1; + + if (separate_debug_info_dir) + len += strlen (separate_debug_info_dir); + + debug_filename = (char *) malloc (len); if (debug_filename == NULL) { warn (_("Out of memory\n")); @@ -13398,7 +13405,15 @@ load_separate_debug_info (const char * main_filename, return NULL; } - /* First try in the current directory. */ + /* If the user has supplied a debug info directory then try that first. */ + if (separate_debug_info_dir != NULL) + { + sprintf (debug_filename, "%s/%s", separate_debug_info_dir, separate_filename); + if (check_func (debug_filename, func_data)) + goto found; + } + + /* Next try in the current directory. */ sprintf (debug_filename, "%s", separate_filename); if (check_func (debug_filename, func_data)) goto found; @@ -13425,7 +13440,7 @@ load_separate_debug_info (const char * main_filename, goto found; /* Try the first extra debug file root. */ - sprintf (debug_filename, "%s/%s/%s", EXTRA_DEBUG_ROOT1, canon_dir, separate_filename); + sprintf (debug_filename, "%s/%s%s", EXTRA_DEBUG_ROOT1, canon_dir, separate_filename); if (check_func (debug_filename, func_data)) goto found; #endif @@ -13468,37 +13483,19 @@ load_separate_debug_info (const char * main_filename, if (do_debug_links) { /* Failed to find the file. */ - warn (_("could not find separate debug file '%s'\n"), - separate_filename); - warn (_("tried: %s\n"), debug_filename); - -#ifdef EXTRA_DEBUG_ROOT2 - sprintf (debug_filename, "%s/%s", EXTRA_DEBUG_ROOT2, - separate_filename); - warn (_("tried: %s\n"), debug_filename); -#endif - + warn (_("could not find separate debug file '%s'\n"), separate_filename); + if (separate_debug_info_dir != NULL) + warn (_("tried: %s/%s\n"), separate_debug_info_dir, separate_filename); + warn (_("tried: %s\n"), separate_filename); + warn (_("tried: .debug/%s\n"), separate_filename); + warn (_("tried: %s%s\n"), canon_dir, separate_filename); #ifdef EXTRA_DEBUG_ROOT1 - sprintf (debug_filename, "%s/%s/%s", EXTRA_DEBUG_ROOT1, - canon_dir, separate_filename); - warn (_("tried: %s\n"), debug_filename); - - sprintf (debug_filename, "%s/%s", EXTRA_DEBUG_ROOT1, - separate_filename); - warn (_("tried: %s\n"), debug_filename); + warn (_("tried: %s/%s\n"), EXTRA_DEBUG_ROOT1, separate_filename); + warn (_("tried: %s/%s%s\n"), EXTRA_DEBUG_ROOT1, canon_dir, separate_filename); +#endif +#ifdef EXTRA_DEBUG_ROOT2 + warn (_("tried: %s/%s\n"), EXTRA_DEBUG_ROOT2, separate_filename); #endif - - sprintf (debug_filename, "%s.debug/%s", canon_dir, - separate_filename); - warn (_("tried: %s\n"), debug_filename); - - sprintf (debug_filename, "%s%s", canon_dir, separate_filename); - warn (_("tried: %s\n"), debug_filename); - - sprintf (debug_filename, ".debug/%s", separate_filename); - warn (_("tried: %s\n"), debug_filename); - - sprintf (debug_filename, "%s", separate_filename); warn (_("tried: %s\n"), debug_filename); #if HAVE_LIBDEBUGINFOD @@ -13547,6 +13544,7 @@ load_separate_debug_info (const char * main_filename, if (do_debug_links) printf (_("\n%s: Found separate debug info file: %s\n"), main_filename, debug_filename); + add_separate_debug_file (debug_filename, debug_handle); /* Do not free debug_filename - it might be referenced inside @@ -13906,6 +13904,7 @@ load_separate_debug_files (void * file, const char * filename) /* FIXME: We do not check for the presence of a dwo link as well as a debuglink. */ check_for_and_load_links (file, filename); + if (first_separate_info != NULL) return true; diff --git a/binutils/dwarf.h b/binutils/dwarf.h index 3ab25933052..e6b51bf368e 100644 --- a/binutils/dwarf.h +++ b/binutils/dwarf.h @@ -462,6 +462,7 @@ typedef struct separate_info extern separate_info * first_separate_info; extern unsigned int eh_addr_size; +extern const char * separate_debug_info_dir; extern int do_debug_info; extern int do_debug_abbrevs; diff --git a/binutils/objdump.c b/binutils/objdump.c index 8b6021a20fe..944b81b17e0 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -160,7 +160,6 @@ static enum color_selection off; #endif -static int dump_any_debugging; static int demangle_flags = DMGL_ANSI | DMGL_PARAMS; /* This is reset to false each time we enter the disassembler, and set true @@ -328,6 +327,8 @@ usage (FILE *stream, int status) -WE --dwarf=do-not-use-debuginfod\n\ When following links, do not query debuginfod servers\n")); #endif + fprintf (stream, _("\ + --debug-dir= Search DIR for debug info files\n")); fprintf (stream, _("\ --map-global-vars Display memory mapping of global variables\n")); fprintf (stream, _("\ @@ -481,6 +482,7 @@ enum option_values OPTION_START_ADDRESS, OPTION_STOP_ADDRESS, OPTION_DWARF, + OPTION_DEBUG_DIR, OPTION_PREFIX, OPTION_PREFIX_STRIP, OPTION_INSN_WIDTH, @@ -514,6 +516,7 @@ static struct option long_options[]= {"ctf-parent", required_argument, NULL, OPTION_CTF_PARENT}, {"ctf-parent-section", required_argument, NULL, OPTION_CTF_PARENT_SECTION}, #endif + {"debug-dir", required_argument, NULL, OPTION_DEBUG_DIR}, {"debugging", no_argument, NULL, 'g'}, {"debugging-tags", no_argument, NULL, 'e'}, {"decompress", no_argument, NULL, 'Z'}, @@ -4402,9 +4405,6 @@ load_debug_section (enum dwarf_section_display_enum debug, void *file) asection *sec; const char *name; - if (!dump_any_debugging) - return false; - /* If it is already loaded, do nothing. */ if (section->start != NULL) { @@ -5742,6 +5742,9 @@ might_need_separate_debug_info (bool is_mainfile) return true; if (process_links || dump_symtab || dump_debugging + /* Disassembly benefits from symbol tables, which might + be stored in the separate debug info file. */ + || disassemble || dump_dwarf_section_info || with_source_code) return true; @@ -5765,7 +5768,9 @@ dump_bfd (bfd *abfd, bool is_mainfile) /* Load any separate debug information files. */ if (byte_get != NULL && might_need_separate_debug_info (is_mainfile)) { - load_separate_debug_files (abfd, bfd_get_filename (abfd)); + /* Since it is possible that there are no separate debug files, + do not complain if calling load_separate_debug_files returns false. */ + (void) load_separate_debug_files (abfd, bfd_get_filename (abfd)); /* If asked to do so, recursively dump the separate files. */ if (do_follow_links) @@ -6386,6 +6391,9 @@ main (int argc, char **argv) case OPTION_DWARF_CHECK: dwarf_check = true; break; + case OPTION_DEBUG_DIR: + separate_debug_info_dir = optarg; + break; #ifdef ENABLE_LIBCTF case OPTION_CTF: dump_ctf_section_info = true; @@ -6474,12 +6482,6 @@ main (int argc, char **argv) if (!seenflag) usage (stderr, 2); - dump_any_debugging = (dump_debugging - || dump_dwarf_section_info - || dump_global_vars - || process_links - || with_source_code); - if (formats_info) exit_status = display_info (); else diff --git a/binutils/readelf.c b/binutils/readelf.c index 869bb23e48f..7b2c1c9ae88 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -6471,6 +6471,7 @@ enum long_option_values OPTION_DWARF_DEPTH, OPTION_DWARF_START, OPTION_DWARF_CHECK, + OPTION_DEBUG_DIR, OPTION_CTF_DUMP, OPTION_CTF_PARENT, OPTION_CTF_SYMBOLS, @@ -6537,6 +6538,7 @@ static struct option options[] = {"dwarf-depth", required_argument, 0, OPTION_DWARF_DEPTH}, {"dwarf-start", required_argument, 0, OPTION_DWARF_START}, {"dwarf-check", no_argument, 0, OPTION_DWARF_CHECK}, + {"debug-dir", required_argument, NULL, OPTION_DEBUG_DIR}, #ifdef ENABLE_LIBCTF {"ctf", required_argument, 0, OPTION_CTF_DUMP}, {"ctf-symbols", required_argument, 0, OPTION_CTF_SYMBOLS}, @@ -6680,6 +6682,8 @@ usage (FILE * stream) --dwarf-depth=N Do not display DIEs at depth N or greater\n")); fprintf (stream, _("\ --dwarf-start=N Display DIEs starting at offset N\n")); + fprintf (stream, _("\ + --debug-dir= Search DIR for debug info files\n")); #ifdef ENABLE_LIBCTF fprintf (stream, _("\ --ctf= Display CTF info from section \n")); @@ -6959,6 +6963,9 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv) case OPTION_DWARF_CHECK: dwarf_check = true; break; + case OPTION_DEBUG_DIR: + separate_debug_info_dir = optarg; + break; case OPTION_CTF_DUMP: request_dump (dumpdata, CTF_DUMP); break;