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