]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/solib-aix.c
Rename objfile::sections
[thirdparty/binutils-gdb.git] / gdb / solib-aix.c
CommitLineData
213516ef 1/* Copyright (C) 2013-2023 Free Software Foundation, Inc.
4d1eb6b4
JB
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"
e26d0dab 20#include "solib.h"
4d1eb6b4
JB
21#include "solist.h"
22#include "inferior.h"
23#include "gdb_bfd.h"
24#include "gdbcore.h"
25#include "objfiles.h"
26#include "symtab.h"
27#include "xcoffread.h"
76727919 28#include "observable.h"
4d1eb6b4 29#include "gdbcmd.h"
268a13a5 30#include "gdbsupport/scope-exit.h"
4d1eb6b4 31
4d1eb6b4
JB
32/* Our private data in struct so_list. */
33
d0e449a1 34struct lm_info_aix : public lm_info_base
4d1eb6b4
JB
35{
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"
39 command). */
6c401f72 40 std::string filename;
4d1eb6b4
JB
41
42 /* The name of the shared object file with the actual dynamic
6c401f72
SM
43 loading dependency. This may be empty (Eg. main executable). */
44 std::string member_name;
4d1eb6b4
JB
45
46 /* The address in inferior memory where the text section got mapped. */
6c401f72 47 CORE_ADDR text_addr = 0;
4d1eb6b4
JB
48
49 /* The size of the text section, obtained via the loader data. */
6c401f72 50 ULONGEST text_size = 0;
4d1eb6b4
JB
51
52 /* The address in inferior memory where the data section got mapped. */
6c401f72 53 CORE_ADDR data_addr = 0;
4d1eb6b4
JB
54
55 /* The size of the data section, obtained via the loader data. */
6c401f72 56 ULONGEST data_size = 0;
4d1eb6b4
JB
57};
58
4d1eb6b4
JB
59/* This module's per-inferior data. */
60
61struct solib_aix_inferior_data
62{
a269fbf1 63 /* The list of shared libraries.
4d1eb6b4
JB
64
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
70 of this list. */
a269fbf1 71 gdb::optional<std::vector<lm_info_aix>> library_list;
4d1eb6b4
JB
72};
73
74/* Key to our per-inferior data. */
08b8a139
TT
75static const registry<inferior>::key<solib_aix_inferior_data>
76 solib_aix_inferior_data_handle;
4d1eb6b4
JB
77
78/* Return this module's data for the given inferior.
79 If none is found, add a zero'ed one now. */
80
81static struct solib_aix_inferior_data *
82get_solib_aix_inferior_data (struct inferior *inf)
83{
84 struct solib_aix_inferior_data *data;
85
a269fbf1 86 data = solib_aix_inferior_data_handle.get (inf);
4d1eb6b4 87 if (data == NULL)
a269fbf1 88 data = solib_aix_inferior_data_handle.emplace (inf);
4d1eb6b4
JB
89
90 return data;
91}
92
93#if !defined(HAVE_LIBEXPAT)
94
95/* Dummy implementation if XML support is not compiled in. */
96
a269fbf1 97static gdb::optional<std::vector<lm_info_aix>>
4d1eb6b4
JB
98solib_aix_parse_libraries (const char *library)
99{
100 static int have_warned;
101
102 if (!have_warned)
103 {
104 have_warned = 1;
105 warning (_("Can not parse XML library list; XML support was disabled "
dda83cd7 106 "at compile time"));
4d1eb6b4
JB
107 }
108
a269fbf1 109 return {};
814a3ff7
JB
110}
111
4d1eb6b4
JB
112#else /* HAVE_LIBEXPAT */
113
114#include "xml-support.h"
115
116/* Handle the start of a <library> element. */
117
118static void
119library_list_start_library (struct gdb_xml_parser *parser,
120 const struct gdb_xml_element *element,
121 void *user_data,
4d0fdd9b 122 std::vector<gdb_xml_value> &attributes)
4d1eb6b4 123{
a269fbf1
TT
124 std::vector<lm_info_aix> *list = (std::vector<lm_info_aix> *) user_data;
125 lm_info_aix item;
4d1eb6b4
JB
126 struct gdb_xml_value *attr;
127
128 attr = xml_find_attribute (attributes, "name");
a269fbf1 129 item.filename = (const char *) attr->value.get ();
4d1eb6b4
JB
130
131 attr = xml_find_attribute (attributes, "member");
132 if (attr != NULL)
a269fbf1 133 item.member_name = (const char *) attr->value.get ();
4d1eb6b4
JB
134
135 attr = xml_find_attribute (attributes, "text_addr");
a269fbf1 136 item.text_addr = * (ULONGEST *) attr->value.get ();
4d1eb6b4
JB
137
138 attr = xml_find_attribute (attributes, "text_size");
a269fbf1 139 item.text_size = * (ULONGEST *) attr->value.get ();
4d1eb6b4
JB
140
141 attr = xml_find_attribute (attributes, "data_addr");
a269fbf1 142 item.data_addr = * (ULONGEST *) attr->value.get ();
4d1eb6b4
JB
143
144 attr = xml_find_attribute (attributes, "data_size");
a269fbf1 145 item.data_size = * (ULONGEST *) attr->value.get ();
4d1eb6b4 146
a269fbf1 147 list->push_back (std::move (item));
4d1eb6b4
JB
148}
149
8c56e112 150/* Handle the start of a <library-list-aix> element. */
4d1eb6b4
JB
151
152static void
153library_list_start_list (struct gdb_xml_parser *parser,
dda83cd7
SM
154 const struct gdb_xml_element *element,
155 void *user_data,
4d0fdd9b 156 std::vector<gdb_xml_value> &attributes)
4d1eb6b4 157{
4d0fdd9b
SM
158 char *version
159 = (char *) xml_find_attribute (attributes, "version")->value.get ();
4d1eb6b4
JB
160
161 if (strcmp (version, "1.0") != 0)
162 gdb_xml_error (parser,
dda83cd7
SM
163 _("Library list has unsupported version \"%s\""),
164 version);
4d1eb6b4
JB
165}
166
4d1eb6b4 167/* The allowed elements and attributes for an AIX library list
8c56e112 168 described in XML format. The root element is a <library-list-aix>. */
4d1eb6b4
JB
169
170static const struct gdb_xml_attribute library_attributes[] =
171{
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 }
179};
180
181static const struct gdb_xml_element library_list_children[] =
182{
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 }
187};
188
189static const struct gdb_xml_attribute library_list_attributes[] =
190{
191 { "version", GDB_XML_AF_NONE, NULL, NULL },
192 { NULL, GDB_XML_AF_NONE, NULL, NULL }
193};
194
195static const struct gdb_xml_element library_list_elements[] =
196{
8c56e112 197 { "library-list-aix", library_list_attributes, library_list_children,
4d1eb6b4
JB
198 GDB_XML_EF_NONE, library_list_start_list, NULL },
199 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
200};
201
202/* Parse LIBRARY, a string containing the loader info in XML format,
a269fbf1 203 and return a vector of lm_info_aix objects.
4d1eb6b4 204
a269fbf1 205 Return an empty option if the parsing failed. */
4d1eb6b4 206
a269fbf1 207static gdb::optional<std::vector<lm_info_aix>>
4d1eb6b4
JB
208solib_aix_parse_libraries (const char *library)
209{
a269fbf1 210 std::vector<lm_info_aix> result;
4d1eb6b4
JB
211
212 if (gdb_xml_parse_quick (_("aix library list"), "library-list-aix.dtd",
a269fbf1
TT
213 library_list_elements, library, &result) == 0)
214 return result;
4d1eb6b4 215
a269fbf1 216 return {};
4d1eb6b4
JB
217}
218
219#endif /* HAVE_LIBEXPAT */
220
a269fbf1
TT
221/* Return the loader info for the given inferior (INF), or an empty
222 option if the list could not be computed.
4d1eb6b4
JB
223
224 Cache the result in per-inferior data, so as to avoid recomputing it
225 each time this function is called.
226
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. */
230
a269fbf1 231static gdb::optional<std::vector<lm_info_aix>> &
4d1eb6b4
JB
232solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
233{
234 struct solib_aix_inferior_data *data;
4d1eb6b4
JB
235
236 /* If already computed, return the cached value. */
237 data = get_solib_aix_inferior_data (inf);
a269fbf1 238 if (data->library_list.has_value ())
4d1eb6b4
JB
239 return data->library_list;
240
9018be22 241 gdb::optional<gdb::char_vector> library_document
328d42d8
SM
242 = target_read_stralloc (current_inferior ()->top_target (),
243 TARGET_OBJECT_LIBRARIES_AIX,
b7b030ad 244 NULL);
9018be22 245 if (!library_document && warning_msg != NULL)
4d1eb6b4 246 {
ff99b71b 247 warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"),
4d1eb6b4 248 warning_msg);
a269fbf1 249 return data->library_list;
4d1eb6b4 250 }
4d1eb6b4 251
e26d0dab
SM
252 solib_debug_printf ("TARGET_OBJECT_LIBRARIES_AIX = %s",
253 library_document->data ());
4d1eb6b4 254
9018be22 255 data->library_list = solib_aix_parse_libraries (library_document->data ());
a269fbf1
TT
256 if (!data->library_list.has_value () && warning_msg != NULL)
257 warning (_("%s (missing XML support?)"), warning_msg);
4d1eb6b4 258
4d1eb6b4
JB
259 return data->library_list;
260}
261
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.
265
266 Motivation:
267
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.
272
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
279 correctly).
280
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). */
285
286static CORE_ADDR
287solib_aix_bss_data_overlap (bfd *abfd)
288{
289 struct bfd_section *data_sect, *bss_sect;
290
291 data_sect = bfd_get_section_by_name (abfd, ".data");
292 if (data_sect == NULL)
293 return 0; /* No overlap possible. */
294
295 bss_sect = bfd_get_section_by_name (abfd, ".bss");
296 if (bss_sect == NULL)
297 return 0; /* No overlap possible. */
298
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). */
fd361982 303 if (bfd_section_vma (bss_sect) < bfd_section_vma (data_sect))
4d1eb6b4
JB
304 return 0;
305
fd361982
AM
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));
4d1eb6b4
JB
310
311 return 0;
312}
313
314/* Implement the "relocate_section_addresses" target_so_ops method. */
315
316static void
317solib_aix_relocate_section_addresses (struct so_list *so,
318 struct target_section *sec)
319{
4d1eb6b4 320 struct bfd_section *bfd_sect = sec->the_bfd_section;
57e6060e 321 bfd *abfd = bfd_sect->owner;
fd361982 322 const char *section_name = bfd_section_name (bfd_sect);
d0e449a1 323 lm_info_aix *info = (lm_info_aix *) so->lm_info;
4d1eb6b4
JB
324
325 if (strcmp (section_name, ".text") == 0)
326 {
327 sec->addr = info->text_addr;
328 sec->endaddr = sec->addr + info->text_size;
329
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;
333 }
334 else if (strcmp (section_name, ".data") == 0)
335 {
336 sec->addr = info->data_addr;
337 sec->endaddr = sec->addr + info->data_size;
338 }
339 else if (strcmp (section_name, ".bss") == 0)
340 {
060cfbef
JB
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;
351
352 if (data_sect != NULL)
fd361982 353 data_offset = info->data_addr - bfd_section_vma (data_sect);
060cfbef 354
fd361982 355 sec->addr = bfd_section_vma (bfd_sect) + data_offset;
4d1eb6b4 356 sec->addr += solib_aix_bss_data_overlap (abfd);
fd361982 357 sec->endaddr = sec->addr + bfd_section_size (bfd_sect);
4d1eb6b4
JB
358 }
359 else
360 {
361 /* All other sections should not be relocated. */
fd361982
AM
362 sec->addr = bfd_section_vma (bfd_sect);
363 sec->endaddr = sec->addr + bfd_section_size (bfd_sect);
4d1eb6b4
JB
364 }
365}
366
367/* Implement the "free_so" target_so_ops method. */
368
369static void
370solib_aix_free_so (struct so_list *so)
371{
6c401f72
SM
372 lm_info_aix *li = (lm_info_aix *) so->lm_info;
373
e26d0dab 374 solib_debug_printf ("%s", so->so_name);
6c401f72
SM
375
376 delete li;
4d1eb6b4
JB
377}
378
379/* Implement the "clear_solib" target_so_ops method. */
380
381static void
382solib_aix_clear_solib (void)
383{
384 /* Nothing needed. */
385}
386
387/* Compute and return the OBJFILE's section_offset array, using
6a053cb1 388 the associated loader info (INFO). */
4d1eb6b4 389
6a053cb1 390static section_offsets
4d1eb6b4 391solib_aix_get_section_offsets (struct objfile *objfile,
d0e449a1 392 lm_info_aix *info)
4d1eb6b4 393{
98badbfd 394 bfd *abfd = objfile->obfd.get ();
4d1eb6b4 395
6a053cb1 396 section_offsets offsets (objfile->section_offsets.size ());
4d1eb6b4
JB
397
398 /* .text */
399
400 if (objfile->sect_index_text != -1)
401 {
402 struct bfd_section *sect
9ed8433a 403 = objfile->sections_start[objfile->sect_index_text].the_bfd_section;
4d1eb6b4 404
6a053cb1 405 offsets[objfile->sect_index_text]
fd361982 406 = info->text_addr + sect->filepos - bfd_section_vma (sect);
4d1eb6b4
JB
407 }
408
409 /* .data */
410
411 if (objfile->sect_index_data != -1)
412 {
413 struct bfd_section *sect
9ed8433a 414 = objfile->sections_start[objfile->sect_index_data].the_bfd_section;
4d1eb6b4 415
6a053cb1 416 offsets[objfile->sect_index_data]
fd361982 417 = info->data_addr - bfd_section_vma (sect);
4d1eb6b4
JB
418 }
419
420 /* .bss
421
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. */
425
426 if (objfile->sect_index_bss != -1
427 && objfile->sect_index_data != -1)
428 {
6a053cb1
TT
429 offsets[objfile->sect_index_bss]
430 = (offsets[objfile->sect_index_data]
4d1eb6b4
JB
431 + solib_aix_bss_data_overlap (abfd));
432 }
433
434 /* All other sections should not need relocation. */
435
436 return offsets;
437}
438
439/* Implement the "solib_create_inferior_hook" target_so_ops method. */
440
441static void
442solib_aix_solib_create_inferior_hook (int from_tty)
443{
444 const char *warning_msg = "unable to relocate main executable";
4d1eb6b4
JB
445
446 /* We need to relocate the main executable... */
447
a269fbf1
TT
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 ())
4d1eb6b4
JB
451 return; /* Warning already printed. */
452
a269fbf1 453 if (library_list->empty ())
4d1eb6b4
JB
454 {
455 warning (_("unable to relocate main executable (no info from loader)"));
456 return;
457 }
458
a269fbf1 459 lm_info_aix &exec_info = (*library_list)[0];
a42d7dd8 460 if (current_program_space->symfile_object_file != NULL)
4d1eb6b4 461 {
a42d7dd8
TT
462 objfile *objf = current_program_space->symfile_object_file;
463 section_offsets offsets = solib_aix_get_section_offsets (objf,
464 &exec_info);
4d1eb6b4 465
a42d7dd8 466 objfile_relocate (objf, offsets);
4d1eb6b4
JB
467 }
468}
469
4d1eb6b4
JB
470/* Implement the "current_sos" target_so_ops method. */
471
472static struct so_list *
473solib_aix_current_sos (void)
474{
475 struct so_list *start = NULL, *last = NULL;
4d1eb6b4
JB
476 int ix;
477
a269fbf1
TT
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 ())
4d1eb6b4
JB
481 return NULL;
482
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. */
a269fbf1 486 for (ix = 1; ix < library_list->size (); ix++)
4d1eb6b4 487 {
41bf6aca 488 struct so_list *new_solib = XCNEW (struct so_list);
6c401f72 489 std::string so_name;
4d1eb6b4 490
a269fbf1
TT
491 lm_info_aix &info = (*library_list)[ix];
492 if (info.member_name.empty ())
4d1eb6b4 493 {
a269fbf1 494 /* INFO.FILENAME is probably not an archive, but rather
4d1eb6b4
JB
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. */
a269fbf1 498 so_name = info.filename;
4d1eb6b4
JB
499 }
500 else
501 {
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)"). */
a269fbf1
TT
506 so_name = string_printf ("%s(%s)", info.filename.c_str (),
507 info.member_name.c_str ());
4d1eb6b4 508 }
6c401f72 509 strncpy (new_solib->so_original_name, so_name.c_str (),
4d1eb6b4
JB
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);
a269fbf1 514 new_solib->lm_info = new lm_info_aix (info);
4d1eb6b4
JB
515
516 /* Add it to the list. */
517 if (!start)
dda83cd7 518 last = start = new_solib;
4d1eb6b4 519 else
dda83cd7
SM
520 {
521 last->next = new_solib;
522 last = new_solib;
523 }
4d1eb6b4
JB
524 }
525
526 return start;
527}
528
529/* Implement the "open_symbol_file_object" target_so_ops method. */
530
531static int
bf469271 532solib_aix_open_symbol_file_object (int from_tty)
4d1eb6b4
JB
533{
534 return 0;
535}
536
537/* Implement the "in_dynsym_resolve_code" target_so_ops method. */
538
539static int
540solib_aix_in_dynsym_resolve_code (CORE_ADDR pc)
541{
542 return 0;
543}
544
545/* Implement the "bfd_open" target_so_ops method. */
546
192b62ce 547static gdb_bfd_ref_ptr
692d6f97 548solib_aix_bfd_open (const char *pathname)
4d1eb6b4
JB
549{
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.
553
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);
692d6f97 557 const char *sep;
4d1eb6b4 558 int filename_len;
754c39c2 559 int found_file;
4d1eb6b4
JB
560
561 if (pathname[path_len - 1] != ')')
562 return solib_bfd_open (pathname);
563
564 /* Search for the associated parens. */
565 sep = strrchr (pathname, '(');
566 if (sep == NULL)
567 {
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);
573 }
574 filename_len = sep - pathname;
575
192b62ce
TT
576 std::string filename (string_printf ("%.*s", filename_len, pathname));
577 std::string member_name (string_printf ("%.*s", path_len - filename_len - 2,
578 sep + 1));
4d1eb6b4 579
754c39c2
UW
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. */
797bc1cb
TT
583 gdb::unique_xmalloc_ptr<char> found_pathname
584 = solib_find (filename.c_str (), &found_file);
754c39c2
UW
585 if (found_pathname == NULL)
586 perror_with_name (pathname);
797bc1cb
TT
587 gdb_bfd_ref_ptr archive_bfd (solib_bfd_fopen (found_pathname.get (),
588 found_file));
4d1eb6b4
JB
589 if (archive_bfd == NULL)
590 {
591 warning (_("Could not open `%s' as an executable file: %s"),
192b62ce 592 filename.c_str (), bfd_errmsg (bfd_get_error ()));
4d1eb6b4
JB
593 return NULL;
594 }
595
192b62ce
TT
596 if (bfd_check_format (archive_bfd.get (), bfd_object))
597 return archive_bfd;
4d1eb6b4 598
192b62ce 599 if (! bfd_check_format (archive_bfd.get (), bfd_archive))
4d1eb6b4
JB
600 {
601 warning (_("\"%s\": not in executable format: %s."),
192b62ce 602 filename.c_str (), bfd_errmsg (bfd_get_error ()));
4d1eb6b4
JB
603 return NULL;
604 }
605
192b62ce
TT
606 gdb_bfd_ref_ptr object_bfd
607 (gdb_bfd_openr_next_archived_file (archive_bfd.get (), NULL));
4d1eb6b4
JB
608 while (object_bfd != NULL)
609 {
c7e97679 610 if (member_name == bfd_get_filename (object_bfd.get ()))
4d1eb6b4
JB
611 break;
612
7a2a5ff8
AVK
613 std::string s = bfd_get_filename (object_bfd.get ());
614
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. */
618
619 if (s.find ('(') != std::string::npos)
620 {
621 int pos = s.find ('(');
622 int len = s.find (')') - s.find ('(');
623 if (s.substr (pos+1, len-1) == member_name)
624 return object_bfd;
625 }
626
192b62ce
TT
627 object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd.get (),
628 object_bfd.get ());
4d1eb6b4
JB
629 }
630
631 if (object_bfd == NULL)
632 {
192b62ce
TT
633 warning (_("\"%s\": member \"%s\" missing."), filename.c_str (),
634 member_name.c_str ());
4d1eb6b4
JB
635 return NULL;
636 }
637
192b62ce 638 if (! bfd_check_format (object_bfd.get (), bfd_object))
4d1eb6b4
JB
639 {
640 warning (_("%s(%s): not in object format: %s."),
192b62ce
TT
641 filename.c_str (), member_name.c_str (),
642 bfd_errmsg (bfd_get_error ()));
4d1eb6b4
JB
643 return NULL;
644 }
645
754c39c2
UW
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. */
7b958a48
AM
650 std::string fname = string_printf ("%s%s",
651 bfd_get_filename (archive_bfd.get ()),
652 sep);
653 bfd_set_filename (object_bfd.get (), fname.c_str ());
b030cf11 654
4d1eb6b4
JB
655 return object_bfd;
656}
657
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? */
661
662static struct obj_section *
663data_obj_section_from_objfile (struct objfile *objfile)
664{
665 struct obj_section *osect;
666
667 ALL_OBJFILE_OSECTIONS (objfile, osect)
fd361982 668 if (strcmp (bfd_section_name (osect->the_bfd_section), ".data") == 0)
4d1eb6b4
JB
669 return osect;
670
671 return NULL;
672}
673
674/* Return the TOC value corresponding to the given PC address,
675 or raise an error if the value could not be determined. */
676
677CORE_ADDR
678solib_aix_get_toc_value (CORE_ADDR pc)
679{
680 struct obj_section *pc_osect = find_pc_section (pc);
681 struct obj_section *data_osect;
682 CORE_ADDR result;
683
684 if (pc_osect == NULL)
685 error (_("unable to find TOC entry for pc %s "
686 "(no section contains this PC)"),
687 core_addr_to_string (pc));
688
689 data_osect = data_obj_section_from_objfile (pc_osect->objfile);
690 if (data_osect == NULL)
691 error (_("unable to find TOC entry for pc %s "
692 "(%s has no data section)"),
4262abfb 693 core_addr_to_string (pc), objfile_name (pc_osect->objfile));
4d1eb6b4 694
0c1bcd23 695 result = data_osect->addr () + xcoff_get_toc_offset (pc_osect->objfile);
eef401dc 696
e26d0dab
SM
697 solib_debug_printf ("pc=%s -> %s", core_addr_to_string (pc),
698 core_addr_to_string (result));
4d1eb6b4
JB
699
700 return result;
701}
702
703/* This module's normal_stop observer. */
704
705static void
313f3b21 706solib_aix_normal_stop_observer (struct bpstat *unused_1, int unused_2)
4d1eb6b4
JB
707{
708 struct solib_aix_inferior_data *data
709 = get_solib_aix_inferior_data (current_inferior ());
710
711 /* The inferior execution has been resumed, and it just stopped
712 again. This means that the list of shared libraries may have
713 evolved. Reset our cached value. */
a269fbf1 714 data->library_list.reset ();
4d1eb6b4
JB
715}
716
4d1eb6b4 717/* The target_so_ops for AIX targets. */
549dfc51
TT
718const struct target_so_ops solib_aix_so_ops =
719{
720 solib_aix_relocate_section_addresses,
721 solib_aix_free_so,
722 nullptr,
723 solib_aix_clear_solib,
724 solib_aix_solib_create_inferior_hook,
725 solib_aix_current_sos,
726 solib_aix_open_symbol_file_object,
727 solib_aix_in_dynsym_resolve_code,
728 solib_aix_bfd_open,
729};
4d1eb6b4 730
6c265988 731void _initialize_solib_aix ();
4d1eb6b4 732void
6c265988 733_initialize_solib_aix ()
4d1eb6b4 734{
c90e7d63
SM
735 gdb::observers::normal_stop.attach (solib_aix_normal_stop_observer,
736 "solib-aix");
4d1eb6b4 737}