[RFC] Group errors for many missing shared libraries

Pedro Alves
2010-04-12T10:30:19Z

This patch groups errors for many missing shared libraries. For
example, With a linux gdb pointing at a sysroot containing only ld.so
(and doing "set sysroot /home/pedro/garbage/test_sysroot"),
with a patched GDB one sees this:

warning: Could not load shared library symbols for 10 libraries, e.g. /lib/libncurses.so.5.
Do you need "set solib-search-path" or "set sysroot"?

instead of:

(top-gdb) set sysroot /home/pedro/garbage/test_sysroot
(top-gdb) start
Temporary breakpoint 3 at 0x4572b3: file ../../src/gdb/gdb.c, line 28.
Starting program: /home/pedro/gdb/baseline/build/gdb/gdb
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
Error while mapping shared library sections:
/lib/libncurses.so.5: No such file or directory.
Error while mapping shared library sections:
/lib/libz.so.1: No such file or directory.
Error while mapping shared library sections:
/lib/libm.so.6: No such file or directory.
Error while mapping shared library sections:
/usr/lib/libpython2.6.so.1.0: No such file or directory.
Error while mapping shared library sections:
/lib/libexpat.so.1: No such file or directory.
Error while mapping shared library sections:
/lib/libdl.so.2: No such file or directory.
Error while mapping shared library sections:
/lib/libc.so.6: No such file or directory.
Error while mapping shared library sections:
/lib/libpthread.so.0: No such file or directory.
Error while mapping shared library sections:
/lib/libutil.so.1: No such file or directory.
Error while mapping shared library sections:
/lib64/ld-linux-x86-64.so.2: No such file or directory.
:
:

Temporary breakpoint 3, main (argc=1, argv=0x7fffffffe148) at ../../src/gdb/gdb.c:28
28 memset (&args, 0, sizeof args);
(top-gdb)

You can later still do "info sharedlibrary" to check
exactly which shared libraries don't have symbols read in:

(top-gdb) info sharedlibrary
From To Syms Read Shared Object Library
No /lib/libncurses.so.5
No /lib/libz.so.1
No /lib/libm.so.6
No /usr/lib/libpython2.6.so.1.0
No /lib/libexpat.so.1
No /lib/libdl.so.2
No /lib/libc.so.6
No /lib/libpthread.so.0
No /lib/libutil.so.1
No /lib64/ld-linux-x86-64.so.2
(top-gdb)

Daniel originaly wrote for SymbianOS, where a GUI application is
normally linked to many many dlls; forgetting to set the proper
sysroot, or not having debug info for the system dlls makes gdb
be very noisy.

WDYT?

--
Pedro Alves

2010-04-12 Daniel Jacobowitz <dan@codesourcery.com>
Pedro Alves <pedro@codesourcery.com>

Group errors for many missing shared libraries, ported from the
symbian-fsf branch.

gdb/
* solist.h (struct so_list): Remove from_tty.
* solib.c: Include "exceptions.h".
(solib_bfd_open): Return NULL if we failed to open a BFD.
(solib_map_sections): Take so_list argument. Return 0 if we
failed to open a BFD. Add target sections here.
(symbol_add_stub): Delete.
(solib_read_symbols): Inline symbol_add_stub. Use current flags,
not from_tty copied from the so_list. Don't warn a second time
for a missing library.
(update_solib_list): Don't save from_tty. Use TRY_CATCH. Do not
add to the section table here. Print out a single warning for all
missing libraries.
* bsd-uthread.c (bsd_uthread_solib_loaded): Always pass 0 for
flags.

---
gdb/bsd-uthread.c | 2
gdb/solib.c | 146 ++++++++++++++++++++++++++++++++++--------------------
gdb/solist.h | 1
3 files changed, 95 insertions(+), 54 deletions(-)

Index: src/gdb/solist.h
===================================================================
--- src.orig/gdb/solist.h 2010-04-12 09:58:14.000000000 +0100
+++ src/gdb/solist.h 2010-04-12 09:59:49.000000000 +0100
@@ -63,7 +63,6 @@ struct so_list

