)]}'
{
  "commit": "230952d4dc07231e5e01e7744c6dad6ec9ceda4d",
  "tree": "fbe1342cb53bacb9f1900bfbaa260975ac99d992",
  "parents": [
    "5713f3b05038b4b879bdc0922d7c8ab5a9cf76aa"
  ],
  "author": {
    "name": "Simon Marchi",
    "email": "simon.marchi@polymtl.ca",
    "time": "Tue Dec 09 14:32:15 2025 -0500"
  },
  "committer": {
    "name": "Simon Marchi",
    "email": "simon.marchi@polymtl.ca",
    "time": "Wed Jul 08 17:40:41 2026 -0400"
  },
  "message": "gdb: multiple solib_ops per program space\n\nThis patch adds the possibility for a program space to have multiple\nsolib_ops.  The motivation for this is to support ROCm (GPU) debugging\nmore cleanly.\n\nCurrently, when debugging a ROCm program, in order to be able to list\ndevice code objects (the equivalent of shared libraries but for the\nGPU), we install an instance of rocm_solib_ops as the program space\u0027s\nsole solib_ops.  But in order to still be able to list host shared\nlibraries, the rocm_solib_ops wraps the previously installed solib_ops\n(currently always an svr4_solib_ops instance) and forwards method calls\nto it.\n\nBy allowing program spaces to use multiple solib_ops, each solib_ops can\nwork side by side and rocm_solib_ops won\u0027t need to care about the host\nsolib_ops.\n\nThis change starts by making program_space::m_solib_ops a vector of\nsolib_ops_up instead of a single solib_ops_up, and it propagates from\nthere.\n\nprogram_space::set_solib_ops becomes program_space::add_solib_ops.  I\nput in the restriction that there can be only one instance of a given\nkind of solib_ops in the vector (it wouldn\u0027t make sense to have two\nsvr4_solib_ops instances in there, it would likely be a bug).\n\nRemove program_space::unset_solib_ops, but add\nprogram_space::remove_solib_ops (to remove a single solib_ops) and\nprogram_space::clear_solib_ops (to remove all solib_ops).  Removing an\nsolib_ops now automatically removes all the solibs produced by that\nsolib_ops, to avoid having solibs with stale solib_ops backlinks.\n\nAdd program_space::find_solib_ops, which can be used to find the\ninstance of a given kind of solib_ops.\n\nThen, the code in solib.c gets adapted to deal with the fact that there\nmight be multiple solib_ops.  The logic is done on a case by case basis:\n\n - update_solib_list: where we call open_symbol_file_object, iterate\n   over all solib_ops until we find one that knows how to find and open\n   the main executable\n\n - also update_solib_list: where we fetch the list of current SOs from\n   the inferior and compare it against the list of SOs know to GDB,\n   iterate over all solib_ops and fetch current SOs from all of them.\n   When comparing the SOs fetched from the solib_ops with the SOs\n   known to GDB, also compare the solib_ops before considering it a\n   match.\n\n - print_solib_list_table: to determine whether to print the namespace\n   column, iterate over all solib_ops until we find one for which\n   supports_namespaces returns true and num_active_namespaces returns\n   greater than 0.  If the namespace column is printed and some solibs\n   are from an solib_ops that doesn\u0027t support namespaces, skip the\n   column.\n\n - info_linker_namespace_command: iterate over all solib_ops.  For each\n   solib_ops, print all namespaces.\n\n - solib_keep_data_in_core: iterate over all solib_ops until one says\n   that the given memory range should be kept.\n\n - clear_solib: call clear_solib on all solib_ops\n\n - solib_create_inferior_hook: call create_inferior_hook on all\n   solib_ops\n\n - in_solib_dynsym_resolve_code: iterate over all solib_ops until one\n   says that the given PC falls into dynsym resolve code\n\n - update_solib_breakpoints: call update_breakpoints on all solib_ops\n\n - handle_solib_event: call handle_event on all solib_ops.  The event\n   normally concern only one of those solib_ops, but at the moment we\n   have no way to tell which solib_ops that is.  Perhaps, in the future,\n   we can link bp_shlib_event breakpoints to which solib_ops the event\n   is for, and call handle_event just for that solib_ops.  In the mean\n   time, it is expected that for solib_ops not concerned by the event,\n   calling handle_event will have no effect.\n\n - reload_shared_libraries: call clear_solib on all solib_ops\n\n - solib_linker_namespace_count: sum the number of active linker\n   namespace over all solib_ops.  I don\u0027t know if this makes sense, but\n   there is no known case today of two solib_ops supporting namespaces\n   working side-by-side, so it\u0027s a theoretical problem for now.\n\nWith multiple solib_ops, the concept of\niterate_over_objfiles_in_search_order becomes a bit more complex.  The\nimplementation is mostly based on suppositions on my part.  The idea\nimplemented in this patch is to give priority to the solib_ops\nresponsible for an objfile when searching for a symbol.  If you\u0027re\nstopped debugging some GPU code and look up a variable, and there is a\nvariable by that name both on the host and GPU side, I believe it is\nmore likely that you are interested in the GPU one.\n\nSince we\u0027re going to ask multiple solib_ops to search successively,\nchange solib_ops::iterate_over_objfiles_in_search_order to return a\nbool, to indicate if the search was successful or if we should continue.\n\nThen, change solib_ops::iterate_over_objfiles_in_search_order (the\nimplementation used by all except svr4_solib_ops) to only search the\nobjfiles from that solib_ops as well as (optionally) the main objfile\n(program_space::symfile_object_file).  The idea regarding the main\nobjfile is that it falls under the \"linking domain\" of the host-side\nsolib_ops, even though it wasn\u0027t produced by that solib_ops.\nsvr4_solib_ops has its own implementation of\niterate_over_objfiles_in_search_order, which does check the main\nobjfile.\n\nChecking the main objfile is predicated by the HANDE_MAIN_OBJFILE\nsolib_ops constructor parameter, for which rocm_solib_ops passes false.\n\nThen in program_space::iterate_over_objfiles_in_search_order, the search\nstrategy becomes:\n\n  - if there is a current objfile:\n    - if that objfile was contributed by an solib_ops:\n      - call that solib_ops\u0027 iterate_over_objfiles_in_search_order\n    - else:\n      - search the current objfile by itself\n\nIf we didn\u0027t find anything interesting, we continue the search by asking\nother solib_ops to search:\n\n  - for all solib_ops except the one searched before (if any):\n    - call that solib_ops\u0027 iterate_over_objfiles_in_search_order\n\nFinally, \"orphan\" objfiles (not mapped to any solib) haven\u0027t been\nsearched (except possibly the current objfile), so:\n\n  - for all objfile without an solib_ops backlink, except the current one (if any):\n    - search that objfile\n\nNote that if the current objfile is the main one\n(program_space::symfile_object_file), then we won\u0027t enter the host\nsolib_ops::iterate_over_objfiles_in_search_order in the first part,\nbecause that objfile is not associated to any solib, and therefore to\nany solib_ops.  Instead, we will enter it in the first iteration of the\nsecond part.  This relies on the fact that the host solib_ops will\nalways be first in the solib_ops list, with complementary solib_ops\nfollowing.  This is always true today, given the order in which\nsolib_ops instances are pushed.  Otherwise, we could go look for the\nsolib_ops for which M_HANDLE_MAIN_OBJFILE is true, but it didn\u0027t seem\nlike it was worth the extra complexity.\n\nI wrote the gdb.rocm/symbol-lookup.exp test to try to exercise this\nsymbol lookup order thing.  The test program loads some shared libraries\nand some ROCm code objects, then does some symbol lookups while stopped\nin different places.\n\nFinally, the goal of all this, rocm_solib_ops gets changed to not wrap a\nhost solib_ops anymore!  rocm_solib_ops previously had to use\nlm_info_svr4, to avoid confusing svr4_solib_ops.  It doesn\u0027t have to\nanymore, so introduce a simpler lm_info_rocm that just holds an address.\n\nrocm_solib_ops no longer needs to implement a bunch of methods just to\nforward the call to the host solib_ops, so remove them.  In the methods\nthat rocm_solib_ops actually needs to implement, it no longer needs to\ncall the host ops, which simplifies things.\n\nThings also get simpler at the points where we push a new\nrocm_solib_ops.\n\nChange-Id: I260cdc0dcb9b11f33040059f300719dacac63d69\nApproved-By: Tom Tromey \u003ctom@tromey.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "bd5dbb02f48547085067247350c08fb7fc84e581",
      "old_mode": 33188,
      "old_path": "gdb/infcmd.c",
      "new_id": "8f7f5eecc6697d61cb82d153d88ad6597268dfaa",
      "new_mode": 33188,
      "new_path": "gdb/infcmd.c"
    },
    {
      "type": "modify",
      "old_id": "9c031035a23dd7bb2cb3fe0036d8c01ffb4674cd",
      "old_mode": 33188,
      "old_path": "gdb/inferior.h",
      "new_id": "19c5da76ca59c402847c040c6a8b8d8dcf348640",
      "new_mode": 33188,
      "new_path": "gdb/inferior.h"
    },
    {
      "type": "modify",
      "old_id": "ab3fde11cf940b909af6ee563c70b476d48ac141",
      "old_mode": 33188,
      "old_path": "gdb/infrun.c",
      "new_id": "5372bc8e53c128cc708da8121c92be0b968d075c",
      "new_mode": 33188,
      "new_path": "gdb/infrun.c"
    },
    {
      "type": "modify",
      "old_id": "7023ccddc546cac90f2777529d638d4055f3a594",
      "old_mode": 33188,
      "old_path": "gdb/progspace.c",
      "new_id": "b513cfd6822ad10d71ba5070eebba31ee8851868",
      "new_mode": 33188,
      "new_path": "gdb/progspace.c"
    },
    {
      "type": "modify",
      "old_id": "21977747cb9464b27fbf21850a5af4069e433071",
      "old_mode": 33188,
      "old_path": "gdb/progspace.h",
      "new_id": "a5ef3deb337d9f6b2eca1dd7e295416a5e9e4b50",
      "new_mode": 33188,
      "new_path": "gdb/progspace.h"
    },
    {
      "type": "modify",
      "old_id": "28f69ed9cbb4d50948f418e46815e7508c51cb7f",
      "old_mode": 33188,
      "old_path": "gdb/solib-aix.c",
      "new_id": "28bae833efbc1f437f5e9e2c434be18cd0017955",
      "new_mode": 33188,
      "new_path": "gdb/solib-aix.c"
    },
    {
      "type": "modify",
      "old_id": "07cd88d0e0c6672b792769512dc8e722c589f556",
      "old_mode": 33188,
      "old_path": "gdb/solib-darwin.c",
      "new_id": "11ed0bb154e92c113018b8d723ce733d3938ad93",
      "new_mode": 33188,
      "new_path": "gdb/solib-darwin.c"
    },
    {
      "type": "modify",
      "old_id": "22b9a581546a28c15be19aa87353aa248c09c641",
      "old_mode": 33188,
      "old_path": "gdb/solib-dsbt.c",
      "new_id": "54cd4257d5554212d1e19b8dd0470231e4944ce6",
      "new_mode": 33188,
      "new_path": "gdb/solib-dsbt.c"
    },
    {
      "type": "modify",
      "old_id": "cff3c3ca0193f5d18475a710ad0a5b054cbada64",
      "old_mode": 33188,
      "old_path": "gdb/solib-frv.c",
      "new_id": "7b444ecb3ea319c44c993e26543aaf78a20566dc",
      "new_mode": 33188,
      "new_path": "gdb/solib-frv.c"
    },
    {
      "type": "modify",
      "old_id": "6f8ba8c00ac446678d823b095e1d57707ffe308b",
      "old_mode": 33188,
      "old_path": "gdb/solib-rocm.c",
      "new_id": "61b3dcaf716a8e2e7680362ff1ad3f17b21c93af",
      "new_mode": 33188,
      "new_path": "gdb/solib-rocm.c"
    },
    {
      "type": "modify",
      "old_id": "33fb6e3cd97012b518372e7a6f663bed8829a2f3",
      "old_mode": 33188,
      "old_path": "gdb/solib-svr4.c",
      "new_id": "04000f6797ed59cccc1b57577837b661edff0103",
      "new_mode": 33188,
      "new_path": "gdb/solib-svr4.c"
    },
    {
      "type": "modify",
      "old_id": "d7f58a76224db395739e7d50b19aa3fac2f9f1b1",
      "old_mode": 33188,
      "old_path": "gdb/solib-svr4.h",
      "new_id": "69b79d051d3fa846962fb875586cb6efc5c623ef",
      "new_mode": 33188,
      "new_path": "gdb/solib-svr4.h"
    },
    {
      "type": "modify",
      "old_id": "0df8c6048aef385638a0c5e357c6d3eadfa256b7",
      "old_mode": 33188,
      "old_path": "gdb/solib-target.c",
      "new_id": "28558a03f5ba48eb34e631a8b7a05190eca37d9c",
      "new_mode": 33188,
      "new_path": "gdb/solib-target.c"
    },
    {
      "type": "modify",
      "old_id": "6ed56aaf51592a0567e15f925e197af285868eaa",
      "old_mode": 33188,
      "old_path": "gdb/solib.c",
      "new_id": "ef5d20247517b51ca008b155c2e13a93b5a6020f",
      "new_mode": 33188,
      "new_path": "gdb/solib.c"
    },
    {
      "type": "modify",
      "old_id": "903b9d7b2a866ed90f031a6e36269e29e9ff959a",
      "old_mode": 33188,
      "old_path": "gdb/solib.h",
      "new_id": "4ca3c205ef29c773057d0b9d9f4061b70de661fe",
      "new_mode": 33188,
      "new_path": "gdb/solib.h"
    },
    {
      "type": "modify",
      "old_id": "5d937f3ae858651ba80fd6777d807ab0fc2b24b3",
      "old_mode": 33188,
      "old_path": "gdb/target.c",
      "new_id": "e680943d5b27a71c0939e7b57ea7b57e262dfc72",
      "new_mode": 33188,
      "new_path": "gdb/target.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "7de2f6a34992565a83a1a82f9de6247d279e3ac2",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.rocm/symbol-lookup.cpp"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "1eb658a3e4c229ea3c278ec8c7b7930e7046bda2",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.rocm/symbol-lookup.exp"
    },
    {
      "type": "modify",
      "old_id": "d65e6e76faeb09c042394624f68b74238dec0497",
      "old_mode": 33188,
      "old_path": "gdb/windows-tdep.c",
      "new_id": "2201c17818beef15d240a0f2c020ef64f7bcc3ca",
      "new_mode": 33188,
      "new_path": "gdb/windows-tdep.c"
    }
  ]
}
