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