123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751 |
- /* Copyright (C) 2013-2022 Free Software Foundation, Inc.
- This file is part of GDB.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- #include "defs.h"
- #include "solib-aix.h"
- #include "solist.h"
- #include "inferior.h"
- #include "gdb_bfd.h"
- #include "gdbcore.h"
- #include "objfiles.h"
- #include "symtab.h"
- #include "xcoffread.h"
- #include "observable.h"
- #include "gdbcmd.h"
- #include "gdbsupport/scope-exit.h"
- /* Variable controlling the output of the debugging traces for
- this module. */
- static bool solib_aix_debug;
- /* Print an "aix-solib" debug statement. */
- #define solib_aix_debug_printf(fmt, ...) \
- debug_prefixed_printf_cond (solib_aix_debug, "aix-solib",fmt, ##__VA_ARGS__)
- /* Our private data in struct so_list. */
- struct lm_info_aix : public lm_info_base
- {
- /* The name of the file mapped by the loader. Apart from the entry
- for the main executable, this is usually a shared library (which,
- on AIX, is an archive library file, created using the "ar"
- command). */
- std::string filename;
- /* The name of the shared object file with the actual dynamic
- loading dependency. This may be empty (Eg. main executable). */
- std::string member_name;
- /* The address in inferior memory where the text section got mapped. */
- CORE_ADDR text_addr = 0;
- /* The size of the text section, obtained via the loader data. */
- ULONGEST text_size = 0;
- /* The address in inferior memory where the data section got mapped. */
- CORE_ADDR data_addr = 0;
- /* The size of the data section, obtained via the loader data. */
- ULONGEST data_size = 0;
- };
- /* This module's per-inferior data. */
- struct solib_aix_inferior_data
- {
- /* The list of shared libraries.
- Note that the first element of this list is always the main
- executable, which is not technically a shared library. But
- we need that information to perform its relocation, and
- the same principles applied to shared libraries also apply
- to the main executable. So it's simpler to keep it as part
- of this list. */
- gdb::optional<std::vector<lm_info_aix>> library_list;
- };
- /* Key to our per-inferior data. */
- static inferior_key<solib_aix_inferior_data> solib_aix_inferior_data_handle;
- /* Return this module's data for the given inferior.
- If none is found, add a zero'ed one now. */
- static struct solib_aix_inferior_data *
- get_solib_aix_inferior_data (struct inferior *inf)
- {
- struct solib_aix_inferior_data *data;
- data = solib_aix_inferior_data_handle.get (inf);
- if (data == NULL)
- data = solib_aix_inferior_data_handle.emplace (inf);
- return data;
- }
- #if !defined(HAVE_LIBEXPAT)
- /* Dummy implementation if XML support is not compiled in. */
- static gdb::optional<std::vector<lm_info_aix>>
- solib_aix_parse_libraries (const char *library)
- {
- static int have_warned;
- if (!have_warned)
- {
- have_warned = 1;
- warning (_("Can not parse XML library list; XML support was disabled "
- "at compile time"));
- }
- return {};
- }
- #else /* HAVE_LIBEXPAT */
- #include "xml-support.h"
- /* Handle the start of a <library> element. */
- static void
- library_list_start_library (struct gdb_xml_parser *parser,
- const struct gdb_xml_element *element,
- void *user_data,
- std::vector<gdb_xml_value> &attributes)
- {
- std::vector<lm_info_aix> *list = (std::vector<lm_info_aix> *) user_data;
- lm_info_aix item;
- struct gdb_xml_value *attr;
- attr = xml_find_attribute (attributes, "name");
- item.filename = (const char *) attr->value.get ();
- attr = xml_find_attribute (attributes, "member");
- if (attr != NULL)
- item.member_name = (const char *) attr->value.get ();
- attr = xml_find_attribute (attributes, "text_addr");
- item.text_addr = * (ULONGEST *) attr->value.get ();
- attr = xml_find_attribute (attributes, "text_size");
- item.text_size = * (ULONGEST *) attr->value.get ();
- attr = xml_find_attribute (attributes, "data_addr");
- item.data_addr = * (ULONGEST *) attr->value.get ();
- attr = xml_find_attribute (attributes, "data_size");
- item.data_size = * (ULONGEST *) attr->value.get ();
- list->push_back (std::move (item));
- }
- /* Handle the start of a <library-list-aix> element. */
- static void
- library_list_start_list (struct gdb_xml_parser *parser,
- const struct gdb_xml_element *element,
- void *user_data,
- std::vector<gdb_xml_value> &attributes)
- {
- char *version
- = (char *) xml_find_attribute (attributes, "version")->value.get ();
- if (strcmp (version, "1.0") != 0)
- gdb_xml_error (parser,
- _("Library list has unsupported version \"%s\""),
- version);
- }
- /* The allowed elements and attributes for an AIX library list
- described in XML format. The root element is a <library-list-aix>. */
- static const struct gdb_xml_attribute library_attributes[] =
- {
- { "name", GDB_XML_AF_NONE, NULL, NULL },
- { "member", GDB_XML_AF_OPTIONAL, NULL, NULL },
- { "text_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
- { "text_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
- { "data_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
- { "data_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
- { NULL, GDB_XML_AF_NONE, NULL, NULL }
- };
- static const struct gdb_xml_element library_list_children[] =
- {
- { "library", library_attributes, NULL,
- GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
- library_list_start_library, NULL},
- { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
- };
- static const struct gdb_xml_attribute library_list_attributes[] =
- {
- { "version", GDB_XML_AF_NONE, NULL, NULL },
- { NULL, GDB_XML_AF_NONE, NULL, NULL }
- };
- static const struct gdb_xml_element library_list_elements[] =
- {
- { "library-list-aix", library_list_attributes, library_list_children,
- GDB_XML_EF_NONE, library_list_start_list, NULL },
- { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
- };
- /* Parse LIBRARY, a string containing the loader info in XML format,
- and return a vector of lm_info_aix objects.
- Return an empty option if the parsing failed. */
- static gdb::optional<std::vector<lm_info_aix>>
- solib_aix_parse_libraries (const char *library)
- {
- std::vector<lm_info_aix> result;
- if (gdb_xml_parse_quick (_("aix library list"), "library-list-aix.dtd",
- library_list_elements, library, &result) == 0)
- return result;
- return {};
- }
- #endif /* HAVE_LIBEXPAT */
- /* Return the loader info for the given inferior (INF), or an empty
- option if the list could not be computed.
- Cache the result in per-inferior data, so as to avoid recomputing it
- each time this function is called.
- If an error occurs while computing this list, and WARNING_MSG
- is not NULL, then print a warning including WARNING_MSG and
- a description of the error. */
- static gdb::optional<std::vector<lm_info_aix>> &
- solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
- {
- struct solib_aix_inferior_data *data;
- /* If already computed, return the cached value. */
- data = get_solib_aix_inferior_data (inf);
- if (data->library_list.has_value ())
- return data->library_list;
- gdb::optional<gdb::char_vector> library_document
- = target_read_stralloc (current_inferior ()->top_target (),
- TARGET_OBJECT_LIBRARIES_AIX,
- NULL);
- if (!library_document && warning_msg != NULL)
- {
- warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"),
- warning_msg);
- return data->library_list;
- }
- solib_aix_debug_printf ("TARGET_OBJECT_LIBRARIES_AIX = %s",
- library_document->data ());
- data->library_list = solib_aix_parse_libraries (library_document->data ());
- if (!data->library_list.has_value () && warning_msg != NULL)
- warning (_("%s (missing XML support?)"), warning_msg);
- return data->library_list;
- }
- /* If the .bss section's VMA is set to an address located before
- the end of the .data section, causing the two sections to overlap,
- return the overlap in bytes. Otherwise, return zero.
- Motivation:
- The GNU linker sometimes sets the start address of the .bss session
- before the end of the .data section, making the 2 sections overlap.
- The loader appears to handle this situation gracefully, by simply
- loading the bss section right after the end of the .data section.
- This means that the .data and the .bss sections are sometimes
- no longer relocated by the same amount. The problem is that
- the ldinfo data does not contain any information regarding
- the relocation of the .bss section, assuming that it would be
- identical to the information provided for the .data section
- (this is what would normally happen if the program was linked
- correctly).
- GDB therefore needs to detect those cases, and make the corresponding
- adjustment to the .bss section offset computed from the ldinfo data
- when necessary. This function returns the adjustment amount (or
- zero when no adjustment is needed). */
- static CORE_ADDR
- solib_aix_bss_data_overlap (bfd *abfd)
- {
- struct bfd_section *data_sect, *bss_sect;
- data_sect = bfd_get_section_by_name (abfd, ".data");
- if (data_sect == NULL)
- return 0; /* No overlap possible. */
- bss_sect = bfd_get_section_by_name (abfd, ".bss");
- if (bss_sect == NULL)
- return 0; /* No overlap possible. */
- /* Assume the problem only occurs with linkers that place the .bss
- section after the .data section (the problem has only been
- observed when using the GNU linker, and the default linker
- script always places the .data and .bss sections in that order). */
- if (bfd_section_vma (bss_sect) < bfd_section_vma (data_sect))
- return 0;
- if (bfd_section_vma (bss_sect)
- < bfd_section_vma (data_sect) + bfd_section_size (data_sect))
- return (bfd_section_vma (data_sect) + bfd_section_size (data_sect)
- - bfd_section_vma (bss_sect));
- return 0;
- }
- /* Implement the "relocate_section_addresses" target_so_ops method. */
- static void
- solib_aix_relocate_section_addresses (struct so_list *so,
- struct target_section *sec)
- {
- struct bfd_section *bfd_sect = sec->the_bfd_section;
- bfd *abfd = bfd_sect->owner;
- const char *section_name = bfd_section_name (bfd_sect);
- lm_info_aix *info = (lm_info_aix *) so->lm_info;
- if (strcmp (section_name, ".text") == 0)
- {
- sec->addr = info->text_addr;
- sec->endaddr = sec->addr + info->text_size;
- /* The text address given to us by the loader contains
- XCOFF headers, so we need to adjust by this much. */
- sec->addr += bfd_sect->filepos;
- }
- else if (strcmp (section_name, ".data") == 0)
- {
- sec->addr = info->data_addr;
- sec->endaddr = sec->addr + info->data_size;
- }
- else if (strcmp (section_name, ".bss") == 0)
- {
- /* The information provided by the loader does not include
- the address of the .bss section, but we know that it gets
- relocated by the same offset as the .data section. So,
- compute the relocation offset for the .data section, and
- apply it to the .bss section as well. If the .data section
- is not defined (which seems highly unlikely), do our best
- by assuming no relocation. */
- struct bfd_section *data_sect
- = bfd_get_section_by_name (abfd, ".data");
- CORE_ADDR data_offset = 0;
- if (data_sect != NULL)
- data_offset = info->data_addr - bfd_section_vma (data_sect);
- sec->addr = bfd_section_vma (bfd_sect) + data_offset;
- sec->addr += solib_aix_bss_data_overlap (abfd);
- sec->endaddr = sec->addr + bfd_section_size (bfd_sect);
- }
- else
- {
- /* All other sections should not be relocated. */
- sec->addr = bfd_section_vma (bfd_sect);
- sec->endaddr = sec->addr + bfd_section_size (bfd_sect);
- }
- }
- /* Implement the "free_so" target_so_ops method. */
- static void
- solib_aix_free_so (struct so_list *so)
- {
- lm_info_aix *li = (lm_info_aix *) so->lm_info;
- solib_aix_debug_printf ("%s", so->so_name);
- delete li;
- }
- /* Implement the "clear_solib" target_so_ops method. */
- static void
- solib_aix_clear_solib (void)
- {
- /* Nothing needed. */
- }
- /* Compute and return the OBJFILE's section_offset array, using
- the associated loader info (INFO). */
- static section_offsets
- solib_aix_get_section_offsets (struct objfile *objfile,
- lm_info_aix *info)
- {
- bfd *abfd = objfile->obfd;
- section_offsets offsets (objfile->section_offsets.size ());
- /* .text */
- if (objfile->sect_index_text != -1)
- {
- struct bfd_section *sect
- = objfile->sections[objfile->sect_index_text].the_bfd_section;
- offsets[objfile->sect_index_text]
- = info->text_addr + sect->filepos - bfd_section_vma (sect);
- }
- /* .data */
- if (objfile->sect_index_data != -1)
- {
- struct bfd_section *sect
- = objfile->sections[objfile->sect_index_data].the_bfd_section;
- offsets[objfile->sect_index_data]
- = info->data_addr - bfd_section_vma (sect);
- }
- /* .bss
- The offset of the .bss section should be identical to the offset
- of the .data section. If no .data section (which seems hard to
- believe it is possible), assume it is zero. */
- if (objfile->sect_index_bss != -1
- && objfile->sect_index_data != -1)
- {
- offsets[objfile->sect_index_bss]
- = (offsets[objfile->sect_index_data]
- + solib_aix_bss_data_overlap (abfd));
- }
- /* All other sections should not need relocation. */
- return offsets;
- }
- /* Implement the "solib_create_inferior_hook" target_so_ops method. */
- static void
- solib_aix_solib_create_inferior_hook (int from_tty)
- {
- const char *warning_msg = "unable to relocate main executable";
- /* We need to relocate the main executable... */
- gdb::optional<std::vector<lm_info_aix>> &library_list
- = solib_aix_get_library_list (current_inferior (), warning_msg);
- if (!library_list.has_value ())
- return; /* Warning already printed. */
- if (library_list->empty ())
- {
- warning (_("unable to relocate main executable (no info from loader)"));
- return;
- }
- lm_info_aix &exec_info = (*library_list)[0];
- if (current_program_space->symfile_object_file != NULL)
- {
- objfile *objf = current_program_space->symfile_object_file;
- section_offsets offsets = solib_aix_get_section_offsets (objf,
- &exec_info);
- objfile_relocate (objf, offsets);
- }
- }
- /* Implement the "current_sos" target_so_ops method. */
- static struct so_list *
- solib_aix_current_sos (void)
- {
- struct so_list *start = NULL, *last = NULL;
- int ix;
- gdb::optional<std::vector<lm_info_aix>> &library_list
- = solib_aix_get_library_list (current_inferior (), NULL);
- if (!library_list.has_value ())
- return NULL;
- /* Build a struct so_list for each entry on the list.
- We skip the first entry, since this is the entry corresponding
- to the main executable, not a shared library. */
- for (ix = 1; ix < library_list->size (); ix++)
- {
- struct so_list *new_solib = XCNEW (struct so_list);
- std::string so_name;
- lm_info_aix &info = (*library_list)[ix];
- if (info.member_name.empty ())
- {
- /* INFO.FILENAME is probably not an archive, but rather
- a shared object. Unusual, but it should be possible
- to link a program against a shared object directory,
- without having to put it in an archive first. */
- so_name = info.filename;
- }
- else
- {
- /* This is the usual case on AIX, where the shared object
- is a member of an archive. Create a synthetic so_name
- that follows the same convention as AIX's ldd tool
- (Eg: "/lib/libc.a(shr.o)"). */
- so_name = string_printf ("%s(%s)", info.filename.c_str (),
- info.member_name.c_str ());
- }
- strncpy (new_solib->so_original_name, so_name.c_str (),
- SO_NAME_MAX_PATH_SIZE - 1);
- new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
- memcpy (new_solib->so_name, new_solib->so_original_name,
- SO_NAME_MAX_PATH_SIZE);
- new_solib->lm_info = new lm_info_aix (info);
- /* Add it to the list. */
- if (!start)
- last = start = new_solib;
- else
- {
- last->next = new_solib;
- last = new_solib;
- }
- }
- return start;
- }
- /* Implement the "open_symbol_file_object" target_so_ops method. */
- static int
- solib_aix_open_symbol_file_object (int from_tty)
- {
- return 0;
- }
- /* Implement the "in_dynsym_resolve_code" target_so_ops method. */
- static int
- solib_aix_in_dynsym_resolve_code (CORE_ADDR pc)
- {
- return 0;
- }
- /* Implement the "bfd_open" target_so_ops method. */
- static gdb_bfd_ref_ptr
- solib_aix_bfd_open (const char *pathname)
- {
- /* The pathname is actually a synthetic filename with the following
- form: "/path/to/sharedlib(member.o)" (double-quotes excluded).
- split this into archive name and member name.
- FIXME: This is a little hacky. Perhaps we should provide access
- to the solib's lm_info here? */
- const int path_len = strlen (pathname);
- const char *sep;
- int filename_len;
- int found_file;
- if (pathname[path_len - 1] != ')')
- return solib_bfd_open (pathname);
- /* Search for the associated parens. */
- sep = strrchr (pathname, '(');
- if (sep == NULL)
- {
- /* Should never happen, but recover as best as we can (trying
- to open pathname without decoding, possibly leading to
- a failure), rather than triggering an assert failure). */
- warning (_("missing '(' in shared object pathname: %s"), pathname);
- return solib_bfd_open (pathname);
- }
- filename_len = sep - pathname;
- std::string filename (string_printf ("%.*s", filename_len, pathname));
- std::string member_name (string_printf ("%.*s", path_len - filename_len - 2,
- sep + 1));
- /* Calling solib_find makes certain that sysroot path is set properly
- if program has a dependency on .a archive and sysroot is set via
- set sysroot command. */
- gdb::unique_xmalloc_ptr<char> found_pathname
- = solib_find (filename.c_str (), &found_file);
- if (found_pathname == NULL)
- perror_with_name (pathname);
- gdb_bfd_ref_ptr archive_bfd (solib_bfd_fopen (found_pathname.get (),
- found_file));
- if (archive_bfd == NULL)
- {
- warning (_("Could not open `%s' as an executable file: %s"),
- filename.c_str (), bfd_errmsg (bfd_get_error ()));
- return NULL;
- }
- if (bfd_check_format (archive_bfd.get (), bfd_object))
- return archive_bfd;
- if (! bfd_check_format (archive_bfd.get (), bfd_archive))
- {
- warning (_("\"%s\": not in executable format: %s."),
- filename.c_str (), bfd_errmsg (bfd_get_error ()));
- return NULL;
- }
- gdb_bfd_ref_ptr object_bfd
- (gdb_bfd_openr_next_archived_file (archive_bfd.get (), NULL));
- while (object_bfd != NULL)
- {
- if (member_name == bfd_get_filename (object_bfd.get ()))
- break;
- object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd.get (),
- object_bfd.get ());
- }
- if (object_bfd == NULL)
- {
- warning (_("\"%s\": member \"%s\" missing."), filename.c_str (),
- member_name.c_str ());
- return NULL;
- }
- if (! bfd_check_format (object_bfd.get (), bfd_object))
- {
- warning (_("%s(%s): not in object format: %s."),
- filename.c_str (), member_name.c_str (),
- bfd_errmsg (bfd_get_error ()));
- return NULL;
- }
- /* Override the returned bfd's name with the name returned from solib_find
- along with appended parenthesized member name in order to allow commands
- listing all shared libraries to display. Otherwise, we would only be
- displaying the name of the archive member object. */
- std::string fname = string_printf ("%s%s",
- bfd_get_filename (archive_bfd.get ()),
- sep);
- bfd_set_filename (object_bfd.get (), fname.c_str ());
- return object_bfd;
- }
- /* Return the obj_section corresponding to OBJFILE's data section,
- or NULL if not found. */
- /* FIXME: Define in a more general location? */
- static struct obj_section *
- data_obj_section_from_objfile (struct objfile *objfile)
- {
- struct obj_section *osect;
- ALL_OBJFILE_OSECTIONS (objfile, osect)
- if (strcmp (bfd_section_name (osect->the_bfd_section), ".data") == 0)
- return osect;
- return NULL;
- }
- /* Return the TOC value corresponding to the given PC address,
- or raise an error if the value could not be determined. */
- CORE_ADDR
- solib_aix_get_toc_value (CORE_ADDR pc)
- {
- struct obj_section *pc_osect = find_pc_section (pc);
- struct obj_section *data_osect;
- CORE_ADDR result;
- if (pc_osect == NULL)
- error (_("unable to find TOC entry for pc %s "
- "(no section contains this PC)"),
- core_addr_to_string (pc));
- data_osect = data_obj_section_from_objfile (pc_osect->objfile);
- if (data_osect == NULL)
- error (_("unable to find TOC entry for pc %s "
- "(%s has no data section)"),
- core_addr_to_string (pc), objfile_name (pc_osect->objfile));
- result = data_osect->addr () + xcoff_get_toc_offset (pc_osect->objfile);
- solib_aix_debug_printf ("pc=%s -> %s", core_addr_to_string (pc),
- core_addr_to_string (result));
- return result;
- }
- /* This module's normal_stop observer. */
- static void
- solib_aix_normal_stop_observer (struct bpstat *unused_1, int unused_2)
- {
- struct solib_aix_inferior_data *data
- = get_solib_aix_inferior_data (current_inferior ());
- /* The inferior execution has been resumed, and it just stopped
- again. This means that the list of shared libraries may have
- evolved. Reset our cached value. */
- data->library_list.reset ();
- }
- /* Implements the "show debug aix-solib" command. */
- static void
- show_solib_aix_debug (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
- {
- gdb_printf (file, _("solib-aix debugging is %s.\n"), value);
- }
- /* The target_so_ops for AIX targets. */
- struct target_so_ops solib_aix_so_ops;
- void _initialize_solib_aix ();
- void
- _initialize_solib_aix ()
- {
- solib_aix_so_ops.relocate_section_addresses
- = solib_aix_relocate_section_addresses;
- solib_aix_so_ops.free_so = solib_aix_free_so;
- solib_aix_so_ops.clear_solib = solib_aix_clear_solib;
- solib_aix_so_ops.solib_create_inferior_hook
- = solib_aix_solib_create_inferior_hook;
- solib_aix_so_ops.current_sos = solib_aix_current_sos;
- solib_aix_so_ops.open_symbol_file_object
- = solib_aix_open_symbol_file_object;
- solib_aix_so_ops.in_dynsym_resolve_code
- = solib_aix_in_dynsym_resolve_code;
- solib_aix_so_ops.bfd_open = solib_aix_bfd_open;
- gdb::observers::normal_stop.attach (solib_aix_normal_stop_observer,
- "solib-aix");
- /* Debug this file's internals. */
- add_setshow_boolean_cmd ("aix-solib", class_maintenance,
- &solib_aix_debug, _("\
- Control the debugging traces for the solib-aix module."), _("\
- Show whether solib-aix debugging traces are enabled."), _("\
- When on, solib-aix debugging traces are enabled."),
- NULL,
- show_solib_aix_debug,
- &setdebuglist, &showdebuglist);
- }
|