diff options
Diffstat (limited to 'gdb/solib.h')
-rw-r--r-- | gdb/solib.h | 255 |
1 files changed, 246 insertions, 9 deletions
diff --git a/gdb/solib.h b/gdb/solib.h index 577bcae..b9465e1 100644 --- a/gdb/solib.h +++ b/gdb/solib.h @@ -1,6 +1,6 @@ /* Shared library declarations for GDB, the GNU Debugger. - Copyright (C) 1992-2024 Free Software Foundation, Inc. + Copyright (C) 1992-2025 Free Software Foundation, Inc. This file is part of GDB. @@ -20,15 +20,14 @@ #ifndef GDB_SOLIB_H #define GDB_SOLIB_H -/* Forward decl's for prototypes */ -struct solib; -struct target_ops; -struct solib_ops; -struct program_space; - #include "gdb_bfd.h" -#include "symfile-add-flags.h" #include "gdbsupport/function-view.h" +#include "gdbsupport/intrusive_list.h" +#include "gdbsupport/owning_intrusive_list.h" +#include "symfile-add-flags.h" +#include "target-section.h" + +struct program_space; /* Value of the 'set debug solib' configuration variable. */ @@ -42,6 +41,243 @@ extern bool debug_solib; #define SOLIB_SCOPED_DEBUG_START_END(fmt, ...) \ scoped_debug_start_end (debug_solib, "solib", fmt, ##__VA_ARGS__) +#define SO_NAME_MAX_PATH_SIZE 512 /* FIXME: Should be dynamic */ + +/* Base class for target-specific link map information. */ + +struct lm_info +{ + lm_info () = default; + lm_info (const lm_info &) = default; + virtual ~lm_info () = 0; +}; + +using lm_info_up = std::unique_ptr<lm_info>; + +struct solib_ops; + +struct solib : intrusive_list_node<solib> +{ + /* Constructor + + OPS is the solib_ops implementation providing this solib. */ + explicit solib (const solib_ops &ops) : m_ops (&ops) {} + + /* Return the solib_ops implementation providing this solib. */ + const solib_ops &ops () const + { return *m_ops; } + + /* Free symbol-file related contents of SO and reset for possible reloading + of SO. If we have opened a BFD for SO, close it. If we have placed SO's + sections in some target's section table, the caller is responsible for + removing them. + + This function doesn't mess with objfiles at all. If there is an + objfile associated with SO that needs to be removed, the caller is + responsible for taking care of that. */ + void clear () ; + + /* The following fields of the structure come directly from the + dynamic linker's tables in the inferior, and are initialized by + current_sos. */ + + /* A pointer to target specific link map information. Often this + will be a copy of struct link_map from the user process, but + it need not be; it can be any collection of data needed to + traverse the dynamic linker's data structures. */ + lm_info_up lm_info; + + /* Shared object file name, exactly as it appears in the + inferior's link map. This may be a relative path, or something + which needs to be looked up in LD_LIBRARY_PATH, etc. We use it + to tell which entries in the inferior's dynamic linker's link + map we've already loaded. */ + std::string original_name; + + /* Shared object file name, expanded to something GDB can open. */ + std::string name; + + /* The following fields of the structure are built from + information gathered from the shared object file itself, and + are set when we actually add it to our symbol tables. + + current_sos must initialize these fields to 0. */ + + gdb_bfd_ref_ptr abfd; + + /* True if symbols have been read in. */ + bool symbols_loaded = false; + + /* objfile with symbols for a loaded library. Target memory is read from + ABFD. OBJFILE may be NULL either before symbols have been loaded, if + the file cannot be found or after the command "nosharedlibrary". */ + struct objfile *objfile = nullptr; + + std::vector<target_section> sections; + + /* Record the range of addresses belonging to this shared library. + There may not be just one (e.g. if two segments are relocated + differently). This is used for "info sharedlibrary" and + the MI command "-file-list-shared-libraries". The latter has a format + that supports outputting multiple segments once the related code + supports them. */ + CORE_ADDR addr_low = 0, addr_high = 0; + +private: + /* The solib_ops responsible for this solib. */ + const solib_ops *m_ops; +}; + +/* A unique pointer to an solib. */ +using solib_up = std::unique_ptr<solib>; + +struct solib_ops +{ + virtual ~solib_ops () = default; + + /* Adjust the section binding addresses by the base address at + which the object was actually mapped. */ + virtual void relocate_section_addresses (solib &so, target_section *) const + = 0; + + /* Reset private data structures associated with SO. + This is called when SO is about to be reloaded. + It is also called when SO is about to be freed. + + Defaults to no-op. */ + virtual void clear_so (const solib &so) const {} + + /* Free private data structures associated to PSPACE. This method + should not free resources associated to individual solib entries, + those are cleared by the clear_so method. + + Defaults to no-op. */ + virtual void clear_solib (program_space *pspace) const {} + + /* Target dependent code to run after child process fork. + + Defaults to no-op. */ + virtual void create_inferior_hook (int from_tty) const {}; + + /* Construct a list of the currently loaded shared objects. This + list does not include an entry for the main executable file. + + Note that we only gather information directly available from the + inferior --- we don't examine any of the shared library files + themselves. The declaration of `struct solib' says which fields + we provide values for. */ + virtual owning_intrusive_list<solib> current_sos () const = 0; + + /* Find, open, and read the symbols for the main executable. If + FROM_TTY is non-zero, allow messages to be printed. + + Return true if this was done successfully. Defaults to false. */ + virtual bool open_symbol_file_object (int from_tty) const { return false; } + + /* Determine if PC lies in the dynamic symbol resolution code of + the run time loader. + + Defaults to false. */ + virtual bool in_dynsym_resolve_code (CORE_ADDR pc) const + { return false; }; + + /* Find and open shared library binary file. */ + virtual gdb_bfd_ref_ptr bfd_open (const char *pathname) const; + + /* Given two solib objects, GDB from the GDB thread list and INFERIOR from the + list returned by current_sos, return true if they represent the same library. + + Defaults to comparing the solib original names using filename_cmp. */ + virtual bool same (const solib &gdb, const solib &inferior) const; + + /* Return whether a region of memory must be kept in a core file + for shared libraries loaded before "gcore" is used to be + handled correctly when the core file is loaded. This only + applies when the section would otherwise not be kept in the + core file (in particular, for readonly sections). + + Defaults to false. */ + virtual bool keep_data_in_core (CORE_ADDR vaddr, unsigned long size) const + { return false; }; + + /* Enable or disable optional solib event breakpoints as appropriate. This + should be called whenever stop_on_solib_events is changed. + + Defaults to no-op. */ + virtual void update_breakpoints () const {}; + + /* Target-specific processing of solib events that will be performed before + solib_add is called. + + Defaults to no-op. */ + virtual void handle_event () const {}; + + /* Return an address within the inferior's address space which is known + to be part of SO. If there is no such address, or GDB doesn't know + how to figure out such an address then an empty optional is + returned. + + The returned address can be used when loading the shared libraries + for a core file. GDB knows the build-ids for (some) files mapped + into the inferior's address space, and knows the address ranges which + those mapped files cover. If GDB can figure out a representative + address for the library then this can be used to match a library to a + mapped file, and thus to a build-id. GDB can then use this + information to help locate the shared library objfile, if the objfile + is not in the expected place (as defined by the shared libraries file + name). + + The default implementation of returns an empty option, indicating GDB is + unable to find an address within the library SO. */ + virtual std::optional<CORE_ADDR> find_solib_addr (solib &so) const + { return {}; }; + + /* Return true if the linker or libc supports linkage namespaces. + + Defaults to false. */ + virtual bool supports_namespaces () const { return false; } + + /* Return which linker namespace contains SO. + + The supports_namespaces method must return true for this to be + called. + + Throw an error if the namespace can not be determined (such as when we're + stepping though the dynamic linker). */ + virtual int find_solib_ns (const solib &so) const + { gdb_assert_not_reached ("namespaces not supported"); } + + /* Returns the number of active namespaces in the inferior. + + The supports_namespaces method must return true for this to be called. */ + virtual int num_active_namespaces () const + { gdb_assert_not_reached ("namespaces not supported"); } + + /* Returns all solibs for a given namespace. If the namespace is not + active, returns an empty vector. + + The supports_namespaces method must return true for this to be called. */ + virtual std::vector<const solib *> get_solibs_in_ns (int ns) const + { gdb_assert_not_reached ("namespaces not supported"); } +}; + +/* A unique pointer to an solib_ops. */ +using solib_ops_up = std::unique_ptr<solib_ops>; + +/* Find main executable binary file. */ +extern gdb::unique_xmalloc_ptr<char> exec_file_find (const char *in_pathname, + int *fd); + +/* Find shared library binary file. */ +extern gdb::unique_xmalloc_ptr<char> solib_find (const char *in_pathname, + int *fd); + +/* Open BFD for shared library file. */ +extern gdb_bfd_ref_ptr solib_bfd_fopen (const char *pathname, int fd); + +/* Find solib binary file and open it. */ +extern gdb_bfd_ref_ptr solib_bfd_open (const char *in_pathname); + /* Called when we free all symtabs of PSPACE, to free the shared library information as well. */ @@ -89,7 +325,8 @@ extern void no_shared_libraries (program_space *pspace); Extract the list of currently loaded shared objects from the inferior, and compare it with the list of shared objects in the current program space's list of shared libraries. Edit - so_list_head to bring it in sync with the inferior's new list. + the current program space's solib list to bring it in sync with the + inferior's new list. If we notice that the inferior has unloaded some shared objects, free any symbolic info GDB had read about those shared objects. |