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