GDB (API)
/home/stan/gdb/src/gdb/solib-aix.c
Go to the documentation of this file.
00001 /* Copyright (C) 2013 Free Software Foundation, Inc.
00002 
00003    This file is part of GDB.
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 3 of the License, or
00008    (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00017 
00018 #include "defs.h"
00019 #include "solib-aix.h"
00020 #include "solist.h"
00021 #include "inferior.h"
00022 #include "gdb_bfd.h"
00023 #include "gdbcore.h"
00024 #include "objfiles.h"
00025 #include "symtab.h"
00026 #include "xcoffread.h"
00027 #include "observer.h"
00028 #include "gdbcmd.h"
00029 
00030 /* Variable controlling the output of the debugging traces for
00031    this module.  */
00032 static int solib_aix_debug;
00033 
00034 /* Our private data in struct so_list.  */
00035 
00036 struct lm_info
00037 {
00038   /* The name of the file mapped by the loader.  Apart from the entry
00039      for the main executable, this is usually a shared library (which,
00040      on AIX, is an archive library file, created using the "ar"
00041      command).  */
00042   char *filename;
00043 
00044   /* The name of the shared object file with the actual dynamic
00045      loading dependency.  This may be NULL (Eg. main executable).  */
00046   char *member_name;
00047 
00048   /* The address in inferior memory where the text section got mapped.  */
00049   CORE_ADDR text_addr;
00050 
00051   /* The size of the text section, obtained via the loader data.  */
00052   ULONGEST text_size;
00053 
00054   /* The address in inferior memory where the data section got mapped.  */
00055   CORE_ADDR data_addr;
00056 
00057   /* The size of the data section, obtained via the loader data.  */
00058   ULONGEST data_size;
00059 };
00060 
00061 typedef struct lm_info *lm_info_p;
00062 DEF_VEC_P(lm_info_p);
00063 
00064 /* Return a deep copy of the given struct lm_info object.  */
00065 
00066 static struct lm_info *
00067 solib_aix_new_lm_info (struct lm_info *info)
00068 {
00069   struct lm_info *result = xmalloc (sizeof (struct lm_info));
00070 
00071   memcpy (result, info, sizeof (struct lm_info));
00072   result->filename = xstrdup (info->filename);
00073   if (info->member_name != NULL)
00074     result->member_name = xstrdup (info->member_name);
00075 
00076   return result;
00077 }
00078 
00079 /* Free the memory allocated for the given lm_info.  */
00080 
00081 static void
00082 solib_aix_xfree_lm_info (struct lm_info *info)
00083 {
00084   xfree (info->filename);
00085   xfree (info->member_name);
00086   xfree (info);
00087 }
00088 
00089 /* This module's per-inferior data.  */
00090 
00091 struct solib_aix_inferior_data
00092 {
00093   /* The list of shared libraries.  NULL if not computed yet.
00094 
00095      Note that the first element of this list is always the main
00096      executable, which is not technically a shared library.  But
00097      we need that information to perform its relocation, and
00098      the same principles applied to shared libraries also apply
00099      to the main executable.  So it's simpler to keep it as part
00100      of this list.  */
00101   VEC (lm_info_p) *library_list;
00102 };
00103 
00104 /* Key to our per-inferior data.  */
00105 static const struct inferior_data *solib_aix_inferior_data_handle;
00106 
00107 /* Return this module's data for the given inferior.
00108    If none is found, add a zero'ed one now.  */
00109 
00110 static struct solib_aix_inferior_data *
00111 get_solib_aix_inferior_data (struct inferior *inf)
00112 {
00113   struct solib_aix_inferior_data *data;
00114 
00115   data = inferior_data (inf, solib_aix_inferior_data_handle);
00116   if (data == NULL)
00117     {
00118       data = XZALLOC (struct solib_aix_inferior_data);
00119       set_inferior_data (inf, solib_aix_inferior_data_handle, data);
00120     }
00121 
00122   return data;
00123 }
00124 
00125 #if !defined(HAVE_LIBEXPAT)
00126 
00127 /* Dummy implementation if XML support is not compiled in.  */
00128 
00129 static VEC (lm_info_p) *
00130 solib_aix_parse_libraries (const char *library)
00131 {
00132   static int have_warned;
00133 
00134   if (!have_warned)
00135     {
00136       have_warned = 1;
00137       warning (_("Can not parse XML library list; XML support was disabled "
00138                  "at compile time"));
00139     }
00140 
00141   return NULL;
00142 }
00143 
00144 /* Dummy implementation if XML support is not compiled in.  */
00145 
00146 static void
00147 solib_aix_free_library_list (void *p)
00148 {
00149 }
00150 
00151 #else /* HAVE_LIBEXPAT */
00152 
00153 #include "xml-support.h"
00154 
00155 /* Handle the start of a <library> element.  */
00156 
00157 static void
00158 library_list_start_library (struct gdb_xml_parser *parser,
00159                             const struct gdb_xml_element *element,
00160                             void *user_data,
00161                             VEC (gdb_xml_value_s) *attributes)
00162 {
00163   VEC (lm_info_p) **list = user_data;
00164   struct lm_info *item = XZALLOC (struct lm_info);
00165   struct gdb_xml_value *attr;
00166 
00167   attr = xml_find_attribute (attributes, "name");
00168   item->filename = xstrdup (attr->value);
00169 
00170   attr = xml_find_attribute (attributes, "member");
00171   if (attr != NULL)
00172     item->member_name = xstrdup (attr->value);
00173 
00174   attr = xml_find_attribute (attributes, "text_addr");
00175   item->text_addr = * (ULONGEST *) attr->value;
00176 
00177   attr = xml_find_attribute (attributes, "text_size");
00178   item->text_size = * (ULONGEST *) attr->value;
00179 
00180   attr = xml_find_attribute (attributes, "data_addr");
00181   item->data_addr = * (ULONGEST *) attr->value;
00182 
00183   attr = xml_find_attribute (attributes, "data_size");
00184   item->data_size = * (ULONGEST *) attr->value;
00185 
00186   VEC_safe_push (lm_info_p, *list, item);
00187 }
00188 
00189 /* Handle the start of a <library-list-aix> element.  */
00190 
00191 static void
00192 library_list_start_list (struct gdb_xml_parser *parser,
00193                          const struct gdb_xml_element *element,
00194                          void *user_data, VEC (gdb_xml_value_s) *attributes)
00195 {
00196   char *version = xml_find_attribute (attributes, "version")->value;
00197 
00198   if (strcmp (version, "1.0") != 0)
00199     gdb_xml_error (parser,
00200                    _("Library list has unsupported version \"%s\""),
00201                    version);
00202 }
00203 
00204 /* Discard the constructed library list.  */
00205 
00206 static void
00207 solib_aix_free_library_list (void *p)
00208 {
00209   VEC (lm_info_p) **result = p;
00210   struct lm_info *info;
00211   int ix;
00212 
00213   if (solib_aix_debug)
00214     fprintf_unfiltered (gdb_stdlog, "DEBUG: solib_aix_free_library_list\n");
00215 
00216   for (ix = 0; VEC_iterate (lm_info_p, *result, ix, info); ix++)
00217     solib_aix_xfree_lm_info (info);
00218   VEC_free (lm_info_p, *result);
00219   *result = NULL;
00220 }
00221 
00222 /* The allowed elements and attributes for an AIX library list
00223    described in XML format.  The root element is a <library-list-aix>.  */
00224 
00225 static const struct gdb_xml_attribute library_attributes[] =
00226 {
00227   { "name", GDB_XML_AF_NONE, NULL, NULL },
00228   { "member", GDB_XML_AF_OPTIONAL, NULL, NULL },
00229   { "text_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
00230   { "text_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
00231   { "data_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
00232   { "data_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
00233   { NULL, GDB_XML_AF_NONE, NULL, NULL }
00234 };
00235 
00236 static const struct gdb_xml_element library_list_children[] =
00237 {
00238   { "library", library_attributes, NULL,
00239     GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
00240     library_list_start_library, NULL},
00241   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
00242 };
00243 
00244 static const struct gdb_xml_attribute library_list_attributes[] =
00245 {
00246   { "version", GDB_XML_AF_NONE, NULL, NULL },
00247   { NULL, GDB_XML_AF_NONE, NULL, NULL }
00248 };
00249 
00250 static const struct gdb_xml_element library_list_elements[] =
00251 {
00252   { "library-list-aix", library_list_attributes, library_list_children,
00253     GDB_XML_EF_NONE, library_list_start_list, NULL },
00254   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
00255 };
00256 
00257 /* Parse LIBRARY, a string containing the loader info in XML format,
00258    and return an lm_info_p vector.
00259 
00260    Return NULL if the parsing failed.  */
00261 
00262 static VEC (lm_info_p) *
00263 solib_aix_parse_libraries (const char *library)
00264 {
00265   VEC (lm_info_p) *result = NULL;
00266   struct cleanup *back_to = make_cleanup (solib_aix_free_library_list,
00267                                           &result);
00268 
00269   if (gdb_xml_parse_quick (_("aix library list"), "library-list-aix.dtd",
00270                            library_list_elements, library, &result) == 0)
00271     {
00272       /* Parsed successfully, keep the result.  */
00273       discard_cleanups (back_to);
00274       return result;
00275     }
00276 
00277   do_cleanups (back_to);
00278   return NULL;
00279 }
00280 
00281 #endif /* HAVE_LIBEXPAT */
00282 
00283 /* Return the loader info for the given inferior (INF), or NULL if
00284    the list could not be computed.
00285 
00286    Cache the result in per-inferior data, so as to avoid recomputing it
00287    each time this function is called.
00288 
00289    If an error occurs while computing this list, and WARNING_MSG
00290    is not NULL, then print a warning including WARNING_MSG and
00291    a description of the error.  */
00292 
00293 static VEC (lm_info_p) *
00294 solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
00295 {
00296   struct solib_aix_inferior_data *data;
00297   char *library_document;
00298   struct cleanup *cleanup;
00299 
00300   /* If already computed, return the cached value.  */
00301   data = get_solib_aix_inferior_data (inf);
00302   if (data->library_list != NULL)
00303     return data->library_list;
00304 
00305   library_document = target_read_stralloc (&current_target,
00306                                            TARGET_OBJECT_LIBRARIES_AIX,
00307                                            NULL);
00308   if (library_document == NULL && warning_msg != NULL)
00309     {
00310       warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"),
00311                warning_msg);
00312       return NULL;
00313     }
00314   cleanup = make_cleanup (xfree, library_document);
00315 
00316   if (solib_aix_debug)
00317     fprintf_unfiltered (gdb_stdlog,
00318                         "DEBUG: TARGET_OBJECT_LIBRARIES_AIX = \n%s\n",
00319                         library_document);
00320 
00321   data->library_list = solib_aix_parse_libraries (library_document);
00322   if (data->library_list == NULL && warning_msg != NULL)
00323     {
00324       warning (_("%s (missing XML support?)"), warning_msg);
00325       do_cleanups (cleanup);
00326       return NULL;
00327     }
00328 
00329   do_cleanups (cleanup);
00330   return data->library_list;
00331 }
00332 
00333 /* If the .bss section's VMA is set to an address located before
00334    the end of the .data section, causing the two sections to overlap,
00335    return the overlap in bytes.  Otherwise, return zero.
00336 
00337    Motivation:
00338 
00339    The GNU linker sometimes sets the start address of the .bss session
00340    before the end of the .data section, making the 2 sections overlap.
00341    The loader appears to handle this situation gracefully, by simply
00342    loading the bss section right after the end of the .data section.
00343 
00344    This means that the .data and the .bss sections are sometimes
00345    no longer relocated by the same amount.  The problem is that
00346    the ldinfo data does not contain any information regarding
00347    the relocation of the .bss section, assuming that it would be
00348    identical to the information provided for the .data section
00349    (this is what would normally happen if the program was linked
00350    correctly).
00351 
00352    GDB therefore needs to detect those cases, and make the corresponding
00353    adjustment to the .bss section offset computed from the ldinfo data
00354    when necessary.  This function returns the adjustment amount  (or
00355    zero when no adjustment is needed).  */
00356 
00357 static CORE_ADDR
00358 solib_aix_bss_data_overlap (bfd *abfd)
00359 {
00360   struct bfd_section *data_sect, *bss_sect;
00361 
00362   data_sect = bfd_get_section_by_name (abfd, ".data");
00363   if (data_sect == NULL)
00364     return 0; /* No overlap possible.  */
00365 
00366   bss_sect = bfd_get_section_by_name (abfd, ".bss");
00367   if (bss_sect == NULL)
00368     return 0; /* No overlap possible.  */
00369 
00370   /* Assume the problem only occurs with linkers that place the .bss
00371      section after the .data section (the problem has only been
00372      observed when using the GNU linker, and the default linker
00373      script always places the .data and .bss sections in that order).  */
00374   if (bfd_section_vma (abfd, bss_sect)
00375       < bfd_section_vma (abfd, data_sect))
00376     return 0;
00377 
00378   if (bfd_section_vma (abfd, bss_sect)
00379       < bfd_section_vma (abfd, data_sect) + bfd_get_section_size (data_sect))
00380     return ((bfd_section_vma (abfd, data_sect)
00381              + bfd_get_section_size (data_sect))
00382             - bfd_section_vma (abfd, bss_sect));
00383 
00384   return 0;
00385 }
00386 
00387 /* Implement the "relocate_section_addresses" target_so_ops method.  */
00388 
00389 static void
00390 solib_aix_relocate_section_addresses (struct so_list *so,
00391                                       struct target_section *sec)
00392 {
00393   struct bfd_section *bfd_sect = sec->the_bfd_section;
00394   bfd *abfd = bfd_sect->owner;
00395   const char *section_name = bfd_section_name (abfd, bfd_sect);
00396   struct lm_info *info = so->lm_info;
00397 
00398   if (strcmp (section_name, ".text") == 0)
00399     {
00400       sec->addr = info->text_addr;
00401       sec->endaddr = sec->addr + info->text_size;
00402 
00403       /* The text address given to us by the loader contains
00404          XCOFF headers, so we need to adjust by this much.  */
00405       sec->addr += bfd_sect->filepos;
00406     }
00407   else if (strcmp (section_name, ".data") == 0)
00408     {
00409       sec->addr = info->data_addr;
00410       sec->endaddr = sec->addr + info->data_size;
00411     }
00412   else if (strcmp (section_name, ".bss") == 0)
00413     {
00414       /* The information provided by the loader does not include
00415          the address of the .bss section, but we know that it gets
00416          relocated by the same offset as the .data section.  So,
00417          compute the relocation offset for the .data section, and
00418          apply it to the .bss section as well.  If the .data section
00419          is not defined (which seems highly unlikely), do our best
00420          by assuming no relocation.  */
00421       struct bfd_section *data_sect
00422         = bfd_get_section_by_name (abfd, ".data");
00423       CORE_ADDR data_offset = 0;
00424 
00425       if (data_sect != NULL)
00426         data_offset = info->data_addr - bfd_section_vma (abfd, data_sect);
00427 
00428       sec->addr = bfd_section_vma (abfd, bfd_sect) + data_offset;
00429       sec->addr += solib_aix_bss_data_overlap (abfd);
00430       sec->endaddr = sec->addr + bfd_section_size (abfd, bfd_sect);
00431     }
00432   else
00433     {
00434       /* All other sections should not be relocated.  */
00435       sec->addr = bfd_section_vma (abfd, bfd_sect);
00436       sec->endaddr = sec->addr + bfd_section_size (abfd, bfd_sect);
00437     }
00438 }
00439 
00440 /* Implement the "free_so" target_so_ops method.  */
00441 
00442 static void
00443 solib_aix_free_so (struct so_list *so)
00444 {
00445   if (solib_aix_debug)
00446     fprintf_unfiltered (gdb_stdlog, "DEBUG: solib_aix_free_so (%s)\n",
00447                         so->so_name);
00448   solib_aix_xfree_lm_info (so->lm_info);
00449 }
00450 
00451 /* Implement the "clear_solib" target_so_ops method.  */
00452 
00453 static void
00454 solib_aix_clear_solib (void)
00455 {
00456   /* Nothing needed.  */
00457 }
00458 
00459 /* Compute and return the OBJFILE's section_offset array, using
00460    the associated loader info (INFO).
00461 
00462    The resulting array is computed on the heap and must be
00463    deallocated after use.  */
00464 
00465 static struct section_offsets *
00466 solib_aix_get_section_offsets (struct objfile *objfile,
00467                                struct lm_info *info)
00468 {
00469   struct section_offsets *offsets;
00470   bfd *abfd = objfile->obfd;
00471   int i;
00472 
00473   offsets = XCALLOC (objfile->num_sections, struct section_offsets);
00474 
00475   /* .text */
00476 
00477   if (objfile->sect_index_text != -1)
00478     {
00479       struct bfd_section *sect
00480         = objfile->sections[objfile->sect_index_text].the_bfd_section;
00481 
00482       offsets->offsets[objfile->sect_index_text]
00483         = info->text_addr + sect->filepos - bfd_section_vma (abfd, sect);
00484     }
00485 
00486   /* .data */
00487 
00488   if (objfile->sect_index_data != -1)
00489     {
00490       struct bfd_section *sect
00491         = objfile->sections[objfile->sect_index_data].the_bfd_section;
00492 
00493       offsets->offsets[objfile->sect_index_data]
00494         = info->data_addr - bfd_section_vma (abfd, sect);
00495     }
00496 
00497   /* .bss
00498 
00499      The offset of the .bss section should be identical to the offset
00500      of the .data section.  If no .data section (which seems hard to
00501      believe it is possible), assume it is zero.  */
00502 
00503   if (objfile->sect_index_bss != -1
00504       && objfile->sect_index_data != -1)
00505     {
00506       offsets->offsets[objfile->sect_index_bss]
00507         = (offsets->offsets[objfile->sect_index_data]
00508            + solib_aix_bss_data_overlap (abfd));
00509     }
00510 
00511   /* All other sections should not need relocation.  */
00512 
00513   return offsets;
00514 }
00515 
00516 /* Implement the "solib_create_inferior_hook" target_so_ops method.  */
00517 
00518 static void
00519 solib_aix_solib_create_inferior_hook (int from_tty)
00520 {
00521   const char *warning_msg = "unable to relocate main executable";
00522   VEC (lm_info_p) *library_list;
00523   struct lm_info *exec_info;
00524 
00525   /* We need to relocate the main executable...  */
00526 
00527   library_list = solib_aix_get_library_list (current_inferior (),
00528                                              warning_msg);
00529   if (library_list == NULL)
00530     return;  /* Warning already printed.  */
00531 
00532   if (VEC_length (lm_info_p, library_list) < 1)
00533     {
00534       warning (_("unable to relocate main executable (no info from loader)"));
00535       return;
00536     }
00537 
00538   exec_info = VEC_index (lm_info_p, library_list, 0);
00539 
00540   if (symfile_objfile != NULL)
00541     {
00542       struct section_offsets *offsets
00543         = solib_aix_get_section_offsets (symfile_objfile, exec_info);
00544       struct cleanup *cleanup = make_cleanup (xfree, offsets);
00545 
00546       objfile_relocate (symfile_objfile, offsets);
00547       do_cleanups (cleanup);
00548     }
00549 }
00550 
00551 /* Implement the "special_symbol_handling" target_so_ops method.  */
00552 
00553 static void
00554 solib_aix_special_symbol_handling (void)
00555 {
00556   /* Nothing needed.  */
00557 }
00558 
00559 /* Implement the "current_sos" target_so_ops method.  */
00560 
00561 static struct so_list *
00562 solib_aix_current_sos (void)
00563 {
00564   struct so_list *start = NULL, *last = NULL;
00565   VEC (lm_info_p) *library_list;
00566   struct lm_info *info;
00567   int ix;
00568 
00569   library_list = solib_aix_get_library_list (current_inferior (), NULL);
00570   if (library_list == NULL)
00571     return NULL;
00572 
00573   /* Build a struct so_list for each entry on the list.
00574      We skip the first entry, since this is the entry corresponding
00575      to the main executable, not a shared library.  */
00576   for (ix = 1; VEC_iterate (lm_info_p, library_list, ix, info); ix++)
00577     {
00578       struct so_list *new_solib = XZALLOC (struct so_list);
00579       char *so_name;
00580 
00581       if (info->member_name == NULL)
00582         {
00583          /* INFO->FILENAME is probably not an archive, but rather
00584             a shared object.  Unusual, but it should be possible
00585             to link a program against a shared object directory,
00586             without having to put it in an archive first.  */
00587          so_name = xstrdup (info->filename);
00588         }
00589       else
00590         {
00591          /* This is the usual case on AIX, where the shared object
00592             is a member of an archive.  Create a synthetic so_name
00593             that follows the same convention as AIX's ldd tool
00594             (Eg: "/lib/libc.a(shr.o)").  */
00595          so_name = xstrprintf ("%s(%s)", info->filename, info->member_name);
00596         }
00597       strncpy (new_solib->so_original_name, so_name,
00598                SO_NAME_MAX_PATH_SIZE - 1);
00599       new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
00600       memcpy (new_solib->so_name, new_solib->so_original_name,
00601               SO_NAME_MAX_PATH_SIZE);
00602       new_solib->lm_info = solib_aix_new_lm_info (info);
00603 
00604       /* Add it to the list.  */
00605       if (!start)
00606         last = start = new_solib;
00607       else
00608         {
00609           last->next = new_solib;
00610           last = new_solib;
00611         }
00612     }
00613 
00614   return start;
00615 }
00616 
00617 /* Implement the "open_symbol_file_object" target_so_ops method.  */
00618 
00619 static int
00620 solib_aix_open_symbol_file_object (void *from_ttyp)
00621 {
00622   return 0;
00623 }
00624 
00625 /* Implement the "in_dynsym_resolve_code" target_so_ops method.  */
00626 
00627 static int
00628 solib_aix_in_dynsym_resolve_code (CORE_ADDR pc)
00629 {
00630   return 0;
00631 }
00632 
00633 /* Implement the "bfd_open" target_so_ops method.  */
00634 
00635 static bfd *
00636 solib_aix_bfd_open (char *pathname)
00637 {
00638   /* The pathname is actually a synthetic filename with the following
00639      form: "/path/to/sharedlib(member.o)" (double-quotes excluded).
00640      split this into archive name and member name.
00641 
00642      FIXME: This is a little hacky.  Perhaps we should provide access
00643      to the solib's lm_info here?  */
00644   const int path_len = strlen (pathname);
00645   char *sep;
00646   char *filename;
00647   int filename_len;
00648   char *member_name;
00649   bfd *archive_bfd, *object_bfd;
00650   struct cleanup *cleanup;
00651 
00652   if (pathname[path_len - 1] != ')')
00653     return solib_bfd_open (pathname);
00654 
00655   /* Search for the associated parens.  */
00656   sep = strrchr (pathname, '(');
00657   if (sep == NULL)
00658     {
00659       /* Should never happen, but recover as best as we can (trying
00660          to open pathname without decoding, possibly leading to
00661          a failure), rather than triggering an assert failure).  */
00662       warning (_("missing '(' in shared object pathname: %s"), pathname);
00663       return solib_bfd_open (pathname);
00664     }
00665   filename_len = sep - pathname;
00666 
00667   filename = xstrprintf ("%.*s", filename_len, pathname);
00668   cleanup = make_cleanup (xfree, filename);
00669   member_name = xstrprintf ("%.*s", path_len - filename_len - 2, sep + 1);
00670   make_cleanup (xfree, member_name);
00671 
00672   archive_bfd = gdb_bfd_open (filename, gnutarget, -1);
00673   if (archive_bfd == NULL)
00674     {
00675       warning (_("Could not open `%s' as an executable file: %s"),
00676                filename, bfd_errmsg (bfd_get_error ()));
00677       do_cleanups (cleanup);
00678       return NULL;
00679     }
00680 
00681   if (bfd_check_format (archive_bfd, bfd_object))
00682     {
00683       do_cleanups (cleanup);
00684       return archive_bfd;
00685     }
00686 
00687   if (! bfd_check_format (archive_bfd, bfd_archive))
00688     {
00689       warning (_("\"%s\": not in executable format: %s."),
00690                filename, bfd_errmsg (bfd_get_error ()));
00691       gdb_bfd_unref (archive_bfd);
00692       do_cleanups (cleanup);
00693       return NULL;
00694     }
00695 
00696   object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd, NULL);
00697   while (object_bfd != NULL)
00698     {
00699       bfd *next;
00700 
00701       if (strcmp (member_name, object_bfd->filename) == 0)
00702         break;
00703 
00704       next = gdb_bfd_openr_next_archived_file (archive_bfd, object_bfd);
00705       gdb_bfd_unref (object_bfd);
00706       object_bfd = next;
00707     }
00708 
00709   if (object_bfd == NULL)
00710     {
00711       warning (_("\"%s\": member \"%s\" missing."), filename, member_name);
00712       gdb_bfd_unref (archive_bfd);
00713       do_cleanups (cleanup);
00714       return NULL;
00715     }
00716 
00717   if (! bfd_check_format (object_bfd, bfd_object))
00718     {
00719       warning (_("%s(%s): not in object format: %s."),
00720                filename, member_name, bfd_errmsg (bfd_get_error ()));
00721       gdb_bfd_unref (archive_bfd);
00722       gdb_bfd_unref (object_bfd);
00723       do_cleanups (cleanup);
00724       return NULL;
00725     }
00726 
00727   gdb_bfd_unref (archive_bfd);
00728   do_cleanups (cleanup);
00729   return object_bfd;
00730 }
00731 
00732 /* Return the obj_section corresponding to OBJFILE's data section,
00733    or NULL if not found.  */
00734 /* FIXME: Define in a more general location? */
00735 
00736 static struct obj_section *
00737 data_obj_section_from_objfile (struct objfile *objfile)
00738 {
00739   struct obj_section *osect;
00740 
00741   ALL_OBJFILE_OSECTIONS (objfile, osect)
00742     if (strcmp (bfd_section_name (objfile->obfd, osect->the_bfd_section),
00743                 ".data") == 0)
00744       return osect;
00745 
00746   return NULL;
00747 }
00748 
00749 /* Return the TOC value corresponding to the given PC address,
00750    or raise an error if the value could not be determined.  */
00751 
00752 CORE_ADDR
00753 solib_aix_get_toc_value (CORE_ADDR pc)
00754 {
00755   struct obj_section *pc_osect = find_pc_section (pc);
00756   struct obj_section *data_osect;
00757   CORE_ADDR result;
00758 
00759   if (pc_osect == NULL)
00760     error (_("unable to find TOC entry for pc %s "
00761              "(no section contains this PC)"),
00762            core_addr_to_string (pc));
00763 
00764   data_osect = data_obj_section_from_objfile (pc_osect->objfile);
00765   if (data_osect == NULL)
00766     error (_("unable to find TOC entry for pc %s "
00767              "(%s has no data section)"),
00768            core_addr_to_string (pc), objfile_name (pc_osect->objfile));
00769 
00770   result = (obj_section_addr (data_osect)
00771             + xcoff_get_toc_offset (pc_osect->objfile));
00772   if (solib_aix_debug)
00773     fprintf_unfiltered (gdb_stdlog,
00774                         "DEBUG: solib_aix_get_toc_value (pc=%s) -> %s\n",
00775                         core_addr_to_string (pc),
00776                         core_addr_to_string (result));
00777 
00778   return result;
00779 }
00780 
00781 /* This module's normal_stop observer.  */
00782 
00783 static void
00784 solib_aix_normal_stop_observer (struct bpstats *unused_1, int unused_2)
00785 {
00786   struct solib_aix_inferior_data *data
00787     = get_solib_aix_inferior_data (current_inferior ());
00788 
00789   /* The inferior execution has been resumed, and it just stopped
00790      again.  This means that the list of shared libraries may have
00791      evolved.  Reset our cached value.  */
00792   solib_aix_free_library_list (&data->library_list);
00793 }
00794 
00795 /* Implements the "show debug aix-solib" command.  */
00796 
00797 static void
00798 show_solib_aix_debug (struct ui_file *file, int from_tty,
00799                       struct cmd_list_element *c, const char *value)
00800 {
00801   fprintf_filtered (file, _("solib-aix debugging is %s.\n"), value);
00802 }
00803 
00804 /* The target_so_ops for AIX targets.  */
00805 struct target_so_ops solib_aix_so_ops;
00806 
00807 /* -Wmissing-prototypes */
00808 extern initialize_file_ftype _initialize_solib_aix;
00809 
00810 void
00811 _initialize_solib_aix (void)
00812 {
00813   solib_aix_so_ops.relocate_section_addresses
00814     = solib_aix_relocate_section_addresses;
00815   solib_aix_so_ops.free_so = solib_aix_free_so;
00816   solib_aix_so_ops.clear_solib = solib_aix_clear_solib;
00817   solib_aix_so_ops.solib_create_inferior_hook
00818     = solib_aix_solib_create_inferior_hook;
00819   solib_aix_so_ops.special_symbol_handling
00820     = solib_aix_special_symbol_handling;
00821   solib_aix_so_ops.current_sos = solib_aix_current_sos;
00822   solib_aix_so_ops.open_symbol_file_object
00823     = solib_aix_open_symbol_file_object;
00824   solib_aix_so_ops.in_dynsym_resolve_code
00825     = solib_aix_in_dynsym_resolve_code;
00826   solib_aix_so_ops.bfd_open = solib_aix_bfd_open;
00827 
00828   solib_aix_inferior_data_handle = register_inferior_data ();
00829 
00830   observer_attach_normal_stop (solib_aix_normal_stop_observer);
00831 
00832   /* Debug this file's internals.  */
00833   add_setshow_boolean_cmd ("aix-solib", class_maintenance,
00834                            &solib_aix_debug, _("\
00835 Control the debugging traces for the solib-aix module."), _("\
00836 Show whether solib-aix debugging traces are enabled."), _("\
00837 When on, solib-aix debugging traces are enabled."),
00838                             NULL,
00839                             show_solib_aix_debug,
00840                             &setdebuglist, &showdebuglist);
00841 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines