Automatic date update in version.in
[binutils-gdb.git] / gdb / solib-aix.c
blob926f1ed766d07df4cbaaf58fa05df8a521dd34e4
1 /* Copyright (C) 2013-2024 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/>. */
18 #include "solib-aix.h"
19 #include "solib.h"
20 #include "solist.h"
21 #include "inferior.h"
22 #include "gdb_bfd.h"
23 #include "objfiles.h"
24 #include "symtab.h"
25 #include "xcoffread.h"
26 #include "observable.h"
28 /* Our private data in struct solib. */
30 struct lm_info_aix final : public lm_info
32 /* The name of the file mapped by the loader. Apart from the entry
33 for the main executable, this is usually a shared library (which,
34 on AIX, is an archive library file, created using the "ar"
35 command). */
36 std::string filename;
38 /* The name of the shared object file with the actual dynamic
39 loading dependency. This may be empty (Eg. main executable). */
40 std::string member_name;
42 /* The address in inferior memory where the text section got mapped. */
43 CORE_ADDR text_addr = 0;
45 /* The size of the text section, obtained via the loader data. */
46 ULONGEST text_size = 0;
48 /* The address in inferior memory where the data section got mapped. */
49 CORE_ADDR data_addr = 0;
51 /* The size of the data section, obtained via the loader data. */
52 ULONGEST data_size = 0;
55 /* This module's per-inferior data. */
57 struct solib_aix_inferior_data
59 /* The list of shared libraries.
61 Note that the first element of this list is always the main
62 executable, which is not technically a shared library. But
63 we need that information to perform its relocation, and
64 the same principles applied to shared libraries also apply
65 to the main executable. So it's simpler to keep it as part
66 of this list. */
67 std::optional<std::vector<lm_info_aix>> library_list;
70 /* Key to our per-inferior data. */
71 static const registry<inferior>::key<solib_aix_inferior_data>
72 solib_aix_inferior_data_handle;
74 /* Return this module's data for the given inferior.
75 If none is found, add a zero'ed one now. */
77 static struct solib_aix_inferior_data *
78 get_solib_aix_inferior_data (struct inferior *inf)
80 struct solib_aix_inferior_data *data;
82 data = solib_aix_inferior_data_handle.get (inf);
83 if (data == NULL)
84 data = solib_aix_inferior_data_handle.emplace (inf);
86 return data;
89 #if !defined(HAVE_LIBEXPAT)
91 /* Dummy implementation if XML support is not compiled in. */
93 static std::optional<std::vector<lm_info_aix>>
94 solib_aix_parse_libraries (const char *library)
96 static int have_warned;
98 if (!have_warned)
100 have_warned = 1;
101 warning (_("Can not parse XML library list; XML support was disabled "
102 "at compile time"));
105 return {};
108 #else /* HAVE_LIBEXPAT */
110 #include "xml-support.h"
112 /* Handle the start of a <library> element. */
114 static void
115 library_list_start_library (struct gdb_xml_parser *parser,
116 const struct gdb_xml_element *element,
117 void *user_data,
118 std::vector<gdb_xml_value> &attributes)
120 std::vector<lm_info_aix> *list = (std::vector<lm_info_aix> *) user_data;
121 lm_info_aix item;
122 struct gdb_xml_value *attr;
124 attr = xml_find_attribute (attributes, "name");
125 item.filename = (const char *) attr->value.get ();
127 attr = xml_find_attribute (attributes, "member");
128 if (attr != NULL)
129 item.member_name = (const char *) attr->value.get ();
131 attr = xml_find_attribute (attributes, "text_addr");
132 item.text_addr = * (ULONGEST *) attr->value.get ();
134 attr = xml_find_attribute (attributes, "text_size");
135 item.text_size = * (ULONGEST *) attr->value.get ();
137 attr = xml_find_attribute (attributes, "data_addr");
138 item.data_addr = * (ULONGEST *) attr->value.get ();
140 attr = xml_find_attribute (attributes, "data_size");
141 item.data_size = * (ULONGEST *) attr->value.get ();
143 list->push_back (std::move (item));
146 /* Handle the start of a <library-list-aix> element. */
148 static void
149 library_list_start_list (struct gdb_xml_parser *parser,
150 const struct gdb_xml_element *element,
151 void *user_data,
152 std::vector<gdb_xml_value> &attributes)
154 char *version
155 = (char *) xml_find_attribute (attributes, "version")->value.get ();
157 if (strcmp (version, "1.0") != 0)
158 gdb_xml_error (parser,
159 _("Library list has unsupported version \"%s\""),
160 version);
163 /* The allowed elements and attributes for an AIX library list
164 described in XML format. The root element is a <library-list-aix>. */
166 static const struct gdb_xml_attribute library_attributes[] =
168 { "name", GDB_XML_AF_NONE, NULL, NULL },
169 { "member", GDB_XML_AF_OPTIONAL, NULL, NULL },
170 { "text_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
171 { "text_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
172 { "data_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
173 { "data_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
174 { NULL, GDB_XML_AF_NONE, NULL, NULL }
177 static const struct gdb_xml_element library_list_children[] =
179 { "library", library_attributes, NULL,
180 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
181 library_list_start_library, NULL},
182 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
185 static const struct gdb_xml_attribute library_list_attributes[] =
187 { "version", GDB_XML_AF_NONE, NULL, NULL },
188 { NULL, GDB_XML_AF_NONE, NULL, NULL }
191 static const struct gdb_xml_element library_list_elements[] =
193 { "library-list-aix", library_list_attributes, library_list_children,
194 GDB_XML_EF_NONE, library_list_start_list, NULL },
195 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
198 /* Parse LIBRARY, a string containing the loader info in XML format,
199 and return a vector of lm_info_aix objects.
201 Return an empty option if the parsing failed. */
203 static std::optional<std::vector<lm_info_aix>>
204 solib_aix_parse_libraries (const char *library)
206 std::vector<lm_info_aix> result;
208 if (gdb_xml_parse_quick (_("aix library list"), "library-list-aix.dtd",
209 library_list_elements, library, &result) == 0)
210 return result;
212 return {};
215 #endif /* HAVE_LIBEXPAT */
217 /* Return the loader info for the given inferior (INF), or an empty
218 option if the list could not be computed.
220 Cache the result in per-inferior data, so as to avoid recomputing it
221 each time this function is called.
223 If an error occurs while computing this list, and WARNING_MSG
224 is not NULL, then print a warning including WARNING_MSG and
225 a description of the error. */
227 static std::optional<std::vector<lm_info_aix>> &
228 solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
230 struct solib_aix_inferior_data *data;
232 /* If already computed, return the cached value. */
233 data = get_solib_aix_inferior_data (inf);
234 if (data->library_list.has_value ())
235 return data->library_list;
237 std::optional<gdb::char_vector> library_document
238 = target_read_stralloc (current_inferior ()->top_target (),
239 TARGET_OBJECT_LIBRARIES_AIX,
240 NULL);
241 if (!library_document && warning_msg != NULL)
243 warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"),
244 warning_msg);
245 return data->library_list;
248 solib_debug_printf ("TARGET_OBJECT_LIBRARIES_AIX = %s",
249 library_document->data ());
251 data->library_list = solib_aix_parse_libraries (library_document->data ());
252 if (!data->library_list.has_value () && warning_msg != NULL)
253 warning (_("%s (missing XML support?)"), warning_msg);
255 return data->library_list;
258 /* If the .bss section's VMA is set to an address located before
259 the end of the .data section, causing the two sections to overlap,
260 return the overlap in bytes. Otherwise, return zero.
262 Motivation:
264 The GNU linker sometimes sets the start address of the .bss session
265 before the end of the .data section, making the 2 sections overlap.
266 The loader appears to handle this situation gracefully, by simply
267 loading the bss section right after the end of the .data section.
269 This means that the .data and the .bss sections are sometimes
270 no longer relocated by the same amount. The problem is that
271 the ldinfo data does not contain any information regarding
272 the relocation of the .bss section, assuming that it would be
273 identical to the information provided for the .data section
274 (this is what would normally happen if the program was linked
275 correctly).
277 GDB therefore needs to detect those cases, and make the corresponding
278 adjustment to the .bss section offset computed from the ldinfo data
279 when necessary. This function returns the adjustment amount (or
280 zero when no adjustment is needed). */
282 static CORE_ADDR
283 solib_aix_bss_data_overlap (bfd *abfd)
285 struct bfd_section *data_sect, *bss_sect;
287 data_sect = bfd_get_section_by_name (abfd, ".data");
288 if (data_sect == NULL)
289 return 0; /* No overlap possible. */
291 bss_sect = bfd_get_section_by_name (abfd, ".bss");
292 if (bss_sect == NULL)
293 return 0; /* No overlap possible. */
295 /* Assume the problem only occurs with linkers that place the .bss
296 section after the .data section (the problem has only been
297 observed when using the GNU linker, and the default linker
298 script always places the .data and .bss sections in that order). */
299 if (bfd_section_vma (bss_sect) < bfd_section_vma (data_sect))
300 return 0;
302 if (bfd_section_vma (bss_sect)
303 < bfd_section_vma (data_sect) + bfd_section_size (data_sect))
304 return (bfd_section_vma (data_sect) + bfd_section_size (data_sect)
305 - bfd_section_vma (bss_sect));
307 return 0;
310 /* Implement the "relocate_section_addresses" solib_ops method. */
312 static void
313 solib_aix_relocate_section_addresses (solib &so, target_section *sec)
315 struct bfd_section *bfd_sect = sec->the_bfd_section;
316 bfd *abfd = bfd_sect->owner;
317 const char *section_name = bfd_section_name (bfd_sect);
318 auto *info = gdb::checked_static_cast<lm_info_aix *> (so.lm_info.get ());
320 if (strcmp (section_name, ".text") == 0)
322 sec->addr = info->text_addr;
323 sec->endaddr = sec->addr + info->text_size;
325 /* The text address given to us by the loader contains
326 XCOFF headers, so we need to adjust by this much. */
327 sec->addr += bfd_sect->filepos;
329 else if (strcmp (section_name, ".data") == 0)
331 sec->addr = info->data_addr;
332 sec->endaddr = sec->addr + info->data_size;
334 else if (strcmp (section_name, ".bss") == 0)
336 /* The information provided by the loader does not include
337 the address of the .bss section, but we know that it gets
338 relocated by the same offset as the .data section. So,
339 compute the relocation offset for the .data section, and
340 apply it to the .bss section as well. If the .data section
341 is not defined (which seems highly unlikely), do our best
342 by assuming no relocation. */
343 struct bfd_section *data_sect
344 = bfd_get_section_by_name (abfd, ".data");
345 CORE_ADDR data_offset = 0;
347 if (data_sect != NULL)
348 data_offset = info->data_addr - bfd_section_vma (data_sect);
350 sec->addr = bfd_section_vma (bfd_sect) + data_offset;
351 sec->addr += solib_aix_bss_data_overlap (abfd);
352 sec->endaddr = sec->addr + bfd_section_size (bfd_sect);
354 else
356 /* All other sections should not be relocated. */
357 sec->addr = bfd_section_vma (bfd_sect);
358 sec->endaddr = sec->addr + bfd_section_size (bfd_sect);
362 /* Compute and return the OBJFILE's section_offset array, using
363 the associated loader info (INFO). */
365 static section_offsets
366 solib_aix_get_section_offsets (struct objfile *objfile,
367 lm_info_aix *info)
369 bfd *abfd = objfile->obfd.get ();
371 section_offsets offsets (objfile->section_offsets.size ());
373 /* .text */
375 if (objfile->sect_index_text != -1)
377 struct bfd_section *sect
378 = objfile->sections_start[objfile->sect_index_text].the_bfd_section;
380 offsets[objfile->sect_index_text]
381 = info->text_addr + sect->filepos - bfd_section_vma (sect);
384 /* .data */
386 if (objfile->sect_index_data != -1)
388 struct bfd_section *sect
389 = objfile->sections_start[objfile->sect_index_data].the_bfd_section;
391 offsets[objfile->sect_index_data]
392 = info->data_addr - bfd_section_vma (sect);
395 /* .bss
397 The offset of the .bss section should be identical to the offset
398 of the .data section. If no .data section (which seems hard to
399 believe it is possible), assume it is zero. */
401 if (objfile->sect_index_bss != -1
402 && objfile->sect_index_data != -1)
404 offsets[objfile->sect_index_bss]
405 = (offsets[objfile->sect_index_data]
406 + solib_aix_bss_data_overlap (abfd));
409 /* All other sections should not need relocation. */
411 return offsets;
414 /* Implement the "solib_create_inferior_hook" solib_ops method. */
416 static void
417 solib_aix_solib_create_inferior_hook (int from_tty)
419 const char *warning_msg = "unable to relocate main executable";
421 /* We need to relocate the main executable... */
423 std::optional<std::vector<lm_info_aix>> &library_list
424 = solib_aix_get_library_list (current_inferior (), warning_msg);
425 if (!library_list.has_value ())
426 return; /* Warning already printed. */
428 if (library_list->empty ())
430 warning (_("unable to relocate main executable (no info from loader)"));
431 return;
434 lm_info_aix &exec_info = (*library_list)[0];
435 if (current_program_space->symfile_object_file != NULL)
437 objfile *objf = current_program_space->symfile_object_file;
438 section_offsets offsets = solib_aix_get_section_offsets (objf,
439 &exec_info);
441 objfile_relocate (objf, offsets);
445 /* Implement the "current_sos" solib_ops method. */
447 static owning_intrusive_list<solib>
448 solib_aix_current_sos ()
450 std::optional<std::vector<lm_info_aix>> &library_list
451 = solib_aix_get_library_list (current_inferior (), NULL);
452 if (!library_list.has_value ())
453 return {};
455 owning_intrusive_list<solib> sos;
457 /* Build a struct solib for each entry on the list.
458 We skip the first entry, since this is the entry corresponding
459 to the main executable, not a shared library. */
460 for (int ix = 1; ix < library_list->size (); ix++)
462 std::string so_name;
464 lm_info_aix &info = (*library_list)[ix];
465 if (info.member_name.empty ())
467 /* INFO.FILENAME is probably not an archive, but rather
468 a shared object. Unusual, but it should be possible
469 to link a program against a shared object directory,
470 without having to put it in an archive first. */
471 so_name = info.filename;
473 else
475 /* This is the usual case on AIX, where the shared object
476 is a member of an archive. Create a synthetic so_name
477 that follows the same convention as AIX's ldd tool
478 (Eg: "/lib/libc.a(shr.o)"). */
479 so_name = string_printf ("%s(%s)", info.filename.c_str (),
480 info.member_name.c_str ());
483 /* Add it to the list. */
484 auto &new_solib = sos.emplace_back ();
485 new_solib.so_original_name = so_name;
486 new_solib.so_name = so_name;
487 new_solib.lm_info = std::make_unique<lm_info_aix> (info);
490 return sos;
493 /* Implement the "open_symbol_file_object" solib_ops method. */
495 static int
496 solib_aix_open_symbol_file_object (int from_tty)
498 return 0;
501 /* Implement the "in_dynsym_resolve_code" solib_ops method. */
503 static int
504 solib_aix_in_dynsym_resolve_code (CORE_ADDR pc)
506 return 0;
509 /* Implement the "bfd_open" solib_ops method. */
511 static gdb_bfd_ref_ptr
512 solib_aix_bfd_open (const char *pathname)
514 /* The pathname is actually a synthetic filename with the following
515 form: "/path/to/sharedlib(member.o)" (double-quotes excluded).
516 split this into archive name and member name.
518 FIXME: This is a little hacky. Perhaps we should provide access
519 to the solib's lm_info here? */
520 const int path_len = strlen (pathname);
521 const char *sep;
522 int filename_len;
523 int found_file;
525 if (pathname[path_len - 1] != ')')
526 return solib_bfd_open (pathname);
528 /* Search for the associated parens. */
529 sep = strrchr (pathname, '(');
530 if (sep == NULL)
532 /* Should never happen, but recover as best as we can (trying
533 to open pathname without decoding, possibly leading to
534 a failure), rather than triggering an assert failure). */
535 warning (_("missing '(' in shared object pathname: %s"), pathname);
536 return solib_bfd_open (pathname);
538 filename_len = sep - pathname;
540 std::string filename (string_printf ("%.*s", filename_len, pathname));
541 std::string member_name (string_printf ("%.*s", path_len - filename_len - 2,
542 sep + 1));
544 /* Calling solib_find makes certain that sysroot path is set properly
545 if program has a dependency on .a archive and sysroot is set via
546 set sysroot command. */
547 gdb::unique_xmalloc_ptr<char> found_pathname
548 = solib_find (filename.c_str (), &found_file);
549 if (found_pathname == NULL)
550 perror_with_name (pathname);
551 gdb_bfd_ref_ptr archive_bfd (solib_bfd_fopen (found_pathname.get (),
552 found_file));
553 if (archive_bfd == NULL)
555 warning (_("Could not open `%s' as an executable file: %s"),
556 filename.c_str (), bfd_errmsg (bfd_get_error ()));
557 return NULL;
560 if (bfd_check_format (archive_bfd.get (), bfd_object))
561 return archive_bfd;
563 if (! bfd_check_format (archive_bfd.get (), bfd_archive))
565 warning (_("\"%s\": not in executable format: %s."),
566 filename.c_str (), bfd_errmsg (bfd_get_error ()));
567 return NULL;
570 gdb_bfd_ref_ptr object_bfd
571 (gdb_bfd_openr_next_archived_file (archive_bfd.get (), NULL));
572 while (object_bfd != NULL)
574 if (member_name == bfd_get_filename (object_bfd.get ()))
575 break;
577 std::string s = bfd_get_filename (object_bfd.get ());
579 /* For every inferior after first int bfd system we
580 will have the pathname instead of the member name
581 registered. Hence the below condition exists. */
583 if (s.find ('(') != std::string::npos)
585 int pos = s.find ('(');
586 int len = s.find (')') - s.find ('(');
587 if (s.substr (pos+1, len-1) == member_name)
588 return object_bfd;
591 object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd.get (),
592 object_bfd.get ());
595 if (object_bfd == NULL)
597 warning (_("\"%s\": member \"%s\" missing."), filename.c_str (),
598 member_name.c_str ());
599 return NULL;
602 if (! bfd_check_format (object_bfd.get (), bfd_object))
604 warning (_("%s(%s): not in object format: %s."),
605 filename.c_str (), member_name.c_str (),
606 bfd_errmsg (bfd_get_error ()));
607 return NULL;
610 /* Override the returned bfd's name with the name returned from solib_find
611 along with appended parenthesized member name in order to allow commands
612 listing all shared libraries to display. Otherwise, we would only be
613 displaying the name of the archive member object. */
614 std::string fname = string_printf ("%s%s",
615 bfd_get_filename (archive_bfd.get ()),
616 sep);
617 bfd_set_filename (object_bfd.get (), fname.c_str ());
619 return object_bfd;
622 /* Return the obj_section corresponding to OBJFILE's data section,
623 or NULL if not found. */
624 /* FIXME: Define in a more general location? */
626 static struct obj_section *
627 data_obj_section_from_objfile (struct objfile *objfile)
629 for (obj_section *osect : objfile->sections ())
630 if (strcmp (bfd_section_name (osect->the_bfd_section), ".data") == 0)
631 return osect;
633 return NULL;
636 /* Return the TOC value corresponding to the given PC address,
637 or raise an error if the value could not be determined. */
639 CORE_ADDR
640 solib_aix_get_toc_value (CORE_ADDR pc)
642 struct obj_section *pc_osect = find_pc_section (pc);
643 struct obj_section *data_osect;
644 CORE_ADDR result;
646 if (pc_osect == NULL)
647 error (_("unable to find TOC entry for pc %s "
648 "(no section contains this PC)"),
649 core_addr_to_string (pc));
651 data_osect = data_obj_section_from_objfile (pc_osect->objfile);
652 if (data_osect == NULL)
653 error (_("unable to find TOC entry for pc %s "
654 "(%s has no data section)"),
655 core_addr_to_string (pc), objfile_name (pc_osect->objfile));
657 result = data_osect->addr () + xcoff_get_toc_offset (pc_osect->objfile);
659 solib_debug_printf ("pc=%s -> %s", core_addr_to_string (pc),
660 core_addr_to_string (result));
662 return result;
665 /* This module's normal_stop observer. */
667 static void
668 solib_aix_normal_stop_observer (struct bpstat *unused_1, int unused_2)
670 struct solib_aix_inferior_data *data
671 = get_solib_aix_inferior_data (current_inferior ());
673 /* The inferior execution has been resumed, and it just stopped
674 again. This means that the list of shared libraries may have
675 evolved. Reset our cached value. */
676 data->library_list.reset ();
679 /* The solib_ops for AIX targets. */
680 const solib_ops solib_aix_so_ops =
682 solib_aix_relocate_section_addresses,
683 nullptr,
684 nullptr,
685 solib_aix_solib_create_inferior_hook,
686 solib_aix_current_sos,
687 solib_aix_open_symbol_file_object,
688 solib_aix_in_dynsym_resolve_code,
689 solib_aix_bfd_open,
690 nullptr,
691 nullptr,
692 nullptr,
693 nullptr,
694 default_find_solib_addr,
697 void _initialize_solib_aix ();
698 void
699 _initialize_solib_aix ()
701 gdb::observers::normal_stop.attach (solib_aix_normal_stop_observer,
702 "solib-aix");