1 /* Copyright (C) 2013-2019 Free Software Foundation, Inc.
3 This file is part of GDB.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include "solib-aix.h"
26 #include "xcoffread.h"
27 #include "observable.h"
29 #include "common/scope-exit.h"
31 /* Variable controlling the output of the debugging traces for
33 static int solib_aix_debug;
35 /* Our private data in struct so_list. */
37 struct lm_info_aix : public lm_info_base
39 /* The name of the file mapped by the loader. Apart from the entry
40 for the main executable, this is usually a shared library (which,
41 on AIX, is an archive library file, created using the "ar"
45 /* The name of the shared object file with the actual dynamic
46 loading dependency. This may be empty (Eg. main executable). */
47 std::string member_name;
49 /* The address in inferior memory where the text section got mapped. */
50 CORE_ADDR text_addr = 0;
52 /* The size of the text section, obtained via the loader data. */
53 ULONGEST text_size = 0;
55 /* The address in inferior memory where the data section got mapped. */
56 CORE_ADDR data_addr = 0;
58 /* The size of the data section, obtained via the loader data. */
59 ULONGEST data_size = 0;
62 typedef lm_info_aix *lm_info_aix_p;
63 DEF_VEC_P(lm_info_aix_p);
65 /* This module's per-inferior data. */
67 struct solib_aix_inferior_data
69 /* The list of shared libraries. NULL if not computed yet.
71 Note that the first element of this list is always the main
72 executable, which is not technically a shared library. But
73 we need that information to perform its relocation, and
74 the same principles applied to shared libraries also apply
75 to the main executable. So it's simpler to keep it as part
77 VEC (lm_info_aix_p) *library_list;
80 /* Key to our per-inferior data. */
81 static const struct inferior_data *solib_aix_inferior_data_handle;
83 /* Return this module's data for the given inferior.
84 If none is found, add a zero'ed one now. */
86 static struct solib_aix_inferior_data *
87 get_solib_aix_inferior_data (struct inferior *inf)
89 struct solib_aix_inferior_data *data;
91 data = ((struct solib_aix_inferior_data *)
92 inferior_data (inf, solib_aix_inferior_data_handle));
95 data = XCNEW (struct solib_aix_inferior_data);
96 set_inferior_data (inf, solib_aix_inferior_data_handle, data);
102 #if !defined(HAVE_LIBEXPAT)
104 /* Dummy implementation if XML support is not compiled in. */
106 static VEC (lm_info_aix_p) *
107 solib_aix_parse_libraries (const char *library)
109 static int have_warned;
114 warning (_("Can not parse XML library list; XML support was disabled "
121 /* Dummy implementation if XML support is not compiled in. */
124 solib_aix_free_library_list (void *p)
128 #else /* HAVE_LIBEXPAT */
130 #include "xml-support.h"
132 /* Handle the start of a <library> element. */
135 library_list_start_library (struct gdb_xml_parser *parser,
136 const struct gdb_xml_element *element,
138 std::vector<gdb_xml_value> &attributes)
140 VEC (lm_info_aix_p) **list = (VEC (lm_info_aix_p) **) user_data;
141 lm_info_aix *item = new lm_info_aix;
142 struct gdb_xml_value *attr;
144 attr = xml_find_attribute (attributes, "name");
145 item->filename = xstrdup ((const char *) attr->value.get ());
147 attr = xml_find_attribute (attributes, "member");
149 item->member_name = xstrdup ((const char *) attr->value.get ());
151 attr = xml_find_attribute (attributes, "text_addr");
152 item->text_addr = * (ULONGEST *) attr->value.get ();
154 attr = xml_find_attribute (attributes, "text_size");
155 item->text_size = * (ULONGEST *) attr->value.get ();
157 attr = xml_find_attribute (attributes, "data_addr");
158 item->data_addr = * (ULONGEST *) attr->value.get ();
160 attr = xml_find_attribute (attributes, "data_size");
161 item->data_size = * (ULONGEST *) attr->value.get ();
163 VEC_safe_push (lm_info_aix_p, *list, item);
166 /* Handle the start of a <library-list-aix> element. */
169 library_list_start_list (struct gdb_xml_parser *parser,
170 const struct gdb_xml_element *element,
172 std::vector<gdb_xml_value> &attributes)
175 = (char *) xml_find_attribute (attributes, "version")->value.get ();
177 if (strcmp (version, "1.0") != 0)
178 gdb_xml_error (parser,
179 _("Library list has unsupported version \"%s\""),
183 /* Discard the constructed library list. */
186 solib_aix_free_library_list (void *p)
188 VEC (lm_info_aix_p) **result = (VEC (lm_info_aix_p) **) p;
193 fprintf_unfiltered (gdb_stdlog, "DEBUG: solib_aix_free_library_list\n");
195 for (ix = 0; VEC_iterate (lm_info_aix_p, *result, ix, info); ix++)
198 VEC_free (lm_info_aix_p, *result);
202 /* The allowed elements and attributes for an AIX library list
203 described in XML format. The root element is a <library-list-aix>. */
205 static const struct gdb_xml_attribute library_attributes[] =
207 { "name", GDB_XML_AF_NONE, NULL, NULL },
208 { "member", GDB_XML_AF_OPTIONAL, NULL, NULL },
209 { "text_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
210 { "text_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
211 { "data_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
212 { "data_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
213 { NULL, GDB_XML_AF_NONE, NULL, NULL }
216 static const struct gdb_xml_element library_list_children[] =
218 { "library", library_attributes, NULL,
219 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
220 library_list_start_library, NULL},
221 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
224 static const struct gdb_xml_attribute library_list_attributes[] =
226 { "version", GDB_XML_AF_NONE, NULL, NULL },
227 { NULL, GDB_XML_AF_NONE, NULL, NULL }
230 static const struct gdb_xml_element library_list_elements[] =
232 { "library-list-aix", library_list_attributes, library_list_children,
233 GDB_XML_EF_NONE, library_list_start_list, NULL },
234 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
237 /* Parse LIBRARY, a string containing the loader info in XML format,
238 and return an lm_info_aix_p vector.
240 Return NULL if the parsing failed. */
242 static VEC (lm_info_aix_p) *
243 solib_aix_parse_libraries (const char *library)
245 VEC (lm_info_aix_p) *result = NULL;
246 auto cleanup = make_scope_exit ([&] ()
248 solib_aix_free_library_list (&result);
251 if (gdb_xml_parse_quick (_("aix library list"), "library-list-aix.dtd",
252 library_list_elements, library, &result) == 0)
254 /* Parsed successfully, keep the result. */
262 #endif /* HAVE_LIBEXPAT */
264 /* Return the loader info for the given inferior (INF), or NULL if
265 the list could not be computed.
267 Cache the result in per-inferior data, so as to avoid recomputing it
268 each time this function is called.
270 If an error occurs while computing this list, and WARNING_MSG
271 is not NULL, then print a warning including WARNING_MSG and
272 a description of the error. */
274 static VEC (lm_info_aix_p) *
275 solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
277 struct solib_aix_inferior_data *data;
279 /* If already computed, return the cached value. */
280 data = get_solib_aix_inferior_data (inf);
281 if (data->library_list != NULL)
282 return data->library_list;
284 gdb::optional<gdb::char_vector> library_document
285 = target_read_stralloc (current_top_target (), TARGET_OBJECT_LIBRARIES_AIX,
287 if (!library_document && warning_msg != NULL)
289 warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"),
295 fprintf_unfiltered (gdb_stdlog,
296 "DEBUG: TARGET_OBJECT_LIBRARIES_AIX = \n%s\n",
297 library_document->data ());
299 data->library_list = solib_aix_parse_libraries (library_document->data ());
300 if (data->library_list == NULL && warning_msg != NULL)
302 warning (_("%s (missing XML support?)"), warning_msg);
306 return data->library_list;
309 /* If the .bss section's VMA is set to an address located before
310 the end of the .data section, causing the two sections to overlap,
311 return the overlap in bytes. Otherwise, return zero.
315 The GNU linker sometimes sets the start address of the .bss session
316 before the end of the .data section, making the 2 sections overlap.
317 The loader appears to handle this situation gracefully, by simply
318 loading the bss section right after the end of the .data section.
320 This means that the .data and the .bss sections are sometimes
321 no longer relocated by the same amount. The problem is that
322 the ldinfo data does not contain any information regarding
323 the relocation of the .bss section, assuming that it would be
324 identical to the information provided for the .data section
325 (this is what would normally happen if the program was linked
328 GDB therefore needs to detect those cases, and make the corresponding
329 adjustment to the .bss section offset computed from the ldinfo data
330 when necessary. This function returns the adjustment amount (or
331 zero when no adjustment is needed). */
334 solib_aix_bss_data_overlap (bfd *abfd)
336 struct bfd_section *data_sect, *bss_sect;
338 data_sect = bfd_get_section_by_name (abfd, ".data");
339 if (data_sect == NULL)
340 return 0; /* No overlap possible. */
342 bss_sect = bfd_get_section_by_name (abfd, ".bss");
343 if (bss_sect == NULL)
344 return 0; /* No overlap possible. */
346 /* Assume the problem only occurs with linkers that place the .bss
347 section after the .data section (the problem has only been
348 observed when using the GNU linker, and the default linker
349 script always places the .data and .bss sections in that order). */
350 if (bfd_section_vma (abfd, bss_sect)
351 < bfd_section_vma (abfd, data_sect))
354 if (bfd_section_vma (abfd, bss_sect)
355 < bfd_section_vma (abfd, data_sect) + bfd_get_section_size (data_sect))
356 return ((bfd_section_vma (abfd, data_sect)
357 + bfd_get_section_size (data_sect))
358 - bfd_section_vma (abfd, bss_sect));
363 /* Implement the "relocate_section_addresses" target_so_ops method. */
366 solib_aix_relocate_section_addresses (struct so_list *so,
367 struct target_section *sec)
369 struct bfd_section *bfd_sect = sec->the_bfd_section;
370 bfd *abfd = bfd_sect->owner;
371 const char *section_name = bfd_section_name (abfd, bfd_sect);
372 lm_info_aix *info = (lm_info_aix *) so->lm_info;
374 if (strcmp (section_name, ".text") == 0)
376 sec->addr = info->text_addr;
377 sec->endaddr = sec->addr + info->text_size;
379 /* The text address given to us by the loader contains
380 XCOFF headers, so we need to adjust by this much. */
381 sec->addr += bfd_sect->filepos;
383 else if (strcmp (section_name, ".data") == 0)
385 sec->addr = info->data_addr;
386 sec->endaddr = sec->addr + info->data_size;
388 else if (strcmp (section_name, ".bss") == 0)
390 /* The information provided by the loader does not include
391 the address of the .bss section, but we know that it gets
392 relocated by the same offset as the .data section. So,
393 compute the relocation offset for the .data section, and
394 apply it to the .bss section as well. If the .data section
395 is not defined (which seems highly unlikely), do our best
396 by assuming no relocation. */
397 struct bfd_section *data_sect
398 = bfd_get_section_by_name (abfd, ".data");
399 CORE_ADDR data_offset = 0;
401 if (data_sect != NULL)
402 data_offset = info->data_addr - bfd_section_vma (abfd, data_sect);
404 sec->addr = bfd_section_vma (abfd, bfd_sect) + data_offset;
405 sec->addr += solib_aix_bss_data_overlap (abfd);
406 sec->endaddr = sec->addr + bfd_section_size (abfd, bfd_sect);
410 /* All other sections should not be relocated. */
411 sec->addr = bfd_section_vma (abfd, bfd_sect);
412 sec->endaddr = sec->addr + bfd_section_size (abfd, bfd_sect);
416 /* Implement the "free_so" target_so_ops method. */
419 solib_aix_free_so (struct so_list *so)
421 lm_info_aix *li = (lm_info_aix *) so->lm_info;
424 fprintf_unfiltered (gdb_stdlog, "DEBUG: solib_aix_free_so (%s)\n",
430 /* Implement the "clear_solib" target_so_ops method. */
433 solib_aix_clear_solib (void)
435 /* Nothing needed. */
438 /* Compute and return the OBJFILE's section_offset array, using
439 the associated loader info (INFO).
441 The resulting array is computed on the heap and must be
442 deallocated after use. */
444 static gdb::unique_xmalloc_ptr<struct section_offsets>
445 solib_aix_get_section_offsets (struct objfile *objfile,
448 bfd *abfd = objfile->obfd;
450 gdb::unique_xmalloc_ptr<struct section_offsets> offsets
451 (XCNEWVEC (struct section_offsets, objfile->num_sections));
455 if (objfile->sect_index_text != -1)
457 struct bfd_section *sect
458 = objfile->sections[objfile->sect_index_text].the_bfd_section;
460 offsets->offsets[objfile->sect_index_text]
461 = info->text_addr + sect->filepos - bfd_section_vma (abfd, sect);
466 if (objfile->sect_index_data != -1)
468 struct bfd_section *sect
469 = objfile->sections[objfile->sect_index_data].the_bfd_section;
471 offsets->offsets[objfile->sect_index_data]
472 = info->data_addr - bfd_section_vma (abfd, sect);
477 The offset of the .bss section should be identical to the offset
478 of the .data section. If no .data section (which seems hard to
479 believe it is possible), assume it is zero. */
481 if (objfile->sect_index_bss != -1
482 && objfile->sect_index_data != -1)
484 offsets->offsets[objfile->sect_index_bss]
485 = (offsets->offsets[objfile->sect_index_data]
486 + solib_aix_bss_data_overlap (abfd));
489 /* All other sections should not need relocation. */
494 /* Implement the "solib_create_inferior_hook" target_so_ops method. */
497 solib_aix_solib_create_inferior_hook (int from_tty)
499 const char *warning_msg = "unable to relocate main executable";
500 VEC (lm_info_aix_p) *library_list;
501 lm_info_aix *exec_info;
503 /* We need to relocate the main executable... */
505 library_list = solib_aix_get_library_list (current_inferior (),
507 if (library_list == NULL)
508 return; /* Warning already printed. */
510 if (VEC_length (lm_info_aix_p, library_list) < 1)
512 warning (_("unable to relocate main executable (no info from loader)"));
516 exec_info = VEC_index (lm_info_aix_p, library_list, 0);
518 if (symfile_objfile != NULL)
520 gdb::unique_xmalloc_ptr<struct section_offsets> offsets
521 = solib_aix_get_section_offsets (symfile_objfile, exec_info);
523 objfile_relocate (symfile_objfile, offsets.get ());
527 /* Implement the "current_sos" target_so_ops method. */
529 static struct so_list *
530 solib_aix_current_sos (void)
532 struct so_list *start = NULL, *last = NULL;
533 VEC (lm_info_aix_p) *library_list;
537 library_list = solib_aix_get_library_list (current_inferior (), NULL);
538 if (library_list == NULL)
541 /* Build a struct so_list for each entry on the list.
542 We skip the first entry, since this is the entry corresponding
543 to the main executable, not a shared library. */
544 for (ix = 1; VEC_iterate (lm_info_aix_p, library_list, ix, info); ix++)
546 struct so_list *new_solib = XCNEW (struct so_list);
549 if (info->member_name.empty ())
551 /* INFO->FILENAME is probably not an archive, but rather
552 a shared object. Unusual, but it should be possible
553 to link a program against a shared object directory,
554 without having to put it in an archive first. */
555 so_name = info->filename;
559 /* This is the usual case on AIX, where the shared object
560 is a member of an archive. Create a synthetic so_name
561 that follows the same convention as AIX's ldd tool
562 (Eg: "/lib/libc.a(shr.o)"). */
563 so_name = string_printf ("%s(%s)", info->filename.c_str (),
564 info->member_name.c_str ());
566 strncpy (new_solib->so_original_name, so_name.c_str (),
567 SO_NAME_MAX_PATH_SIZE - 1);
568 new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
569 memcpy (new_solib->so_name, new_solib->so_original_name,
570 SO_NAME_MAX_PATH_SIZE);
571 new_solib->lm_info = new lm_info_aix (*info);
573 /* Add it to the list. */
575 last = start = new_solib;
578 last->next = new_solib;
586 /* Implement the "open_symbol_file_object" target_so_ops method. */
589 solib_aix_open_symbol_file_object (int from_tty)
594 /* Implement the "in_dynsym_resolve_code" target_so_ops method. */
597 solib_aix_in_dynsym_resolve_code (CORE_ADDR pc)
602 /* Implement the "bfd_open" target_so_ops method. */
604 static gdb_bfd_ref_ptr
605 solib_aix_bfd_open (const char *pathname)
607 /* The pathname is actually a synthetic filename with the following
608 form: "/path/to/sharedlib(member.o)" (double-quotes excluded).
609 split this into archive name and member name.
611 FIXME: This is a little hacky. Perhaps we should provide access
612 to the solib's lm_info here? */
613 const int path_len = strlen (pathname);
618 if (pathname[path_len - 1] != ')')
619 return solib_bfd_open (pathname);
621 /* Search for the associated parens. */
622 sep = strrchr (pathname, '(');
625 /* Should never happen, but recover as best as we can (trying
626 to open pathname without decoding, possibly leading to
627 a failure), rather than triggering an assert failure). */
628 warning (_("missing '(' in shared object pathname: %s"), pathname);
629 return solib_bfd_open (pathname);
631 filename_len = sep - pathname;
633 std::string filename (string_printf ("%.*s", filename_len, pathname));
634 std::string member_name (string_printf ("%.*s", path_len - filename_len - 2,
637 /* Calling solib_find makes certain that sysroot path is set properly
638 if program has a dependency on .a archive and sysroot is set via
639 set sysroot command. */
640 gdb::unique_xmalloc_ptr<char> found_pathname
641 = solib_find (filename.c_str (), &found_file);
642 if (found_pathname == NULL)
643 perror_with_name (pathname);
644 gdb_bfd_ref_ptr archive_bfd (solib_bfd_fopen (found_pathname.get (),
646 if (archive_bfd == NULL)
648 warning (_("Could not open `%s' as an executable file: %s"),
649 filename.c_str (), bfd_errmsg (bfd_get_error ()));
653 if (bfd_check_format (archive_bfd.get (), bfd_object))
656 if (! bfd_check_format (archive_bfd.get (), bfd_archive))
658 warning (_("\"%s\": not in executable format: %s."),
659 filename.c_str (), bfd_errmsg (bfd_get_error ()));
663 gdb_bfd_ref_ptr object_bfd
664 (gdb_bfd_openr_next_archived_file (archive_bfd.get (), NULL));
665 while (object_bfd != NULL)
667 if (member_name == object_bfd->filename)
670 object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd.get (),
674 if (object_bfd == NULL)
676 warning (_("\"%s\": member \"%s\" missing."), filename.c_str (),
677 member_name.c_str ());
681 if (! bfd_check_format (object_bfd.get (), bfd_object))
683 warning (_("%s(%s): not in object format: %s."),
684 filename.c_str (), member_name.c_str (),
685 bfd_errmsg (bfd_get_error ()));
689 /* Override the returned bfd's name with the name returned from solib_find
690 along with appended parenthesized member name in order to allow commands
691 listing all shared libraries to display. Otherwise, we would only be
692 displaying the name of the archive member object. */
693 xfree (bfd_get_filename (object_bfd.get ()));
694 object_bfd->filename = xstrprintf ("%s%s",
695 bfd_get_filename (archive_bfd.get ()),
701 /* Return the obj_section corresponding to OBJFILE's data section,
702 or NULL if not found. */
703 /* FIXME: Define in a more general location? */
705 static struct obj_section *
706 data_obj_section_from_objfile (struct objfile *objfile)
708 struct obj_section *osect;
710 ALL_OBJFILE_OSECTIONS (objfile, osect)
711 if (strcmp (bfd_section_name (objfile->obfd, osect->the_bfd_section),
718 /* Return the TOC value corresponding to the given PC address,
719 or raise an error if the value could not be determined. */
722 solib_aix_get_toc_value (CORE_ADDR pc)
724 struct obj_section *pc_osect = find_pc_section (pc);
725 struct obj_section *data_osect;
728 if (pc_osect == NULL)
729 error (_("unable to find TOC entry for pc %s "
730 "(no section contains this PC)"),
731 core_addr_to_string (pc));
733 data_osect = data_obj_section_from_objfile (pc_osect->objfile);
734 if (data_osect == NULL)
735 error (_("unable to find TOC entry for pc %s "
736 "(%s has no data section)"),
737 core_addr_to_string (pc), objfile_name (pc_osect->objfile));
739 result = (obj_section_addr (data_osect)
740 + xcoff_get_toc_offset (pc_osect->objfile));
742 fprintf_unfiltered (gdb_stdlog,
743 "DEBUG: solib_aix_get_toc_value (pc=%s) -> %s\n",
744 core_addr_to_string (pc),
745 core_addr_to_string (result));
750 /* This module's normal_stop observer. */
753 solib_aix_normal_stop_observer (struct bpstats *unused_1, int unused_2)
755 struct solib_aix_inferior_data *data
756 = get_solib_aix_inferior_data (current_inferior ());
758 /* The inferior execution has been resumed, and it just stopped
759 again. This means that the list of shared libraries may have
760 evolved. Reset our cached value. */
761 solib_aix_free_library_list (&data->library_list);
764 /* Implements the "show debug aix-solib" command. */
767 show_solib_aix_debug (struct ui_file *file, int from_tty,
768 struct cmd_list_element *c, const char *value)
770 fprintf_filtered (file, _("solib-aix debugging is %s.\n"), value);
773 /* The target_so_ops for AIX targets. */
774 struct target_so_ops solib_aix_so_ops;
777 _initialize_solib_aix (void)
779 solib_aix_so_ops.relocate_section_addresses
780 = solib_aix_relocate_section_addresses;
781 solib_aix_so_ops.free_so = solib_aix_free_so;
782 solib_aix_so_ops.clear_solib = solib_aix_clear_solib;
783 solib_aix_so_ops.solib_create_inferior_hook
784 = solib_aix_solib_create_inferior_hook;
785 solib_aix_so_ops.current_sos = solib_aix_current_sos;
786 solib_aix_so_ops.open_symbol_file_object
787 = solib_aix_open_symbol_file_object;
788 solib_aix_so_ops.in_dynsym_resolve_code
789 = solib_aix_in_dynsym_resolve_code;
790 solib_aix_so_ops.bfd_open = solib_aix_bfd_open;
792 solib_aix_inferior_data_handle = register_inferior_data ();
794 gdb::observers::normal_stop.attach (solib_aix_normal_stop_observer);
796 /* Debug this file's internals. */
797 add_setshow_boolean_cmd ("aix-solib", class_maintenance,
798 &solib_aix_debug, _("\
799 Control the debugging traces for the solib-aix module."), _("\
800 Show whether solib-aix debugging traces are enabled."), _("\
801 When on, solib-aix debugging traces are enabled."),
803 show_solib_aix_debug,
804 &setdebuglist, &showdebuglist);