1 /* Copyright (C) 2013-2023 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"
27 #include "xcoffread.h"
28 #include "observable.h"
30 #include "gdbsupport/scope-exit.h"
32 /* Our private data in struct so_list. */
34 struct lm_info_aix
: public lm_info_base
36 /* The name of the file mapped by the loader. Apart from the entry
37 for the main executable, this is usually a shared library (which,
38 on AIX, is an archive library file, created using the "ar"
42 /* The name of the shared object file with the actual dynamic
43 loading dependency. This may be empty (Eg. main executable). */
44 std::string member_name
;
46 /* The address in inferior memory where the text section got mapped. */
47 CORE_ADDR text_addr
= 0;
49 /* The size of the text section, obtained via the loader data. */
50 ULONGEST text_size
= 0;
52 /* The address in inferior memory where the data section got mapped. */
53 CORE_ADDR data_addr
= 0;
55 /* The size of the data section, obtained via the loader data. */
56 ULONGEST data_size
= 0;
59 /* This module's per-inferior data. */
61 struct solib_aix_inferior_data
63 /* The list of shared libraries.
65 Note that the first element of this list is always the main
66 executable, which is not technically a shared library. But
67 we need that information to perform its relocation, and
68 the same principles applied to shared libraries also apply
69 to the main executable. So it's simpler to keep it as part
71 gdb::optional
<std::vector
<lm_info_aix
>> library_list
;
74 /* Key to our per-inferior data. */
75 static const registry
<inferior
>::key
<solib_aix_inferior_data
>
76 solib_aix_inferior_data_handle
;
78 /* Return this module's data for the given inferior.
79 If none is found, add a zero'ed one now. */
81 static struct solib_aix_inferior_data
*
82 get_solib_aix_inferior_data (struct inferior
*inf
)
84 struct solib_aix_inferior_data
*data
;
86 data
= solib_aix_inferior_data_handle
.get (inf
);
88 data
= solib_aix_inferior_data_handle
.emplace (inf
);
93 #if !defined(HAVE_LIBEXPAT)
95 /* Dummy implementation if XML support is not compiled in. */
97 static gdb::optional
<std::vector
<lm_info_aix
>>
98 solib_aix_parse_libraries (const char *library
)
100 static int have_warned
;
105 warning (_("Can not parse XML library list; XML support was disabled "
112 #else /* HAVE_LIBEXPAT */
114 #include "xml-support.h"
116 /* Handle the start of a <library> element. */
119 library_list_start_library (struct gdb_xml_parser
*parser
,
120 const struct gdb_xml_element
*element
,
122 std::vector
<gdb_xml_value
> &attributes
)
124 std::vector
<lm_info_aix
> *list
= (std::vector
<lm_info_aix
> *) user_data
;
126 struct gdb_xml_value
*attr
;
128 attr
= xml_find_attribute (attributes
, "name");
129 item
.filename
= (const char *) attr
->value
.get ();
131 attr
= xml_find_attribute (attributes
, "member");
133 item
.member_name
= (const char *) attr
->value
.get ();
135 attr
= xml_find_attribute (attributes
, "text_addr");
136 item
.text_addr
= * (ULONGEST
*) attr
->value
.get ();
138 attr
= xml_find_attribute (attributes
, "text_size");
139 item
.text_size
= * (ULONGEST
*) attr
->value
.get ();
141 attr
= xml_find_attribute (attributes
, "data_addr");
142 item
.data_addr
= * (ULONGEST
*) attr
->value
.get ();
144 attr
= xml_find_attribute (attributes
, "data_size");
145 item
.data_size
= * (ULONGEST
*) attr
->value
.get ();
147 list
->push_back (std::move (item
));
150 /* Handle the start of a <library-list-aix> element. */
153 library_list_start_list (struct gdb_xml_parser
*parser
,
154 const struct gdb_xml_element
*element
,
156 std::vector
<gdb_xml_value
> &attributes
)
159 = (char *) xml_find_attribute (attributes
, "version")->value
.get ();
161 if (strcmp (version
, "1.0") != 0)
162 gdb_xml_error (parser
,
163 _("Library list has unsupported version \"%s\""),
167 /* The allowed elements and attributes for an AIX library list
168 described in XML format. The root element is a <library-list-aix>. */
170 static const struct gdb_xml_attribute library_attributes
[] =
172 { "name", GDB_XML_AF_NONE
, NULL
, NULL
},
173 { "member", GDB_XML_AF_OPTIONAL
, NULL
, NULL
},
174 { "text_addr", GDB_XML_AF_NONE
, gdb_xml_parse_attr_ulongest
, NULL
},
175 { "text_size", GDB_XML_AF_NONE
, gdb_xml_parse_attr_ulongest
, NULL
},
176 { "data_addr", GDB_XML_AF_NONE
, gdb_xml_parse_attr_ulongest
, NULL
},
177 { "data_size", GDB_XML_AF_NONE
, gdb_xml_parse_attr_ulongest
, NULL
},
178 { NULL
, GDB_XML_AF_NONE
, NULL
, NULL
}
181 static const struct gdb_xml_element library_list_children
[] =
183 { "library", library_attributes
, NULL
,
184 GDB_XML_EF_REPEATABLE
| GDB_XML_EF_OPTIONAL
,
185 library_list_start_library
, NULL
},
186 { NULL
, NULL
, NULL
, GDB_XML_EF_NONE
, NULL
, NULL
}
189 static const struct gdb_xml_attribute library_list_attributes
[] =
191 { "version", GDB_XML_AF_NONE
, NULL
, NULL
},
192 { NULL
, GDB_XML_AF_NONE
, NULL
, NULL
}
195 static const struct gdb_xml_element library_list_elements
[] =
197 { "library-list-aix", library_list_attributes
, library_list_children
,
198 GDB_XML_EF_NONE
, library_list_start_list
, NULL
},
199 { NULL
, NULL
, NULL
, GDB_XML_EF_NONE
, NULL
, NULL
}
202 /* Parse LIBRARY, a string containing the loader info in XML format,
203 and return a vector of lm_info_aix objects.
205 Return an empty option if the parsing failed. */
207 static gdb::optional
<std::vector
<lm_info_aix
>>
208 solib_aix_parse_libraries (const char *library
)
210 std::vector
<lm_info_aix
> result
;
212 if (gdb_xml_parse_quick (_("aix library list"), "library-list-aix.dtd",
213 library_list_elements
, library
, &result
) == 0)
219 #endif /* HAVE_LIBEXPAT */
221 /* Return the loader info for the given inferior (INF), or an empty
222 option if the list could not be computed.
224 Cache the result in per-inferior data, so as to avoid recomputing it
225 each time this function is called.
227 If an error occurs while computing this list, and WARNING_MSG
228 is not NULL, then print a warning including WARNING_MSG and
229 a description of the error. */
231 static gdb::optional
<std::vector
<lm_info_aix
>> &
232 solib_aix_get_library_list (struct inferior
*inf
, const char *warning_msg
)
234 struct solib_aix_inferior_data
*data
;
236 /* If already computed, return the cached value. */
237 data
= get_solib_aix_inferior_data (inf
);
238 if (data
->library_list
.has_value ())
239 return data
->library_list
;
241 gdb::optional
<gdb::char_vector
> library_document
242 = target_read_stralloc (current_inferior ()->top_target (),
243 TARGET_OBJECT_LIBRARIES_AIX
,
245 if (!library_document
&& warning_msg
!= NULL
)
247 warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"),
249 return data
->library_list
;
252 solib_debug_printf ("TARGET_OBJECT_LIBRARIES_AIX = %s",
253 library_document
->data ());
255 data
->library_list
= solib_aix_parse_libraries (library_document
->data ());
256 if (!data
->library_list
.has_value () && warning_msg
!= NULL
)
257 warning (_("%s (missing XML support?)"), warning_msg
);
259 return data
->library_list
;
262 /* If the .bss section's VMA is set to an address located before
263 the end of the .data section, causing the two sections to overlap,
264 return the overlap in bytes. Otherwise, return zero.
268 The GNU linker sometimes sets the start address of the .bss session
269 before the end of the .data section, making the 2 sections overlap.
270 The loader appears to handle this situation gracefully, by simply
271 loading the bss section right after the end of the .data section.
273 This means that the .data and the .bss sections are sometimes
274 no longer relocated by the same amount. The problem is that
275 the ldinfo data does not contain any information regarding
276 the relocation of the .bss section, assuming that it would be
277 identical to the information provided for the .data section
278 (this is what would normally happen if the program was linked
281 GDB therefore needs to detect those cases, and make the corresponding
282 adjustment to the .bss section offset computed from the ldinfo data
283 when necessary. This function returns the adjustment amount (or
284 zero when no adjustment is needed). */
287 solib_aix_bss_data_overlap (bfd
*abfd
)
289 struct bfd_section
*data_sect
, *bss_sect
;
291 data_sect
= bfd_get_section_by_name (abfd
, ".data");
292 if (data_sect
== NULL
)
293 return 0; /* No overlap possible. */
295 bss_sect
= bfd_get_section_by_name (abfd
, ".bss");
296 if (bss_sect
== NULL
)
297 return 0; /* No overlap possible. */
299 /* Assume the problem only occurs with linkers that place the .bss
300 section after the .data section (the problem has only been
301 observed when using the GNU linker, and the default linker
302 script always places the .data and .bss sections in that order). */
303 if (bfd_section_vma (bss_sect
) < bfd_section_vma (data_sect
))
306 if (bfd_section_vma (bss_sect
)
307 < bfd_section_vma (data_sect
) + bfd_section_size (data_sect
))
308 return (bfd_section_vma (data_sect
) + bfd_section_size (data_sect
)
309 - bfd_section_vma (bss_sect
));
314 /* Implement the "relocate_section_addresses" target_so_ops method. */
317 solib_aix_relocate_section_addresses (struct so_list
*so
,
318 struct target_section
*sec
)
320 struct bfd_section
*bfd_sect
= sec
->the_bfd_section
;
321 bfd
*abfd
= bfd_sect
->owner
;
322 const char *section_name
= bfd_section_name (bfd_sect
);
323 lm_info_aix
*info
= (lm_info_aix
*) so
->lm_info
;
325 if (strcmp (section_name
, ".text") == 0)
327 sec
->addr
= info
->text_addr
;
328 sec
->endaddr
= sec
->addr
+ info
->text_size
;
330 /* The text address given to us by the loader contains
331 XCOFF headers, so we need to adjust by this much. */
332 sec
->addr
+= bfd_sect
->filepos
;
334 else if (strcmp (section_name
, ".data") == 0)
336 sec
->addr
= info
->data_addr
;
337 sec
->endaddr
= sec
->addr
+ info
->data_size
;
339 else if (strcmp (section_name
, ".bss") == 0)
341 /* The information provided by the loader does not include
342 the address of the .bss section, but we know that it gets
343 relocated by the same offset as the .data section. So,
344 compute the relocation offset for the .data section, and
345 apply it to the .bss section as well. If the .data section
346 is not defined (which seems highly unlikely), do our best
347 by assuming no relocation. */
348 struct bfd_section
*data_sect
349 = bfd_get_section_by_name (abfd
, ".data");
350 CORE_ADDR data_offset
= 0;
352 if (data_sect
!= NULL
)
353 data_offset
= info
->data_addr
- bfd_section_vma (data_sect
);
355 sec
->addr
= bfd_section_vma (bfd_sect
) + data_offset
;
356 sec
->addr
+= solib_aix_bss_data_overlap (abfd
);
357 sec
->endaddr
= sec
->addr
+ bfd_section_size (bfd_sect
);
361 /* All other sections should not be relocated. */
362 sec
->addr
= bfd_section_vma (bfd_sect
);
363 sec
->endaddr
= sec
->addr
+ bfd_section_size (bfd_sect
);
367 /* Implement the "free_so" target_so_ops method. */
370 solib_aix_free_so (struct so_list
*so
)
372 lm_info_aix
*li
= (lm_info_aix
*) so
->lm_info
;
374 solib_debug_printf ("%s", so
->so_name
);
379 /* Implement the "clear_solib" target_so_ops method. */
382 solib_aix_clear_solib (void)
384 /* Nothing needed. */
387 /* Compute and return the OBJFILE's section_offset array, using
388 the associated loader info (INFO). */
390 static section_offsets
391 solib_aix_get_section_offsets (struct objfile
*objfile
,
394 bfd
*abfd
= objfile
->obfd
.get ();
396 section_offsets
offsets (objfile
->section_offsets
.size ());
400 if (objfile
->sect_index_text
!= -1)
402 struct bfd_section
*sect
403 = objfile
->sections_start
[objfile
->sect_index_text
].the_bfd_section
;
405 offsets
[objfile
->sect_index_text
]
406 = info
->text_addr
+ sect
->filepos
- bfd_section_vma (sect
);
411 if (objfile
->sect_index_data
!= -1)
413 struct bfd_section
*sect
414 = objfile
->sections_start
[objfile
->sect_index_data
].the_bfd_section
;
416 offsets
[objfile
->sect_index_data
]
417 = info
->data_addr
- bfd_section_vma (sect
);
422 The offset of the .bss section should be identical to the offset
423 of the .data section. If no .data section (which seems hard to
424 believe it is possible), assume it is zero. */
426 if (objfile
->sect_index_bss
!= -1
427 && objfile
->sect_index_data
!= -1)
429 offsets
[objfile
->sect_index_bss
]
430 = (offsets
[objfile
->sect_index_data
]
431 + solib_aix_bss_data_overlap (abfd
));
434 /* All other sections should not need relocation. */
439 /* Implement the "solib_create_inferior_hook" target_so_ops method. */
442 solib_aix_solib_create_inferior_hook (int from_tty
)
444 const char *warning_msg
= "unable to relocate main executable";
446 /* We need to relocate the main executable... */
448 gdb::optional
<std::vector
<lm_info_aix
>> &library_list
449 = solib_aix_get_library_list (current_inferior (), warning_msg
);
450 if (!library_list
.has_value ())
451 return; /* Warning already printed. */
453 if (library_list
->empty ())
455 warning (_("unable to relocate main executable (no info from loader)"));
459 lm_info_aix
&exec_info
= (*library_list
)[0];
460 if (current_program_space
->symfile_object_file
!= NULL
)
462 objfile
*objf
= current_program_space
->symfile_object_file
;
463 section_offsets offsets
= solib_aix_get_section_offsets (objf
,
466 objfile_relocate (objf
, offsets
);
470 /* Implement the "current_sos" target_so_ops method. */
472 static struct so_list
*
473 solib_aix_current_sos (void)
475 struct so_list
*start
= NULL
, *last
= NULL
;
478 gdb::optional
<std::vector
<lm_info_aix
>> &library_list
479 = solib_aix_get_library_list (current_inferior (), NULL
);
480 if (!library_list
.has_value ())
483 /* Build a struct so_list for each entry on the list.
484 We skip the first entry, since this is the entry corresponding
485 to the main executable, not a shared library. */
486 for (ix
= 1; ix
< library_list
->size (); ix
++)
488 struct so_list
*new_solib
= XCNEW (struct so_list
);
491 lm_info_aix
&info
= (*library_list
)[ix
];
492 if (info
.member_name
.empty ())
494 /* INFO.FILENAME is probably not an archive, but rather
495 a shared object. Unusual, but it should be possible
496 to link a program against a shared object directory,
497 without having to put it in an archive first. */
498 so_name
= info
.filename
;
502 /* This is the usual case on AIX, where the shared object
503 is a member of an archive. Create a synthetic so_name
504 that follows the same convention as AIX's ldd tool
505 (Eg: "/lib/libc.a(shr.o)"). */
506 so_name
= string_printf ("%s(%s)", info
.filename
.c_str (),
507 info
.member_name
.c_str ());
509 strncpy (new_solib
->so_original_name
, so_name
.c_str (),
510 SO_NAME_MAX_PATH_SIZE
- 1);
511 new_solib
->so_name
[SO_NAME_MAX_PATH_SIZE
- 1] = '\0';
512 memcpy (new_solib
->so_name
, new_solib
->so_original_name
,
513 SO_NAME_MAX_PATH_SIZE
);
514 new_solib
->lm_info
= new lm_info_aix (info
);
516 /* Add it to the list. */
518 last
= start
= new_solib
;
521 last
->next
= new_solib
;
529 /* Implement the "open_symbol_file_object" target_so_ops method. */
532 solib_aix_open_symbol_file_object (int from_tty
)
537 /* Implement the "in_dynsym_resolve_code" target_so_ops method. */
540 solib_aix_in_dynsym_resolve_code (CORE_ADDR pc
)
545 /* Implement the "bfd_open" target_so_ops method. */
547 static gdb_bfd_ref_ptr
548 solib_aix_bfd_open (const char *pathname
)
550 /* The pathname is actually a synthetic filename with the following
551 form: "/path/to/sharedlib(member.o)" (double-quotes excluded).
552 split this into archive name and member name.
554 FIXME: This is a little hacky. Perhaps we should provide access
555 to the solib's lm_info here? */
556 const int path_len
= strlen (pathname
);
561 if (pathname
[path_len
- 1] != ')')
562 return solib_bfd_open (pathname
);
564 /* Search for the associated parens. */
565 sep
= strrchr (pathname
, '(');
568 /* Should never happen, but recover as best as we can (trying
569 to open pathname without decoding, possibly leading to
570 a failure), rather than triggering an assert failure). */
571 warning (_("missing '(' in shared object pathname: %s"), pathname
);
572 return solib_bfd_open (pathname
);
574 filename_len
= sep
- pathname
;
576 std::string
filename (string_printf ("%.*s", filename_len
, pathname
));
577 std::string
member_name (string_printf ("%.*s", path_len
- filename_len
- 2,
580 /* Calling solib_find makes certain that sysroot path is set properly
581 if program has a dependency on .a archive and sysroot is set via
582 set sysroot command. */
583 gdb::unique_xmalloc_ptr
<char> found_pathname
584 = solib_find (filename
.c_str (), &found_file
);
585 if (found_pathname
== NULL
)
586 perror_with_name (pathname
);
587 gdb_bfd_ref_ptr
archive_bfd (solib_bfd_fopen (found_pathname
.get (),
589 if (archive_bfd
== NULL
)
591 warning (_("Could not open `%s' as an executable file: %s"),
592 filename
.c_str (), bfd_errmsg (bfd_get_error ()));
596 if (bfd_check_format (archive_bfd
.get (), bfd_object
))
599 if (! bfd_check_format (archive_bfd
.get (), bfd_archive
))
601 warning (_("\"%s\": not in executable format: %s."),
602 filename
.c_str (), bfd_errmsg (bfd_get_error ()));
606 gdb_bfd_ref_ptr object_bfd
607 (gdb_bfd_openr_next_archived_file (archive_bfd
.get (), NULL
));
608 while (object_bfd
!= NULL
)
610 if (member_name
== bfd_get_filename (object_bfd
.get ()))
613 std::string s
= bfd_get_filename (object_bfd
.get ());
615 /* For every inferior after first int bfd system we
616 will have the pathname instead of the member name
617 registered. Hence the below condition exists. */
619 if (s
.find ('(') != std::string::npos
)
621 int pos
= s
.find ('(');
622 int len
= s
.find (')') - s
.find ('(');
623 if (s
.substr (pos
+1, len
-1) == member_name
)
627 object_bfd
= gdb_bfd_openr_next_archived_file (archive_bfd
.get (),
631 if (object_bfd
== NULL
)
633 warning (_("\"%s\": member \"%s\" missing."), filename
.c_str (),
634 member_name
.c_str ());
638 if (! bfd_check_format (object_bfd
.get (), bfd_object
))
640 warning (_("%s(%s): not in object format: %s."),
641 filename
.c_str (), member_name
.c_str (),
642 bfd_errmsg (bfd_get_error ()));
646 /* Override the returned bfd's name with the name returned from solib_find
647 along with appended parenthesized member name in order to allow commands
648 listing all shared libraries to display. Otherwise, we would only be
649 displaying the name of the archive member object. */
650 std::string fname
= string_printf ("%s%s",
651 bfd_get_filename (archive_bfd
.get ()),
653 bfd_set_filename (object_bfd
.get (), fname
.c_str ());
658 /* Return the obj_section corresponding to OBJFILE's data section,
659 or NULL if not found. */
660 /* FIXME: Define in a more general location? */
662 static struct obj_section
*
663 data_obj_section_from_objfile (struct objfile
*objfile
)
665 for (obj_section
*osect
: objfile
->sections ())
666 if (strcmp (bfd_section_name (osect
->the_bfd_section
), ".data") == 0)
672 /* Return the TOC value corresponding to the given PC address,
673 or raise an error if the value could not be determined. */
676 solib_aix_get_toc_value (CORE_ADDR pc
)
678 struct obj_section
*pc_osect
= find_pc_section (pc
);
679 struct obj_section
*data_osect
;
682 if (pc_osect
== NULL
)
683 error (_("unable to find TOC entry for pc %s "
684 "(no section contains this PC)"),
685 core_addr_to_string (pc
));
687 data_osect
= data_obj_section_from_objfile (pc_osect
->objfile
);
688 if (data_osect
== NULL
)
689 error (_("unable to find TOC entry for pc %s "
690 "(%s has no data section)"),
691 core_addr_to_string (pc
), objfile_name (pc_osect
->objfile
));
693 result
= data_osect
->addr () + xcoff_get_toc_offset (pc_osect
->objfile
);
695 solib_debug_printf ("pc=%s -> %s", core_addr_to_string (pc
),
696 core_addr_to_string (result
));
701 /* This module's normal_stop observer. */
704 solib_aix_normal_stop_observer (struct bpstat
*unused_1
, int unused_2
)
706 struct solib_aix_inferior_data
*data
707 = get_solib_aix_inferior_data (current_inferior ());
709 /* The inferior execution has been resumed, and it just stopped
710 again. This means that the list of shared libraries may have
711 evolved. Reset our cached value. */
712 data
->library_list
.reset ();
715 /* The target_so_ops for AIX targets. */
716 const struct target_so_ops solib_aix_so_ops
=
718 solib_aix_relocate_section_addresses
,
721 solib_aix_clear_solib
,
722 solib_aix_solib_create_inferior_hook
,
723 solib_aix_current_sos
,
724 solib_aix_open_symbol_file_object
,
725 solib_aix_in_dynsym_resolve_code
,
729 void _initialize_solib_aix ();
731 _initialize_solib_aix ()
733 gdb::observers::normal_stop
.attach (solib_aix_normal_stop_observer
,