bfd *abfd;
char symbols_loaded; /* flag: symbols read in yet? */
- char from_tty; /* flag: print msgs? */
struct objfile *objfile; /* objfile for loaded lib */
struct target_section *sections;
struct target_section *sections_end;
Index: src/gdb/solib.c
===================================================================
--- src.orig/gdb/solib.c 2010-04-12 09:58:14.000000000 +0100
+++ src/gdb/solib.c 2010-04-12 10:02:08.000000000 +0100
@@ -43,6 +43,7 @@
#include "exec.h"
#include "solist.h"
#include "observer.h"
+#include "exceptions.h"
#include "readline/readline.h"
#include "remote.h"
#include "solib.h"
@@ -319,7 +320,14 @@ solib_bfd_open (char *pathname)
/* Search for shared library file. */
found_pathname = solib_find (pathname, &found_file);
if (found_pathname == NULL)
- perror_with_name (pathname);
+ {
+ /* Return failure if the file could not be found, so that we can
+ accumulate messages about missing libraries. */
+ if (errno == ENOENT)
+ return NULL;
+
+ perror_with_name (pathname);
+ }

/* Open bfd for shared library. */
abfd = solib_bfd_fopen (found_pathname, found_file);
@@ -372,9 +380,8 @@ solib_bfd_open (char *pathname)
*/

static int
-solib_map_sections (void *arg)
+solib_map_sections (struct so_list *so)
{
- struct so_list *so = (struct so_list *) arg; /* catch_errors bogon */
struct target_so_ops *ops = solib_ops (target_gdbarch);
char *filename;
struct target_section *p;
@@ -386,6 +393,9 @@ solib_map_sections (void *arg)
abfd = ops->bfd_open (filename);
do_cleanups (old_chain);

+ if (abfd == NULL)
+ return 0;
+
/* Leave bfd open, core_xfer_memory and "info files" need it. */
so->abfd = gdb_bfd_ref (abfd);

@@ -419,6 +429,12 @@ solib_map_sections (void *arg)
}
}

+ /* Add the shared object's sections to the current set of file
+ section tables. Do this immediately after mapping the object so
+ that later nodes in the list can query this object, as is needed
+ in solib-osf.c. */
+ add_target_sections (so->sections, so->sections_end);
+
return (1);
}

@@ -466,27 +482,6 @@ master_so_list (void)
return so_list_head;
}

-static void
-symbol_add_stub (struct so_list *so, int flags)
-{
- struct section_addr_info *sap;
-
- /* Have we already loaded this shared object? */
- ALL_OBJFILES (so->objfile)
- {
- if (strcmp (so->objfile->name, so->so_name) == 0)
- return;
- }
-
- sap = build_section_addr_info_from_section_table (so->sections,
- so->sections_end);
-
- so->objfile = symbol_file_add_from_bfd (so->abfd, flags, sap, OBJF_SHARED);
- free_section_addr_info (sap);
-
- return;
-}
-
/* Read in symbols for shared object SO. If SYMFILE_VERBOSE is set in FLAGS,
be chatty about it. Return non-zero if any symbols were actually
loaded. */
@@ -503,25 +498,46 @@ solib_read_symbols (struct so_list *so,
}
else if (so->abfd == NULL)
{
- if (from_tty || info_verbose)
- printf_unfiltered (_("Symbol file not found for %s\n"), so->so_name);
+ /* We've already warned about this library, when trying to open
+ it. */
}
else
{
- volatile struct gdb_exception exception;
- TRY_CATCH (exception, RETURN_MASK_ALL)
- {
- symbol_add_stub (so, flags);
- }
- if (exception.reason != 0)
- {
- exception_fprintf (gdb_stderr, exception,
- "Error while reading shared library symbols:\n");
- return 0;
- }
- if (from_tty || info_verbose)
- printf_unfiltered (_("Loaded symbols for %s\n"), so->so_name);
- so->symbols_loaded = 1;
+ volatile struct gdb_exception e;
+
+ TRY_CATCH (e, RETURN_MASK_ERROR)
+ {
+ struct section_addr_info *sap;
+
+ /* Have we already loaded this shared object? */
+ ALL_OBJFILES (so->objfile)
+ {
+ if (strcmp (so->objfile->name, so->so_name) == 0)
+ break;
+ }
+ if (so->objfile != NULL)
+ break;
+
+ sap = build_section_addr_info_from_section_table (so->sections,
+ so->sections_end);
+ so->objfile = symbol_file_add_from_bfd (so->abfd,
+ flags, sap, OBJF_SHARED);
+ free_section_addr_info (sap);
+ }
+
+ if (e.reason < 0)
+ {
+ if (from_tty)
+ exception_fprintf
+ (gdb_stderr, e,
+ _("Error while reading shared library symbols:\n"));
+ }
+ else
+ {
+ if (from_tty || info_verbose)
+ printf_unfiltered (_("Loaded symbols for %s\n"), so->so_name);
+ so->symbols_loaded = 1;
+ }
return 1;
}

