1 /* Copyright (C) 2013-2022 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 "gdbsupport/scope-exit.h"
31 /* Variable controlling the output of the debugging traces for
33 static bool solib_aix_debug
;
35 /* Print an "aix-solib" debug statement. */
37 #define solib_aix_debug_printf(fmt, ...) \
38 debug_prefixed_printf_cond (solib_aix_debug, "aix-solib",fmt, ##__VA_ARGS__)
40 /* Our private data in struct so_list. */
42 struct lm_info_aix
: public lm_info_base
44 /* The name of the file mapped by the loader. Apart from the entry
45 for the main executable, this is usually a shared library (which,
46 on AIX, is an archive library file, created using the "ar"
50 /* The name of the shared object file with the actual dynamic
51 loading dependency. This may be empty (Eg. main executable). */
52 std::string member_name
;
54 /* The address in inferior memory where the text section got mapped. */
55 CORE_ADDR text_addr
= 0;
57 /* The size of the text section, obtained via the loader data. */
58 ULONGEST text_size
= 0;
60 /* The address in inferior memory where the data section got mapped. */
61 CORE_ADDR data_addr
= 0;
63 /* The size of the data section, obtained via the loader data. */
64 ULONGEST data_size
= 0;
67 /* This module's per-inferior data. */
69 struct solib_aix_inferior_data
71 /* The list of shared libraries.
73 Note that the first element of this list is always the main
74 executable, which is not technically a shared library. But
75 we need that information to perform its relocation, and
76 the same principles applied to shared libraries also apply
77 to the main executable. So it's simpler to keep it as part
79 gdb::optional
<std::vector
<lm_info_aix
>> library_list
;
82 /* Key to our per-inferior data. */
83 static const registry
<inferior
>::key
<solib_aix_inferior_data
>
84 solib_aix_inferior_data_handle
;
86 /* Return this module's data for the given inferior.
87 If none is found, add a zero'ed one now. */
89 static struct solib_aix_inferior_data
*
90 get_solib_aix_inferior_data (struct inferior
*inf
)
92 struct solib_aix_inferior_data
*data
;
94 data
= solib_aix_inferior_data_handle
.get (inf
);
96 data
= solib_aix_inferior_data_handle
.emplace (inf
);
101 #if !defined(HAVE_LIBEXPAT)
103 /* Dummy implementation if XML support is not compiled in. */
105 static gdb::optional
<std::vector
<lm_info_aix
>>
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 #else /* HAVE_LIBEXPAT */
122 #include "xml-support.h"
124 /* Handle the start of a <library> element. */
127 library_list_start_library (struct gdb_xml_parser
*parser
,
128 const struct gdb_xml_element
*element
,
130 std::vector
<gdb_xml_value
> &attributes
)
132 std::vector
<lm_info_aix
> *list
= (std::vector
<lm_info_aix
> *) user_data
;
134 struct gdb_xml_value
*attr
;
136 attr
= xml_find_attribute (attributes
, "name");
137 item
.filename
= (const char *) attr
->value
.get ();
139 attr
= xml_find_attribute (attributes
, "member");
141 item
.member_name
= (const char *) attr
->value
.get ();
143 attr
= xml_find_attribute (attributes
, "text_addr");
144 item
.text_addr
= * (ULONGEST
*) attr
->value
.get ();
146 attr
= xml_find_attribute (attributes
, "text_size");
147 item
.text_size
= * (ULONGEST
*) attr
->value
.get ();
149 attr
= xml_find_attribute (attributes
, "data_addr");
150 item
.data_addr
= * (ULONGEST
*) attr
->value
.get ();
152 attr
= xml_find_attribute (attributes
, "data_size");
153 item
.data_size
= * (ULONGEST
*) attr
->value
.get ();
155 list
->push_back (std::move (item
));
158 /* Handle the start of a <library-list-aix> element. */
161 library_list_start_list (struct gdb_xml_parser
*parser
,
162 const struct gdb_xml_element
*element
,
164 std::vector
<gdb_xml_value
> &attributes
)
167 = (char *) xml_find_attribute (attributes
, "version")->value
.get ();
169 if (strcmp (version
, "1.0") != 0)
170 gdb_xml_error (parser
,
171 _("Library list has unsupported version \"%s\""),
175 /* The allowed elements and attributes for an AIX library list
176 described in XML format. The root element is a <library-list-aix>. */
178 static const struct gdb_xml_attribute library_attributes
[] =
180 { "name", GDB_XML_AF_NONE
, NULL
, NULL
},
181 { "member", GDB_XML_AF_OPTIONAL
, NULL
, NULL
},
182 { "text_addr", GDB_XML_AF_NONE
, gdb_xml_parse_attr_ulongest
, NULL
},
183 { "text_size", GDB_XML_AF_NONE
, gdb_xml_parse_attr_ulongest
, NULL
},
184 { "data_addr", GDB_XML_AF_NONE
, gdb_xml_parse_attr_ulongest
, NULL
},
185 { "data_size", GDB_XML_AF_NONE
, gdb_xml_parse_attr_ulongest
, NULL
},
186 { NULL
, GDB_XML_AF_NONE
, NULL
, NULL
}
189 static const struct gdb_xml_element library_list_children
[] =
191 { "library", library_attributes
, NULL
,
192 GDB_XML_EF_REPEATABLE
| GDB_XML_EF_OPTIONAL
,
193 library_list_start_library
, NULL
},
194 { NULL
, NULL
, NULL
, GDB_XML_EF_NONE
, NULL
, NULL
}
197 static const struct gdb_xml_attribute library_list_attributes
[] =
199 { "version", GDB_XML_AF_NONE
, NULL
, NULL
},
200 { NULL
, GDB_XML_AF_NONE
, NULL
, NULL
}
203 static const struct gdb_xml_element library_list_elements
[] =
205 { "library-list-aix", library_list_attributes
, library_list_children
,
206 GDB_XML_EF_NONE
, library_list_start_list
, NULL
},
207 { NULL
, NULL
, NULL
, GDB_XML_EF_NONE
, NULL
, NULL
}
210 /* Parse LIBRARY, a string containing the loader info in XML format,
211 and return a vector of lm_info_aix objects.
213 Return an empty option if the parsing failed. */
215 static gdb::optional
<std::vector
<lm_info_aix
>>
216 solib_aix_parse_libraries (const char *library
)
218 std::vector
<lm_info_aix
> result
;
220 if (gdb_xml_parse_quick (_("aix library list"), "library-list-aix.dtd",
221 library_list_elements
, library
, &result
) == 0)
227 #endif /* HAVE_LIBEXPAT */
229 /* Return the loader info for the given inferior (INF), or an empty
230 option if the list could not be computed.
232 Cache the result in per-inferior data, so as to avoid recomputing it
233 each time this function is called.
235 If an error occurs while computing this list, and WARNING_MSG
236 is not NULL, then print a warning including WARNING_MSG and
237 a description of the error. */
239 static gdb::optional
<std::vector
<lm_info_aix
>> &
240 solib_aix_get_library_list (struct inferior
*inf
, const char *warning_msg
)
242 struct solib_aix_inferior_data
*data
;
244 /* If already computed, return the cached value. */
245 data
= get_solib_aix_inferior_data (inf
);
246 if (data
->library_list
.has_value ())
247 return data
->library_list
;
249 gdb::optional
<gdb::char_vector
> library_document
250 = target_read_stralloc (current_inferior ()->top_target (),
251 TARGET_OBJECT_LIBRARIES_AIX
,
253 if (!library_document
&& warning_msg
!= NULL
)
255 warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"),
257 return data
->library_list
;
260 solib_aix_debug_printf ("TARGET_OBJECT_LIBRARIES_AIX = %s",
261 library_document
->data ());
263 data
->library_list
= solib_aix_parse_libraries (library_document
->data ());
264 if (!data
->library_list
.has_value () && warning_msg
!= NULL
)
265 warning (_("%s (missing XML support?)"), warning_msg
);
267 return data
->library_list
;
270 /* If the .bss section's VMA is set to an address located before
271 the end of the .data section, causing the two sections to overlap,
272 return the overlap in bytes. Otherwise, return zero.
276 The GNU linker sometimes sets the start address of the .bss session
277 before the end of the .data section, making the 2 sections overlap.
278 The loader appears to handle this situation gracefully, by simply
279 loading the bss section right after the end of the .data section.
281 This means that the .data and the .bss sections are sometimes
282 no longer relocated by the same amount. The problem is that
283 the ldinfo data does not contain any information regarding
284 the relocation of the .bss section, assuming that it would be
285 identical to the information provided for the .data section
286 (this is what would normally happen if the program was linked
289 GDB therefore needs to detect those cases, and make the corresponding
290 adjustment to the .bss section offset computed from the ldinfo data
291 when necessary. This function returns the adjustment amount (or
292 zero when no adjustment is needed). */
295 solib_aix_bss_data_overlap (bfd
*abfd
)
297 struct bfd_section
*data_sect
, *bss_sect
;
299 data_sect
= bfd_get_section_by_name (abfd
, ".data");
300 if (data_sect
== NULL
)
301 return 0; /* No overlap possible. */
303 bss_sect
= bfd_get_section_by_name (abfd
, ".bss");
304 if (bss_sect
== NULL
)
305 return 0; /* No overlap possible. */
307 /* Assume the problem only occurs with linkers that place the .bss
308 section after the .data section (the problem has only been
309 observed when using the GNU linker, and the default linker
310 script always places the .data and .bss sections in that order). */
311 if (bfd_section_vma (bss_sect
) < bfd_section_vma (data_sect
))
314 if (bfd_section_vma (bss_sect
)
315 < bfd_section_vma (data_sect
) + bfd_section_size (data_sect
))
316 return (bfd_section_vma (data_sect
) + bfd_section_size (data_sect
)
317 - bfd_section_vma (bss_sect
));
322 /* Implement the "relocate_section_addresses" target_so_ops method. */
325 solib_aix_relocate_section_addresses (struct so_list
*so
,
326 struct target_section
*sec
)
328 struct bfd_section
*bfd_sect
= sec
->the_bfd_section
;
329 bfd
*abfd
= bfd_sect
->owner
;
330 const char *section_name
= bfd_section_name (bfd_sect
);
331 lm_info_aix
*info
= (lm_info_aix
*) so
->lm_info
;
333 if (strcmp (section_name
, ".text") == 0)
335 sec
->addr
= info
->text_addr
;
336 sec
->endaddr
= sec
->addr
+ info
->text_size
;
338 /* The text address given to us by the loader contains
339 XCOFF headers, so we need to adjust by this much. */
340 sec
->addr
+= bfd_sect
->filepos
;
342 else if (strcmp (section_name
, ".data") == 0)
344 sec
->addr
= info
->data_addr
;
345 sec
->endaddr
= sec
->addr
+ info
->data_size
;
347 else if (strcmp (section_name
, ".bss") == 0)
349 /* The information provided by the loader does not include
350 the address of the .bss section, but we know that it gets
351 relocated by the same offset as the .data section. So,
352 compute the relocation offset for the .data section, and
353 apply it to the .bss section as well. If the .data section
354 is not defined (which seems highly unlikely), do our best
355 by assuming no relocation. */
356 struct bfd_section
*data_sect
357 = bfd_get_section_by_name (abfd
, ".data");
358 CORE_ADDR data_offset
= 0;
360 if (data_sect
!= NULL
)
361 data_offset
= info
->data_addr
- bfd_section_vma (data_sect
);
363 sec
->addr
= bfd_section_vma (bfd_sect
) + data_offset
;
364 sec
->addr
+= solib_aix_bss_data_overlap (abfd
);
365 sec
->endaddr
= sec
->addr
+ bfd_section_size (bfd_sect
);
369 /* All other sections should not be relocated. */
370 sec
->addr
= bfd_section_vma (bfd_sect
);
371 sec
->endaddr
= sec
->addr
+ bfd_section_size (bfd_sect
);
375 /* Implement the "free_so" target_so_ops method. */
378 solib_aix_free_so (struct so_list
*so
)
380 lm_info_aix
*li
= (lm_info_aix
*) so
->lm_info
;
382 solib_aix_debug_printf ("%s", so
->so_name
);
387 /* Implement the "clear_solib" target_so_ops method. */
390 solib_aix_clear_solib (void)
392 /* Nothing needed. */
395 /* Compute and return the OBJFILE's section_offset array, using
396 the associated loader info (INFO). */
398 static section_offsets
399 solib_aix_get_section_offsets (struct objfile
*objfile
,
402 bfd
*abfd
= objfile
->obfd
.get ();
404 section_offsets
offsets (objfile
->section_offsets
.size ());
408 if (objfile
->sect_index_text
!= -1)
410 struct bfd_section
*sect
411 = objfile
->sections
[objfile
->sect_index_text
].the_bfd_section
;
413 offsets
[objfile
->sect_index_text
]
414 = info
->text_addr
+ sect
->filepos
- bfd_section_vma (sect
);
419 if (objfile
->sect_index_data
!= -1)
421 struct bfd_section
*sect
422 = objfile
->sections
[objfile
->sect_index_data
].the_bfd_section
;
424 offsets
[objfile
->sect_index_data
]
425 = info
->data_addr
- bfd_section_vma (sect
);
430 The offset of the .bss section should be identical to the offset
431 of the .data section. If no .data section (which seems hard to
432 believe it is possible), assume it is zero. */
434 if (objfile
->sect_index_bss
!= -1
435 && objfile
->sect_index_data
!= -1)
437 offsets
[objfile
->sect_index_bss
]
438 = (offsets
[objfile
->sect_index_data
]
439 + solib_aix_bss_data_overlap (abfd
));
442 /* All other sections should not need relocation. */
447 /* Implement the "solib_create_inferior_hook" target_so_ops method. */
450 solib_aix_solib_create_inferior_hook (int from_tty
)
452 const char *warning_msg
= "unable to relocate main executable";
454 /* We need to relocate the main executable... */
456 gdb::optional
<std::vector
<lm_info_aix
>> &library_list
457 = solib_aix_get_library_list (current_inferior (), warning_msg
);
458 if (!library_list
.has_value ())
459 return; /* Warning already printed. */
461 if (library_list
->empty ())
463 warning (_("unable to relocate main executable (no info from loader)"));
467 lm_info_aix
&exec_info
= (*library_list
)[0];
468 if (current_program_space
->symfile_object_file
!= NULL
)
470 objfile
*objf
= current_program_space
->symfile_object_file
;
471 section_offsets offsets
= solib_aix_get_section_offsets (objf
,
474 objfile_relocate (objf
, offsets
);
478 /* Implement the "current_sos" target_so_ops method. */
480 static struct so_list
*
481 solib_aix_current_sos (void)
483 struct so_list
*start
= NULL
, *last
= NULL
;
486 gdb::optional
<std::vector
<lm_info_aix
>> &library_list
487 = solib_aix_get_library_list (current_inferior (), NULL
);
488 if (!library_list
.has_value ())
491 /* Build a struct so_list for each entry on the list.
492 We skip the first entry, since this is the entry corresponding
493 to the main executable, not a shared library. */
494 for (ix
= 1; ix
< library_list
->size (); ix
++)
496 struct so_list
*new_solib
= XCNEW (struct so_list
);
499 lm_info_aix
&info
= (*library_list
)[ix
];
500 if (info
.member_name
.empty ())
502 /* INFO.FILENAME is probably not an archive, but rather
503 a shared object. Unusual, but it should be possible
504 to link a program against a shared object directory,
505 without having to put it in an archive first. */
506 so_name
= info
.filename
;
510 /* This is the usual case on AIX, where the shared object
511 is a member of an archive. Create a synthetic so_name
512 that follows the same convention as AIX's ldd tool
513 (Eg: "/lib/libc.a(shr.o)"). */
514 so_name
= string_printf ("%s(%s)", info
.filename
.c_str (),
515 info
.member_name
.c_str ());
517 strncpy (new_solib
->so_original_name
, so_name
.c_str (),
518 SO_NAME_MAX_PATH_SIZE
- 1);
519 new_solib
->so_name
[SO_NAME_MAX_PATH_SIZE
- 1] = '\0';
520 memcpy (new_solib
->so_name
, new_solib
->so_original_name
,
521 SO_NAME_MAX_PATH_SIZE
);
522 new_solib
->lm_info
= new lm_info_aix (info
);
524 /* Add it to the list. */
526 last
= start
= new_solib
;
529 last
->next
= new_solib
;
537 /* Implement the "open_symbol_file_object" target_so_ops method. */
540 solib_aix_open_symbol_file_object (int from_tty
)
545 /* Implement the "in_dynsym_resolve_code" target_so_ops method. */
548 solib_aix_in_dynsym_resolve_code (CORE_ADDR pc
)
553 /* Implement the "bfd_open" target_so_ops method. */
555 static gdb_bfd_ref_ptr
556 solib_aix_bfd_open (const char *pathname
)
558 /* The pathname is actually a synthetic filename with the following
559 form: "/path/to/sharedlib(member.o)" (double-quotes excluded).
560 split this into archive name and member name.
562 FIXME: This is a little hacky. Perhaps we should provide access
563 to the solib's lm_info here? */
564 const int path_len
= strlen (pathname
);
569 if (pathname
[path_len
- 1] != ')')
570 return solib_bfd_open (pathname
);
572 /* Search for the associated parens. */
573 sep
= strrchr (pathname
, '(');
576 /* Should never happen, but recover as best as we can (trying
577 to open pathname without decoding, possibly leading to
578 a failure), rather than triggering an assert failure). */
579 warning (_("missing '(' in shared object pathname: %s"), pathname
);
580 return solib_bfd_open (pathname
);
582 filename_len
= sep
- pathname
;
584 std::string
filename (string_printf ("%.*s", filename_len
, pathname
));
585 std::string
member_name (string_printf ("%.*s", path_len
- filename_len
- 2,
588 /* Calling solib_find makes certain that sysroot path is set properly
589 if program has a dependency on .a archive and sysroot is set via
590 set sysroot command. */
591 gdb::unique_xmalloc_ptr
<char> found_pathname
592 = solib_find (filename
.c_str (), &found_file
);
593 if (found_pathname
== NULL
)
594 perror_with_name (pathname
);
595 gdb_bfd_ref_ptr
archive_bfd (solib_bfd_fopen (found_pathname
.get (),
597 if (archive_bfd
== NULL
)
599 warning (_("Could not open `%s' as an executable file: %s"),
600 filename
.c_str (), bfd_errmsg (bfd_get_error ()));
604 if (bfd_check_format (archive_bfd
.get (), bfd_object
))
607 if (! bfd_check_format (archive_bfd
.get (), bfd_archive
))
609 warning (_("\"%s\": not in executable format: %s."),
610 filename
.c_str (), bfd_errmsg (bfd_get_error ()));
614 gdb_bfd_ref_ptr object_bfd
615 (gdb_bfd_openr_next_archived_file (archive_bfd
.get (), NULL
));
616 while (object_bfd
!= NULL
)
618 if (member_name
== bfd_get_filename (object_bfd
.get ()))
621 object_bfd
= gdb_bfd_openr_next_archived_file (archive_bfd
.get (),
625 if (object_bfd
== NULL
)
627 warning (_("\"%s\": member \"%s\" missing."), filename
.c_str (),
628 member_name
.c_str ());
632 if (! bfd_check_format (object_bfd
.get (), bfd_object
))
634 warning (_("%s(%s): not in object format: %s."),
635 filename
.c_str (), member_name
.c_str (),
636 bfd_errmsg (bfd_get_error ()));
640 /* Override the returned bfd's name with the name returned from solib_find
641 along with appended parenthesized member name in order to allow commands
642 listing all shared libraries to display. Otherwise, we would only be
643 displaying the name of the archive member object. */
644 std::string fname
= string_printf ("%s%s",
645 bfd_get_filename (archive_bfd
.get ()),
647 bfd_set_filename (object_bfd
.get (), fname
.c_str ());
652 /* Return the obj_section corresponding to OBJFILE's data section,
653 or NULL if not found. */
654 /* FIXME: Define in a more general location? */
656 static struct obj_section
*
657 data_obj_section_from_objfile (struct objfile
*objfile
)
659 struct obj_section
*osect
;
661 ALL_OBJFILE_OSECTIONS (objfile
, osect
)
662 if (strcmp (bfd_section_name (osect
->the_bfd_section
), ".data") == 0)
668 /* Return the TOC value corresponding to the given PC address,
669 or raise an error if the value could not be determined. */
672 solib_aix_get_toc_value (CORE_ADDR pc
)
674 struct obj_section
*pc_osect
= find_pc_section (pc
);
675 struct obj_section
*data_osect
;
678 if (pc_osect
== NULL
)
679 error (_("unable to find TOC entry for pc %s "
680 "(no section contains this PC)"),
681 core_addr_to_string (pc
));
683 data_osect
= data_obj_section_from_objfile (pc_osect
->objfile
);
684 if (data_osect
== NULL
)
685 error (_("unable to find TOC entry for pc %s "
686 "(%s has no data section)"),
687 core_addr_to_string (pc
), objfile_name (pc_osect
->objfile
));
689 result
= data_osect
->addr () + xcoff_get_toc_offset (pc_osect
->objfile
);
691 solib_aix_debug_printf ("pc=%s -> %s", core_addr_to_string (pc
),
692 core_addr_to_string (result
));
697 /* This module's normal_stop observer. */
700 solib_aix_normal_stop_observer (struct bpstat
*unused_1
, int unused_2
)
702 struct solib_aix_inferior_data
*data
703 = get_solib_aix_inferior_data (current_inferior ());
705 /* The inferior execution has been resumed, and it just stopped
706 again. This means that the list of shared libraries may have
707 evolved. Reset our cached value. */
708 data
->library_list
.reset ();
711 /* Implements the "show debug aix-solib" command. */
714 show_solib_aix_debug (struct ui_file
*file
, int from_tty
,
715 struct cmd_list_element
*c
, const char *value
)
717 gdb_printf (file
, _("solib-aix debugging is %s.\n"), value
);
720 /* The target_so_ops for AIX targets. */
721 const struct target_so_ops solib_aix_so_ops
=
723 solib_aix_relocate_section_addresses
,
726 solib_aix_clear_solib
,
727 solib_aix_solib_create_inferior_hook
,
728 solib_aix_current_sos
,
729 solib_aix_open_symbol_file_object
,
730 solib_aix_in_dynsym_resolve_code
,
734 void _initialize_solib_aix ();
736 _initialize_solib_aix ()
738 gdb::observers::normal_stop
.attach (solib_aix_normal_stop_observer
,
741 /* Debug this file's internals. */
742 add_setshow_boolean_cmd ("aix-solib", class_maintenance
,
743 &solib_aix_debug
, _("\
744 Control the debugging traces for the solib-aix module."), _("\
745 Show whether solib-aix debugging traces are enabled."), _("\
746 When on, solib-aix debugging traces are enabled."),
748 show_solib_aix_debug
,
749 &setdebuglist
, &showdebuglist
);