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