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