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