1 /* Copyright (C) 2013-2017 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"
30 /* Variable controlling the output of the debugging traces for
32 static int solib_aix_debug;
34 /* Our private data in struct so_list. */
36 struct lm_info_aix : public lm_info_base
38 /* The name of the file mapped by the loader. Apart from the entry
39 for the main executable, this is usually a shared library (which,
40 on AIX, is an archive library file, created using the "ar"
44 /* The name of the shared object file with the actual dynamic
45 loading dependency. This may be empty (Eg. main executable). */
46 std::string member_name;
48 /* The address in inferior memory where the text section got mapped. */
49 CORE_ADDR text_addr = 0;
51 /* The size of the text section, obtained via the loader data. */
52 ULONGEST text_size = 0;
54 /* The address in inferior memory where the data section got mapped. */
55 CORE_ADDR data_addr = 0;
57 /* The size of the data section, obtained via the loader data. */
58 ULONGEST data_size = 0;
61 typedef lm_info_aix *lm_info_aix_p;
62 DEF_VEC_P(lm_info_aix_p);
64 /* This module's per-inferior data. */
66 struct solib_aix_inferior_data
68 /* The list of shared libraries. NULL if not computed yet.
70 Note that the first element of this list is always the main
71 executable, which is not technically a shared library. But
72 we need that information to perform its relocation, and
73 the same principles applied to shared libraries also apply
74 to the main executable. So it's simpler to keep it as part
76 VEC (lm_info_aix_p) *library_list;
79 /* Key to our per-inferior data. */
80 static const struct inferior_data *solib_aix_inferior_data_handle;
82 /* Return this module's data for the given inferior.
83 If none is found, add a zero'ed one now. */
85 static struct solib_aix_inferior_data *
86 get_solib_aix_inferior_data (struct inferior *inf)
88 struct solib_aix_inferior_data *data;
90 data = ((struct solib_aix_inferior_data *)
91 inferior_data (inf, solib_aix_inferior_data_handle));
94 data = XCNEW (struct solib_aix_inferior_data);
95 set_inferior_data (inf, solib_aix_inferior_data_handle, data);
101 #if !defined(HAVE_LIBEXPAT)
103 /* Dummy implementation if XML support is not compiled in. */
105 static VEC (lm_info_aix_p) *
106 solib_aix_parse_libraries (const char *library)
108 static int have_warned;
113 warning (_("Can not parse XML library list; XML support was disabled "
120 /* Dummy implementation if XML support is not compiled in. */
123 solib_aix_free_library_list (void *p)
127 #else /* HAVE_LIBEXPAT */
129 #include "xml-support.h"
131 /* Handle the start of a <library> element. */
134 library_list_start_library (struct gdb_xml_parser *parser,
135 const struct gdb_xml_element *element,
137 VEC (gdb_xml_value_s) *attributes)
139 VEC (lm_info_aix_p) **list = (VEC (lm_info_aix_p) **) user_data;
140 lm_info_aix *item = new lm_info_aix;
141 struct gdb_xml_value *attr;
143 attr = xml_find_attribute (attributes, "name");
144 item->filename = xstrdup ((const char *) attr->value);
146 attr = xml_find_attribute (attributes, "member");
148 item->member_name = xstrdup ((const char *) attr->value);
150 attr = xml_find_attribute (attributes, "text_addr");
151 item->text_addr = * (ULONGEST *) attr->value;
153 attr = xml_find_attribute (attributes, "text_size");
154 item->text_size = * (ULONGEST *) attr->value;
156 attr = xml_find_attribute (attributes, "data_addr");
157 item->data_addr = * (ULONGEST *) attr->value;
159 attr = xml_find_attribute (attributes, "data_size");
160 item->data_size = * (ULONGEST *) attr->value;
162 VEC_safe_push (lm_info_aix_p, *list, item);
165 /* Handle the start of a <library-list-aix> element. */
168 library_list_start_list (struct gdb_xml_parser *parser,
169 const struct gdb_xml_element *element,
170 void *user_data, VEC (gdb_xml_value_s) *attributes)
172 char *version = (char *) xml_find_attribute (attributes, "version")->value;
174 if (strcmp (version, "1.0") != 0)
175 gdb_xml_error (parser,
176 _("Library list has unsupported version \"%s\""),
180 /* Discard the constructed library list. */
183 solib_aix_free_library_list (void *p)
185 VEC (lm_info_aix_p) **result = (VEC (lm_info_aix_p) **) p;
190 fprintf_unfiltered (gdb_stdlog, "DEBUG: solib_aix_free_library_list\n");
192 for (ix = 0; VEC_iterate (lm_info_aix_p, *result, ix, info); ix++)
195 VEC_free (lm_info_aix_p, *result);
199 /* The allowed elements and attributes for an AIX library list
200 described in XML format. The root element is a <library-list-aix>. */
202 static const struct gdb_xml_attribute library_attributes[] =
204 { "name", GDB_XML_AF_NONE, NULL, NULL },
205 { "member", GDB_XML_AF_OPTIONAL, NULL, NULL },
206 { "text_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
207 { "text_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
208 { "data_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
209 { "data_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
210 { NULL, GDB_XML_AF_NONE, NULL, NULL }
213 static const struct gdb_xml_element library_list_children[] =
215 { "library", library_attributes, NULL,
216 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
217 library_list_start_library, NULL},
218 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
221 static const struct gdb_xml_attribute library_list_attributes[] =
223 { "version", GDB_XML_AF_NONE, NULL, NULL },
224 { NULL, GDB_XML_AF_NONE, NULL, NULL }
227 static const struct gdb_xml_element library_list_elements[] =
229 { "library-list-aix", library_list_attributes, library_list_children,
230 GDB_XML_EF_NONE, library_list_start_list, NULL },
231 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
234 /* Parse LIBRARY, a string containing the loader info in XML format,
235 and return an lm_info_aix_p vector.
237 Return NULL if the parsing failed. */
239 static VEC (lm_info_aix_p) *
240 solib_aix_parse_libraries (const char *library)
242 VEC (lm_info_aix_p) *result = NULL;
243 struct cleanup *back_to = make_cleanup (solib_aix_free_library_list,
246 if (gdb_xml_parse_quick (_("aix library list"), "library-list-aix.dtd",
247 library_list_elements, library, &result) == 0)
249 /* Parsed successfully, keep the result. */
250 discard_cleanups (back_to);
254 do_cleanups (back_to);
258 #endif /* HAVE_LIBEXPAT */
260 /* Return the loader info for the given inferior (INF), or NULL if
261 the list could not be computed.
263 Cache the result in per-inferior data, so as to avoid recomputing it
264 each time this function is called.
266 If an error occurs while computing this list, and WARNING_MSG
267 is not NULL, then print a warning including WARNING_MSG and
268 a description of the error. */
270 static VEC (lm_info_aix_p) *
271 solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
273 struct solib_aix_inferior_data *data;
274 char *library_document;
275 struct cleanup *cleanup;
277 /* If already computed, return the cached value. */
278 data = get_solib_aix_inferior_data (inf);
279 if (data->library_list != NULL)
280 return data->library_list;
282 library_document = target_read_stralloc (¤t_target,
283 TARGET_OBJECT_LIBRARIES_AIX,
285 if (library_document == NULL && warning_msg != NULL)
287 warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"),
291 cleanup = make_cleanup (xfree, library_document);
294 fprintf_unfiltered (gdb_stdlog,
295 "DEBUG: TARGET_OBJECT_LIBRARIES_AIX = \n%s\n",
298 data->library_list = solib_aix_parse_libraries (library_document);
299 if (data->library_list == NULL && warning_msg != NULL)
301 warning (_("%s (missing XML support?)"), warning_msg);
302 do_cleanups (cleanup);
306 do_cleanups (cleanup);
307 return data->library_list;
310 /* If the .bss section's VMA is set to an address located before
311 the end of the .data section, causing the two sections to overlap,
312 return the overlap in bytes. Otherwise, return zero.
316 The GNU linker sometimes sets the start address of the .bss session
317 before the end of the .data section, making the 2 sections overlap.
318 The loader appears to handle this situation gracefully, by simply
319 loading the bss section right after the end of the .data section.
321 This means that the .data and the .bss sections are sometimes
322 no longer relocated by the same amount. The problem is that
323 the ldinfo data does not contain any information regarding
324 the relocation of the .bss section, assuming that it would be
325 identical to the information provided for the .data section
326 (this is what would normally happen if the program was linked
329 GDB therefore needs to detect those cases, and make the corresponding
330 adjustment to the .bss section offset computed from the ldinfo data
331 when necessary. This function returns the adjustment amount (or
332 zero when no adjustment is needed). */
335 solib_aix_bss_data_overlap (bfd *abfd)
337 struct bfd_section *data_sect, *bss_sect;
339 data_sect = bfd_get_section_by_name (abfd, ".data");
340 if (data_sect == NULL)
341 return 0; /* No overlap possible. */
343 bss_sect = bfd_get_section_by_name (abfd, ".bss");
344 if (bss_sect == NULL)
345 return 0; /* No overlap possible. */
347 /* Assume the problem only occurs with linkers that place the .bss
348 section after the .data section (the problem has only been
349 observed when using the GNU linker, and the default linker
350 script always places the .data and .bss sections in that order). */
351 if (bfd_section_vma (abfd, bss_sect)
352 < bfd_section_vma (abfd, data_sect))
355 if (bfd_section_vma (abfd, bss_sect)
356 < bfd_section_vma (abfd, data_sect) + bfd_get_section_size (data_sect))
357 return ((bfd_section_vma (abfd, data_sect)
358 + bfd_get_section_size (data_sect))
359 - bfd_section_vma (abfd, bss_sect));
364 /* Implement the "relocate_section_addresses" target_so_ops method. */
367 solib_aix_relocate_section_addresses (struct so_list *so,
368 struct target_section *sec)
370 struct bfd_section *bfd_sect = sec->the_bfd_section;
371 bfd *abfd = bfd_sect->owner;
372 const char *section_name = bfd_section_name (abfd, bfd_sect);
373 lm_info_aix *info = (lm_info_aix *) so->lm_info;
375 if (strcmp (section_name, ".text") == 0)
377 sec->addr = info->text_addr;
378 sec->endaddr = sec->addr + info->text_size;
380 /* The text address given to us by the loader contains
381 XCOFF headers, so we need to adjust by this much. */
382 sec->addr += bfd_sect->filepos;
384 else if (strcmp (section_name, ".data") == 0)
386 sec->addr = info->data_addr;
387 sec->endaddr = sec->addr + info->data_size;
389 else if (strcmp (section_name, ".bss") == 0)
391 /* The information provided by the loader does not include
392 the address of the .bss section, but we know that it gets
393 relocated by the same offset as the .data section. So,
394 compute the relocation offset for the .data section, and
395 apply it to the .bss section as well. If the .data section
396 is not defined (which seems highly unlikely), do our best
397 by assuming no relocation. */
398 struct bfd_section *data_sect
399 = bfd_get_section_by_name (abfd, ".data");
400 CORE_ADDR data_offset = 0;
402 if (data_sect != NULL)
403 data_offset = info->data_addr - bfd_section_vma (abfd, data_sect);
405 sec->addr = bfd_section_vma (abfd, bfd_sect) + data_offset;
406 sec->addr += solib_aix_bss_data_overlap (abfd);
407 sec->endaddr = sec->addr + bfd_section_size (abfd, bfd_sect);
411 /* All other sections should not be relocated. */
412 sec->addr = bfd_section_vma (abfd, bfd_sect);
413 sec->endaddr = sec->addr + bfd_section_size (abfd, bfd_sect);
417 /* Implement the "free_so" target_so_ops method. */
420 solib_aix_free_so (struct so_list *so)
422 lm_info_aix *li = (lm_info_aix *) so->lm_info;
425 fprintf_unfiltered (gdb_stdlog, "DEBUG: solib_aix_free_so (%s)\n",
431 /* Implement the "clear_solib" target_so_ops method. */
434 solib_aix_clear_solib (void)
436 /* Nothing needed. */
439 /* Compute and return the OBJFILE's section_offset array, using
440 the associated loader info (INFO).
442 The resulting array is computed on the heap and must be
443 deallocated after use. */
445 static struct section_offsets *
446 solib_aix_get_section_offsets (struct objfile *objfile,
449 struct section_offsets *offsets;
450 bfd *abfd = objfile->obfd;
452 offsets = XCNEWVEC (struct section_offsets, objfile->num_sections);
456 if (objfile->sect_index_text != -1)
458 struct bfd_section *sect
459 = objfile->sections[objfile->sect_index_text].the_bfd_section;
461 offsets->offsets[objfile->sect_index_text]
462 = info->text_addr + sect->filepos - bfd_section_vma (abfd, sect);
467 if (objfile->sect_index_data != -1)
469 struct bfd_section *sect
470 = objfile->sections[objfile->sect_index_data].the_bfd_section;
472 offsets->offsets[objfile->sect_index_data]
473 = info->data_addr - bfd_section_vma (abfd, sect);
478 The offset of the .bss section should be identical to the offset
479 of the .data section. If no .data section (which seems hard to
480 believe it is possible), assume it is zero. */
482 if (objfile->sect_index_bss != -1
483 && objfile->sect_index_data != -1)
485 offsets->offsets[objfile->sect_index_bss]
486 = (offsets->offsets[objfile->sect_index_data]
487 + solib_aix_bss_data_overlap (abfd));
490 /* All other sections should not need relocation. */
495 /* Implement the "solib_create_inferior_hook" target_so_ops method. */
498 solib_aix_solib_create_inferior_hook (int from_tty)
500 const char *warning_msg = "unable to relocate main executable";
501 VEC (lm_info_aix_p) *library_list;
502 lm_info_aix *exec_info;
504 /* We need to relocate the main executable... */
506 library_list = solib_aix_get_library_list (current_inferior (),
508 if (library_list == NULL)
509 return; /* Warning already printed. */
511 if (VEC_length (lm_info_aix_p, library_list) < 1)
513 warning (_("unable to relocate main executable (no info from loader)"));
517 exec_info = VEC_index (lm_info_aix_p, library_list, 0);
519 if (symfile_objfile != NULL)
521 struct section_offsets *offsets
522 = solib_aix_get_section_offsets (symfile_objfile, exec_info);
523 struct cleanup *cleanup = make_cleanup (xfree, offsets);
525 objfile_relocate (symfile_objfile, offsets);
526 do_cleanups (cleanup);
530 /* Implement the "current_sos" target_so_ops method. */
532 static struct so_list *
533 solib_aix_current_sos (void)
535 struct so_list *start = NULL, *last = NULL;
536 VEC (lm_info_aix_p) *library_list;
540 library_list = solib_aix_get_library_list (current_inferior (), NULL);
541 if (library_list == NULL)
544 /* Build a struct so_list for each entry on the list.
545 We skip the first entry, since this is the entry corresponding
546 to the main executable, not a shared library. */
547 for (ix = 1; VEC_iterate (lm_info_aix_p, library_list, ix, info); ix++)
549 struct so_list *new_solib = XCNEW (struct so_list);
552 if (info->member_name.empty ())
554 /* INFO->FILENAME is probably not an archive, but rather
555 a shared object. Unusual, but it should be possible
556 to link a program against a shared object directory,
557 without having to put it in an archive first. */
558 so_name = info->filename;
562 /* This is the usual case on AIX, where the shared object
563 is a member of an archive. Create a synthetic so_name
564 that follows the same convention as AIX's ldd tool
565 (Eg: "/lib/libc.a(shr.o)"). */
566 so_name = string_printf ("%s(%s)", info->filename.c_str (),
567 info->member_name.c_str ());
569 strncpy (new_solib->so_original_name, so_name.c_str (),
570 SO_NAME_MAX_PATH_SIZE - 1);
571 new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
572 memcpy (new_solib->so_name, new_solib->so_original_name,
573 SO_NAME_MAX_PATH_SIZE);
574 new_solib->lm_info = new lm_info_aix (*info);
576 /* Add it to the list. */
578 last = start = new_solib;
581 last->next = new_solib;
589 /* Implement the "open_symbol_file_object" target_so_ops method. */
592 solib_aix_open_symbol_file_object (void *from_ttyp)
597 /* Implement the "in_dynsym_resolve_code" target_so_ops method. */
600 solib_aix_in_dynsym_resolve_code (CORE_ADDR pc)
605 /* Implement the "bfd_open" target_so_ops method. */
607 static gdb_bfd_ref_ptr
608 solib_aix_bfd_open (char *pathname)
610 /* The pathname is actually a synthetic filename with the following
611 form: "/path/to/sharedlib(member.o)" (double-quotes excluded).
612 split this into archive name and member name.
614 FIXME: This is a little hacky. Perhaps we should provide access
615 to the solib's lm_info here? */
616 const int path_len = strlen (pathname);
620 char *found_pathname;
622 if (pathname[path_len - 1] != ')')
623 return solib_bfd_open (pathname);
625 /* Search for the associated parens. */
626 sep = strrchr (pathname, '(');
629 /* Should never happen, but recover as best as we can (trying
630 to open pathname without decoding, possibly leading to
631 a failure), rather than triggering an assert failure). */
632 warning (_("missing '(' in shared object pathname: %s"), pathname);
633 return solib_bfd_open (pathname);
635 filename_len = sep - pathname;
637 std::string filename (string_printf ("%.*s", filename_len, pathname));
638 std::string member_name (string_printf ("%.*s", path_len - filename_len - 2,
641 /* Calling solib_find makes certain that sysroot path is set properly
642 if program has a dependency on .a archive and sysroot is set via
643 set sysroot command. */
644 found_pathname = solib_find (filename.c_str (), &found_file);
645 if (found_pathname == NULL)
646 perror_with_name (pathname);
647 gdb_bfd_ref_ptr archive_bfd (solib_bfd_fopen (found_pathname, found_file));
648 if (archive_bfd == NULL)
650 warning (_("Could not open `%s' as an executable file: %s"),
651 filename.c_str (), bfd_errmsg (bfd_get_error ()));
655 if (bfd_check_format (archive_bfd.get (), bfd_object))
658 if (! bfd_check_format (archive_bfd.get (), bfd_archive))
660 warning (_("\"%s\": not in executable format: %s."),
661 filename.c_str (), bfd_errmsg (bfd_get_error ()));
665 gdb_bfd_ref_ptr object_bfd
666 (gdb_bfd_openr_next_archived_file (archive_bfd.get (), NULL));
667 while (object_bfd != NULL)
669 if (member_name == object_bfd->filename)
672 object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd.get (),
676 if (object_bfd == NULL)
678 warning (_("\"%s\": member \"%s\" missing."), filename.c_str (),
679 member_name.c_str ());
683 if (! bfd_check_format (object_bfd.get (), bfd_object))
685 warning (_("%s(%s): not in object format: %s."),
686 filename.c_str (), member_name.c_str (),
687 bfd_errmsg (bfd_get_error ()));
691 /* Override the returned bfd's name with the name returned from solib_find
692 along with appended parenthesized member name in order to allow commands
693 listing all shared libraries to display. Otherwise, we would only be
694 displaying the name of the archive member object. */
695 xfree (bfd_get_filename (object_bfd.get ()));
696 object_bfd->filename = xstrprintf ("%s%s",
697 bfd_get_filename (archive_bfd.get ()),
703 /* Return the obj_section corresponding to OBJFILE's data section,
704 or NULL if not found. */
705 /* FIXME: Define in a more general location? */
707 static struct obj_section *
708 data_obj_section_from_objfile (struct objfile *objfile)
710 struct obj_section *osect;
712 ALL_OBJFILE_OSECTIONS (objfile, osect)
713 if (strcmp (bfd_section_name (objfile->obfd, osect->the_bfd_section),
720 /* Return the TOC value corresponding to the given PC address,
721 or raise an error if the value could not be determined. */
724 solib_aix_get_toc_value (CORE_ADDR pc)
726 struct obj_section *pc_osect = find_pc_section (pc);
727 struct obj_section *data_osect;
730 if (pc_osect == NULL)
731 error (_("unable to find TOC entry for pc %s "
732 "(no section contains this PC)"),
733 core_addr_to_string (pc));
735 data_osect = data_obj_section_from_objfile (pc_osect->objfile);
736 if (data_osect == NULL)
737 error (_("unable to find TOC entry for pc %s "
738 "(%s has no data section)"),
739 core_addr_to_string (pc), objfile_name (pc_osect->objfile));
741 result = (obj_section_addr (data_osect)
742 + xcoff_get_toc_offset (pc_osect->objfile));
744 fprintf_unfiltered (gdb_stdlog,
745 "DEBUG: solib_aix_get_toc_value (pc=%s) -> %s\n",
746 core_addr_to_string (pc),
747 core_addr_to_string (result));
752 /* This module's normal_stop observer. */
755 solib_aix_normal_stop_observer (struct bpstats *unused_1, int unused_2)
757 struct solib_aix_inferior_data *data
758 = get_solib_aix_inferior_data (current_inferior ());
760 /* The inferior execution has been resumed, and it just stopped
761 again. This means that the list of shared libraries may have
762 evolved. Reset our cached value. */
763 solib_aix_free_library_list (&data->library_list);
766 /* Implements the "show debug aix-solib" command. */
769 show_solib_aix_debug (struct ui_file *file, int from_tty,
770 struct cmd_list_element *c, const char *value)
772 fprintf_filtered (file, _("solib-aix debugging is %s.\n"), value);
775 /* The target_so_ops for AIX targets. */
776 struct target_so_ops solib_aix_so_ops;
778 /* -Wmissing-prototypes */
779 extern initialize_file_ftype _initialize_solib_aix;
782 _initialize_solib_aix (void)
784 solib_aix_so_ops.relocate_section_addresses
785 = solib_aix_relocate_section_addresses;
786 solib_aix_so_ops.free_so = solib_aix_free_so;
787 solib_aix_so_ops.clear_solib = solib_aix_clear_solib;
788 solib_aix_so_ops.solib_create_inferior_hook
789 = solib_aix_solib_create_inferior_hook;
790 solib_aix_so_ops.current_sos = solib_aix_current_sos;
791 solib_aix_so_ops.open_symbol_file_object
792 = solib_aix_open_symbol_file_object;
793 solib_aix_so_ops.in_dynsym_resolve_code
794 = solib_aix_in_dynsym_resolve_code;
795 solib_aix_so_ops.bfd_open = solib_aix_bfd_open;
797 solib_aix_inferior_data_handle = register_inferior_data ();
799 observer_attach_normal_stop (solib_aix_normal_stop_observer);
801 /* Debug this file's internals. */
802 add_setshow_boolean_cmd ("aix-solib", class_maintenance,
803 &solib_aix_debug, _("\
804 Control the debugging traces for the solib-aix module."), _("\
805 Show whether solib-aix debugging traces are enabled."), _("\
806 When on, solib-aix debugging traces are enabled."),
808 show_solib_aix_debug,
809 &setdebuglist, &showdebuglist);