]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/solib-aix.c
Update copyright year range in all GDB files.
[thirdparty/binutils-gdb.git] / gdb / solib-aix.c
CommitLineData
42a4f53d 1/* Copyright (C) 2013-2019 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
JB
28#include "gdbcmd.h"
29
30/* Variable controlling the output of the debugging traces for
31 this module. */
32static int solib_aix_debug;
33
34/* Our private data in struct so_list. */
35
d0e449a1 36struct lm_info_aix : public lm_info_base
4d1eb6b4
JB
37{
38 /* The name of the file mapped by the loader. Apart from the entry
39 for the main executable, this is usually a shared library (which,
40 on AIX, is an archive library file, created using the "ar"
41 command). */
6c401f72 42 std::string filename;
4d1eb6b4
JB
43
44 /* The name of the shared object file with the actual dynamic
6c401f72
SM
45 loading dependency. This may be empty (Eg. main executable). */
46 std::string member_name;
4d1eb6b4
JB
47
48 /* The address in inferior memory where the text section got mapped. */
6c401f72 49 CORE_ADDR text_addr = 0;
4d1eb6b4
JB
50
51 /* The size of the text section, obtained via the loader data. */
6c401f72 52 ULONGEST text_size = 0;
4d1eb6b4
JB
53
54 /* The address in inferior memory where the data section got mapped. */
6c401f72 55 CORE_ADDR data_addr = 0;
4d1eb6b4
JB
56
57 /* The size of the data section, obtained via the loader data. */
6c401f72 58 ULONGEST data_size = 0;
4d1eb6b4
JB
59};
60
d0e449a1
SM
61typedef lm_info_aix *lm_info_aix_p;
62DEF_VEC_P(lm_info_aix_p);
4d1eb6b4 63
4d1eb6b4
JB
64/* This module's per-inferior data. */
65
66struct solib_aix_inferior_data
67{
68 /* The list of shared libraries. NULL if not computed yet.
69
70 Note that the first element of this list is always the main
71 executable, which is not technically a shared library. But
72 we need that information to perform its relocation, and
73 the same principles applied to shared libraries also apply
74 to the main executable. So it's simpler to keep it as part
75 of this list. */
d0e449a1 76 VEC (lm_info_aix_p) *library_list;
4d1eb6b4
JB
77};
78
79/* Key to our per-inferior data. */
80static const struct inferior_data *solib_aix_inferior_data_handle;
81
82/* Return this module's data for the given inferior.
83 If none is found, add a zero'ed one now. */
84
85static struct solib_aix_inferior_data *
86get_solib_aix_inferior_data (struct inferior *inf)
87{
88 struct solib_aix_inferior_data *data;
89
19ba03f4
SM
90 data = ((struct solib_aix_inferior_data *)
91 inferior_data (inf, solib_aix_inferior_data_handle));
4d1eb6b4
JB
92 if (data == NULL)
93 {
41bf6aca 94 data = XCNEW (struct solib_aix_inferior_data);
4d1eb6b4
JB
95 set_inferior_data (inf, solib_aix_inferior_data_handle, data);
96 }
97
98 return data;
99}
100
101#if !defined(HAVE_LIBEXPAT)
102
103/* Dummy implementation if XML support is not compiled in. */
104
d0e449a1 105static VEC (lm_info_aix_p) *
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 "
114 "at compile time"));
115 }
116
117 return NULL;
118}
119
814a3ff7
JB
120/* Dummy implementation if XML support is not compiled in. */
121
122static void
123solib_aix_free_library_list (void *p)
124{
125}
126
4d1eb6b4
JB
127#else /* HAVE_LIBEXPAT */
128
129#include "xml-support.h"
130
131/* Handle the start of a <library> element. */
132
133static void
134library_list_start_library (struct gdb_xml_parser *parser,
135 const struct gdb_xml_element *element,
136 void *user_data,
4d0fdd9b 137 std::vector<gdb_xml_value> &attributes)
4d1eb6b4 138{
d0e449a1 139 VEC (lm_info_aix_p) **list = (VEC (lm_info_aix_p) **) user_data;
6c401f72 140 lm_info_aix *item = new lm_info_aix;
4d1eb6b4
JB
141 struct gdb_xml_value *attr;
142
143 attr = xml_find_attribute (attributes, "name");
4d0fdd9b 144 item->filename = xstrdup ((const char *) attr->value.get ());
4d1eb6b4
JB
145
146 attr = xml_find_attribute (attributes, "member");
147 if (attr != NULL)
4d0fdd9b 148 item->member_name = xstrdup ((const char *) attr->value.get ());
4d1eb6b4
JB
149
150 attr = xml_find_attribute (attributes, "text_addr");
4d0fdd9b 151 item->text_addr = * (ULONGEST *) attr->value.get ();
4d1eb6b4
JB
152
153 attr = xml_find_attribute (attributes, "text_size");
4d0fdd9b 154 item->text_size = * (ULONGEST *) attr->value.get ();
4d1eb6b4
JB
155
156 attr = xml_find_attribute (attributes, "data_addr");
4d0fdd9b 157 item->data_addr = * (ULONGEST *) attr->value.get ();
4d1eb6b4
JB
158
159 attr = xml_find_attribute (attributes, "data_size");
4d0fdd9b 160 item->data_size = * (ULONGEST *) attr->value.get ();
4d1eb6b4 161
d0e449a1 162 VEC_safe_push (lm_info_aix_p, *list, item);
4d1eb6b4
JB
163}
164
8c56e112 165/* Handle the start of a <library-list-aix> element. */
4d1eb6b4
JB
166
167static void
168library_list_start_list (struct gdb_xml_parser *parser,
169 const struct gdb_xml_element *element,
4d0fdd9b
SM
170 void *user_data,
171 std::vector<gdb_xml_value> &attributes)
4d1eb6b4 172{
4d0fdd9b
SM
173 char *version
174 = (char *) xml_find_attribute (attributes, "version")->value.get ();
4d1eb6b4
JB
175
176 if (strcmp (version, "1.0") != 0)
177 gdb_xml_error (parser,
178 _("Library list has unsupported version \"%s\""),
179 version);
180}
181
182/* Discard the constructed library list. */
183
184static void
185solib_aix_free_library_list (void *p)
186{
d0e449a1
SM
187 VEC (lm_info_aix_p) **result = (VEC (lm_info_aix_p) **) p;
188 lm_info_aix *info;
4d1eb6b4
JB
189 int ix;
190
191 if (solib_aix_debug)
192 fprintf_unfiltered (gdb_stdlog, "DEBUG: solib_aix_free_library_list\n");
193
d0e449a1 194 for (ix = 0; VEC_iterate (lm_info_aix_p, *result, ix, info); ix++)
6c401f72
SM
195 delete info;
196
d0e449a1 197 VEC_free (lm_info_aix_p, *result);
4d1eb6b4
JB
198 *result = NULL;
199}
200
201/* The allowed elements and attributes for an AIX library list
8c56e112 202 described in XML format. The root element is a <library-list-aix>. */
4d1eb6b4
JB
203
204static const struct gdb_xml_attribute library_attributes[] =
205{
206 { "name", GDB_XML_AF_NONE, NULL, NULL },
207 { "member", GDB_XML_AF_OPTIONAL, NULL, NULL },
208 { "text_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
209 { "text_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
210 { "data_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
211 { "data_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
212 { NULL, GDB_XML_AF_NONE, NULL, NULL }
213};
214
215static const struct gdb_xml_element library_list_children[] =
216{
217 { "library", library_attributes, NULL,
218 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
219 library_list_start_library, NULL},
220 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
221};
222
223static const struct gdb_xml_attribute library_list_attributes[] =
224{
225 { "version", GDB_XML_AF_NONE, NULL, NULL },
226 { NULL, GDB_XML_AF_NONE, NULL, NULL }
227};
228
229static const struct gdb_xml_element library_list_elements[] =
230{
8c56e112 231 { "library-list-aix", library_list_attributes, library_list_children,
4d1eb6b4
JB
232 GDB_XML_EF_NONE, library_list_start_list, NULL },
233 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
234};
235
236/* Parse LIBRARY, a string containing the loader info in XML format,
d0e449a1 237 and return an lm_info_aix_p vector.
4d1eb6b4
JB
238
239 Return NULL if the parsing failed. */
240
d0e449a1 241static VEC (lm_info_aix_p) *
4d1eb6b4
JB
242solib_aix_parse_libraries (const char *library)
243{
d0e449a1 244 VEC (lm_info_aix_p) *result = NULL;
4d1eb6b4
JB
245 struct cleanup *back_to = make_cleanup (solib_aix_free_library_list,
246 &result);
247
248 if (gdb_xml_parse_quick (_("aix library list"), "library-list-aix.dtd",
249 library_list_elements, library, &result) == 0)
250 {
251 /* Parsed successfully, keep the result. */
252 discard_cleanups (back_to);
253 return result;
254 }
255
256 do_cleanups (back_to);
257 return NULL;
258}
259
260#endif /* HAVE_LIBEXPAT */
261
262/* Return the loader info for the given inferior (INF), or NULL if
263 the list could not be computed.
264
265 Cache the result in per-inferior data, so as to avoid recomputing it
266 each time this function is called.
267
268 If an error occurs while computing this list, and WARNING_MSG
269 is not NULL, then print a warning including WARNING_MSG and
270 a description of the error. */
271
d0e449a1 272static VEC (lm_info_aix_p) *
4d1eb6b4
JB
273solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
274{
275 struct solib_aix_inferior_data *data;
4d1eb6b4
JB
276
277 /* If already computed, return the cached value. */
278 data = get_solib_aix_inferior_data (inf);
279 if (data->library_list != NULL)
280 return data->library_list;
281
9018be22 282 gdb::optional<gdb::char_vector> library_document
8b88a78e 283 = target_read_stralloc (current_top_target (), TARGET_OBJECT_LIBRARIES_AIX,
b7b030ad 284 NULL);
9018be22 285 if (!library_document && warning_msg != NULL)
4d1eb6b4 286 {
ff99b71b 287 warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"),
4d1eb6b4
JB
288 warning_msg);
289 return NULL;
290 }
4d1eb6b4
JB
291
292 if (solib_aix_debug)
293 fprintf_unfiltered (gdb_stdlog,
ff99b71b 294 "DEBUG: TARGET_OBJECT_LIBRARIES_AIX = \n%s\n",
9018be22 295 library_document->data ());
4d1eb6b4 296
9018be22 297 data->library_list = solib_aix_parse_libraries (library_document->data ());
4d1eb6b4
JB
298 if (data->library_list == NULL && warning_msg != NULL)
299 {
300 warning (_("%s (missing XML support?)"), warning_msg);
4d1eb6b4
JB
301 return NULL;
302 }
303
4d1eb6b4
JB
304 return data->library_list;
305}
306
307/* If the .bss section's VMA is set to an address located before
308 the end of the .data section, causing the two sections to overlap,
309 return the overlap in bytes. Otherwise, return zero.
310
311 Motivation:
312
313 The GNU linker sometimes sets the start address of the .bss session
314 before the end of the .data section, making the 2 sections overlap.
315 The loader appears to handle this situation gracefully, by simply
316 loading the bss section right after the end of the .data section.
317
318 This means that the .data and the .bss sections are sometimes
319 no longer relocated by the same amount. The problem is that
320 the ldinfo data does not contain any information regarding
321 the relocation of the .bss section, assuming that it would be
322 identical to the information provided for the .data section
323 (this is what would normally happen if the program was linked
324 correctly).
325
326 GDB therefore needs to detect those cases, and make the corresponding
327 adjustment to the .bss section offset computed from the ldinfo data
328 when necessary. This function returns the adjustment amount (or
329 zero when no adjustment is needed). */
330
331static CORE_ADDR
332solib_aix_bss_data_overlap (bfd *abfd)
333{
334 struct bfd_section *data_sect, *bss_sect;
335
336 data_sect = bfd_get_section_by_name (abfd, ".data");
337 if (data_sect == NULL)
338 return 0; /* No overlap possible. */
339
340 bss_sect = bfd_get_section_by_name (abfd, ".bss");
341 if (bss_sect == NULL)
342 return 0; /* No overlap possible. */
343
344 /* Assume the problem only occurs with linkers that place the .bss
345 section after the .data section (the problem has only been
346 observed when using the GNU linker, and the default linker
347 script always places the .data and .bss sections in that order). */
348 if (bfd_section_vma (abfd, bss_sect)
349 < bfd_section_vma (abfd, data_sect))
350 return 0;
351
352 if (bfd_section_vma (abfd, bss_sect)
353 < bfd_section_vma (abfd, data_sect) + bfd_get_section_size (data_sect))
354 return ((bfd_section_vma (abfd, data_sect)
355 + bfd_get_section_size (data_sect))
356 - bfd_section_vma (abfd, bss_sect));
357
358 return 0;
359}
360
361/* Implement the "relocate_section_addresses" target_so_ops method. */
362
363static void
364solib_aix_relocate_section_addresses (struct so_list *so,
365 struct target_section *sec)
366{
4d1eb6b4 367 struct bfd_section *bfd_sect = sec->the_bfd_section;
57e6060e 368 bfd *abfd = bfd_sect->owner;
4d1eb6b4 369 const char *section_name = bfd_section_name (abfd, bfd_sect);
d0e449a1 370 lm_info_aix *info = (lm_info_aix *) so->lm_info;
4d1eb6b4
JB
371
372 if (strcmp (section_name, ".text") == 0)
373 {
374 sec->addr = info->text_addr;
375 sec->endaddr = sec->addr + info->text_size;
376
377 /* The text address given to us by the loader contains
378 XCOFF headers, so we need to adjust by this much. */
379 sec->addr += bfd_sect->filepos;
380 }
381 else if (strcmp (section_name, ".data") == 0)
382 {
383 sec->addr = info->data_addr;
384 sec->endaddr = sec->addr + info->data_size;
385 }
386 else if (strcmp (section_name, ".bss") == 0)
387 {
060cfbef
JB
388 /* The information provided by the loader does not include
389 the address of the .bss section, but we know that it gets
390 relocated by the same offset as the .data section. So,
391 compute the relocation offset for the .data section, and
392 apply it to the .bss section as well. If the .data section
393 is not defined (which seems highly unlikely), do our best
394 by assuming no relocation. */
395 struct bfd_section *data_sect
396 = bfd_get_section_by_name (abfd, ".data");
397 CORE_ADDR data_offset = 0;
398
399 if (data_sect != NULL)
400 data_offset = info->data_addr - bfd_section_vma (abfd, data_sect);
401
402 sec->addr = bfd_section_vma (abfd, bfd_sect) + data_offset;
4d1eb6b4
JB
403 sec->addr += solib_aix_bss_data_overlap (abfd);
404 sec->endaddr = sec->addr + bfd_section_size (abfd, bfd_sect);
405 }
406 else
407 {
408 /* All other sections should not be relocated. */
4d1eb6b4
JB
409 sec->addr = bfd_section_vma (abfd, bfd_sect);
410 sec->endaddr = sec->addr + bfd_section_size (abfd, bfd_sect);
411 }
412}
413
414/* Implement the "free_so" target_so_ops method. */
415
416static void
417solib_aix_free_so (struct so_list *so)
418{
6c401f72
SM
419 lm_info_aix *li = (lm_info_aix *) so->lm_info;
420
4d1eb6b4
JB
421 if (solib_aix_debug)
422 fprintf_unfiltered (gdb_stdlog, "DEBUG: solib_aix_free_so (%s)\n",
423 so->so_name);
6c401f72
SM
424
425 delete li;
4d1eb6b4
JB
426}
427
428/* Implement the "clear_solib" target_so_ops method. */
429
430static void
431solib_aix_clear_solib (void)
432{
433 /* Nothing needed. */
434}
435
436/* Compute and return the OBJFILE's section_offset array, using
437 the associated loader info (INFO).
438
439 The resulting array is computed on the heap and must be
440 deallocated after use. */
441
f709fabb 442static gdb::unique_xmalloc_ptr<struct section_offsets>
4d1eb6b4 443solib_aix_get_section_offsets (struct objfile *objfile,
d0e449a1 444 lm_info_aix *info)
4d1eb6b4 445{
4d1eb6b4 446 bfd *abfd = objfile->obfd;
4d1eb6b4 447
f709fabb
TT
448 gdb::unique_xmalloc_ptr<struct section_offsets> offsets
449 (XCNEWVEC (struct section_offsets, objfile->num_sections));
4d1eb6b4
JB
450
451 /* .text */
452
453 if (objfile->sect_index_text != -1)
454 {
455 struct bfd_section *sect
456 = objfile->sections[objfile->sect_index_text].the_bfd_section;
457
458 offsets->offsets[objfile->sect_index_text]
459 = info->text_addr + sect->filepos - bfd_section_vma (abfd, sect);
460 }
461
462 /* .data */
463
464 if (objfile->sect_index_data != -1)
465 {
466 struct bfd_section *sect
467 = objfile->sections[objfile->sect_index_data].the_bfd_section;
468
469 offsets->offsets[objfile->sect_index_data]
470 = info->data_addr - bfd_section_vma (abfd, sect);
471 }
472
473 /* .bss
474
475 The offset of the .bss section should be identical to the offset
476 of the .data section. If no .data section (which seems hard to
477 believe it is possible), assume it is zero. */
478
479 if (objfile->sect_index_bss != -1
480 && objfile->sect_index_data != -1)
481 {
482 offsets->offsets[objfile->sect_index_bss]
483 = (offsets->offsets[objfile->sect_index_data]
484 + solib_aix_bss_data_overlap (abfd));
485 }
486
487 /* All other sections should not need relocation. */
488
489 return offsets;
490}
491
492/* Implement the "solib_create_inferior_hook" target_so_ops method. */
493
494static void
495solib_aix_solib_create_inferior_hook (int from_tty)
496{
497 const char *warning_msg = "unable to relocate main executable";
d0e449a1
SM
498 VEC (lm_info_aix_p) *library_list;
499 lm_info_aix *exec_info;
4d1eb6b4
JB
500
501 /* We need to relocate the main executable... */
502
503 library_list = solib_aix_get_library_list (current_inferior (),
504 warning_msg);
505 if (library_list == NULL)
506 return; /* Warning already printed. */
507
d0e449a1 508 if (VEC_length (lm_info_aix_p, library_list) < 1)
4d1eb6b4
JB
509 {
510 warning (_("unable to relocate main executable (no info from loader)"));
511 return;
512 }
513
d0e449a1 514 exec_info = VEC_index (lm_info_aix_p, library_list, 0);
4d1eb6b4
JB
515
516 if (symfile_objfile != NULL)
517 {
f709fabb 518 gdb::unique_xmalloc_ptr<struct section_offsets> offsets
4d1eb6b4 519 = solib_aix_get_section_offsets (symfile_objfile, exec_info);
4d1eb6b4 520
f709fabb 521 objfile_relocate (symfile_objfile, offsets.get ());
4d1eb6b4
JB
522 }
523}
524
4d1eb6b4
JB
525/* Implement the "current_sos" target_so_ops method. */
526
527static struct so_list *
528solib_aix_current_sos (void)
529{
530 struct so_list *start = NULL, *last = NULL;
d0e449a1
SM
531 VEC (lm_info_aix_p) *library_list;
532 lm_info_aix *info;
4d1eb6b4
JB
533 int ix;
534
535 library_list = solib_aix_get_library_list (current_inferior (), NULL);
536 if (library_list == NULL)
537 return NULL;
538
539 /* Build a struct so_list for each entry on the list.
540 We skip the first entry, since this is the entry corresponding
541 to the main executable, not a shared library. */
d0e449a1 542 for (ix = 1; VEC_iterate (lm_info_aix_p, library_list, ix, info); ix++)
4d1eb6b4 543 {
41bf6aca 544 struct so_list *new_solib = XCNEW (struct so_list);
6c401f72 545 std::string so_name;
4d1eb6b4 546
6c401f72 547 if (info->member_name.empty ())
4d1eb6b4
JB
548 {
549 /* INFO->FILENAME is probably not an archive, but rather
550 a shared object. Unusual, but it should be possible
551 to link a program against a shared object directory,
552 without having to put it in an archive first. */
6c401f72 553 so_name = info->filename;
4d1eb6b4
JB
554 }
555 else
556 {
557 /* This is the usual case on AIX, where the shared object
558 is a member of an archive. Create a synthetic so_name
559 that follows the same convention as AIX's ldd tool
560 (Eg: "/lib/libc.a(shr.o)"). */
6c401f72
SM
561 so_name = string_printf ("%s(%s)", info->filename.c_str (),
562 info->member_name.c_str ());
4d1eb6b4 563 }
6c401f72 564 strncpy (new_solib->so_original_name, so_name.c_str (),
4d1eb6b4
JB
565 SO_NAME_MAX_PATH_SIZE - 1);
566 new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
567 memcpy (new_solib->so_name, new_solib->so_original_name,
568 SO_NAME_MAX_PATH_SIZE);
6c401f72 569 new_solib->lm_info = new lm_info_aix (*info);
4d1eb6b4
JB
570
571 /* Add it to the list. */
572 if (!start)
573 last = start = new_solib;
574 else
575 {
576 last->next = new_solib;
577 last = new_solib;
578 }
579 }
580
581 return start;
582}
583
584/* Implement the "open_symbol_file_object" target_so_ops method. */
585
586static int
bf469271 587solib_aix_open_symbol_file_object (int from_tty)
4d1eb6b4
JB
588{
589 return 0;
590}
591
592/* Implement the "in_dynsym_resolve_code" target_so_ops method. */
593
594static int
595solib_aix_in_dynsym_resolve_code (CORE_ADDR pc)
596{
597 return 0;
598}
599
600/* Implement the "bfd_open" target_so_ops method. */
601
192b62ce 602static gdb_bfd_ref_ptr
692d6f97 603solib_aix_bfd_open (const char *pathname)
4d1eb6b4
JB
604{
605 /* The pathname is actually a synthetic filename with the following
606 form: "/path/to/sharedlib(member.o)" (double-quotes excluded).
607 split this into archive name and member name.
608
609 FIXME: This is a little hacky. Perhaps we should provide access
610 to the solib's lm_info here? */
611 const int path_len = strlen (pathname);
692d6f97 612 const char *sep;
4d1eb6b4 613 int filename_len;
754c39c2 614 int found_file;
4d1eb6b4
JB
615
616 if (pathname[path_len - 1] != ')')
617 return solib_bfd_open (pathname);
618
619 /* Search for the associated parens. */
620 sep = strrchr (pathname, '(');
621 if (sep == NULL)
622 {
623 /* Should never happen, but recover as best as we can (trying
624 to open pathname without decoding, possibly leading to
625 a failure), rather than triggering an assert failure). */
626 warning (_("missing '(' in shared object pathname: %s"), pathname);
627 return solib_bfd_open (pathname);
628 }
629 filename_len = sep - pathname;
630
192b62ce
TT
631 std::string filename (string_printf ("%.*s", filename_len, pathname));
632 std::string member_name (string_printf ("%.*s", path_len - filename_len - 2,
633 sep + 1));
4d1eb6b4 634
754c39c2
UW
635 /* Calling solib_find makes certain that sysroot path is set properly
636 if program has a dependency on .a archive and sysroot is set via
637 set sysroot command. */
797bc1cb
TT
638 gdb::unique_xmalloc_ptr<char> found_pathname
639 = solib_find (filename.c_str (), &found_file);
754c39c2
UW
640 if (found_pathname == NULL)
641 perror_with_name (pathname);
797bc1cb
TT
642 gdb_bfd_ref_ptr archive_bfd (solib_bfd_fopen (found_pathname.get (),
643 found_file));
4d1eb6b4
JB
644 if (archive_bfd == NULL)
645 {
646 warning (_("Could not open `%s' as an executable file: %s"),
192b62ce 647 filename.c_str (), bfd_errmsg (bfd_get_error ()));
4d1eb6b4
JB
648 return NULL;
649 }
650
192b62ce
TT
651 if (bfd_check_format (archive_bfd.get (), bfd_object))
652 return archive_bfd;
4d1eb6b4 653
192b62ce 654 if (! bfd_check_format (archive_bfd.get (), bfd_archive))
4d1eb6b4
JB
655 {
656 warning (_("\"%s\": not in executable format: %s."),
192b62ce 657 filename.c_str (), bfd_errmsg (bfd_get_error ()));
4d1eb6b4
JB
658 return NULL;
659 }
660
192b62ce
TT
661 gdb_bfd_ref_ptr object_bfd
662 (gdb_bfd_openr_next_archived_file (archive_bfd.get (), NULL));
4d1eb6b4
JB
663 while (object_bfd != NULL)
664 {
192b62ce 665 if (member_name == object_bfd->filename)
4d1eb6b4
JB
666 break;
667
192b62ce
TT
668 object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd.get (),
669 object_bfd.get ());
4d1eb6b4
JB
670 }
671
672 if (object_bfd == NULL)
673 {
192b62ce
TT
674 warning (_("\"%s\": member \"%s\" missing."), filename.c_str (),
675 member_name.c_str ());
4d1eb6b4
JB
676 return NULL;
677 }
678
192b62ce 679 if (! bfd_check_format (object_bfd.get (), bfd_object))
4d1eb6b4
JB
680 {
681 warning (_("%s(%s): not in object format: %s."),
192b62ce
TT
682 filename.c_str (), member_name.c_str (),
683 bfd_errmsg (bfd_get_error ()));
4d1eb6b4
JB
684 return NULL;
685 }
686
754c39c2
UW
687 /* Override the returned bfd's name with the name returned from solib_find
688 along with appended parenthesized member name in order to allow commands
689 listing all shared libraries to display. Otherwise, we would only be
690 displaying the name of the archive member object. */
192b62ce 691 xfree (bfd_get_filename (object_bfd.get ()));
754c39c2 692 object_bfd->filename = xstrprintf ("%s%s",
192b62ce
TT
693 bfd_get_filename (archive_bfd.get ()),
694 sep);
b030cf11 695
4d1eb6b4
JB
696 return object_bfd;
697}
698
699/* Return the obj_section corresponding to OBJFILE's data section,
700 or NULL if not found. */
701/* FIXME: Define in a more general location? */
702
703static struct obj_section *
704data_obj_section_from_objfile (struct objfile *objfile)
705{
706 struct obj_section *osect;
707
708 ALL_OBJFILE_OSECTIONS (objfile, osect)
709 if (strcmp (bfd_section_name (objfile->obfd, osect->the_bfd_section),
710 ".data") == 0)
711 return osect;
712
713 return NULL;
714}
715
716/* Return the TOC value corresponding to the given PC address,
717 or raise an error if the value could not be determined. */
718
719CORE_ADDR
720solib_aix_get_toc_value (CORE_ADDR pc)
721{
722 struct obj_section *pc_osect = find_pc_section (pc);
723 struct obj_section *data_osect;
724 CORE_ADDR result;
725
726 if (pc_osect == NULL)
727 error (_("unable to find TOC entry for pc %s "
728 "(no section contains this PC)"),
729 core_addr_to_string (pc));
730
731 data_osect = data_obj_section_from_objfile (pc_osect->objfile);
732 if (data_osect == NULL)
733 error (_("unable to find TOC entry for pc %s "
734 "(%s has no data section)"),
4262abfb 735 core_addr_to_string (pc), objfile_name (pc_osect->objfile));
4d1eb6b4
JB
736
737 result = (obj_section_addr (data_osect)
738 + xcoff_get_toc_offset (pc_osect->objfile));
739 if (solib_aix_debug)
740 fprintf_unfiltered (gdb_stdlog,
741 "DEBUG: solib_aix_get_toc_value (pc=%s) -> %s\n",
742 core_addr_to_string (pc),
743 core_addr_to_string (result));
744
745 return result;
746}
747
748/* This module's normal_stop observer. */
749
750static void
751solib_aix_normal_stop_observer (struct bpstats *unused_1, int unused_2)
752{
753 struct solib_aix_inferior_data *data
754 = get_solib_aix_inferior_data (current_inferior ());
755
756 /* The inferior execution has been resumed, and it just stopped
757 again. This means that the list of shared libraries may have
758 evolved. Reset our cached value. */
759 solib_aix_free_library_list (&data->library_list);
760}
761
762/* Implements the "show debug aix-solib" command. */
763
764static void
765show_solib_aix_debug (struct ui_file *file, int from_tty,
766 struct cmd_list_element *c, const char *value)
767{
768 fprintf_filtered (file, _("solib-aix debugging is %s.\n"), value);
769}
770
771/* The target_so_ops for AIX targets. */
772struct target_so_ops solib_aix_so_ops;
773
4d1eb6b4
JB
774void
775_initialize_solib_aix (void)
776{
777 solib_aix_so_ops.relocate_section_addresses
778 = solib_aix_relocate_section_addresses;
779 solib_aix_so_ops.free_so = solib_aix_free_so;
780 solib_aix_so_ops.clear_solib = solib_aix_clear_solib;
781 solib_aix_so_ops.solib_create_inferior_hook
782 = solib_aix_solib_create_inferior_hook;
4d1eb6b4
JB
783 solib_aix_so_ops.current_sos = solib_aix_current_sos;
784 solib_aix_so_ops.open_symbol_file_object
785 = solib_aix_open_symbol_file_object;
786 solib_aix_so_ops.in_dynsym_resolve_code
787 = solib_aix_in_dynsym_resolve_code;
788 solib_aix_so_ops.bfd_open = solib_aix_bfd_open;
789
790 solib_aix_inferior_data_handle = register_inferior_data ();
791
76727919 792 gdb::observers::normal_stop.attach (solib_aix_normal_stop_observer);
4d1eb6b4
JB
793
794 /* Debug this file's internals. */
795 add_setshow_boolean_cmd ("aix-solib", class_maintenance,
796 &solib_aix_debug, _("\
797Control the debugging traces for the solib-aix module."), _("\
798Show whether solib-aix debugging traces are enabled."), _("\
799When on, solib-aix debugging traces are enabled."),
800 NULL,
801 show_solib_aix_debug,
802 &setdebuglist, &showdebuglist);
803}