1 /* Copyright (C) 2013-2018 Free Software Foundation, Inc.
3 This file is part of GDB.
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.
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.
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/>. */
19 #include "solib-aix.h"
26 #include "xcoffread.h"
30 /* Variable controlling the output of the debugging traces for
32 static int solib_aix_debug
;
34 /* Our private data in struct so_list. */
36 struct lm_info_aix
: public lm_info_base
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"
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
;
48 /* The address in inferior memory where the text section got mapped. */
49 CORE_ADDR text_addr
= 0;
51 /* The size of the text section, obtained via the loader data. */
52 ULONGEST text_size
= 0;
54 /* The address in inferior memory where the data section got mapped. */
55 CORE_ADDR data_addr
= 0;
57 /* The size of the data section, obtained via the loader data. */
58 ULONGEST data_size
= 0;
61 typedef lm_info_aix
*lm_info_aix_p
;
62 DEF_VEC_P(lm_info_aix_p
);
64 /* This module's per-inferior data. */
66 struct solib_aix_inferior_data
68 /* The list of shared libraries. NULL if not computed yet.
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
76 VEC (lm_info_aix_p
) *library_list
;
79 /* Key to our per-inferior data. */
80 static const struct inferior_data
*solib_aix_inferior_data_handle
;
82 /* Return this module's data for the given inferior.
83 If none is found, add a zero'ed one now. */
85 static struct solib_aix_inferior_data
*
86 get_solib_aix_inferior_data (struct inferior
*inf
)
88 struct solib_aix_inferior_data
*data
;
90 data
= ((struct solib_aix_inferior_data
*)
91 inferior_data (inf
, solib_aix_inferior_data_handle
));
94 data
= XCNEW (struct solib_aix_inferior_data
);
95 set_inferior_data (inf
, solib_aix_inferior_data_handle
, data
);
101 #if !defined(HAVE_LIBEXPAT)
103 /* Dummy implementation if XML support is not compiled in. */
105 static VEC (lm_info_aix_p
) *
106 solib_aix_parse_libraries (const char *library
)
108 static int have_warned
;
113 warning (_("Can not parse XML library list; XML support was disabled "
120 /* Dummy implementation if XML support is not compiled in. */
123 solib_aix_free_library_list (void *p
)
127 #else /* HAVE_LIBEXPAT */
129 #include "xml-support.h"
131 /* Handle the start of a <library> element. */
134 library_list_start_library (struct gdb_xml_parser
*parser
,
135 const struct gdb_xml_element
*element
,
137 std::vector
<gdb_xml_value
> &attributes
)
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
;
143 attr
= xml_find_attribute (attributes
, "name");
144 item
->filename
= xstrdup ((const char *) attr
->value
.get ());
146 attr
= xml_find_attribute (attributes
, "member");
148 item
->member_name
= xstrdup ((const char *) attr
->value
.get ());
150 attr
= xml_find_attribute (attributes
, "text_addr");
151 item
->text_addr
= * (ULONGEST
*) attr
->value
.get ();
153 attr
= xml_find_attribute (attributes
, "text_size");
154 item
->text_size
= * (ULONGEST
*) attr
->value
.get ();
156 attr
= xml_find_attribute (attributes
, "data_addr");
157 item
->data_addr
= * (ULONGEST
*) attr
->value
.get ();
159 attr
= xml_find_attribute (attributes
, "data_size");
160 item
->data_size
= * (ULONGEST
*) attr
->value
.get ();
162 VEC_safe_push (lm_info_aix_p
, *list
, item
);
165 /* Handle the start of a <library-list-aix> element. */
168 library_list_start_list (struct gdb_xml_parser
*parser
,
169 const struct gdb_xml_element
*element
,
171 std::vector
<gdb_xml_value
> &attributes
)
174 = (char *) xml_find_attribute (attributes
, "version")->value
.get ();
176 if (strcmp (version
, "1.0") != 0)
177 gdb_xml_error (parser
,
178 _("Library list has unsupported version \"%s\""),
182 /* Discard the constructed library list. */
185 solib_aix_free_library_list (void *p
)
187 VEC (lm_info_aix_p
) **result
= (VEC (lm_info_aix_p
) **) p
;
192 fprintf_unfiltered (gdb_stdlog
, "DEBUG: solib_aix_free_library_list\n");
194 for (ix
= 0; VEC_iterate (lm_info_aix_p
, *result
, ix
, info
); ix
++)
197 VEC_free (lm_info_aix_p
, *result
);
201 /* The allowed elements and attributes for an AIX library list
202 described in XML format. The root element is a <library-list-aix>. */
204 static const struct gdb_xml_attribute library_attributes
[] =
206 { "name", GDB_XML_AF_NONE
, NULL
, NULL
},
207 { "member", GDB_XML_AF_OPTIONAL
, NULL
, NULL
},
208 { "text_addr", GDB_XML_AF_NONE
, gdb_xml_parse_attr_ulongest
, NULL
},
209 { "text_size", GDB_XML_AF_NONE
, gdb_xml_parse_attr_ulongest
, NULL
},
210 { "data_addr", GDB_XML_AF_NONE
, gdb_xml_parse_attr_ulongest
, NULL
},
211 { "data_size", GDB_XML_AF_NONE
, gdb_xml_parse_attr_ulongest
, NULL
},
212 { NULL
, GDB_XML_AF_NONE
, NULL
, NULL
}
215 static const struct gdb_xml_element library_list_children
[] =
217 { "library", library_attributes
, NULL
,
218 GDB_XML_EF_REPEATABLE
| GDB_XML_EF_OPTIONAL
,
219 library_list_start_library
, NULL
},
220 { NULL
, NULL
, NULL
, GDB_XML_EF_NONE
, NULL
, NULL
}
223 static const struct gdb_xml_attribute library_list_attributes
[] =
225 { "version", GDB_XML_AF_NONE
, NULL
, NULL
},
226 { NULL
, GDB_XML_AF_NONE
, NULL
, NULL
}
229 static const struct gdb_xml_element library_list_elements
[] =
231 { "library-list-aix", library_list_attributes
, library_list_children
,
232 GDB_XML_EF_NONE
, library_list_start_list
, NULL
},
233 { NULL
, NULL
, NULL
, GDB_XML_EF_NONE
, NULL
, NULL
}
236 /* Parse LIBRARY, a string containing the loader info in XML format,
237 and return an lm_info_aix_p vector.
239 Return NULL if the parsing failed. */
241 static VEC (lm_info_aix_p
) *
242 solib_aix_parse_libraries (const char *library
)
244 VEC (lm_info_aix_p
) *result
= NULL
;
245 struct cleanup
*back_to
= make_cleanup (solib_aix_free_library_list
,
248 if (gdb_xml_parse_quick (_("aix library list"), "library-list-aix.dtd",
249 library_list_elements
, library
, &result
) == 0)
251 /* Parsed successfully, keep the result. */
252 discard_cleanups (back_to
);
256 do_cleanups (back_to
);
260 #endif /* HAVE_LIBEXPAT */
262 /* Return the loader info for the given inferior (INF), or NULL if
263 the list could not be computed.
265 Cache the result in per-inferior data, so as to avoid recomputing it
266 each time this function is called.
268 If an error occurs while computing this list, and WARNING_MSG
269 is not NULL, then print a warning including WARNING_MSG and
270 a description of the error. */
272 static VEC (lm_info_aix_p
) *
273 solib_aix_get_library_list (struct inferior
*inf
, const char *warning_msg
)
275 struct solib_aix_inferior_data
*data
;
277 /* If already computed, return the cached value. */
278 data
= get_solib_aix_inferior_data (inf
);
279 if (data
->library_list
!= NULL
)
280 return data
->library_list
;
282 gdb::unique_xmalloc_ptr
<char> library_document
283 = target_read_stralloc (¤t_target
, TARGET_OBJECT_LIBRARIES_AIX
,
285 if (library_document
== NULL
&& warning_msg
!= NULL
)
287 warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"),
293 fprintf_unfiltered (gdb_stdlog
,
294 "DEBUG: TARGET_OBJECT_LIBRARIES_AIX = \n%s\n",
295 library_document
.get ());
297 data
->library_list
= solib_aix_parse_libraries (library_document
.get ());
298 if (data
->library_list
== NULL
&& warning_msg
!= NULL
)
300 warning (_("%s (missing XML support?)"), warning_msg
);
304 return data
->library_list
;
307 /* If the .bss section's VMA is set to an address located before
308 the end of the .data section, causing the two sections to overlap,
309 return the overlap in bytes. Otherwise, return zero.
313 The GNU linker sometimes sets the start address of the .bss session
314 before the end of the .data section, making the 2 sections overlap.
315 The loader appears to handle this situation gracefully, by simply
316 loading the bss section right after the end of the .data section.
318 This means that the .data and the .bss sections are sometimes
319 no longer relocated by the same amount. The problem is that
320 the ldinfo data does not contain any information regarding
321 the relocation of the .bss section, assuming that it would be
322 identical to the information provided for the .data section
323 (this is what would normally happen if the program was linked
326 GDB therefore needs to detect those cases, and make the corresponding
327 adjustment to the .bss section offset computed from the ldinfo data
328 when necessary. This function returns the adjustment amount (or
329 zero when no adjustment is needed). */
332 solib_aix_bss_data_overlap (bfd
*abfd
)
334 struct bfd_section
*data_sect
, *bss_sect
;
336 data_sect
= bfd_get_section_by_name (abfd
, ".data");
337 if (data_sect
== NULL
)
338 return 0; /* No overlap possible. */
340 bss_sect
= bfd_get_section_by_name (abfd
, ".bss");
341 if (bss_sect
== NULL
)
342 return 0; /* No overlap possible. */
344 /* Assume the problem only occurs with linkers that place the .bss
345 section after the .data section (the problem has only been
346 observed when using the GNU linker, and the default linker
347 script always places the .data and .bss sections in that order). */
348 if (bfd_section_vma (abfd
, bss_sect
)
349 < bfd_section_vma (abfd
, data_sect
))
352 if (bfd_section_vma (abfd
, bss_sect
)
353 < bfd_section_vma (abfd
, data_sect
) + bfd_get_section_size (data_sect
))
354 return ((bfd_section_vma (abfd
, data_sect
)
355 + bfd_get_section_size (data_sect
))
356 - bfd_section_vma (abfd
, bss_sect
));
361 /* Implement the "relocate_section_addresses" target_so_ops method. */
364 solib_aix_relocate_section_addresses (struct so_list
*so
,
365 struct target_section
*sec
)
367 struct bfd_section
*bfd_sect
= sec
->the_bfd_section
;
368 bfd
*abfd
= bfd_sect
->owner
;
369 const char *section_name
= bfd_section_name (abfd
, bfd_sect
);
370 lm_info_aix
*info
= (lm_info_aix
*) so
->lm_info
;
372 if (strcmp (section_name
, ".text") == 0)
374 sec
->addr
= info
->text_addr
;
375 sec
->endaddr
= sec
->addr
+ info
->text_size
;
377 /* The text address given to us by the loader contains
378 XCOFF headers, so we need to adjust by this much. */
379 sec
->addr
+= bfd_sect
->filepos
;
381 else if (strcmp (section_name
, ".data") == 0)
383 sec
->addr
= info
->data_addr
;
384 sec
->endaddr
= sec
->addr
+ info
->data_size
;
386 else if (strcmp (section_name
, ".bss") == 0)
388 /* The information provided by the loader does not include
389 the address of the .bss section, but we know that it gets
390 relocated by the same offset as the .data section. So,
391 compute the relocation offset for the .data section, and
392 apply it to the .bss section as well. If the .data section
393 is not defined (which seems highly unlikely), do our best
394 by assuming no relocation. */
395 struct bfd_section
*data_sect
396 = bfd_get_section_by_name (abfd
, ".data");
397 CORE_ADDR data_offset
= 0;
399 if (data_sect
!= NULL
)
400 data_offset
= info
->data_addr
- bfd_section_vma (abfd
, data_sect
);
402 sec
->addr
= bfd_section_vma (abfd
, bfd_sect
) + data_offset
;
403 sec
->addr
+= solib_aix_bss_data_overlap (abfd
);
404 sec
->endaddr
= sec
->addr
+ bfd_section_size (abfd
, bfd_sect
);
408 /* All other sections should not be relocated. */
409 sec
->addr
= bfd_section_vma (abfd
, bfd_sect
);
410 sec
->endaddr
= sec
->addr
+ bfd_section_size (abfd
, bfd_sect
);
414 /* Implement the "free_so" target_so_ops method. */
417 solib_aix_free_so (struct so_list
*so
)
419 lm_info_aix
*li
= (lm_info_aix
*) so
->lm_info
;
422 fprintf_unfiltered (gdb_stdlog
, "DEBUG: solib_aix_free_so (%s)\n",
428 /* Implement the "clear_solib" target_so_ops method. */
431 solib_aix_clear_solib (void)
433 /* Nothing needed. */
436 /* Compute and return the OBJFILE's section_offset array, using
437 the associated loader info (INFO).
439 The resulting array is computed on the heap and must be
440 deallocated after use. */
442 static struct section_offsets
*
443 solib_aix_get_section_offsets (struct objfile
*objfile
,
446 struct section_offsets
*offsets
;
447 bfd
*abfd
= objfile
->obfd
;
449 offsets
= XCNEWVEC (struct section_offsets
, objfile
->num_sections
);
453 if (objfile
->sect_index_text
!= -1)
455 struct bfd_section
*sect
456 = objfile
->sections
[objfile
->sect_index_text
].the_bfd_section
;
458 offsets
->offsets
[objfile
->sect_index_text
]
459 = info
->text_addr
+ sect
->filepos
- bfd_section_vma (abfd
, sect
);
464 if (objfile
->sect_index_data
!= -1)
466 struct bfd_section
*sect
467 = objfile
->sections
[objfile
->sect_index_data
].the_bfd_section
;
469 offsets
->offsets
[objfile
->sect_index_data
]
470 = info
->data_addr
- bfd_section_vma (abfd
, sect
);
475 The offset of the .bss section should be identical to the offset
476 of the .data section. If no .data section (which seems hard to
477 believe it is possible), assume it is zero. */
479 if (objfile
->sect_index_bss
!= -1
480 && objfile
->sect_index_data
!= -1)
482 offsets
->offsets
[objfile
->sect_index_bss
]
483 = (offsets
->offsets
[objfile
->sect_index_data
]
484 + solib_aix_bss_data_overlap (abfd
));
487 /* All other sections should not need relocation. */
492 /* Implement the "solib_create_inferior_hook" target_so_ops method. */
495 solib_aix_solib_create_inferior_hook (int from_tty
)
497 const char *warning_msg
= "unable to relocate main executable";
498 VEC (lm_info_aix_p
) *library_list
;
499 lm_info_aix
*exec_info
;
501 /* We need to relocate the main executable... */
503 library_list
= solib_aix_get_library_list (current_inferior (),
505 if (library_list
== NULL
)
506 return; /* Warning already printed. */
508 if (VEC_length (lm_info_aix_p
, library_list
) < 1)
510 warning (_("unable to relocate main executable (no info from loader)"));
514 exec_info
= VEC_index (lm_info_aix_p
, library_list
, 0);
516 if (symfile_objfile
!= NULL
)
518 struct section_offsets
*offsets
519 = solib_aix_get_section_offsets (symfile_objfile
, exec_info
);
520 struct cleanup
*cleanup
= make_cleanup (xfree
, offsets
);
522 objfile_relocate (symfile_objfile
, offsets
);
523 do_cleanups (cleanup
);
527 /* Implement the "current_sos" target_so_ops method. */
529 static struct so_list
*
530 solib_aix_current_sos (void)
532 struct so_list
*start
= NULL
, *last
= NULL
;
533 VEC (lm_info_aix_p
) *library_list
;
537 library_list
= solib_aix_get_library_list (current_inferior (), NULL
);
538 if (library_list
== NULL
)
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
++)
546 struct so_list
*new_solib
= XCNEW (struct so_list
);
549 if (info
->member_name
.empty ())
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
;
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 ());
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
);
573 /* Add it to the list. */
575 last
= start
= new_solib
;
578 last
->next
= new_solib
;
586 /* Implement the "open_symbol_file_object" target_so_ops method. */
589 solib_aix_open_symbol_file_object (int from_tty
)
594 /* Implement the "in_dynsym_resolve_code" target_so_ops method. */
597 solib_aix_in_dynsym_resolve_code (CORE_ADDR pc
)
602 /* Implement the "bfd_open" target_so_ops method. */
604 static gdb_bfd_ref_ptr
605 solib_aix_bfd_open (char *pathname
)
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.
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
);
617 char *found_pathname
;
619 if (pathname
[path_len
- 1] != ')')
620 return solib_bfd_open (pathname
);
622 /* Search for the associated parens. */
623 sep
= strrchr (pathname
, '(');
626 /* Should never happen, but recover as best as we can (trying
627 to open pathname without decoding, possibly leading to
628 a failure), rather than triggering an assert failure). */
629 warning (_("missing '(' in shared object pathname: %s"), pathname
);
630 return solib_bfd_open (pathname
);
632 filename_len
= sep
- pathname
;
634 std::string
filename (string_printf ("%.*s", filename_len
, pathname
));
635 std::string
member_name (string_printf ("%.*s", path_len
- filename_len
- 2,
638 /* Calling solib_find makes certain that sysroot path is set properly
639 if program has a dependency on .a archive and sysroot is set via
640 set sysroot command. */
641 found_pathname
= 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
, found_file
));
645 if (archive_bfd
== NULL
)
647 warning (_("Could not open `%s' as an executable file: %s"),
648 filename
.c_str (), bfd_errmsg (bfd_get_error ()));
652 if (bfd_check_format (archive_bfd
.get (), bfd_object
))
655 if (! bfd_check_format (archive_bfd
.get (), bfd_archive
))
657 warning (_("\"%s\": not in executable format: %s."),
658 filename
.c_str (), bfd_errmsg (bfd_get_error ()));
662 gdb_bfd_ref_ptr object_bfd
663 (gdb_bfd_openr_next_archived_file (archive_bfd
.get (), NULL
));
664 while (object_bfd
!= NULL
)
666 if (member_name
== object_bfd
->filename
)
669 object_bfd
= gdb_bfd_openr_next_archived_file (archive_bfd
.get (),
673 if (object_bfd
== NULL
)
675 warning (_("\"%s\": member \"%s\" missing."), filename
.c_str (),
676 member_name
.c_str ());
680 if (! bfd_check_format (object_bfd
.get (), bfd_object
))
682 warning (_("%s(%s): not in object format: %s."),
683 filename
.c_str (), member_name
.c_str (),
684 bfd_errmsg (bfd_get_error ()));
688 /* Override the returned bfd's name with the name returned from solib_find
689 along with appended parenthesized member name in order to allow commands
690 listing all shared libraries to display. Otherwise, we would only be
691 displaying the name of the archive member object. */
692 xfree (bfd_get_filename (object_bfd
.get ()));
693 object_bfd
->filename
= xstrprintf ("%s%s",
694 bfd_get_filename (archive_bfd
.get ()),
700 /* Return the obj_section corresponding to OBJFILE's data section,
701 or NULL if not found. */
702 /* FIXME: Define in a more general location? */
704 static struct obj_section
*
705 data_obj_section_from_objfile (struct objfile
*objfile
)
707 struct obj_section
*osect
;
709 ALL_OBJFILE_OSECTIONS (objfile
, osect
)
710 if (strcmp (bfd_section_name (objfile
->obfd
, osect
->the_bfd_section
),
717 /* Return the TOC value corresponding to the given PC address,
718 or raise an error if the value could not be determined. */
721 solib_aix_get_toc_value (CORE_ADDR pc
)
723 struct obj_section
*pc_osect
= find_pc_section (pc
);
724 struct obj_section
*data_osect
;
727 if (pc_osect
== NULL
)
728 error (_("unable to find TOC entry for pc %s "
729 "(no section contains this PC)"),
730 core_addr_to_string (pc
));
732 data_osect
= data_obj_section_from_objfile (pc_osect
->objfile
);
733 if (data_osect
== NULL
)
734 error (_("unable to find TOC entry for pc %s "
735 "(%s has no data section)"),
736 core_addr_to_string (pc
), objfile_name (pc_osect
->objfile
));
738 result
= (obj_section_addr (data_osect
)
739 + xcoff_get_toc_offset (pc_osect
->objfile
));
741 fprintf_unfiltered (gdb_stdlog
,
742 "DEBUG: solib_aix_get_toc_value (pc=%s) -> %s\n",
743 core_addr_to_string (pc
),
744 core_addr_to_string (result
));
749 /* This module's normal_stop observer. */
752 solib_aix_normal_stop_observer (struct bpstats
*unused_1
, int unused_2
)
754 struct solib_aix_inferior_data
*data
755 = get_solib_aix_inferior_data (current_inferior ());
757 /* The inferior execution has been resumed, and it just stopped
758 again. This means that the list of shared libraries may have
759 evolved. Reset our cached value. */
760 solib_aix_free_library_list (&data
->library_list
);
763 /* Implements the "show debug aix-solib" command. */
766 show_solib_aix_debug (struct ui_file
*file
, int from_tty
,
767 struct cmd_list_element
*c
, const char *value
)
769 fprintf_filtered (file
, _("solib-aix debugging is %s.\n"), value
);
772 /* The target_so_ops for AIX targets. */
773 struct target_so_ops solib_aix_so_ops
;
776 _initialize_solib_aix (void)
778 solib_aix_so_ops
.relocate_section_addresses
779 = solib_aix_relocate_section_addresses
;
780 solib_aix_so_ops
.free_so
= solib_aix_free_so
;
781 solib_aix_so_ops
.clear_solib
= solib_aix_clear_solib
;
782 solib_aix_so_ops
.solib_create_inferior_hook
783 = solib_aix_solib_create_inferior_hook
;
784 solib_aix_so_ops
.current_sos
= solib_aix_current_sos
;
785 solib_aix_so_ops
.open_symbol_file_object
786 = solib_aix_open_symbol_file_object
;
787 solib_aix_so_ops
.in_dynsym_resolve_code
788 = solib_aix_in_dynsym_resolve_code
;
789 solib_aix_so_ops
.bfd_open
= solib_aix_bfd_open
;
791 solib_aix_inferior_data_handle
= register_inferior_data ();
793 observer_attach_normal_stop (solib_aix_normal_stop_observer
);
795 /* Debug this file's internals. */
796 add_setshow_boolean_cmd ("aix-solib", class_maintenance
,
797 &solib_aix_debug
, _("\
798 Control the debugging traces for the solib-aix module."), _("\
799 Show whether solib-aix debugging traces are enabled."), _("\
800 When on, solib-aix debugging traces are enabled."),
802 show_solib_aix_debug
,
803 &setdebuglist
, &showdebuglist
);