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