Constify target_so_ops::bfd_open
[deliverable/binutils-gdb.git] / gdb / solib-aix.c
1 /* Copyright (C) 2013-2018 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 "observer.h"
28 #include "gdbcmd.h"
29
30 /* Variable controlling the output of the debugging traces for
31 this module. */
32 static int solib_aix_debug;
33
34 /* Our private data in struct so_list. */
35
36 struct lm_info_aix : public lm_info_base
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 std::string filename;
43
44 /* The name of the shared object file with the actual dynamic
45 loading dependency. This may be empty (Eg. main executable). */
46 std::string member_name;
47
48 /* The address in inferior memory where the text section got mapped. */
49 CORE_ADDR text_addr = 0;
50
51 /* The size of the text section, obtained via the loader data. */
52 ULONGEST text_size = 0;
53
54 /* The address in inferior memory where the data section got mapped. */
55 CORE_ADDR data_addr = 0;
56
57 /* The size of the data section, obtained via the loader data. */
58 ULONGEST data_size = 0;
59 };
60
61 typedef lm_info_aix *lm_info_aix_p;
62 DEF_VEC_P(lm_info_aix_p);
63
64 /* This module's per-inferior data. */
65
66 struct 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. */
76 VEC (lm_info_aix_p) *library_list;
77 };
78
79 /* Key to our per-inferior data. */
80 static 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
85 static struct solib_aix_inferior_data *
86 get_solib_aix_inferior_data (struct inferior *inf)
87 {
88 struct solib_aix_inferior_data *data;
89
90 data = ((struct solib_aix_inferior_data *)
91 inferior_data (inf, solib_aix_inferior_data_handle));
92 if (data == NULL)
93 {
94 data = XCNEW (struct solib_aix_inferior_data);
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
105 static VEC (lm_info_aix_p) *
106 solib_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
120 /* Dummy implementation if XML support is not compiled in. */
121
122 static void
123 solib_aix_free_library_list (void *p)
124 {
125 }
126
127 #else /* HAVE_LIBEXPAT */
128
129 #include "xml-support.h"
130
131 /* Handle the start of a <library> element. */
132
133 static void
134 library_list_start_library (struct gdb_xml_parser *parser,
135 const struct gdb_xml_element *element,
136 void *user_data,
137 std::vector<gdb_xml_value> &attributes)
138 {
139 VEC (lm_info_aix_p) **list = (VEC (lm_info_aix_p) **) user_data;
140 lm_info_aix *item = new lm_info_aix;
141 struct gdb_xml_value *attr;
142
143 attr = xml_find_attribute (attributes, "name");
144 item->filename = xstrdup ((const char *) attr->value.get ());
145
146 attr = xml_find_attribute (attributes, "member");
147 if (attr != NULL)
148 item->member_name = xstrdup ((const char *) attr->value.get ());
149
150 attr = xml_find_attribute (attributes, "text_addr");
151 item->text_addr = * (ULONGEST *) attr->value.get ();
152
153 attr = xml_find_attribute (attributes, "text_size");
154 item->text_size = * (ULONGEST *) attr->value.get ();
155
156 attr = xml_find_attribute (attributes, "data_addr");
157 item->data_addr = * (ULONGEST *) attr->value.get ();
158
159 attr = xml_find_attribute (attributes, "data_size");
160 item->data_size = * (ULONGEST *) attr->value.get ();
161
162 VEC_safe_push (lm_info_aix_p, *list, item);
163 }
164
165 /* Handle the start of a <library-list-aix> element. */
166
167 static void
168 library_list_start_list (struct gdb_xml_parser *parser,
169 const struct gdb_xml_element *element,
170 void *user_data,
171 std::vector<gdb_xml_value> &attributes)
172 {
173 char *version
174 = (char *) xml_find_attribute (attributes, "version")->value.get ();
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
184 static void
185 solib_aix_free_library_list (void *p)
186 {
187 VEC (lm_info_aix_p) **result = (VEC (lm_info_aix_p) **) p;
188 lm_info_aix *info;
189 int ix;
190
191 if (solib_aix_debug)
192 fprintf_unfiltered (gdb_stdlog, "DEBUG: solib_aix_free_library_list\n");
193
194 for (ix = 0; VEC_iterate (lm_info_aix_p, *result, ix, info); ix++)
195 delete info;
196
197 VEC_free (lm_info_aix_p, *result);
198 *result = NULL;
199 }
200
201 /* The allowed elements and attributes for an AIX library list
202 described in XML format. The root element is a <library-list-aix>. */
203
204 static 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
215 static 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
223 static 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
229 static const struct gdb_xml_element library_list_elements[] =
230 {
231 { "library-list-aix", library_list_attributes, library_list_children,
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,
237 and return an lm_info_aix_p vector.
238
239 Return NULL if the parsing failed. */
240
241 static VEC (lm_info_aix_p) *
242 solib_aix_parse_libraries (const char *library)
243 {
244 VEC (lm_info_aix_p) *result = NULL;
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
272 static VEC (lm_info_aix_p) *
273 solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
274 {
275 struct solib_aix_inferior_data *data;
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
282 gdb::unique_xmalloc_ptr<char> library_document
283 = target_read_stralloc (&current_target, TARGET_OBJECT_LIBRARIES_AIX,
284 NULL);
285 if (library_document == NULL && warning_msg != NULL)
286 {
287 warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"),
288 warning_msg);
289 return NULL;
290 }
291
292 if (solib_aix_debug)
293 fprintf_unfiltered (gdb_stdlog,
294 "DEBUG: TARGET_OBJECT_LIBRARIES_AIX = \n%s\n",
295 library_document.get ());
296
297 data->library_list = solib_aix_parse_libraries (library_document.get ());
298 if (data->library_list == NULL && warning_msg != NULL)
299 {
300 warning (_("%s (missing XML support?)"), warning_msg);
301 return NULL;
302 }
303
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
331 static CORE_ADDR
332 solib_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
363 static void
364 solib_aix_relocate_section_addresses (struct so_list *so,
365 struct target_section *sec)
366 {
367 struct bfd_section *bfd_sect = sec->the_bfd_section;
368 bfd *abfd = bfd_sect->owner;
369 const char *section_name = bfd_section_name (abfd, bfd_sect);
370 lm_info_aix *info = (lm_info_aix *) so->lm_info;
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 {
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;
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. */
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
416 static void
417 solib_aix_free_so (struct so_list *so)
418 {
419 lm_info_aix *li = (lm_info_aix *) so->lm_info;
420
421 if (solib_aix_debug)
422 fprintf_unfiltered (gdb_stdlog, "DEBUG: solib_aix_free_so (%s)\n",
423 so->so_name);
424
425 delete li;
426 }
427
428 /* Implement the "clear_solib" target_so_ops method. */
429
430 static void
431 solib_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
442 static struct section_offsets *
443 solib_aix_get_section_offsets (struct objfile *objfile,
444 lm_info_aix *info)
445 {
446 struct section_offsets *offsets;
447 bfd *abfd = objfile->obfd;
448
449 offsets = XCNEWVEC (struct section_offsets, objfile->num_sections);
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
494 static void
495 solib_aix_solib_create_inferior_hook (int from_tty)
496 {
497 const char *warning_msg = "unable to relocate main executable";
498 VEC (lm_info_aix_p) *library_list;
499 lm_info_aix *exec_info;
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
508 if (VEC_length (lm_info_aix_p, library_list) < 1)
509 {
510 warning (_("unable to relocate main executable (no info from loader)"));
511 return;
512 }
513
514 exec_info = VEC_index (lm_info_aix_p, library_list, 0);
515
516 if (symfile_objfile != NULL)
517 {
518 struct section_offsets *offsets
519 = solib_aix_get_section_offsets (symfile_objfile, exec_info);
520 struct cleanup *cleanup = make_cleanup (xfree, offsets);
521
522 objfile_relocate (symfile_objfile, offsets);
523 do_cleanups (cleanup);
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 observer_attach_normal_stop (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 }
This page took 0.08739 seconds and 5 git commands to generate.