]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Add --debug-dir option to readelf and objdumo. Load separate debug info files when...
authorNick Clifton <nickc@redhat.com>
Fri, 17 Apr 2026 11:17:27 +0000 (12:17 +0100)
committerNick Clifton <nickc@redhat.com>
Fri, 17 Apr 2026 11:17:27 +0000 (12:17 +0100)
binutils/NEWS
binutils/doc/binutils.texi
binutils/dwarf.c
binutils/dwarf.h
binutils/objdump.c
binutils/readelf.c

index 1a3c25d1fe7c31626202a3ef2aa4a14ebeeaf562..5ac0e8b78114c46ccf83f68e0bb8bdf2360d1363 100644 (file)
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Objdump and readelf now have a --debug-dir=<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 <guillaume.vacherias@foss.st.com>.
index 8025458b2fa3ee21d351019e2d6818ac79cc24ee..59ffe54854327ebb2297aba799886d97ae7a93bb 100644 (file)
@@ -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
index fa8dce25d44725b262e99c8ce1e6fd5c14ff6dd4..42386154b496b63b98d250cb2c24d14dbf8fb464 100644 (file)
@@ -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;
 
index 3ab25933052824e9b1561c2c369aebe9050c3ccd..e6b51bf368e85939bae4592e651425fe509484ca 100644 (file)
@@ -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;
index 8b6021a20fe7c92cc08b9447d32258ad1cb5abc7..944b81b17e0419cb2638718095773c95812ea091 100644 (file)
@@ -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=<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
index 869bb23e48f01f121f0032b155847a742dbfeab3..7b2c1c9ae88c9afdbc4962504693add18edf2960 100644 (file)
@@ -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=<DIR>      Search DIR for debug info files\n"));
 #ifdef ENABLE_LIBCTF
   fprintf (stream, _("\
   --ctf=<number|name>    Display CTF info from section <number|name>\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;