Simon Marchi fcdc6c5aff gdb/solib: don't check filename when checking for duplicate solib
On Arch Linux, I get:

    FAIL: gdb.base/dlmopen-ns-ids.exp: reopen a namespace

The symptom observed is that after stepping over the last dlmopen of the
test, "info sharedlibrary" does not show the library just opened.  After
digging, I found that when stepping over that dlmopen call, the shlib
event breakpoint (that GDB inserts in glibc to get notified of dynamic
linker activity) does not get hit.  I then saw that after the previous
dlclose, the shlib event breakpoints were suddenly all marked as
pending:

    (gdb) maintenance info breakpoints
    Num     Type             Disp Enb Address            What
    -1      shlib events     keep n   <PENDING>
    -1.1                          y-  <PENDING>

The root cause of this problem is the fact that the dynamic linker path
specified in binaries contains a symlink:

    $ readelf --program-headers /bin/ls | grep "Requesting program interpreter"
          [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
    $ ls -l /lib64
    lrwxrwxrwx 1 root root 7 May  3 15:26 /lib64 -> usr/lib
    $ realpath /lib64/ld-linux-x86-64.so.2
    /usr/lib/ld-linux-x86-64.so.2

As a result, the instances of the dynamic linker in the non-base
namespace have the real path instead of the original path:

    (gdb) info sharedlibrary
    From                To                  NS    Syms Read   Shared Object Library
    0x00007ffff7fc6000  0x00007ffff7fff000  [[0]] Yes         /lib64/ld-linux-x86-64.so.2
    ...
    0x00007ffff7fc6000  0x00007ffff7fff000  [[1]] Yes         /usr/lib/ld-linux-x86-64.so.2
    ...
    0x00007ffff7fc6000  0x00007ffff7fff000  [[1]] Yes         /usr/lib/ld-linux-x86-64.so.2
    ...
    0x00007ffff7fc6000  0x00007ffff7fff000  [[1]] Yes         /usr/lib/ld-linux-x86-64.so.2

Notice that all instances of the dynamic loader have the same address
range.  This is expected: the dynamic loader is really loaded just once
in memory, it's just that it's visible in the various namespaces, so
listed multiple times.  Also, notice that the last three specify
namespace 1... seems like a separate bug to me (ignore it for now).

The fact that the paths differ between the first one and the subsequent
ones is not something we control: we receive those paths as-is from the
glibc link map.

Since these multiple solib entries are really the same mapping, we would
expect this code in solib_read_symbols to associate them to the same
objfile:

	  /* Have we already loaded this shared object?  */
	  so.objfile = nullptr;
	  for (objfile *objfile : current_program_space->objfiles ())
	    {
	      if (filename_cmp (objfile_name (objfile), so.name.c_str ())
		    == 0
		  && objfile->addr_low == so.addr_low)
		{
		  so.objfile = objfile;
		  break;
		}
	    }

But because the filenames differ, we end up creating two different
objfiles with the same symbols, same address ranges, etc.  I would guess
that this is not a state we want.

When the dlclose call closes the last library from the non-base
namespace, the dynamic linker entry for that namespace is also
removed.  From GDB's point of view, it just looks like an solib getting
unloaded.  In update_solib_list, we have this code to check if the
objfile behind the solib is used by other solibs, and avoid deleting the
objfile if so:

	  bool still_in_use
	    = (gdb_iter->objfile != nullptr
	       && solib_used (current_program_space, *gdb_iter));

	  /* Notify any observer that the shared object has been
	     unloaded before we remove it from GDB's tables.  */
	  notify_solib_unloaded (current_program_space, *gdb_iter,
				 still_in_use, false);

	  /* Unless the user loaded it explicitly, free SO's objfile.  */
	  if (gdb_iter->objfile != nullptr
	      && !(gdb_iter->objfile->flags & OBJF_USERLOADED)
	      && !still_in_use)
	    gdb_iter->objfile->unlink ();

Because this is the last solib to use that objfile instance, the objfile
is deleted.  In the process, disable_breakpoints_in_unloaded_shlib (in
breakpoint.c) is called.  The breakpoint locations for the shlib event
breakpoints get marked as "shlib_disabled", which then causes them (I
suppose) to not get inserted and be marked as pending.  And then, when
stepping on the subsequent dlmopen call, GDB misses the load of the new
library.

It seems clear to me that, at least, the duplicate objfile detection in
solib_read_symbols needs to be fixed.  Right now, to conclude that an
solib matches an existing objfile, it checks that:

 - the two have equivalent paths (filename_cmp)
 - the two have the same "low" address

In this patch, I remove the filename check.  This makes it such that all
the solibs for dynamic linker entries will share the same objfile.

This assumes that no two different solibs / objfiles will have the same
low address.  At first glance, it seems like a reasonable assumption to
make, but I don't know if there are some corner cases where this is not
true.

To fix my specific case, I could change the code to resolve the symlinks
and realize that these are all the same file.  But I don't think it
would work in a general way.  For example, if debugging remotely and
using the target: filesystem, we would need to resolve the symlink on
the target, and I don't think we can do that today (there is no
readlink/realpath operation in the target file I/O).

With this patch, gdb.base/dlmopen-ns-ids.exp passes cleanly:

    # of expected passes            44

Change-Id: I3b60051085fb9597b7a72f50122c1104c969908e
Reviewed-By: Guinevere Larsen <guinevere@redhat.com>
2025-08-22 10:45:47 -04:00
2025-08-22 00:00:11 +00:00
2025-07-13 08:35:45 +01:00
2025-07-13 08:35:45 +01:00
2025-07-23 19:49:50 -04:00
2025-08-07 22:14:49 +09:30
2025-07-19 12:54:32 -07:00
2025-08-07 22:14:49 +09:30
2025-08-07 10:33:44 +01:00
2025-07-31 14:45:21 +01:00
2025-02-28 16:06:25 +00:00
2025-07-13 08:35:45 +01:00

		   README for GNU development tools

This directory contains various GNU compilers, assemblers, linkers, 
debuggers, etc., plus their support routines, definitions, and documentation.

If you are receiving this as part of a GDB release, see the file gdb/README.
If with a binutils release, see binutils/README;  if with a libg++ release,
see libg++/README, etc.  That'll give you info about this
package -- supported targets, how to use it, how to report bugs, etc.

It is now possible to automatically configure and build a variety of
tools with one command.  To build all of the tools contained herein,
run the ``configure'' script here, e.g.:

	./configure 
	make

To install them (by default in /usr/local/bin, /usr/local/lib, etc),
then do:
	make install

(If the configure script can't determine your type of computer, give it
the name as an argument, for instance ``./configure sun4''.  You can
use the script ``config.sub'' to test whether a name is recognized; if
it is, config.sub translates it to a triplet specifying CPU, vendor,
and OS.)

If you have more than one compiler on your system, it is often best to
explicitly set CC in the environment before running configure, and to
also set CC when running make.  For example (assuming sh/bash/ksh):

	CC=gcc ./configure
	make

A similar example using csh:

	setenv CC gcc
	./configure
	make

Much of the code and documentation enclosed is copyright by
the Free Software Foundation, Inc.  See the file COPYING or
COPYING.LIB in the various directories, for a description of the
GNU General Public License terms under which you can copy the files.

REPORTING BUGS: Again, see gdb/README, binutils/README, etc., for info
on where and how to report problems.
Description
Unofficial mirror of sourceware binutils-gdb repository. Updated daily.
Readme 1 GiB
Languages
C 50.5%
Makefile 22.7%
Assembly 13.2%
C++ 5.9%
Roff 1.5%
Other 5.6%