]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/solib-aix.c
gprofng: fix bug 29410 - Argument " 0." isn't numeric in numeric gt (>)
[thirdparty/binutils-gdb.git] / gdb / solib-aix.c
CommitLineData
4a94e368 1/* Copyright (C) 2013-2022 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"
20#include "solist.h"
21#include "inferior.h"
22#include "gdb_bfd.h"
23#include "gdbcore.h"
24#include "objfiles.h"
25#include "symtab.h"
26#include "xcoffread.h"
76727919 27#include "observable.h"
4d1eb6b4 28#include "gdbcmd.h"
268a13a5 29#include "gdbsupport/scope-exit.h"
4d1eb6b4
JB
30
31/* Variable controlling the output of the debugging traces for
32 this module. */
491144b5 33static bool solib_aix_debug;
4d1eb6b4 34
eef401dc
SM
35/* Print an "aix-solib" debug statement. */
36
37#define solib_aix_debug_printf(fmt, ...) \
38 debug_prefixed_printf_cond (solib_aix_debug, "aix-solib",fmt, ##__VA_ARGS__)
39
4d1eb6b4
JB
40/* Our private data in struct so_list. */
41
d0e449a1 42struct lm_info_aix : public lm_info_base
4d1eb6b4
JB
43{
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"
47 command). */
6c401f72 48 std::string filename;
4d1eb6b4
JB
49
50 /* The name of the shared object file with the actual dynamic
6c401f72
SM
51 loading dependency. This may be empty (Eg. main executable). */
52 std::string member_name;
4d1eb6b4
JB
53
54 /* The address in inferior memory where the text section got mapped. */
6c401f72 55 CORE_ADDR text_addr = 0;
4d1eb6b4
JB
56
57 /* The size of the text section, obtained via the loader data. */
6c401f72 58 ULONGEST text_size = 0;
4d1eb6b4
JB
59
60 /* The address in inferior memory where the data section got mapped. */
6c401f72 61 CORE_ADDR data_addr = 0;
4d1eb6b4
JB
62
63 /* The size of the data section, obtained via the loader data. */
6c401f72 64 ULONGEST data_size = 0;
4d1eb6b4
JB
65};
66
4d1eb6b4
JB
67/* This module's per-inferior data. */
68
69struct solib_aix_inferior_data
70{
a269fbf1 71 /* The list of shared libraries.
4d1eb6b4
JB
72
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
78 of this list. */
a269fbf1 79 gdb::optional<std::vector<lm_info_aix>> library_list;
4d1eb6b4
JB
80};
81
82/* Key to our per-inferior data. */
08b8a139
TT
83static const registry<inferior>::key<solib_aix_inferior_data>
84 solib_aix_inferior_data_handle;
4d1eb6b4
JB
85
86/* Return this module's data for the given inferior.
87 If none is found, add a zero'ed one now. */
88
89static struct solib_aix_inferior_data *
90get_solib_aix_inferior_data (struct inferior *inf)
91{
92 struct solib_aix_inferior_data *data;
93
a269fbf1 94 data = solib_aix_inferior_data_handle.get (inf);
4d1eb6b4 95 if (data == NULL)
a269fbf1 96 data = solib_aix_inferior_data_handle.emplace (inf);
4d1eb6b4
JB
97
98 return data;
99}
100
101#if !defined(HAVE_LIBEXPAT)
102
103/* Dummy implementation if XML support is not compiled in. */
104
a269fbf1 105static gdb::optional<std::vector<lm_info_aix>>
4d1eb6b4
JB
106solib_aix_parse_libraries (const char *library)
107{
108 static int have_warned;
109
110 if (!have_warned)
111 {
112 have_warned = 1;
113 warning (_("Can not parse XML library list; XML support was disabled "
dda83cd7 114 "at compile time"));
4d1eb6b4
JB
115 }
116
a269fbf1 117 return {};
814a3ff7
JB
118}
119
4d1eb6b4
JB
120#else /* HAVE_LIBEXPAT */
121
122#include "xml-support.h"
123
124/* Handle the start of a <library> element. */
125
126static void
127library_list_start_library (struct gdb_xml_parser *parser,
128 const struct gdb_xml_element *element,
129 void *user_data,
4d0fdd9b 130 std::vector<gdb_xml_value> &attributes)
4d1eb6b4 131{
a269fbf1
TT
132 std::vector<lm_info_aix> *list = (std::vector<lm_info_aix> *) user_data;
133 lm_info_aix item;
4d1eb6b4
JB
134 struct gdb_xml_value *attr;
135
136 attr = xml_find_attribute (attributes, "name");
a269fbf1 137 item.filename = (const char *) attr->value.get ();
4d1eb6b4
JB
138
139 attr = xml_find_attribute (attributes, "member");
140 if (attr != NULL)
a269fbf1 141 item.member_name = (const char *) attr->value.get ();
4d1eb6b4
JB
142
143 attr = xml_find_attribute (attributes, "text_addr");
a269fbf1 144 item.text_addr = * (ULONGEST *) attr->value.get ();
4d1eb6b4
JB
145
146 attr = xml_find_attribute (attributes, "text_size");
a269fbf1 147 item.text_size = * (ULONGEST *) attr->value.get ();
4d1eb6b4
JB
148
149 attr = xml_find_attribute (attributes, "data_addr");
a269fbf1 150 item.data_addr = * (ULONGEST *) attr->value.get ();
4d1eb6b4
JB
151
152 attr = xml_find_attribute (attributes, "data_size");
a269fbf1 153 item.data_size = * (ULONGEST *) attr->value.get ();
4d1eb6b4 154
a269fbf1 155 list->push_back (std::move (item));
4d1eb6b4
JB
156}
157
8c56e112 158/* Handle the start of a <library-list-aix> element. */
4d1eb6b4
JB
159
160static void
161library_list_start_list (struct gdb_xml_parser *parser,
dda83cd7
SM
162 const struct gdb_xml_element *element,
163 void *user_data,
4d0fdd9b 164 std::vector<gdb_xml_value> &attributes)
4d1eb6b4 165{
4d0fdd9b
SM
166 char *version
167 = (char *) xml_find_attribute (attributes, "version")->value.get ();
4d1eb6b4
JB
168
169 if (strcmp (version, "1.0") != 0)
170 gdb_xml_error (parser,
dda83cd7
SM
171 _("Library list has unsupported version \"%s\""),
172 version);
4d1eb6b4
JB
173}
174
4d1eb6b4 175/* The allowed elements and attributes for an AIX library list
8c56e112 176 described in XML format. The root element is a <library-list-aix>. */
4d1eb6b4
JB
177
178static const struct gdb_xml_attribute library_attributes[] =
179{
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 }
187};
188
189static const struct gdb_xml_element library_list_children[] =
190{
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 }
195};
196
197static const struct gdb_xml_attribute library_list_attributes[] =
198{
199 { "version", GDB_XML_AF_NONE, NULL, NULL },
200 { NULL, GDB_XML_AF_NONE, NULL, NULL }
201};
202
203static const struct gdb_xml_element library_list_elements[] =
204{
8c56e112 205 { "library-list-aix", library_list_attributes, library_list_children,
4d1eb6b4
JB
206 GDB_XML_EF_NONE, library_list_start_list, NULL },
207 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
208};
209
210/* Parse LIBRARY, a string containing the loader info in XML format,
a269fbf1 211 and return a vector of lm_info_aix objects.
4d1eb6b4 212
a269fbf1 213 Return an empty option if the parsing failed. */
4d1eb6b4 214
a269fbf1 215static gdb::optional<std::vector<lm_info_aix>>
4d1eb6b4
JB
216solib_aix_parse_libraries (const char *library)
217{
a269fbf1 218 std::vector<lm_info_aix> result;
4d1eb6b4
JB
219
220 if (gdb_xml_parse_quick (_("aix library list"), "library-list-aix.dtd",
a269fbf1
TT
221 library_list_elements, library, &result) == 0)
222 return result;
4d1eb6b4 223
a269fbf1 224 return {};
4d1eb6b4
JB
225}
226
227#endif /* HAVE_LIBEXPAT */
228
a269fbf1
TT
229/* Return the loader info for the given inferior (INF), or an empty
230 option if the list could not be computed.
4d1eb6b4
JB
231
232 Cache the result in per-inferior data, so as to avoid recomputing it
233 each time this function is called.
234
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. */
238
a269fbf1 239static gdb::optional<std::vector<lm_info_aix>> &
4d1eb6b4
JB
240solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
241{
242 struct solib_aix_inferior_data *data;
4d1eb6b4
JB
243
244 /* If already computed, return the cached value. */
245 data = get_solib_aix_inferior_data (inf);
a269fbf1 246 if (data->library_list.has_value ())
4d1eb6b4
JB
247 return data->library_list;
248
9018be22 249 gdb::optional<gdb::char_vector> library_document
328d42d8
SM
250 = target_read_stralloc (current_inferior ()->top_target (),
251 TARGET_OBJECT_LIBRARIES_AIX,
b7b030ad 252 NULL);
9018be22 253 if (!library_document && warning_msg != NULL)
4d1eb6b4 254 {
ff99b71b 255 warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"),
4d1eb6b4 256 warning_msg);
a269fbf1 257 return data->library_list;
4d1eb6b4 258 }
4d1eb6b4 259
eef401dc
SM
260 solib_aix_debug_printf ("TARGET_OBJECT_LIBRARIES_AIX = %s",
261 library_document->data ());
4d1eb6b4 262
9018be22 263 data->library_list = solib_aix_parse_libraries (library_document->data ());
a269fbf1
TT
264 if (!data->library_list.has_value () && warning_msg != NULL)
265 warning (_("%s (missing XML support?)"), warning_msg);
4d1eb6b4 266
4d1eb6b4
JB
267 return data->library_list;
268}
269
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.
273
274 Motivation:
275
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.
280
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
287 correctly).
288
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). */
293
294static CORE_ADDR
295solib_aix_bss_data_overlap (bfd *abfd)
296{
297 struct bfd_section *data_sect, *bss_sect;
298
299 data_sect = bfd_get_section_by_name (abfd, ".data");
300 if (data_sect == NULL)
301 return 0; /* No overlap possible. */
302
303 bss_sect = bfd_get_section_by_name (abfd, ".bss");
304 if (bss_sect == NULL)
305 return 0; /* No overlap possible. */
306
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). */
fd361982 311 if (bfd_section_vma (bss_sect) < bfd_section_vma (data_sect))
4d1eb6b4
JB
312 return 0;
313
fd361982
AM
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));
4d1eb6b4
JB
318
319 return 0;
320}
321
322/* Implement the "relocate_section_addresses" target_so_ops method. */
323
324static void
325solib_aix_relocate_section_addresses (struct so_list *so,
326 struct target_section *sec)
327{
4d1eb6b4 328 struct bfd_section *bfd_sect = sec->the_bfd_section;
57e6060e 329 bfd *abfd = bfd_sect->owner;
fd361982 330 const char *section_name = bfd_section_name (bfd_sect);
d0e449a1 331 lm_info_aix *info = (lm_info_aix *) so->lm_info;
4d1eb6b4
JB
332
333 if (strcmp (section_name, ".text") == 0)
334 {
335 sec->addr = info->text_addr;
336 sec->endaddr = sec->addr + info->text_size;
337
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;
341 }
342 else if (strcmp (section_name, ".data") == 0)
343 {
344 sec->addr = info->data_addr;
345 sec->endaddr = sec->addr + info->data_size;
346 }
347 else if (strcmp (section_name, ".bss") == 0)
348 {
060cfbef
JB
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;
359
360 if (data_sect != NULL)
fd361982 361 data_offset = info->data_addr - bfd_section_vma (data_sect);
060cfbef 362
fd361982 363 sec->addr = bfd_section_vma (bfd_sect) + data_offset;
4d1eb6b4 364 sec->addr += solib_aix_bss_data_overlap (abfd);
fd361982 365 sec->endaddr = sec->addr + bfd_section_size (bfd_sect);
4d1eb6b4
JB
366 }
367 else
368 {
369 /* All other sections should not be relocated. */
fd361982
AM
370 sec->addr = bfd_section_vma (bfd_sect);
371 sec->endaddr = sec->addr + bfd_section_size (bfd_sect);
4d1eb6b4
JB
372 }
373}
374
375/* Implement the "free_so" target_so_ops method. */
376
377static void
378solib_aix_free_so (struct so_list *so)
379{
6c401f72
SM
380 lm_info_aix *li = (lm_info_aix *) so->lm_info;
381
eef401dc 382 solib_aix_debug_printf ("%s", so->so_name);
6c401f72
SM
383
384 delete li;
4d1eb6b4
JB
385}
386
387/* Implement the "clear_solib" target_so_ops method. */
388
389static void
390solib_aix_clear_solib (void)
391{
392 /* Nothing needed. */
393}
394
395/* Compute and return the OBJFILE's section_offset array, using
6a053cb1 396 the associated loader info (INFO). */
4d1eb6b4 397
6a053cb1 398static section_offsets
4d1eb6b4 399solib_aix_get_section_offsets (struct objfile *objfile,
d0e449a1 400 lm_info_aix *info)
4d1eb6b4 401{
4d1eb6b4 402 bfd *abfd = objfile->obfd;
4d1eb6b4 403
6a053cb1 404 section_offsets offsets (objfile->section_offsets.size ());
4d1eb6b4
JB
405
406 /* .text */
407
408 if (objfile->sect_index_text != -1)
409 {
410 struct bfd_section *sect
411 = objfile->sections[objfile->sect_index_text].the_bfd_section;
412
6a053cb1 413 offsets[objfile->sect_index_text]
fd361982 414 = info->text_addr + sect->filepos - bfd_section_vma (sect);
4d1eb6b4
JB
415 }
416
417 /* .data */
418
419 if (objfile->sect_index_data != -1)
420 {
421 struct bfd_section *sect
422 = objfile->sections[objfile->sect_index_data].the_bfd_section;
423
6a053cb1 424 offsets[objfile->sect_index_data]
fd361982 425 = info->data_addr - bfd_section_vma (sect);
4d1eb6b4
JB
426 }
427
428 /* .bss
429
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. */
433
434 if (objfile->sect_index_bss != -1
435 && objfile->sect_index_data != -1)
436 {
6a053cb1
TT
437 offsets[objfile->sect_index_bss]
438 = (offsets[objfile->sect_index_data]
4d1eb6b4
JB
439 + solib_aix_bss_data_overlap (abfd));
440 }
441
442 /* All other sections should not need relocation. */
443
444 return offsets;
445}
446
447/* Implement the "solib_create_inferior_hook" target_so_ops method. */
448
449static void
450solib_aix_solib_create_inferior_hook (int from_tty)
451{
452 const char *warning_msg = "unable to relocate main executable";
4d1eb6b4
JB
453
454 /* We need to relocate the main executable... */
455
a269fbf1
TT
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 ())
4d1eb6b4
JB
459 return; /* Warning already printed. */
460
a269fbf1 461 if (library_list->empty ())
4d1eb6b4
JB
462 {
463 warning (_("unable to relocate main executable (no info from loader)"));
464 return;
465 }
466
a269fbf1 467 lm_info_aix &exec_info = (*library_list)[0];
a42d7dd8 468 if (current_program_space->symfile_object_file != NULL)
4d1eb6b4 469 {
a42d7dd8
TT
470 objfile *objf = current_program_space->symfile_object_file;
471 section_offsets offsets = solib_aix_get_section_offsets (objf,
472 &exec_info);
4d1eb6b4 473
a42d7dd8 474 objfile_relocate (objf, offsets);
4d1eb6b4
JB
475 }
476}
477
4d1eb6b4
JB
478/* Implement the "current_sos" target_so_ops method. */
479
480static struct so_list *
481solib_aix_current_sos (void)
482{
483 struct so_list *start = NULL, *last = NULL;
4d1eb6b4
JB
484 int ix;
485
a269fbf1
TT
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 ())
4d1eb6b4
JB
489 return NULL;
490
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. */
a269fbf1 494 for (ix = 1; ix < library_list->size (); ix++)
4d1eb6b4 495 {
41bf6aca 496 struct so_list *new_solib = XCNEW (struct so_list);
6c401f72 497 std::string so_name;
4d1eb6b4 498
a269fbf1
TT
499 lm_info_aix &info = (*library_list)[ix];
500 if (info.member_name.empty ())
4d1eb6b4 501 {
a269fbf1 502 /* INFO.FILENAME is probably not an archive, but rather
4d1eb6b4
JB
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. */
a269fbf1 506 so_name = info.filename;
4d1eb6b4
JB
507 }
508 else
509 {
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)"). */
a269fbf1
TT
514 so_name = string_printf ("%s(%s)", info.filename.c_str (),
515 info.member_name.c_str ());
4d1eb6b4 516 }
6c401f72 517 strncpy (new_solib->so_original_name, so_name.c_str (),
4d1eb6b4
JB
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);
a269fbf1 522 new_solib->lm_info = new lm_info_aix (info);
4d1eb6b4
JB
523
524 /* Add it to the list. */
525 if (!start)
dda83cd7 526 last = start = new_solib;
4d1eb6b4 527 else
dda83cd7
SM
528 {
529 last->next = new_solib;
530 last = new_solib;
531 }
4d1eb6b4
JB
532 }
533
534 return start;
535}
536
537/* Implement the "open_symbol_file_object" target_so_ops method. */
538
539static int
bf469271 540solib_aix_open_symbol_file_object (int from_tty)
4d1eb6b4
JB
541{
542 return 0;
543}
544
545/* Implement the "in_dynsym_resolve_code" target_so_ops method. */
546
547static int
548solib_aix_in_dynsym_resolve_code (CORE_ADDR pc)
549{
550 return 0;
551}
552
553/* Implement the "bfd_open" target_so_ops method. */
554
192b62ce 555static gdb_bfd_ref_ptr
692d6f97 556solib_aix_bfd_open (const char *pathname)
4d1eb6b4
JB
557{
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.
561
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);
692d6f97 565 const char *sep;
4d1eb6b4 566 int filename_len;
754c39c2 567 int found_file;
4d1eb6b4
JB
568
569 if (pathname[path_len - 1] != ')')
570 return solib_bfd_open (pathname);
571
572 /* Search for the associated parens. */
573 sep = strrchr (pathname, '(');
574 if (sep == NULL)
575 {
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);
581 }
582 filename_len = sep - pathname;
583
192b62ce
TT
584 std::string filename (string_printf ("%.*s", filename_len, pathname));
585 std::string member_name (string_printf ("%.*s", path_len - filename_len - 2,
586 sep + 1));
4d1eb6b4 587
754c39c2
UW
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. */
797bc1cb
TT
591 gdb::unique_xmalloc_ptr<char> found_pathname
592 = solib_find (filename.c_str (), &found_file);
754c39c2
UW
593 if (found_pathname == NULL)
594 perror_with_name (pathname);
797bc1cb
TT
595 gdb_bfd_ref_ptr archive_bfd (solib_bfd_fopen (found_pathname.get (),
596 found_file));
4d1eb6b4
JB
597 if (archive_bfd == NULL)
598 {
599 warning (_("Could not open `%s' as an executable file: %s"),
192b62ce 600 filename.c_str (), bfd_errmsg (bfd_get_error ()));
4d1eb6b4
JB
601 return NULL;
602 }
603
192b62ce
TT
604 if (bfd_check_format (archive_bfd.get (), bfd_object))
605 return archive_bfd;
4d1eb6b4 606
192b62ce 607 if (! bfd_check_format (archive_bfd.get (), bfd_archive))
4d1eb6b4
JB
608 {
609 warning (_("\"%s\": not in executable format: %s."),
192b62ce 610 filename.c_str (), bfd_errmsg (bfd_get_error ()));
4d1eb6b4
JB
611 return NULL;
612 }
613
192b62ce
TT
614 gdb_bfd_ref_ptr object_bfd
615 (gdb_bfd_openr_next_archived_file (archive_bfd.get (), NULL));
4d1eb6b4
JB
616 while (object_bfd != NULL)
617 {
c7e97679 618 if (member_name == bfd_get_filename (object_bfd.get ()))
4d1eb6b4
JB
619 break;
620
192b62ce
TT
621 object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd.get (),
622 object_bfd.get ());
4d1eb6b4
JB
623 }
624
625 if (object_bfd == NULL)
626 {
192b62ce
TT
627 warning (_("\"%s\": member \"%s\" missing."), filename.c_str (),
628 member_name.c_str ());
4d1eb6b4
JB
629 return NULL;
630 }
631
192b62ce 632 if (! bfd_check_format (object_bfd.get (), bfd_object))
4d1eb6b4
JB
633 {
634 warning (_("%s(%s): not in object format: %s."),
192b62ce
TT
635 filename.c_str (), member_name.c_str (),
636 bfd_errmsg (bfd_get_error ()));
4d1eb6b4
JB
637 return NULL;
638 }
639
754c39c2
UW
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. */
7b958a48
AM
644 std::string fname = string_printf ("%s%s",
645 bfd_get_filename (archive_bfd.get ()),
646 sep);
647 bfd_set_filename (object_bfd.get (), fname.c_str ());
b030cf11 648
4d1eb6b4
JB
649 return object_bfd;
650}
651
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? */
655
656static struct obj_section *
657data_obj_section_from_objfile (struct objfile *objfile)
658{
659 struct obj_section *osect;
660
661 ALL_OBJFILE_OSECTIONS (objfile, osect)
fd361982 662 if (strcmp (bfd_section_name (osect->the_bfd_section), ".data") == 0)
4d1eb6b4
JB
663 return osect;
664
665 return NULL;
666}
667
668/* Return the TOC value corresponding to the given PC address,
669 or raise an error if the value could not be determined. */
670
671CORE_ADDR
672solib_aix_get_toc_value (CORE_ADDR pc)
673{
674 struct obj_section *pc_osect = find_pc_section (pc);
675 struct obj_section *data_osect;
676 CORE_ADDR result;
677
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));
682
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)"),
4262abfb 687 core_addr_to_string (pc), objfile_name (pc_osect->objfile));
4d1eb6b4 688
0c1bcd23 689 result = data_osect->addr () + xcoff_get_toc_offset (pc_osect->objfile);
eef401dc
SM
690
691 solib_aix_debug_printf ("pc=%s -> %s", core_addr_to_string (pc),
692 core_addr_to_string (result));
4d1eb6b4
JB
693
694 return result;
695}
696
697/* This module's normal_stop observer. */
698
699static void
313f3b21 700solib_aix_normal_stop_observer (struct bpstat *unused_1, int unused_2)
4d1eb6b4
JB
701{
702 struct solib_aix_inferior_data *data
703 = get_solib_aix_inferior_data (current_inferior ());
704
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. */
a269fbf1 708 data->library_list.reset ();
4d1eb6b4
JB
709}
710
711/* Implements the "show debug aix-solib" command. */
712
713static void
714show_solib_aix_debug (struct ui_file *file, int from_tty,
715 struct cmd_list_element *c, const char *value)
716{
6cb06a8c 717 gdb_printf (file, _("solib-aix debugging is %s.\n"), value);
4d1eb6b4
JB
718}
719
720/* The target_so_ops for AIX targets. */
721struct target_so_ops solib_aix_so_ops;
722
6c265988 723void _initialize_solib_aix ();
4d1eb6b4 724void
6c265988 725_initialize_solib_aix ()
4d1eb6b4
JB
726{
727 solib_aix_so_ops.relocate_section_addresses
728 = solib_aix_relocate_section_addresses;
729 solib_aix_so_ops.free_so = solib_aix_free_so;
730 solib_aix_so_ops.clear_solib = solib_aix_clear_solib;
731 solib_aix_so_ops.solib_create_inferior_hook
732 = solib_aix_solib_create_inferior_hook;
4d1eb6b4
JB
733 solib_aix_so_ops.current_sos = solib_aix_current_sos;
734 solib_aix_so_ops.open_symbol_file_object
735 = solib_aix_open_symbol_file_object;
736 solib_aix_so_ops.in_dynsym_resolve_code
737 = solib_aix_in_dynsym_resolve_code;
738 solib_aix_so_ops.bfd_open = solib_aix_bfd_open;
739
c90e7d63
SM
740 gdb::observers::normal_stop.attach (solib_aix_normal_stop_observer,
741 "solib-aix");
4d1eb6b4
JB
742
743 /* Debug this file's internals. */
744 add_setshow_boolean_cmd ("aix-solib", class_maintenance,
745 &solib_aix_debug, _("\
746Control the debugging traces for the solib-aix module."), _("\
747Show whether solib-aix debugging traces are enabled."), _("\
748When on, solib-aix debugging traces are enabled."),
dda83cd7
SM
749 NULL,
750 show_solib_aix_debug,
751 &setdebuglist, &showdebuglist);
4d1eb6b4 752}