1 /* Copyright (C) 2013 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. */
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 NULL (Eg. main executable). */
48 /* The address in inferior memory where the text section got mapped. */
51 /* The size of the text section, obtained via the loader data. */
54 /* The address in inferior memory where the data section got mapped. */
57 /* The size of the data section, obtained via the loader data. */
61 typedef struct lm_info *lm_info_p;
64 /* Return a deep copy of the given struct lm_info object. */
66 static struct lm_info *
67 solib_aix_new_lm_info (struct lm_info *info)
69 struct lm_info *result = xmalloc (sizeof (struct lm_info));
71 memcpy (result, info, sizeof (struct lm_info));
72 result->filename = xstrdup (info->filename);
73 if (info->member_name != NULL)
74 result->member_name = xstrdup (info->member_name);
79 /* Free the memory allocated for the given lm_info. */
82 solib_aix_xfree_lm_info (struct lm_info *info)
84 xfree (info->filename);
85 xfree (info->member_name);
89 /* This module's per-inferior data. */
91 struct solib_aix_inferior_data
93 /* The list of shared libraries. NULL if not computed yet.
95 Note that the first element of this list is always the main
96 executable, which is not technically a shared library. But
97 we need that information to perform its relocation, and
98 the same principles applied to shared libraries also apply
99 to the main executable. So it's simpler to keep it as part
101 VEC (lm_info_p) *library_list;
104 /* Key to our per-inferior data. */
105 static const struct inferior_data *solib_aix_inferior_data_handle;
107 /* Return this module's data for the given inferior.
108 If none is found, add a zero'ed one now. */
110 static struct solib_aix_inferior_data *
111 get_solib_aix_inferior_data (struct inferior *inf)
113 struct solib_aix_inferior_data *data;
115 data = inferior_data (inf, solib_aix_inferior_data_handle);
118 data = XZALLOC (struct solib_aix_inferior_data);
119 set_inferior_data (inf, solib_aix_inferior_data_handle, data);
125 #if !defined(HAVE_LIBEXPAT)
127 /* Dummy implementation if XML support is not compiled in. */
129 static VEC (lm_info_p) *
130 solib_aix_parse_libraries (const char *library)
132 static int have_warned;
137 warning (_("Can not parse XML library list; XML support was disabled "
144 #else /* HAVE_LIBEXPAT */
146 #include "xml-support.h"
148 /* Handle the start of a <library> element. */
151 library_list_start_library (struct gdb_xml_parser *parser,
152 const struct gdb_xml_element *element,
154 VEC (gdb_xml_value_s) *attributes)
156 VEC (lm_info_p) **list = user_data;
157 struct lm_info *item = XZALLOC (struct lm_info);
158 struct gdb_xml_value *attr;
160 attr = xml_find_attribute (attributes, "name");
161 item->filename = xstrdup (attr->value);
163 attr = xml_find_attribute (attributes, "member");
165 item->member_name = xstrdup (attr->value);
167 attr = xml_find_attribute (attributes, "text_addr");
168 item->text_addr = * (ULONGEST *) attr->value;
170 attr = xml_find_attribute (attributes, "text_size");
171 item->text_size = * (ULONGEST *) attr->value;
173 attr = xml_find_attribute (attributes, "data_addr");
174 item->data_addr = * (ULONGEST *) attr->value;
176 attr = xml_find_attribute (attributes, "data_size");
177 item->data_size = * (ULONGEST *) attr->value;
179 VEC_safe_push (lm_info_p, *list, item);
182 /* Handle the start of a <library-list-aix> element. */
185 library_list_start_list (struct gdb_xml_parser *parser,
186 const struct gdb_xml_element *element,
187 void *user_data, VEC (gdb_xml_value_s) *attributes)
189 char *version = xml_find_attribute (attributes, "version")->value;
191 if (strcmp (version, "1.0") != 0)
192 gdb_xml_error (parser,
193 _("Library list has unsupported version \"%s\""),
197 /* Discard the constructed library list. */
200 solib_aix_free_library_list (void *p)
202 VEC (lm_info_p) **result = p;
203 struct lm_info *info;
207 fprintf_unfiltered (gdb_stdlog, "DEBUG: solib_aix_free_library_list\n");
209 for (ix = 0; VEC_iterate (lm_info_p, *result, ix, info); ix++)
210 solib_aix_xfree_lm_info (info);
211 VEC_free (lm_info_p, *result);
215 /* The allowed elements and attributes for an AIX library list
216 described in XML format. The root element is a <library-list-aix>. */
218 static const struct gdb_xml_attribute library_attributes[] =
220 { "name", GDB_XML_AF_NONE, NULL, NULL },
221 { "member", GDB_XML_AF_OPTIONAL, NULL, NULL },
222 { "text_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
223 { "text_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
224 { "data_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
225 { "data_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
226 { NULL, GDB_XML_AF_NONE, NULL, NULL }
229 static const struct gdb_xml_element library_list_children[] =
231 { "library", library_attributes, NULL,
232 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
233 library_list_start_library, NULL},
234 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
237 static const struct gdb_xml_attribute library_list_attributes[] =
239 { "version", GDB_XML_AF_NONE, NULL, NULL },
240 { NULL, GDB_XML_AF_NONE, NULL, NULL }
243 static const struct gdb_xml_element library_list_elements[] =
245 { "library-list-aix", library_list_attributes, library_list_children,
246 GDB_XML_EF_NONE, library_list_start_list, NULL },
247 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
250 /* Parse LIBRARY, a string containing the loader info in XML format,
251 and return an lm_info_p vector.
253 Return NULL if the parsing failed. */
255 static VEC (lm_info_p) *
256 solib_aix_parse_libraries (const char *library)
258 VEC (lm_info_p) *result = NULL;
259 struct cleanup *back_to = make_cleanup (solib_aix_free_library_list,
262 if (gdb_xml_parse_quick (_("aix library list"), "library-list-aix.dtd",
263 library_list_elements, library, &result) == 0)
265 /* Parsed successfully, keep the result. */
266 discard_cleanups (back_to);
270 do_cleanups (back_to);
274 #endif /* HAVE_LIBEXPAT */
276 /* Return the loader info for the given inferior (INF), or NULL if
277 the list could not be computed.
279 Cache the result in per-inferior data, so as to avoid recomputing it
280 each time this function is called.
282 If an error occurs while computing this list, and WARNING_MSG
283 is not NULL, then print a warning including WARNING_MSG and
284 a description of the error. */
286 static VEC (lm_info_p) *
287 solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
289 struct solib_aix_inferior_data *data;
290 char *library_document;
291 struct cleanup *cleanup;
293 /* If already computed, return the cached value. */
294 data = get_solib_aix_inferior_data (inf);
295 if (data->library_list != NULL)
296 return data->library_list;
298 library_document = target_read_stralloc (¤t_target,
299 TARGET_OBJECT_LIBRARIES_AIX,
301 if (library_document == NULL && warning_msg != NULL)
303 warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"),
307 cleanup = make_cleanup (xfree, library_document);
310 fprintf_unfiltered (gdb_stdlog,
311 "DEBUG: TARGET_OBJECT_LIBRARIES_AIX = \n%s\n",
314 data->library_list = solib_aix_parse_libraries (library_document);
315 if (data->library_list == NULL && warning_msg != NULL)
317 warning (_("%s (missing XML support?)"), warning_msg);
318 do_cleanups (cleanup);
322 do_cleanups (cleanup);
323 return data->library_list;
326 /* If the .bss section's VMA is set to an address located before
327 the end of the .data section, causing the two sections to overlap,
328 return the overlap in bytes. Otherwise, return zero.
332 The GNU linker sometimes sets the start address of the .bss session
333 before the end of the .data section, making the 2 sections overlap.
334 The loader appears to handle this situation gracefully, by simply
335 loading the bss section right after the end of the .data section.
337 This means that the .data and the .bss sections are sometimes
338 no longer relocated by the same amount. The problem is that
339 the ldinfo data does not contain any information regarding
340 the relocation of the .bss section, assuming that it would be
341 identical to the information provided for the .data section
342 (this is what would normally happen if the program was linked
345 GDB therefore needs to detect those cases, and make the corresponding
346 adjustment to the .bss section offset computed from the ldinfo data
347 when necessary. This function returns the adjustment amount (or
348 zero when no adjustment is needed). */
351 solib_aix_bss_data_overlap (bfd *abfd)
353 struct bfd_section *data_sect, *bss_sect;
355 data_sect = bfd_get_section_by_name (abfd, ".data");
356 if (data_sect == NULL)
357 return 0; /* No overlap possible. */
359 bss_sect = bfd_get_section_by_name (abfd, ".bss");
360 if (bss_sect == NULL)
361 return 0; /* No overlap possible. */
363 /* Assume the problem only occurs with linkers that place the .bss
364 section after the .data section (the problem has only been
365 observed when using the GNU linker, and the default linker
366 script always places the .data and .bss sections in that order). */
367 if (bfd_section_vma (abfd, bss_sect)
368 < bfd_section_vma (abfd, data_sect))
371 if (bfd_section_vma (abfd, bss_sect)
372 < bfd_section_vma (abfd, data_sect) + bfd_get_section_size (data_sect))
373 return ((bfd_section_vma (abfd, data_sect)
374 + bfd_get_section_size (data_sect))
375 - bfd_section_vma (abfd, bss_sect));
380 /* Implement the "relocate_section_addresses" target_so_ops method. */
383 solib_aix_relocate_section_addresses (struct so_list *so,
384 struct target_section *sec)
386 bfd *abfd = sec->bfd;
387 struct bfd_section *bfd_sect = sec->the_bfd_section;
388 const char *section_name = bfd_section_name (abfd, bfd_sect);
389 struct lm_info *info = so->lm_info;
391 if (strcmp (section_name, ".text") == 0)
393 sec->addr = info->text_addr;
394 sec->endaddr = sec->addr + info->text_size;
396 /* The text address given to us by the loader contains
397 XCOFF headers, so we need to adjust by this much. */
398 sec->addr += bfd_sect->filepos;
400 else if (strcmp (section_name, ".data") == 0)
402 sec->addr = info->data_addr;
403 sec->endaddr = sec->addr + info->data_size;
405 else if (strcmp (section_name, ".bss") == 0)
407 sec->addr = bfd_section_vma (abfd, bfd_sect) + info->data_addr;
408 sec->addr += solib_aix_bss_data_overlap (abfd);
409 sec->endaddr = sec->addr + bfd_section_size (abfd, bfd_sect);
413 /* All other sections should not be relocated. */
414 /* FIXME: GDB complains that the .loader section sometimes
415 overlaps with other sections (Eg: the .data section).
416 As far as I can tell, the loader section had the LOAD flag
417 set, but not the RELOC. So it should not be relocated.
418 There seems to be a problem there, and maybe it has to do
419 with setting sec->addr to 0 (when the vma is indeed 0).
420 But even if there wasn't, the problem then becomes the fact
421 that many shared objects inside shared libraries have
422 a .loader section whose vma is 0, thus also triggering
423 an overlap warning. */
424 sec->addr = bfd_section_vma (abfd, bfd_sect);
425 sec->endaddr = sec->addr + bfd_section_size (abfd, bfd_sect);
429 /* Implement the "free_so" target_so_ops method. */
432 solib_aix_free_so (struct so_list *so)
435 fprintf_unfiltered (gdb_stdlog, "DEBUG: solib_aix_free_so (%s)\n",
437 solib_aix_xfree_lm_info (so->lm_info);
440 /* Implement the "clear_solib" target_so_ops method. */
443 solib_aix_clear_solib (void)
445 /* Nothing needed. */
448 /* Compute and return the OBJFILE's section_offset array, using
449 the associated loader info (INFO).
451 The resulting array is computed on the heap and must be
452 deallocated after use. */
454 static struct section_offsets *
455 solib_aix_get_section_offsets (struct objfile *objfile,
456 struct lm_info *info)
458 struct section_offsets *offsets;
459 bfd *abfd = objfile->obfd;
462 offsets = XCALLOC (objfile->num_sections, struct section_offsets);
466 if (objfile->sect_index_text != -1)
468 struct bfd_section *sect
469 = objfile->sections[objfile->sect_index_text].the_bfd_section;
471 offsets->offsets[objfile->sect_index_text]
472 = info->text_addr + sect->filepos - bfd_section_vma (abfd, sect);
477 if (objfile->sect_index_data != -1)
479 struct bfd_section *sect
480 = objfile->sections[objfile->sect_index_data].the_bfd_section;
482 offsets->offsets[objfile->sect_index_data]
483 = info->data_addr - bfd_section_vma (abfd, sect);
488 The offset of the .bss section should be identical to the offset
489 of the .data section. If no .data section (which seems hard to
490 believe it is possible), assume it is zero. */
492 if (objfile->sect_index_bss != -1
493 && objfile->sect_index_data != -1)
495 offsets->offsets[objfile->sect_index_bss]
496 = (offsets->offsets[objfile->sect_index_data]
497 + solib_aix_bss_data_overlap (abfd));
500 /* All other sections should not need relocation. */
505 /* Implement the "solib_create_inferior_hook" target_so_ops method. */
508 solib_aix_solib_create_inferior_hook (int from_tty)
510 const char *warning_msg = "unable to relocate main executable";
511 VEC (lm_info_p) *library_list;
512 struct lm_info *exec_info;
514 /* We need to relocate the main executable... */
516 library_list = solib_aix_get_library_list (current_inferior (),
518 if (library_list == NULL)
519 return; /* Warning already printed. */
521 if (VEC_length (lm_info_p, library_list) < 1)
523 warning (_("unable to relocate main executable (no info from loader)"));
527 exec_info = VEC_index (lm_info_p, library_list, 0);
529 if (symfile_objfile != NULL)
531 struct section_offsets *offsets
532 = solib_aix_get_section_offsets (symfile_objfile, exec_info);
533 struct cleanup *cleanup = make_cleanup (xfree, offsets);
535 objfile_relocate (symfile_objfile, offsets);
536 do_cleanups (cleanup);
540 /* Implement the "special_symbol_handling" target_so_ops method. */
543 solib_aix_special_symbol_handling (void)
545 /* Nothing needed. */
548 /* Implement the "current_sos" target_so_ops method. */
550 static struct so_list *
551 solib_aix_current_sos (void)
553 struct so_list *start = NULL, *last = NULL;
554 VEC (lm_info_p) *library_list;
555 struct lm_info *info;
558 library_list = solib_aix_get_library_list (current_inferior (), NULL);
559 if (library_list == NULL)
562 /* Build a struct so_list for each entry on the list.
563 We skip the first entry, since this is the entry corresponding
564 to the main executable, not a shared library. */
565 for (ix = 1; VEC_iterate (lm_info_p, library_list, ix, info); ix++)
567 struct so_list *new_solib = XZALLOC (struct so_list);
570 if (info->member_name == NULL)
572 /* INFO->FILENAME is probably not an archive, but rather
573 a shared object. Unusual, but it should be possible
574 to link a program against a shared object directory,
575 without having to put it in an archive first. */
576 so_name = xstrdup (info->filename);
580 /* This is the usual case on AIX, where the shared object
581 is a member of an archive. Create a synthetic so_name
582 that follows the same convention as AIX's ldd tool
583 (Eg: "/lib/libc.a(shr.o)"). */
584 so_name = xstrprintf ("%s(%s)", info->filename, info->member_name);
586 strncpy (new_solib->so_original_name, so_name,
587 SO_NAME_MAX_PATH_SIZE - 1);
588 new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
589 memcpy (new_solib->so_name, new_solib->so_original_name,
590 SO_NAME_MAX_PATH_SIZE);
591 new_solib->lm_info = solib_aix_new_lm_info (info);
593 /* Add it to the list. */
595 last = start = new_solib;
598 last->next = new_solib;
606 /* Implement the "open_symbol_file_object" target_so_ops method. */
609 solib_aix_open_symbol_file_object (void *from_ttyp)
614 /* Implement the "in_dynsym_resolve_code" target_so_ops method. */
617 solib_aix_in_dynsym_resolve_code (CORE_ADDR pc)
622 /* Implement the "bfd_open" target_so_ops method. */
625 solib_aix_bfd_open (char *pathname)
627 /* The pathname is actually a synthetic filename with the following
628 form: "/path/to/sharedlib(member.o)" (double-quotes excluded).
629 split this into archive name and member name.
631 FIXME: This is a little hacky. Perhaps we should provide access
632 to the solib's lm_info here? */
633 const int path_len = strlen (pathname);
638 bfd *archive_bfd, *object_bfd;
639 struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
641 if (pathname[path_len - 1] != ')')
642 return solib_bfd_open (pathname);
644 /* Search for the associated parens. */
645 sep = strrchr (pathname, '(');
648 /* Should never happen, but recover as best as we can (trying
649 to open pathname without decoding, possibly leading to
650 a failure), rather than triggering an assert failure). */
651 warning (_("missing '(' in shared object pathname: %s"), pathname);
652 return solib_bfd_open (pathname);
654 filename_len = sep - pathname;
656 filename = xstrprintf ("%.*s", filename_len, pathname);
657 make_cleanup (xfree, filename);
658 member_name = xstrprintf ("%.*s", path_len - filename_len - 2, sep + 1);
659 make_cleanup (xfree, member_name);
661 archive_bfd = gdb_bfd_open (filename, gnutarget, -1);
662 if (archive_bfd == NULL)
664 warning (_("Could not open `%s' as an executable file: %s"),
665 filename, bfd_errmsg (bfd_get_error ()));
666 do_cleanups (cleanup);
670 if (bfd_check_format (archive_bfd, bfd_object))
672 do_cleanups (cleanup);
676 if (! bfd_check_format (archive_bfd, bfd_archive))
678 warning (_("\"%s\": not in executable format: %s."),
679 filename, bfd_errmsg (bfd_get_error ()));
680 gdb_bfd_unref (archive_bfd);
681 do_cleanups (cleanup);
685 object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd, NULL);
686 while (object_bfd != NULL)
690 if (strcmp (member_name, object_bfd->filename) == 0)
693 next = gdb_bfd_openr_next_archived_file (archive_bfd, object_bfd);
694 gdb_bfd_unref (object_bfd);
698 if (object_bfd == NULL)
700 warning (_("\"%s\": member \"%s\" missing."), filename, member_name);
701 gdb_bfd_unref (archive_bfd);
702 do_cleanups (cleanup);
706 if (! bfd_check_format (object_bfd, bfd_object))
708 warning (_("%s(%s): not in object format: %s."),
709 filename, member_name, bfd_errmsg (bfd_get_error ()));
710 gdb_bfd_unref (archive_bfd);
711 gdb_bfd_unref (object_bfd);
712 do_cleanups (cleanup);
716 gdb_bfd_unref (archive_bfd);
717 do_cleanups (cleanup);
721 /* Return the obj_section corresponding to OBJFILE's data section,
722 or NULL if not found. */
723 /* FIXME: Define in a more general location? */
725 static struct obj_section *
726 data_obj_section_from_objfile (struct objfile *objfile)
728 struct obj_section *osect;
730 ALL_OBJFILE_OSECTIONS (objfile, osect)
731 if (strcmp (bfd_section_name (objfile->obfd, osect->the_bfd_section),
738 /* Return the TOC value corresponding to the given PC address,
739 or raise an error if the value could not be determined. */
742 solib_aix_get_toc_value (CORE_ADDR pc)
744 struct obj_section *pc_osect = find_pc_section (pc);
745 struct obj_section *data_osect;
748 if (pc_osect == NULL)
749 error (_("unable to find TOC entry for pc %s "
750 "(no section contains this PC)"),
751 core_addr_to_string (pc));
753 data_osect = data_obj_section_from_objfile (pc_osect->objfile);
754 if (data_osect == NULL)
755 error (_("unable to find TOC entry for pc %s "
756 "(%s has no data section)"),
757 core_addr_to_string (pc), pc_osect->objfile->name);
759 result = (obj_section_addr (data_osect)
760 + xcoff_get_toc_offset (pc_osect->objfile));
762 fprintf_unfiltered (gdb_stdlog,
763 "DEBUG: solib_aix_get_toc_value (pc=%s) -> %s\n",
764 core_addr_to_string (pc),
765 core_addr_to_string (result));
770 /* This module's normal_stop observer. */
773 solib_aix_normal_stop_observer (struct bpstats *unused_1, int unused_2)
775 struct solib_aix_inferior_data *data
776 = get_solib_aix_inferior_data (current_inferior ());
778 /* The inferior execution has been resumed, and it just stopped
779 again. This means that the list of shared libraries may have
780 evolved. Reset our cached value. */
781 solib_aix_free_library_list (&data->library_list);
784 /* Implements the "show debug aix-solib" command. */
787 show_solib_aix_debug (struct ui_file *file, int from_tty,
788 struct cmd_list_element *c, const char *value)
790 fprintf_filtered (file, _("solib-aix debugging is %s.\n"), value);
793 /* The target_so_ops for AIX targets. */
794 struct target_so_ops solib_aix_so_ops;
796 /* -Wmissing-prototypes */
797 extern initialize_file_ftype _initialize_solib_aix;
800 _initialize_solib_aix (void)
802 solib_aix_so_ops.relocate_section_addresses
803 = solib_aix_relocate_section_addresses;
804 solib_aix_so_ops.free_so = solib_aix_free_so;
805 solib_aix_so_ops.clear_solib = solib_aix_clear_solib;
806 solib_aix_so_ops.solib_create_inferior_hook
807 = solib_aix_solib_create_inferior_hook;
808 solib_aix_so_ops.special_symbol_handling
809 = solib_aix_special_symbol_handling;
810 solib_aix_so_ops.current_sos = solib_aix_current_sos;
811 solib_aix_so_ops.open_symbol_file_object
812 = solib_aix_open_symbol_file_object;
813 solib_aix_so_ops.in_dynsym_resolve_code
814 = solib_aix_in_dynsym_resolve_code;
815 solib_aix_so_ops.bfd_open = solib_aix_bfd_open;
817 solib_aix_inferior_data_handle = register_inferior_data ();
819 observer_attach_normal_stop (solib_aix_normal_stop_observer);
821 /* Debug this file's internals. */
822 add_setshow_boolean_cmd ("aix-solib", class_maintenance,
823 &solib_aix_debug, _("\
824 Control the debugging traces for the solib-aix module."), _("\
825 Show whether solib-aix debugging traces are enabled."), _("\
826 When on, solib-aix debugging traces are enabled."),
828 show_solib_aix_debug,
829 &setdebuglist, &showdebuglist);