Reimplement shared library support on ppc-aix...
[external/binutils.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 #else /* HAVE_LIBEXPAT */
145
146 #include "xml-support.h"
147
148 /* Handle the start of a <library> element.  */
149
150 static void
151 library_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
184 static void
185 library_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
199 static void
200 solib_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
218 static 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
229 static 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
237 static 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
243 static 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
255 static VEC (lm_info_p) *
256 solib_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
286 static VEC (lm_info_p) *
287 solib_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,
299                                            TARGET_OBJECT_AIX_LIBRARIES,
300                                            NULL);
301   if (library_document == NULL && warning_msg != NULL)
302     {
303       warning (_("%s (failed to read TARGET_OBJECT_AIX_LIBRARIES)"),
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,
311                         "DEBUG: TARGET_OBJECT_AIX_LIBRARIES = \n%s\n",
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
350 static CORE_ADDR
351 solib_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
382 static void
383 solib_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
431 static void
432 solib_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
442 static void
443 solib_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
454 static struct section_offsets *
455 solib_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
507 static void
508 solib_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
542 static void
543 solib_aix_special_symbol_handling (void)
544 {
545   /* Nothing needed.  */
546 }
547
548 /* Implement the "current_sos" target_so_ops method.  */
549
550 static struct so_list *
551 solib_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
608 static int
609 solib_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
616 static int
617 solib_aix_in_dynsym_resolve_code (CORE_ADDR pc)
618 {
619   return 0;
620 }
621
622 /* Implement the "bfd_open" target_so_ops method.  */
623
624 static bfd *
625 solib_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
725 static struct obj_section *
726 data_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
741 CORE_ADDR
742 solib_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
772 static void
773 solib_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
786 static void
787 show_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.  */
794 struct target_so_ops solib_aix_so_ops;
795
796 /* -Wmissing-prototypes */
797 extern initialize_file_ftype _initialize_solib_aix;
798
799 void
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, _("\
824 Control the debugging traces for the solib-aix module."), _("\
825 Show whether solib-aix debugging traces are enabled."), _("\
826 When on, solib-aix debugging traces are enabled."),
827                             NULL,
828                             show_solib_aix_debug,
829                             &setdebuglist, &showdebuglist);
830 }