@@ -667,6 +683,9 @@ update_solib_list (int from_tty, struct
to GDB's shared object list. */
if (inferior)
{
+ int not_found = 0;
+ const char *not_found_filename = NULL;
+
struct so_list *i;

/* Add the new shared objects to GDB's list. */
@@ -675,24 +694,47 @@ update_solib_list (int from_tty, struct
/* Fill in the rest of each of the `struct so_list' nodes. */
for (i = inferior; i; i = i->next)
{
- i->from_tty = from_tty;
+ volatile struct gdb_exception e;
+
i->pspace = current_program_space;

- /* Fill in the rest of the `struct so_list' node. */
- catch_errors (solib_map_sections, i,
- "Error while mapping shared library sections:\n",
- RETURN_MASK_ALL);
-
- /* Add the shared object's sections to the current set of
- file section tables. Do this immediately after mapping
- the object so that later nodes in the list can query this
- object, as is needed in solib-osf.c. */
- add_target_sections (i->sections, i->sections_end);
+ TRY_CATCH (e, RETURN_MASK_ERROR)
+ {
+ /* Fill in the rest of the `struct so_list' node. */
+ if (!solib_map_sections (i))
+ {
+ not_found++;
+ if (not_found_filename == NULL)
+ not_found_filename = i->so_original_name;
+ }
+ }
+
+ if (e.reason < 0)
+ exception_fprintf (gdb_stderr, e, _("\
+Error while mapping shared library sections:\n"));

/* Notify any observer that the shared object has been
- loaded now that we've added it to GDB's tables. */
+ loaded now that we've added it to GDB's tables. */
observer_notify_solib_loaded (i);
}
+
+ /* If a library was not found, issue an appropriate warning
+ message. We have to use a single call to warning in case the
+ front end does something special with warnings, e.g., pop up
+ a dialog box. It Would Be Nice if we could get a "warning: "
+ prefix on each line in the CLI front end, though - it doesn't
+ stand out well. */
+
+ if (not_found == 1)
+ warning (_("\
+Could not load shared library symbols for %s.\n\
+Do you need \"set solib-search-path\" or \"set sysroot\"?"),
+ not_found_filename);
+ else if (not_found > 1)
+ warning (_("\
+Could not load shared library symbols for %d libraries, e.g. %s.\n\
+Do you need \"set solib-search-path\" or \"set sysroot\"?"),
+ not_found, not_found_filename);
}
}

Index: src/gdb/bsd-uthread.c
===================================================================
--- src.orig/gdb/bsd-uthread.c 2010-04-12 09:58:14.000000000 +0100
+++ src/gdb/bsd-uthread.c 2010-04-12 09:59:49.000000000 +0100
@@ -250,7 +250,7 @@ bsd_uthread_solib_loaded (struct so_list
{
if (strncmp (so->so_original_name, *names, strlen (*names)) == 0)
{
- solib_read_symbols (so, so->from_tty ? SYMFILE_VERBOSE : 0);
+ solib_read_symbols (so, 0);

if (bsd_uthread_activate (so->objfile))
{