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