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