)]}'
{
  "commit": "fcdc6c5aff198140e0e2c8b94eef48d340e04dbc",
  "tree": "ee4519b58f6d624357031113eb0d43de925d4d49",
  "parents": [
    "7f554749455b363af16be91f3c879664d1b8709c"
  ],
  "author": {
    "name": "Simon Marchi",
    "email": "simon.marchi@efficios.com",
    "time": "Thu Jul 17 15:58:05 2025 -0400"
  },
  "committer": {
    "name": "Simon Marchi",
    "email": "simon.marchi@efficios.com",
    "time": "Fri Aug 22 10:45:47 2025 -0400"
  },
  "message": "gdb/solib: don\u0027t check filename when checking for duplicate solib\n\nOn Arch Linux, I get:\n\n    FAIL: gdb.base/dlmopen-ns-ids.exp: reopen a namespace\n\nThe symptom observed is that after stepping over the last dlmopen of the\ntest, \"info sharedlibrary\" does not show the library just opened.  After\ndigging, I found that when stepping over that dlmopen call, the shlib\nevent breakpoint (that GDB inserts in glibc to get notified of dynamic\nlinker activity) does not get hit.  I then saw that after the previous\ndlclose, the shlib event breakpoints were suddenly all marked as\npending:\n\n    (gdb) maintenance info breakpoints\n    Num     Type             Disp Enb Address            What\n    -1      shlib events     keep n   \u003cPENDING\u003e\n    -1.1                          y-  \u003cPENDING\u003e\n\nThe root cause of this problem is the fact that the dynamic linker path\nspecified in binaries contains a symlink:\n\n    $ readelf --program-headers /bin/ls | grep \"Requesting program interpreter\"\n          [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]\n    $ ls -l /lib64\n    lrwxrwxrwx 1 root root 7 May  3 15:26 /lib64 -\u003e usr/lib\n    $ realpath /lib64/ld-linux-x86-64.so.2\n    /usr/lib/ld-linux-x86-64.so.2\n\nAs a result, the instances of the dynamic linker in the non-base\nnamespace have the real path instead of the original path:\n\n    (gdb) info sharedlibrary\n    From                To                  NS    Syms Read   Shared Object Library\n    0x00007ffff7fc6000  0x00007ffff7fff000  [[0]] Yes         /lib64/ld-linux-x86-64.so.2\n    ...\n    0x00007ffff7fc6000  0x00007ffff7fff000  [[1]] Yes         /usr/lib/ld-linux-x86-64.so.2\n    ...\n    0x00007ffff7fc6000  0x00007ffff7fff000  [[1]] Yes         /usr/lib/ld-linux-x86-64.so.2\n    ...\n    0x00007ffff7fc6000  0x00007ffff7fff000  [[1]] Yes         /usr/lib/ld-linux-x86-64.so.2\n\nNotice that all instances of the dynamic loader have the same address\nrange.  This is expected: the dynamic loader is really loaded just once\nin memory, it\u0027s just that it\u0027s visible in the various namespaces, so\nlisted multiple times.  Also, notice that the last three specify\nnamespace 1... seems like a separate bug to me (ignore it for now).\n\nThe fact that the paths differ between the first one and the subsequent\nones is not something we control: we receive those paths as-is from the\nglibc link map.\n\nSince these multiple solib entries are really the same mapping, we would\nexpect this code in solib_read_symbols to associate them to the same\nobjfile:\n\n\t  /* Have we already loaded this shared object?  */\n\t  so.objfile \u003d nullptr;\n\t  for (objfile *objfile : current_program_space-\u003eobjfiles ())\n\t    {\n\t      if (filename_cmp (objfile_name (objfile), so.name.c_str ())\n\t\t    \u003d\u003d 0\n\t\t  \u0026\u0026 objfile-\u003eaddr_low \u003d\u003d so.addr_low)\n\t\t{\n\t\t  so.objfile \u003d objfile;\n\t\t  break;\n\t\t}\n\t    }\n\nBut because the filenames differ, we end up creating two different\nobjfiles with the same symbols, same address ranges, etc.  I would guess\nthat this is not a state we want.\n\nWhen the dlclose call closes the last library from the non-base\nnamespace, the dynamic linker entry for that namespace is also\nremoved.  From GDB\u0027s point of view, it just looks like an solib getting\nunloaded.  In update_solib_list, we have this code to check if the\nobjfile behind the solib is used by other solibs, and avoid deleting the\nobjfile if so:\n\n\t  bool still_in_use\n\t    \u003d (gdb_iter-\u003eobjfile !\u003d nullptr\n\t       \u0026\u0026 solib_used (current_program_space, *gdb_iter));\n\n\t  /* Notify any observer that the shared object has been\n\t     unloaded before we remove it from GDB\u0027s tables.  */\n\t  notify_solib_unloaded (current_program_space, *gdb_iter,\n\t\t\t\t still_in_use, false);\n\n\t  /* Unless the user loaded it explicitly, free SO\u0027s objfile.  */\n\t  if (gdb_iter-\u003eobjfile !\u003d nullptr\n\t      \u0026\u0026 !(gdb_iter-\u003eobjfile-\u003eflags \u0026 OBJF_USERLOADED)\n\t      \u0026\u0026 !still_in_use)\n\t    gdb_iter-\u003eobjfile-\u003eunlink ();\n\nBecause this is the last solib to use that objfile instance, the objfile\nis deleted.  In the process, disable_breakpoints_in_unloaded_shlib (in\nbreakpoint.c) is called.  The breakpoint locations for the shlib event\nbreakpoints get marked as \"shlib_disabled\", which then causes them (I\nsuppose) to not get inserted and be marked as pending.  And then, when\nstepping on the subsequent dlmopen call, GDB misses the load of the new\nlibrary.\n\nIt seems clear to me that, at least, the duplicate objfile detection in\nsolib_read_symbols needs to be fixed.  Right now, to conclude that an\nsolib matches an existing objfile, it checks that:\n\n - the two have equivalent paths (filename_cmp)\n - the two have the same \"low\" address\n\nIn this patch, I remove the filename check.  This makes it such that all\nthe solibs for dynamic linker entries will share the same objfile.\n\nThis assumes that no two different solibs / objfiles will have the same\nlow address.  At first glance, it seems like a reasonable assumption to\nmake, but I don\u0027t know if there are some corner cases where this is not\ntrue.\n\nTo fix my specific case, I could change the code to resolve the symlinks\nand realize that these are all the same file.  But I don\u0027t think it\nwould work in a general way.  For example, if debugging remotely and\nusing the target: filesystem, we would need to resolve the symlink on\nthe target, and I don\u0027t think we can do that today (there is no\nreadlink/realpath operation in the target file I/O).\n\nWith this patch, gdb.base/dlmopen-ns-ids.exp passes cleanly:\n\n    # of expected passes            44\n\nChange-Id: I3b60051085fb9597b7a72f50122c1104c969908e\nReviewed-By: Guinevere Larsen \u003cguinevere@redhat.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "316ffd64a273945ea87b16bca98dd7dfb53c5733",
      "old_mode": 33188,
      "old_path": "gdb/solib.c",
      "new_id": "edcdce5a1f5ef30ecde834264960fe2a761ab1b5",
      "new_mode": 33188,
      "new_path": "gdb/solib.c"
    }
  ]
}
