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