This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

FYI/prototype: re-implement relocs on ppc-aix


Hello,

This patch is a prototype towards converting all the ad hoc code
and various deprecated features used to implement relocations to
using a target_so_ops vector instead. One of the nice side-effects
is that we are able to get rid of nm-rs6000.h entirely.

This is a fairly lengthy email, which I am not too happy about,
because I think it's going to make it harder for anyone willing
to take a look and comment. But I thought it was important to provide
some general info on it too. The reason for posting the patch
generate comments, but also to ask a couple of questions on topics
open for discussion regarding missing pieces in the core part of GDB.
I will ask these questions again at the next submission, when the
patch is a little cleaner, if no decision is made with that patch.

The interface to the relocation data is itself relatively simple,
and documented through a combination of the PT_LDINFO request in
the ptrace man page, and the ldr.h system include. Basically,
the PT_LDINFO gives us access to a raw buffer which is an array
of structures whose type is defined in ldr.h.

One of the small difficulties came from a specificity of the AIX
platform regarding shared libraries: What we view as shared libraries
on, say, GNU/Linux, is an archive file. For instance, /lib/libc.a.
The linker then searches inside the archive file for dynamic objects
(Eg: shr.o) on which the program depends, and links it against those
specific object files, not just the archive. We observe that through
the use of ldd on a simple program:

    % ldd simple_main
    simple_main needs:
         /lib/libc.a(shr.o)
         /lib/libcrypt.a(shr.o)

This means that the current model where an objfile is a filename
doesn't work very well. In this case, it's a filename and a member
name. This prototype tip-toes around the issue for now, to limit
its scope.

This is a relatively messy prototype, where I have not paid
any attention to memory management or process separation
(Eg: -tdep code calling -nat code). This is a big part of
the next iteration for this patch.

Some elements I would like to have some feedback on:

  - One important bit is something I alluded to above: a solib
    name is now no longer sufficient to identify it; we need
    the filename, which is usually an archive, and a member
    name (which may be NULL). Right now, I store a composite
    into the struct so_list->so_name field which follows the
    same convention as AIX's ldd: Eg. "/lib/lib.c(shr.o)".
    Some minor issues:

      - struct objfile's name is the name from the bfd, and
        thus Eg "shr.o"; any display of that name in the debugger
        output and warning/error messages is incomplete

      - the bfd_open target_so_ops method only takes a pathname
        for getting the bfd; but that's not sufficient.
        What the current does is just parse the pathname
        and split it into real pathname, and member name.
        Acceptable for a prototype, but perhaps we should
        consider passing a reference to the so_list object?

      - See also the FIXME in solib.c:solib_map_sections,
        which overwrites the so_name in the so_list struct.
        This of course overwrites the composite name. Two
        consequences:
           - "info sharedlibrary" does not show the composite name
             (missing piece of info)
           - the bfd_open hook is missing the composite name also,
             at least until the so_list is passed instead of just
             the pathname.

    Some of the options I have considered:

       - For the "info sharedlibrary" command, enhance the solib
         vector to provide a "so_name" function that, given a
         struct so_list, returns the solib's "print" name.
         solib-aix would access the lm_info to do so. Or rather
         than returning a string, with its usual memory management
         issues, would print it to a stream?

       - Stop encoding the archive-name+member-name into the
         so_list so_name. We need to be careful there, because
         even if we were able to print the solib name correct
         (as discussed above), I think we have some mechanism
         in the solib code that deals with duplicates using
         the so_name. Since it is very common for two archives
         to have members with the same name, we need to make
         sure that this identification mechanism keeps working.
         The so_name compositing helps achieving that.

       - Issue when printing the objfile name: This one is going
         to be messy, I think. I was thinking of defining the
         concept of an objfile's "print" name, which could work
         as follow: If the objfile's bfd has a my_archive, then
         it would be "<my_archive->name>(<objfile->name>)";
         otherwise, the usual "<objfile->name>". I don't think
         we really need to address that issue, especially not
         right now.

  - xcoff_symfile_offsets was greatly simplified, and in fact could be
    entirely replaced by default_symfile_offsets, if it wasn't for
    some code which defaults some section indices in the objfile
    to zero even when the section actually does not exist. I could
    probably work with that because this seems to only affect
    the rodata sect index in practice, and that section does not
    exist on AIX (yet). But I think that's taking a chance.
    The code that does that was added a very long time ago, and
    was probably meant for ELF. For now, I've added code in
    xcoff_symfile_offsets to just call default_symfile_offsets
    followed by the undoing of the sect index zero'ing. Fine
    for now, but something we might want to look at eventually?

Some questions I asked myself (with some answers):

  - Because of the dependency on the system ldr.h file, there is
    a temporary dependency of solib-aix on rs6000-nat, which we
    do not want, especially since rs6000-aix-tdep also depends
    on solib-aix (to get the TOC value in order to setup inferior
    function calls). I am planning on fixing this by adding
    a new xfer object.

  - The changes in rs6000-aix-tdep.c are adjustments to the new
    method towards getting the TOC value. It calls a function
    in solib-aix rather than relying on a hook setup by the -nat
    code. This means that it can also be made to work when configured
    as a cross debugger.

  - The new code in rs6000-nat is a little hard to read. It basically
    just gets the raw ld_info data from ptrace (PT_LDINFO), and
    transforms it into a structured VEC. This will likely change
    when integrated into the xfer_memory framework, but the idea
    will remain the same.

  - I am also planning on caching the ld_info data, to avoid
    re-fetching the data multiple times when not necessary.
    But I think that this will be the subject of a followup patch,
    to avoid mixing everything in the same bag.

  - xcoffsolib.[hc] is now gone, as it is redundant with the solib.c
    code;

  - We will need to update the ARI in order to forbid the macros
    finally deleted.

Voila voila,
-- 
Joel

PS: The patch is against AdaCore's HEAD, which is off a fairly recent
    set of sources, but modified to contain AdaCore's changes too.
    This was simpler for me to allow for testing, and may not apply
    cleanly to current FSF HEAD. Sorry if that is the case.
>From 7f78954ffbf98104287f35840684a8b9b664a756 Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>
Date: Fri, 15 Mar 2013 18:44:52 -0400
Subject: [PATCH] WIP: Transition ppc-aix to using target_so_ops.

---
 gdb/Makefile.in               |    2 +-
 gdb/breakpoint.c              |   10 +-
 gdb/config/powerpc/aix.mh     |    5 +-
 gdb/config/rs6000/nm-rs6000.h |   50 ---
 gdb/configure.tgt             |    2 +-
 gdb/corelow.c                 |   18 -
 gdb/doc/gdbint.texinfo        |   19 --
 gdb/exec.c                    |  120 -------
 gdb/infcmd.c                  |   12 +-
 gdb/infrun.c                  |    4 -
 gdb/rs6000-aix-tdep.c         |   21 +-
 gdb/rs6000-nat.c              |  697 ++++++-----------------------------------
 gdb/rs6000-tdep.h             |    4 -
 gdb/solib-aix.c               |  494 +++++++++++++++++++++++++++++
 gdb/solib-aix.h               |   52 +++
 gdb/solib.c                   |   11 +-
 gdb/stack.c                   |    5 +-
 gdb/xcoffread.c               |   84 +++---
 gdb/xcoffsolib.c              |  182 -----------
 gdb/xcoffsolib.h              |   65 ----
 20 files changed, 700 insertions(+), 1157 deletions(-)
 delete mode 100644 gdb/config/rs6000/nm-rs6000.h
 create mode 100644 gdb/solib-aix.c
 create mode 100644 gdb/solib-aix.h
 delete mode 100644 gdb/xcoffsolib.c
 delete mode 100644 gdb/xcoffsolib.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index fc461fb..3242c25 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -821,7 +821,7 @@ inf-child.h p-lang.h event-top.h gdbtypes.h user-regs.h \
 regformats/regdef.h config/alpha/nm-osf3.h  config/i386/nm-i386gnu.h \
 config/i386/nm-fbsd.h \
 config/nm-nto.h config/sparc/nm-sol2.h config/nm-linux.h \
-config/rs6000/nm-rs6000.h top.h bsd-kvm.h gdb-stabs.h reggroups.h \
+top.h bsd-kvm.h gdb-stabs.h reggroups.h \
 annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h	\
 remote-fileio.h i386-linux-tdep.h vax-tdep.h objc-lang.h \
 sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h \
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index bc897cb..748850a 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5374,11 +5374,7 @@ handle_solib_event (void)
      be adding them automatically.  Switch terminal for any messages
      produced by breakpoint_re_set.  */
   target_terminal_ours_for_output ();
-#ifdef SOLIB_ADD
-  SOLIB_ADD (NULL, 0, &current_target, auto_solib_add);
-#else
   solib_add (NULL, 0, &current_target, auto_solib_add);
-#endif
   target_terminal_inferior ();
 }
 
@@ -7421,11 +7417,7 @@ disable_breakpoints_in_shlibs (void)
 	 || (is_tracepoint (b)))
 	&& loc->pspace == current_program_space
 	&& !loc->shlib_disabled
-#ifdef PC_SOLIB
-	&& PC_SOLIB (loc->address)
-#else
 	&& solib_name_from_address (loc->pspace, loc->address)
-#endif
 	)
       {
 	loc->shlib_disabled = 1;
@@ -13272,7 +13264,7 @@ static void
 momentary_bkpt_re_set (struct breakpoint *b)
 {
   /* Keep temporary breakpoints, which can be encountered when we step
-     over a dlopen call and SOLIB_ADD is resetting the breakpoints.
+     over a dlopen call and solib_add is resetting the breakpoints.
      Otherwise these should have been blown away via the cleanup chain
      or by breakpoint_init_inferior when we rerun the executable.  */
 }
diff --git a/gdb/config/powerpc/aix.mh b/gdb/config/powerpc/aix.mh
index d007fff..141501d 100644
--- a/gdb/config/powerpc/aix.mh
+++ b/gdb/config/powerpc/aix.mh
@@ -1,10 +1,7 @@
 # Host: IBM PowerPC running AIX
 
-NAT_FILE= config/rs6000/nm-rs6000.h
-
 # aix-thread.o is not listed in NATDEPFILES as it is pulled in by configure.
-NATDEPFILES= fork-child.o inf-ptrace.o rs6000-nat.o \
-	     xcoffsolib.o
+NATDEPFILES= fork-child.o inf-ptrace.o rs6000-nat.o
 
 # When compiled with cc, for debugging, this argument should be passed.
 # We have no idea who our current compiler is though, so we skip it.
diff --git a/gdb/config/rs6000/nm-rs6000.h b/gdb/config/rs6000/nm-rs6000.h
deleted file mode 100644
index e631521..0000000
--- a/gdb/config/rs6000/nm-rs6000.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* IBM RS/6000 native-dependent macros for GDB, the GNU debugger.
-   Copyright (C) 1986-2013 Free Software Foundation, Inc.
-
-   This file is part of GDB.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/* When a child process is just starting, we sneak in and relocate
-   the symbol table (and other stuff) after the dynamic linker has
-   figured out where they go.  */
-
-#define	SOLIB_CREATE_INFERIOR_HOOK(PID)	\
-  do {					\
-    xcoff_relocate_symtab (PID);	\
-  } while (0)
-
-/* When a target process or core-file has been attached, we sneak in
-   and figure out where the shared libraries have got to.  */
-
-#define	SOLIB_ADD(a, b, c, d)	\
-  if (PIDGET (inferior_ptid))	\
-    /* Attach to process.  */  \
-    xcoff_relocate_symtab (PIDGET (inferior_ptid)); \
-  else		\
-    /* Core file.  */ \
-    xcoff_relocate_core (c);
-
-extern void xcoff_relocate_symtab (unsigned int);
-struct target_ops;
-extern void xcoff_relocate_core (struct target_ops *);
-
-/* If ADDR lies in a shared library, return its name.  */
-
-#define	PC_SOLIB(PC)	xcoff_solib_address(PC)
-extern char *xcoff_solib_address (CORE_ADDR);
-
-/* Flag for machine-specific stuff in shared files.  FIXME */
-#define DEPRECATED_IBM6000_TARGET
-
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index cfefb14..edabcb5 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -441,7 +441,7 @@ powerpc-*-openbsd*)
 powerpc-*-aix* | rs6000-*-*)
 	# Target: PowerPC running AIX
 	gdb_target_obs="rs6000-tdep.o rs6000-aix-tdep.o xcoffread.o \
-			ppc-sysv-tdep.o \
+			ppc-sysv-tdep.o solib-aix.o \
 			ravenscar-thread.o ppc-ravenscar-thread.o"
 	;;
 powerpc-*-linux* | powerpc64-*-linux*)
diff --git a/gdb/corelow.c b/gdb/corelow.c
index a98ae54..abf8dd1 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -465,24 +465,6 @@ core_detach (struct target_ops *ops, char *args, int from_tty)
     printf_filtered (_("No core file now.\n"));
 }
 
-#ifdef DEPRECATED_IBM6000_TARGET
-
-/* Resize the core memory's section table, by NUM_ADDED.  Returns a
-   pointer into the first new slot.  This will not be necessary when
-   the rs6000 target is converted to use the standard solib
-   framework.  */
-
-struct target_section *
-deprecated_core_resize_section_table (int num_added)
-{
-  int old_count;
-
-  old_count = resize_section_table (core_data, num_added);
-  return core_data->sections + old_count;
-}
-
-#endif
-
 /* Try to retrieve registers from a section in core_bfd, and supply
    them to core_vec->core_read_registers, as the register set numbered
    WHICH.
diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo
index 4a75c26..1671cf3 100644
--- a/gdb/doc/gdbint.texinfo
+++ b/gdb/doc/gdbint.texinfo
@@ -4666,13 +4666,6 @@ offset into the @code{jmp_buf}.  (While we might like to get the offset
 from the target's @file{jmpbuf.h}, that header file cannot be assumed
 to be available when building a cross-debugger.)
 
-@item DEPRECATED_IBM6000_TARGET
-@findex DEPRECATED_IBM6000_TARGET
-Shows that we are configured for an IBM RS/6000 system.  This
-conditional should be eliminated (FIXME) and replaced by
-feature-specific macros.  It was introduced in haste and we are
-repenting at leisure.
-
 @item I386_USE_GENERIC_WATCHPOINTS
 An x86-based target can define this to use the generic x86 watchpoint
 support; see @ref{Algorithms, I386_USE_GENERIC_WATCHPOINTS}.
@@ -5412,18 +5405,6 @@ undefined) in @file{nm-@var{system}.h}.
 An x86-based machine can define this to use the generic x86 watchpoint
 support; see @ref{Algorithms, I386_USE_GENERIC_WATCHPOINTS}.
 
-@item SOLIB_ADD (@var{filename}, @var{from_tty}, @var{targ}, @var{readsyms})
-@findex SOLIB_ADD
-Define this to expand into an expression that will cause the symbols in
-@var{filename} to be added to @value{GDBN}'s symbol table.  If
-@var{readsyms} is zero symbols are not read but any necessary low level
-processing for @var{filename} is still done.
-
-@item SOLIB_CREATE_INFERIOR_HOOK
-@findex SOLIB_CREATE_INFERIOR_HOOK
-Define this to expand into any shared-library-relocation code that you
-want to be run just after the child process has been forked.
-
 @item START_INFERIOR_TRAPS_EXPECTED
 @findex START_INFERIOR_TRAPS_EXPECTED
 When starting an inferior, @value{GDBN} normally expects to trap
diff --git a/gdb/exec.c b/gdb/exec.c
index 221e679..3020b94 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -44,10 +44,6 @@
 #include <ctype.h>
 #include "gdb_stat.h"
 
-#include "xcoffsolib.h"
-
-struct vmap *map_vmap (bfd *, bfd *);
-
 void (*deprecated_file_changed_hook) (char *);
 
 /* Prototypes for local functions */
@@ -81,8 +77,6 @@ show_write_files (struct ui_file *file, int from_tty,
 }
 
 
-struct vmap *vmap;
-
 static void
 exec_open (char *args, int from_tty)
 {
@@ -117,25 +111,8 @@ exec_close (void)
 static void
 exec_close_1 (int quitting)
 {
-  struct vmap *vp, *nxt;
-
   using_exec_ops = 0;
 
-  for (nxt = vmap; nxt != NULL;)
-    {
-      vp = nxt;
-      nxt = vp->nxt;
-
-      if (vp->objfile)
-	free_objfile (vp->objfile);
-
-      gdb_bfd_unref (vp->bfd);
-
-      xfree (vp);
-    }
-
-  vmap = NULL;
-
   {
     struct program_space *ss;
     struct cleanup *old_chain;
@@ -248,22 +225,6 @@ exec_file_attach (char *filename, int from_tty)
 		 gdb_bfd_errmsg (bfd_get_error (), matching));
 	}
 
-      /* FIXME - This should only be run for RS6000, but the ifdef is a poor
-         way to accomplish.  */
-#ifdef DEPRECATED_IBM6000_TARGET
-      /* Setup initial vmap.  */
-
-      map_vmap (exec_bfd, 0);
-      if (vmap == NULL)
-	{
-	  /* Make sure to close exec_bfd, or else "run" might try to use
-	     it.  */
-	  exec_close ();
-	  error (_("\"%s\": can't find the file sections: %s"),
-		 scratch_pathname, bfd_errmsg (bfd_get_error ()));
-	}
-#endif /* DEPRECATED_IBM6000_TARGET */
-
       if (build_section_table (exec_bfd, &sections, &sections_end))
 	{
 	  /* Make sure to close exec_bfd, or else "run" might try to use
@@ -507,62 +468,6 @@ remove_target_sections (void *key, bfd *abfd)
 }
 
 
-static void
-bfdsec_to_vmap (struct bfd *abfd, struct bfd_section *sect, void *arg3)
-{
-  struct vmap_and_bfd *vmap_bfd = (struct vmap_and_bfd *) arg3;
-  struct vmap *vp;
-
-  vp = vmap_bfd->pvmap;
-
-  if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0)
-    return;
-
-  if (strcmp (bfd_section_name (abfd, sect), ".text") == 0)
-    {
-      vp->tstart = bfd_section_vma (abfd, sect);
-      vp->tend = vp->tstart + bfd_section_size (abfd, sect);
-      vp->tvma = bfd_section_vma (abfd, sect);
-      vp->toffs = sect->filepos;
-    }
-  else if (strcmp (bfd_section_name (abfd, sect), ".data") == 0)
-    {
-      vp->dstart = bfd_section_vma (abfd, sect);
-      vp->dend = vp->dstart + bfd_section_size (abfd, sect);
-      vp->dvma = bfd_section_vma (abfd, sect);
-    }
-  /* Silently ignore other types of sections.  (FIXME?)  */
-}
-
-/* Make a vmap for ABFD which might be a member of the archive ARCH.
-   Return the new vmap.  */
-
-struct vmap *
-map_vmap (bfd *abfd, bfd *arch)
-{
-  struct vmap_and_bfd vmap_bfd;
-  struct vmap *vp, **vpp;
-
-  vp = (struct vmap *) xmalloc (sizeof (*vp));
-  memset ((char *) vp, '\0', sizeof (*vp));
-  vp->nxt = 0;
-  vp->bfd = abfd;
-  gdb_bfd_ref (abfd);
-  vp->name = bfd_get_filename (arch ? arch : abfd);
-  vp->member = arch ? bfd_get_filename (abfd) : "";
-
-  vmap_bfd.pbfd = arch;
-  vmap_bfd.pvmap = vp;
-  bfd_map_over_sections (abfd, bfdsec_to_vmap, &vmap_bfd);
-
-  /* Find the end of the list and append.  */
-  for (vpp = &vmap; *vpp; vpp = &(*vpp)->nxt)
-    ;
-  *vpp = vp;
-
-  return vp;
-}
-
 
 VEC(mem_range_s) *
 section_table_available_memory (VEC(mem_range_s) *memory,
@@ -758,31 +663,6 @@ exec_files_info (struct target_ops *t)
     print_section_info (current_target_sections, exec_bfd);
   else
     puts_filtered (_("\t<no file loaded>\n"));
-
-  if (vmap)
-    {
-      int addr_size = gdbarch_addr_bit (target_gdbarch ()) / 8;
-      struct vmap *vp;
-
-      printf_unfiltered (_("\tMapping info for file `%s'.\n"), vmap->name);
-      printf_unfiltered ("\t  %*s   %*s   %*s   %*s %8.8s %s\n",
-			 addr_size * 2, "tstart",
-			 addr_size * 2, "tend",
-			 addr_size * 2, "dstart",
-			 addr_size * 2, "dend",
-			 "section",
-			 "file(member)");
-
-      for (vp = vmap; vp; vp = vp->nxt)
-	printf_unfiltered ("\t0x%s 0x%s 0x%s 0x%s %s%s%s%s\n",
-			   phex (vp->tstart, addr_size),
-			   phex (vp->tend, addr_size),
-			   phex (vp->dstart, addr_size),
-			   phex (vp->dend, addr_size),
-			   vp->name,
-			   *vp->member ? "(" : "", vp->member,
-			   *vp->member ? ")" : "");
-    }
 }
 
 static void
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 967dbb1..8a64565 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -432,11 +432,7 @@ post_create_inferior (struct target_ops *target, int from_tty)
 
       /* Create the hooks to handle shared library load and unload
 	 events.  */
-#ifdef SOLIB_CREATE_INFERIOR_HOOK
-      SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
-#else
       solib_create_inferior_hook (from_tty);
-#endif
 
       if (current_program_space->solib_add_generation == solib_add_generation)
 	{
@@ -452,13 +448,7 @@ post_create_inferior (struct target_ops *target, int from_tty)
 	  /* If the solist is global across processes, there's no need to
 	     refetch it here.  */
 	  if (!gdbarch_has_global_solist (target_gdbarch ()))
-	    {
-#ifdef SOLIB_ADD
-	      SOLIB_ADD (NULL, 0, target, auto_solib_add);
-#else
-	      solib_add (NULL, 0, target, auto_solib_add);
-#endif
-	    }
+	    solib_add (NULL, 0, target, auto_solib_add);
 	}
     }
 
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 92874e2..a034699 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -958,11 +958,7 @@ follow_exec (ptid_t pid, char *execd_pathname)
      registers.  */
   target_find_description ();
 
-#ifdef SOLIB_CREATE_INFERIOR_HOOK
-  SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
-#else
   solib_create_inferior_hook (0);
-#endif
 
   jit_inferior_created_hook ();
 
diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c
index ec92237..89b86a8 100644
--- a/gdb/rs6000-aix-tdep.c
+++ b/gdb/rs6000-aix-tdep.c
@@ -36,12 +36,9 @@
 #include "ppc-tdep.h"
 #include "exceptions.h"
 #include "xcoffread.h"
-
-/* Hook for determining the TOC address when calling functions in the
-   inferior under AIX.  The initialization code in rs6000-nat.c sets
-   this hook to point to find_toc_address.  */
-
-CORE_ADDR (*rs6000_find_toc_address_hook) (CORE_ADDR) = NULL;
+#include "solist.h"
+#include "solib.h"
+#include "solib-aix.h"
 
 /* If the kernel has to deliver a signal, it pushes a sigcontext
    structure on the stack and then calls the signal handler, passing
@@ -417,13 +414,9 @@ ran_out_of_registers_for_arguments:
      breakpoint.  */
   regcache_raw_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr);
 
-  /* Set the TOC register, get the value from the objfile reader
-     which, in turn, gets it from the VMAP table.  */
-  if (rs6000_find_toc_address_hook != NULL)
-    {
-      CORE_ADDR tocvalue = (*rs6000_find_toc_address_hook) (func_addr);
-      regcache_raw_write_signed (regcache, tdep->ppc_toc_regnum, tocvalue);
-    }
+  /* Set the TOC register value.  */
+  regcache_raw_write_signed (regcache, tdep->ppc_toc_regnum,
+			     solib_aix_get_toc_value (func_addr));
 
   target_store_registers (regcache, -1);
   return sp;
@@ -798,6 +791,8 @@ rs6000_aix_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
     set_gdbarch_frame_red_zone_size (gdbarch, 0);
 
   set_gdbarch_auto_wide_charset (gdbarch, rs6000_aix_auto_wide_charset);
+
+  set_solib_ops (gdbarch, &solib_aix_so_ops);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff --git a/gdb/rs6000-nat.c b/gdb/rs6000-nat.c
index a40b9a7..d225e97 100644
--- a/gdb/rs6000-nat.c
+++ b/gdb/rs6000-nat.c
@@ -21,7 +21,6 @@
 #include "inferior.h"
 #include "target.h"
 #include "gdbcore.h"
-#include "xcoffsolib.h"
 #include "symfile.h"
 #include "objfiles.h"
 #include "libbfd.h"		/* For bfd_default_set_arch_mach (FIXME) */
@@ -118,18 +117,6 @@ typedef union {
 #define LDI_FD(ldi, arch64)		LDI_FIELD(ldi, arch64, fd)
 #define LDI_FILENAME(ldi, arch64)	LDI_FIELD(ldi, arch64, filename)
 
-extern struct vmap *map_vmap (bfd * bf, bfd * arch);
-
-static void vmap_exec (void);
-
-static void vmap_ldinfo (LdInfo *);
-
-static struct vmap *add_vmap (LdInfo *);
-
-static int objfile_symbol_add (void *);
-
-static void vmap_symtab (struct vmap *);
-
 static void exec_one_dummy_insn (struct regcache *);
 
 extern void fixup_breakpoints (CORE_ADDR low, CORE_ADDR high, CORE_ADDR delta);
@@ -623,431 +610,6 @@ exec_one_dummy_insn (struct regcache *regcache)
 }
 
 
-/* Copy information about text and data sections from LDI to VP for a 64-bit
-   process if ARCH64 and for a 32-bit process otherwise.  */
-
-static void
-vmap_secs (struct vmap *vp, LdInfo *ldi, int arch64)
-{
-  if (arch64)
-    {
-      vp->tstart = (CORE_ADDR) ldi->l64.ldinfo_textorg;
-      vp->tend = vp->tstart + ldi->l64.ldinfo_textsize;
-      vp->dstart = (CORE_ADDR) ldi->l64.ldinfo_dataorg;
-      vp->dend = vp->dstart + ldi->l64.ldinfo_datasize;
-    }
-  else
-    {
-      vp->tstart = (unsigned long) ldi->l32.ldinfo_textorg;
-      vp->tend = vp->tstart + ldi->l32.ldinfo_textsize;
-      vp->dstart = (unsigned long) ldi->l32.ldinfo_dataorg;
-      vp->dend = vp->dstart + ldi->l32.ldinfo_datasize;
-    }
-
-  /* The run time loader maps the file header in addition to the text
-     section and returns a pointer to the header in ldinfo_textorg.
-     Adjust the text start address to point to the real start address
-     of the text section.  */
-  vp->tstart += vp->toffs;
-}
-
-/* If the .bss section's VMA is set to an address located before
-   the end of the .data section, causing the two sections to overlap,
-   return the overlap in bytes.  Otherwise, return zero.
-
-   Motivation:
-
-   The GNU linker sometimes sets the start address of the .bss session
-   before the end of the .data section, making the 2 sections overlap.
-   The loader appears to handle this situation gracefully, by simply
-   loading the bss section right after the end of the .data section.
-
-   This means that the .data and the .bss sections are sometimes
-   no longer relocated by the same amount.  The problem is that
-   the ldinfo data does not contain any information regarding
-   the relocation of the .bss section, assuming that it would be
-   identical to the information provided for the .data section
-   (this is what would normally happen if the program was linked
-   correctly).
-
-   GDB therefore needs to detect those cases, and make the corresponding
-   adjustment to the .bss section offset computed from the ldinfo data
-   when necessary.  This function returns the adjustment amount  (or
-   zero when no adjustment is needed).  */
-
-static CORE_ADDR
-bss_data_overlap (struct objfile *objfile)
-{
-  struct obj_section *osect;
-  struct bfd_section *data = NULL;
-  struct bfd_section *bss = NULL;
-
-  /* First, find the .data and .bss sections.  */
-  ALL_OBJFILE_OSECTIONS (objfile, osect)
-    {
-      if (strcmp (bfd_section_name (objfile->obfd,
-				    osect->the_bfd_section),
-		  ".data") == 0)
-	data = osect->the_bfd_section;
-      else if (strcmp (bfd_section_name (objfile->obfd,
-					 osect->the_bfd_section),
-		       ".bss") == 0)
-	bss = osect->the_bfd_section;
-    }
-
-  /* If either section is not defined, there can be no overlap.  */
-  if (data == NULL || bss == NULL)
-    return 0;
-
-  /* Assume the problem only occurs with linkers that place the .bss
-     section after the .data section (the problem has only been
-     observed when using the GNU linker, and the default linker
-     script always places the .data and .bss sections in that order).  */
-  if (bfd_section_vma (objfile->obfd, bss)
-      < bfd_section_vma (objfile->obfd, data))
-    return 0;
-
-  if (bfd_section_vma (objfile->obfd, bss)
-      < bfd_section_vma (objfile->obfd, data) + bfd_get_section_size (data))
-    return ((bfd_section_vma (objfile->obfd, data)
-	     + bfd_get_section_size (data))
-	    - bfd_section_vma (objfile->obfd, bss));
-
-  return 0;
-}
-
-/* Handle symbol translation on vmapping.  */
-
-static void
-vmap_symtab (struct vmap *vp)
-{
-  struct objfile *objfile;
-  struct section_offsets *new_offsets;
-  int i;
-
-  objfile = vp->objfile;
-  if (objfile == NULL)
-    {
-      /* OK, it's not an objfile we opened ourselves.
-         Currently, that can only happen with the exec file, so
-         relocate the symbols for the symfile.  */
-      if (symfile_objfile == NULL)
-	return;
-      objfile = symfile_objfile;
-    }
-  else if (!vp->loaded)
-    /* If symbols are not yet loaded, offsets are not yet valid.  */
-    return;
-
-  new_offsets =
-    (struct section_offsets *)
-    alloca (SIZEOF_N_SECTION_OFFSETS (objfile->num_sections));
-
-  for (i = 0; i < objfile->num_sections; ++i)
-    new_offsets->offsets[i] = ANOFFSET (objfile->section_offsets, i);
-
-  /* The symbols in the object file are linked to the VMA of the section,
-     relocate them VMA relative.  */
-  new_offsets->offsets[SECT_OFF_TEXT (objfile)] = vp->tstart - vp->tvma;
-  new_offsets->offsets[SECT_OFF_DATA (objfile)] = vp->dstart - vp->dvma;
-  new_offsets->offsets[SECT_OFF_BSS (objfile)] = vp->dstart - vp->dvma;
-
-  /* Perform the same adjustment as the loader if the .data and
-     .bss sections overlap.  */
-  new_offsets->offsets[SECT_OFF_BSS (objfile)] += bss_data_overlap (objfile);
-
-  objfile_relocate (objfile, new_offsets);
-}
-
-/* Add symbols for an objfile.  */
-
-static int
-objfile_symbol_add (void *arg)
-{
-  struct objfile *obj = (struct objfile *) arg;
-
-  syms_from_objfile (obj, NULL, 0, 0, 0);
-  new_symfile_objfile (obj, 0);
-  return 1;
-}
-
-/* Add symbols for a vmap. Return zero upon error.  */
-
-int
-vmap_add_symbols (struct vmap *vp)
-{
-  if (catch_errors (objfile_symbol_add, vp->objfile,
-		    "Error while reading shared library symbols:\n",
-		    RETURN_MASK_ALL))
-    {
-      /* Note this is only done if symbol reading was successful.  */
-      vp->loaded = 1;
-      vmap_symtab (vp);
-      return 1;
-    }
-  return 0;
-}
-
-/* Add a new vmap entry based on ldinfo() information.
-
-   If ldi->ldinfo_fd is not valid (e.g. this struct ld_info is from a
-   core file), the caller should set it to -1, and we will open the file.
-
-   Return the vmap new entry.  */
-
-static struct vmap *
-add_vmap (LdInfo *ldi)
-{
-  bfd *abfd, *last;
-  char *mem, *filename;
-  struct objfile *obj;
-  struct vmap *vp;
-  int fd;
-  ARCH64_DECL (arch64);
-
-  /* This ldi structure was allocated using alloca() in 
-     xcoff_relocate_symtab().  Now we need to have persistent object 
-     and member names, so we should save them.  */
-
-  filename = LDI_FILENAME (ldi, arch64);
-  mem = filename + strlen (filename) + 1;
-  mem = xstrdup (mem);
-
-  fd = LDI_FD (ldi, arch64);
-  abfd = gdb_bfd_open (filename, gnutarget, fd < 0 ? -1 : fd);
-  if (!abfd)
-    {
-      warning (_("Could not open `%s' as an executable file: %s"),
-	       filename, bfd_errmsg (bfd_get_error ()));
-      return NULL;
-    }
-
-  /* Make sure we have an object file.  */
-
-  if (bfd_check_format (abfd, bfd_object))
-    vp = map_vmap (abfd, 0);
-
-  else if (bfd_check_format (abfd, bfd_archive))
-    {
-      last = gdb_bfd_openr_next_archived_file (abfd, NULL);
-      while (last != NULL)
-	{
-	  bfd *next;
-
-	  if (strcmp (mem, last->filename) == 0)
-	    break;
-
-	  next = gdb_bfd_openr_next_archived_file (abfd, last);
-	  gdb_bfd_unref (last);
-	  last = next;
-	}
-
-      if (!last)
-	{
-	  warning (_("\"%s\": member \"%s\" missing."), filename, mem);
-	  gdb_bfd_unref (abfd);
-	  return NULL;
-	}
-
-      if (!bfd_check_format (last, bfd_object))
-	{
-	  warning (_("\"%s\": member \"%s\" not in executable format: %s."),
-		   filename, mem, bfd_errmsg (bfd_get_error ()));
-	  gdb_bfd_unref (last);
-	  gdb_bfd_unref (abfd);
-	  return NULL;
-	}
-
-      vp = map_vmap (last, abfd);
-      /* map_vmap acquired a reference to LAST, so we can release
-	 ours.  */
-      gdb_bfd_unref (last);
-    }
-  else
-    {
-      warning (_("\"%s\": not in executable format: %s."),
-	       filename, bfd_errmsg (bfd_get_error ()));
-      gdb_bfd_unref (abfd);
-      return NULL;
-    }
-  obj = allocate_objfile (vp->bfd, 0);
-  vp->objfile = obj;
-
-  /* Always add symbols for the main objfile.  */
-  if (vp == vmap || auto_solib_add)
-    vmap_add_symbols (vp);
-
-  /* Anything needing a reference to ABFD has already acquired it, so
-     release our local reference.  */
-  gdb_bfd_unref (abfd);
-
-  return vp;
-}
-
-/* update VMAP info with ldinfo() information
-   Input is ptr to ldinfo() results.  */
-
-static void
-vmap_ldinfo (LdInfo *ldi)
-{
-  struct stat ii, vi;
-  struct vmap *vp;
-  int got_one, retried;
-  int got_exec_file = 0;
-  uint next;
-  int arch64 = ARCH64 ();
-
-  /* For each *ldi, see if we have a corresponding *vp.
-     If so, update the mapping, and symbol table.
-     If not, add an entry and symbol table.  */
-
-  do
-    {
-      char *name = LDI_FILENAME (ldi, arch64);
-      char *memb = name + strlen (name) + 1;
-      int fd = LDI_FD (ldi, arch64);
-
-      retried = 0;
-
-      if (fstat (fd, &ii) < 0)
-	{
-	  /* The kernel sets ld_info to -1, if the process is still using the
-	     object, and the object is removed.  Keep the symbol info for the
-	     removed object and issue a warning.  */
-	  warning (_("%s (fd=%d) has disappeared, keeping its symbols"),
-		   name, fd);
-	  continue;
-	}
-    retry:
-      for (got_one = 0, vp = vmap; vp; vp = vp->nxt)
-	{
-	  struct objfile *objfile;
-
-	  /* First try to find a `vp', which is the same as in ldinfo.
-	     If not the same, just continue and grep the next `vp'.  If same,
-	     relocate its tstart, tend, dstart, dend values.  If no such `vp'
-	     found, get out of this for loop, add this ldi entry as a new vmap
-	     (add_vmap) and come back, find its `vp' and so on...  */
-
-	  /* The filenames are not always sufficient to match on.  */
-
-	  if ((name[0] == '/' && strcmp (name, vp->name) != 0)
-	      || (memb[0] && strcmp (memb, vp->member) != 0))
-	    continue;
-
-	  /* See if we are referring to the same file.
-	     We have to check objfile->obfd, symfile.c:reread_symbols might
-	     have updated the obfd after a change.  */
-	  objfile = vp->objfile == NULL ? symfile_objfile : vp->objfile;
-	  if (objfile == NULL
-	      || objfile->obfd == NULL
-	      || bfd_stat (objfile->obfd, &vi) < 0)
-	    {
-	      warning (_("Unable to stat %s, keeping its symbols"), name);
-	      continue;
-	    }
-
-	  if (ii.st_dev != vi.st_dev || ii.st_ino != vi.st_ino)
-	    continue;
-
-	  if (!retried)
-	    close (fd);
-
-	  ++got_one;
-
-	  /* Found a corresponding VMAP.  Remap!  */
-
-	  vmap_secs (vp, ldi, arch64);
-
-	  /* The objfile is only NULL for the exec file.  */
-	  if (vp->objfile == NULL)
-	    got_exec_file = 1;
-
-	  /* relocate symbol table(s).  */
-	  vmap_symtab (vp);
-
-	  /* Announce new object files.  Doing this after symbol relocation
-	     makes aix-thread.c's job easier.  */
-	  if (vp->objfile)
-	    observer_notify_new_objfile (vp->objfile);
-
-	  /* There may be more, so we don't break out of the loop.  */
-	}
-
-      /* If there was no matching *vp, we must perforce create the
-	 sucker(s). */
-      if (!got_one && !retried)
-	{
-	  add_vmap (ldi);
-	  ++retried;
-	  goto retry;
-	}
-    }
-  while ((next = LDI_NEXT (ldi, arch64))
-	 && (ldi = (void *) (next + (char *) ldi)));
-
-  /* If we don't find the symfile_objfile anywhere in the ldinfo, it
-     is unlikely that the symbol file is relocated to the proper
-     address.  And we might have attached to a process which is
-     running a different copy of the same executable.  */
-  if (symfile_objfile != NULL && !got_exec_file)
-    {
-      warning (_("Symbol file %s\nis not mapped; discarding it.\n\
-If in fact that file has symbols which the mapped files listed by\n\
-\"info files\" lack, you can load symbols with the \"symbol-file\" or\n\
-\"add-symbol-file\" commands (note that you must take care of relocating\n\
-symbols to the proper address)."),
-	       symfile_objfile->name);
-      free_objfile (symfile_objfile);
-      gdb_assert (symfile_objfile == NULL);
-    }
-  breakpoint_re_set ();
-}
-
-/* As well as symbol tables, exec_sections need relocation.  After
-   the inferior process' termination, there will be a relocated symbol
-   table exist with no corresponding inferior process.  At that time, we
-   need to use `exec' bfd, rather than the inferior process's memory space
-   to look up symbols.
-
-   `exec_sections' need to be relocated only once, as long as the exec
-   file remains unchanged.  */
-
-static void
-vmap_exec (void)
-{
-  static bfd *execbfd;
-  int i;
-  struct target_section_table *table = target_get_section_table (&exec_ops);
-
-  if (execbfd == exec_bfd)
-    return;
-
-  execbfd = exec_bfd;
-
-  if (!vmap || !table->sections)
-    error (_("vmap_exec: vmap or table->sections == 0."));
-
-  for (i = 0; &table->sections[i] < table->sections_end; i++)
-    {
-      if (strcmp (".text", table->sections[i].the_bfd_section->name) == 0)
-	{
-	  table->sections[i].addr += vmap->tstart - vmap->tvma;
-	  table->sections[i].endaddr += vmap->tstart - vmap->tvma;
-	}
-      else if (strcmp (".data", table->sections[i].the_bfd_section->name) == 0)
-	{
-	  table->sections[i].addr += vmap->dstart - vmap->dvma;
-	  table->sections[i].endaddr += vmap->dstart - vmap->dvma;
-	}
-      else if (strcmp (".bss", table->sections[i].the_bfd_section->name) == 0)
-	{
-	  table->sections[i].addr += vmap->dstart - vmap->dvma;
-	  table->sections[i].endaddr += vmap->dstart - vmap->dvma;
-	}
-    }
-}
-
 /* Set the current architecture from the host running GDB.  Called when
    starting a child process.  */
 
@@ -1103,195 +665,128 @@ rs6000_create_inferior (struct target_ops * ops, char *exec_file,
 		    _("rs6000_create_inferior: failed "
 		      "to select architecture"));
 }
-
 
-/* xcoff_relocate_symtab -      hook for symbol table relocation.
-   
-   This is only applicable to live processes, and is a no-op when
-   debugging a core file.  */
 
-void
-xcoff_relocate_symtab (unsigned int pid)
-{
-  int load_segs = 64; /* number of load segments */
-  int rc;
-  LdInfo *ldi = NULL;
-  int arch64 = ARCH64 ();
-  int ldisize = arch64 ? sizeof (ldi->l64) : sizeof (ldi->l32);
-  int size;
+/* Shared Object support.  */
 
-  /* Nothing to do if we are debugging a core file.  */
-  if (!target_has_execution)
-    return;
+#include "solib-aix.h"
 
-  do
+static LdInfo *
+rs6000_ptrace_ldinfo (int pid)
+{
+  int ldi_size = 1024;
+  LdInfo *ldi = xmalloc (ldi_size);
+  int rc = -1;
+
+  while (1)
     {
-      size = load_segs * ldisize;
-      ldi = (void *) xrealloc (ldi, size);
+      if (ARCH64 ())
+	rc = rs6000_ptrace64 (PT_LDINFO, pid, (unsigned long) ldi, ldi_size,
+			      NULL);
+      else
+	rc = rs6000_ptrace32 (PT_LDINFO, pid, (int *) ldi, ldi_size, NULL);
 
-#if 0
-      /* According to my humble theory, AIX has some timing problems and
-         when the user stack grows, kernel doesn't update stack info in time
-         and ptrace calls step on user stack.  That is why we sleep here a
-         little, and give kernel to update its internals.  */
-      usleep (36000);
-#endif
+      if (rc != -1)
+	break; /* Success, we got the entire ld_info data.  */
 
-      if (arch64)
-	rc = rs6000_ptrace64 (PT_LDINFO, pid, (unsigned long) ldi, size, NULL);
-      else
-	rc = rs6000_ptrace32 (PT_LDINFO, pid, (int *) ldi, size, NULL);
-
-      if (rc == -1)
-        {
-          if (errno == ENOMEM)
-            load_segs *= 2;
-          else
-            perror_with_name (_("ptrace ldinfo"));
-        }
-      else
-	{
-          vmap_ldinfo (ldi);
-          vmap_exec (); /* relocate the exec and core sections as well.  */
-	}
-    } while (rc == -1);
-  if (ldi)
-    xfree (ldi);
-}
-
-/* Core file stuff.  */
+      if (errno != ENOMEM)
+	perror_with_name (_("ptrace ldinfo"));
 
-/* Relocate symtabs and read in shared library info, based on symbols
-   from the core file.  */
+      /* ldi is not big enough.  Double it and try again.  */
+      ldi_size *= 2;
+      ldi = xrealloc (ldi, ldi_size);
+    }
 
-void
-xcoff_relocate_core (struct target_ops *target)
+  return ldi;
+}
+
+static LdInfo *
+rs6000_core_ldinfo (bfd *abfd)
 {
   struct bfd_section *ldinfo_sec;
-  int offset = 0;
-  LdInfo *ldi;
-  struct vmap *vp;
-  int arch64 = ARCH64 ();
+  int ldinfo_size;
+  gdb_byte *ldinfo_buf;
+  struct cleanup *cleanup;
 
-  /* Size of a struct ld_info except for the variable-length filename.  */
-  int nonfilesz = (int)LDI_FILENAME ((LdInfo *)0, arch64);
-
-  /* Allocated size of buffer.  */
-  int buffer_size = nonfilesz;
-  char *buffer = xmalloc (buffer_size);
-  struct cleanup *old = make_cleanup (free_current_contents, &buffer);
-
-  ldinfo_sec = bfd_get_section_by_name (core_bfd, ".ldinfo");
+  ldinfo_sec = bfd_get_section_by_name (abfd, ".ldinfo");
   if (ldinfo_sec == NULL)
-    {
-    bfd_err:
-      fprintf_filtered (gdb_stderr, "Couldn't get ldinfo from core file: %s\n",
-			bfd_errmsg (bfd_get_error ()));
-      do_cleanups (old);
-      return;
-    }
-  do
-    {
-      int i;
-      int names_found = 0;
-
-      /* Read in everything but the name.  */
-      if (bfd_get_section_contents (core_bfd, ldinfo_sec, buffer,
-				    offset, nonfilesz) == 0)
-	goto bfd_err;
+    error (_("cannot find .ldinfo section from core file: %s\n"),
+	   bfd_errmsg (bfd_get_error ()));
+  ldinfo_size = bfd_get_section_size (ldinfo_sec);
 
-      /* Now the name.  */
-      i = nonfilesz;
-      do
-	{
-	  if (i == buffer_size)
-	    {
-	      buffer_size *= 2;
-	      buffer = xrealloc (buffer, buffer_size);
-	    }
-	  if (bfd_get_section_contents (core_bfd, ldinfo_sec, &buffer[i],
-					offset + i, 1) == 0)
-	    goto bfd_err;
-	  if (buffer[i++] == '\0')
-	    ++names_found;
-	}
-      while (names_found < 2);
+  ldinfo_buf = xmalloc (ldinfo_size);
+  cleanup = make_cleanup (xfree, ldinfo_buf);
 
-      ldi = (LdInfo *) buffer;
+  if (! bfd_get_section_contents (abfd, ldinfo_sec,
+				  ldinfo_buf, 0, ldinfo_size))
+    error (_("unable to read .ldinfo section from core file: %s\n"),
+	   bfd_errmsg (bfd_get_error ()));
 
-      /* Can't use a file descriptor from the core file; need to open it.  */
-      if (arch64)
-	ldi->l64.ldinfo_fd = -1;
-      else
-	ldi->l32.ldinfo_fd = -1;
+  discard_cleanups (cleanup);
+  return (LdInfo *) ldinfo_buf;
+}
 
-      /* The first ldinfo is for the exec file, allocated elsewhere.  */
-      if (offset == 0 && vmap != NULL)
-	vp = vmap;
-      else
-	vp = add_vmap (ldi);
+VEC (aix_ld_info_t) *
+get_ld_info_list (int pid)
+{
+  const int arch64 = ARCH64 ();
+  LdInfo *ldi_data;
+  LdInfo *ldi;
+  VEC (aix_ld_info_t) *ld_info_list = VEC_alloc (aix_ld_info_t, 64);
 
-      /* Process next shared library upon error.  */
-      offset += LDI_NEXT (ldi, arch64);
-      if (vp == NULL)
-	continue;
+  /* Get the ldinfo raw data: If debugging a live process, we get it
+     using ptrace.  Otherwise, the info is stored in the .ldinfo
+     section of the core file.  */
 
-      vmap_secs (vp, ldi, arch64);
+  if (target_has_execution)
+    ldi_data = rs6000_ptrace_ldinfo (pid);
+  else
+    ldi_data = rs6000_core_ldinfo (core_bfd);
 
-      /* Unless this is the exec file,
-         add our sections to the section table for the core target.  */
-      if (vp != vmap)
-	{
-	  struct target_section *stp;
+  /* Read the raw data, and turn it into a list/vector.  */
 
-	  stp = deprecated_core_resize_section_table (2);
+  ldi = ldi_data;
+  while (1)
+    {
+      aix_ld_info_t info;
+      const char *archive_name = LDI_FILENAME (ldi, arch64);
+      const char *object_name = archive_name + strlen (archive_name) + 1;
 
-	  stp->bfd = vp->bfd;
-	  stp->the_bfd_section = bfd_get_section_by_name (stp->bfd, ".text");
-	  stp->addr = vp->tstart;
-	  stp->endaddr = vp->tend;
-	  stp++;
+      /* Close the fd.  We cannot use it, because we cannot assume
+	 that the user of this descriptor will be in the same
+	 process.  */
+      close (LDI_FD (ldi, arch64));
 
-	  stp->bfd = vp->bfd;
-	  stp->the_bfd_section = bfd_get_section_by_name (stp->bfd, ".data");
-	  stp->addr = vp->dstart;
-	  stp->endaddr = vp->dend;
+      info.archive_filename = xstrdup (archive_name);
+      info.object_filename = xstrdup (object_name);
+      if (arch64)
+	{
+	  info.text_addr = ldi->l64.ldinfo_textorg;
+	  info.text_size = ldi->l64.ldinfo_textsize;
+	  info.data_addr = ldi->l64.ldinfo_dataorg;
+	  info.data_size = ldi->l64.ldinfo_datasize;
 	}
-
-      vmap_symtab (vp);
-
-      if (vp != vmap && vp->objfile)
-	observer_notify_new_objfile (vp->objfile);
-    }
-  while (LDI_NEXT (ldi, arch64) != 0);
-  vmap_exec ();
-  breakpoint_re_set ();
-  do_cleanups (old);
-}
-
-/* Under AIX, we have to pass the correct TOC pointer to a function
-   when calling functions in the inferior.
-   We try to find the relative toc offset of the objfile containing PC
-   and add the current load address of the data segment from the vmap.  */
-
-static CORE_ADDR
-find_toc_address (CORE_ADDR pc)
-{
-  struct vmap *vp;
-
-  for (vp = vmap; vp; vp = vp->nxt)
-    {
-      if (pc >= vp->tstart && pc < vp->tend)
+      else
 	{
-	  /* vp->objfile is only NULL for the exec file.  */
-	  return vp->dstart + xcoff_get_toc_offset (vp->objfile == NULL
-						    ? symfile_objfile
-						    : vp->objfile);
+	  /* The text and data addresses are defined as pointers.
+	     To avoid sign-extending their value when saving them
+	     in our aix_ld_info structure, we cast their value to
+	     unsigned long first.  */
+	  info.text_addr = (unsigned long) ldi->l32.ldinfo_textorg;
+	  info.text_size = ldi->l32.ldinfo_textsize;
+	  info.data_addr = (unsigned long) ldi->l32.ldinfo_dataorg;
+	  info.data_size = ldi->l32.ldinfo_datasize;
 	}
+      VEC_safe_push (aix_ld_info_t, ld_info_list, &info);
+
+      if (!LDI_NEXT (ldi, arch64))
+	break;
+      ldi = (LdInfo *) ((char *) ldi + LDI_NEXT (ldi, arch64));
     }
-  error (_("Unable to find TOC entry for pc %s."), hex_string (pc));
+
+  xfree (ldi_data);
+  return ld_info_list;
 }
-
 
 void _initialize_rs6000_nat (void);
 
@@ -1311,8 +806,4 @@ _initialize_rs6000_nat (void)
   t->to_wait = rs6000_wait;
 
   add_target (t);
-
-  /* Initialize hook in rs6000-tdep.c for determining the TOC address
-     when calling functions in the inferior.  */
-  rs6000_find_toc_address_hook = find_toc_address;
 }
diff --git a/gdb/rs6000-tdep.h b/gdb/rs6000-tdep.h
index 569655a..ad983bb 100644
--- a/gdb/rs6000-tdep.h
+++ b/gdb/rs6000-tdep.h
@@ -15,10 +15,6 @@
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-/* Hook in rs6000-aix-tdep.c for determining the TOC address when
-   calling functions in the inferior.  */
-extern CORE_ADDR (*rs6000_find_toc_address_hook) (CORE_ADDR);
-
 /* Minimum possible text address in AIX.  */
 #define AIX_TEXT_SEGMENT_BASE 0x10000000
 
diff --git a/gdb/solib-aix.c b/gdb/solib-aix.c
new file mode 100644
index 0000000..dbd9048
--- /dev/null
+++ b/gdb/solib-aix.c
@@ -0,0 +1,494 @@
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "solib-aix.h"
+#include "solist.h"
+#include "inferior.h"
+#include "gdb_bfd.h"
+#include "gdbcore.h"
+#include "objfiles.h"
+#include "symtab.h"
+#include "xcoffread.h"
+
+struct lm_info
+{
+  /* The info collected from the loader.  */
+  struct aix_ld_info info;
+};
+
+/* If the .bss section's VMA is set to an address located before
+   the end of the .data section, causing the two sections to overlap,
+   return the overlap in bytes.  Otherwise, return zero.
+
+   Motivation:
+
+   The GNU linker sometimes sets the start address of the .bss session
+   before the end of the .data section, making the 2 sections overlap.
+   The loader appears to handle this situation gracefully, by simply
+   loading the bss section right after the end of the .data section.
+
+   This means that the .data and the .bss sections are sometimes
+   no longer relocated by the same amount.  The problem is that
+   the ldinfo data does not contain any information regarding
+   the relocation of the .bss section, assuming that it would be
+   identical to the information provided for the .data section
+   (this is what would normally happen if the program was linked
+   correctly).
+
+   GDB therefore needs to detect those cases, and make the corresponding
+   adjustment to the .bss section offset computed from the ldinfo data
+   when necessary.  This function returns the adjustment amount  (or
+   zero when no adjustment is needed).  */
+
+static CORE_ADDR
+solib_aix_bss_data_overlap (bfd *abfd)
+{
+  struct bfd_section *data_sect, *bss_sect;
+
+  data_sect = bfd_get_section_by_name (abfd, ".data");
+  if (data_sect == NULL)
+    return 0; /* No overlap possible.  */
+
+  bss_sect = bfd_get_section_by_name (abfd, ".bss");
+  if (bss_sect == NULL)
+    return 0; /* No overlap possible.  */
+
+  /* Assume the problem only occurs with linkers that place the .bss
+     section after the .data section (the problem has only been
+     observed when using the GNU linker, and the default linker
+     script always places the .data and .bss sections in that order).  */
+  if (bfd_section_vma (abfd, bss_sect)
+      < bfd_section_vma (abfd, data_sect))
+    return 0;
+
+  if (bfd_section_vma (abfd, bss_sect)
+      < bfd_section_vma (abfd, data_sect) + bfd_get_section_size (data_sect))
+    return ((bfd_section_vma (abfd, data_sect)
+	     + bfd_get_section_size (data_sect))
+	    - bfd_section_vma (abfd, bss_sect));
+
+  return 0;
+}
+
+/* Implement the "relocate_section_addresses" target_so_ops method.  */
+
+static void
+solib_aix_relocate_section_addresses (struct so_list *so,
+				      struct target_section *sec)
+{
+  bfd *abfd = sec->bfd;
+  struct bfd_section *bfd_sect = sec->the_bfd_section;
+  const char *section_name = bfd_section_name (abfd, bfd_sect);
+  struct aix_ld_info info = so->lm_info->info;
+
+  if (strcmp (section_name, ".text") == 0)
+    {
+      sec->addr = info.text_addr;
+      sec->endaddr = sec->addr + info.text_size;
+
+      /* The text address given to us by the loader contains
+	 XCOFF headers, so we need to adjust by this much.  */
+      sec->addr += bfd_sect->filepos;
+    }
+  else if (strcmp (section_name, ".data") == 0)
+    {
+      sec->addr = info.data_addr;
+      sec->endaddr = sec->addr + info.data_size;
+    }
+  else if (strcmp (section_name, ".bss") == 0)
+    {
+      sec->addr = bfd_section_vma (abfd, bfd_sect) + info.data_addr;
+      sec->addr += solib_aix_bss_data_overlap (abfd);
+      sec->endaddr = sec->addr + bfd_section_size (abfd, bfd_sect);
+    }
+  else
+    {
+      /* All other sections should not be relocated.  */
+      /* FIXME: GDB complains that the .loader section sometimes
+	 overlaps with other sections (Eg: the .data section).
+	 As far as I can tell, the loader section had the LOAD flag
+	 set, but not the RELOC.  So it should not be relocated.
+	 There seems to be a problem there, and maybe it has to do
+	 with setting sec->addr to 0 (when the vma is indeed 0).
+	 But even if there wasn't, the problem then becomes the fact
+	 that many shared objects inside shared libraries have
+	 a .loader section whose vma is 0, thus also triggering
+	 an overlap warning.  */
+      sec->addr = bfd_section_vma (abfd, bfd_sect);
+      sec->endaddr = sec->addr + bfd_section_size (abfd, bfd_sect);
+    }
+}
+
+/* Implement the "free_so" target_so_ops method.  */
+
+static void
+solib_aix_free_so (struct so_list *so)
+{
+  xfree (so->lm_info);
+}
+
+/* Implement the "clear_solib" target_so_ops method.  */
+
+static void
+solib_aix_clear_solib (void)
+{
+  /* Nothing needed.  */
+}
+
+static struct section_offsets *
+solib_aix_get_section_offsets (struct objfile *objfile,
+			       struct aix_ld_info *info)
+{
+  struct section_offsets *offsets;
+  bfd *abfd = objfile->obfd;
+  int i;
+
+  offsets = XCALLOC (objfile->num_sections, struct section_offsets);
+
+  /* .text */
+
+  if (objfile->sect_index_text != -1)
+    {
+      struct bfd_section *sect
+	= objfile->sections[objfile->sect_index_text].the_bfd_section;
+
+      offsets->offsets[objfile->sect_index_text]
+	= info->text_addr + sect->filepos - bfd_section_vma (abfd, sect);
+    }
+
+  /* .data */
+
+  if (objfile->sect_index_data != -1)
+    {
+      struct bfd_section *sect
+	= objfile->sections[objfile->sect_index_data].the_bfd_section;
+
+      offsets->offsets[objfile->sect_index_data]
+	= info->data_addr - bfd_section_vma (abfd, sect);
+
+      /* The .bss section displacement should be the same as
+	 the .data section displacement.  */
+
+    }
+
+  /* .bss
+
+     The offset of the .bss section should be identical to the offset
+     of the .data section.  If no .data section (which seems hard to
+     believe it is possible), assume it is zero.  */
+
+  if (objfile->sect_index_bss != -1
+      && objfile->sect_index_data != -1)
+    {
+      offsets->offsets[objfile->sect_index_bss]
+	= (offsets->offsets[objfile->sect_index_data]
+	   + solib_aix_bss_data_overlap (abfd));
+    }
+
+  /* All other sections should not need relocation.  */
+
+  return offsets;
+}
+
+/* Implement the "solib_create_inferior_hook" target_so_ops method.  */
+
+static void
+solib_aix_solib_create_inferior_hook (int from_tty)
+{
+  VEC (aix_ld_info_t) *info_list;
+  struct aix_ld_info *exec_info;
+
+  /* Relocate the main executable.  */
+  info_list = get_ld_info_list (ptid_get_pid (inferior_ptid));
+  if (VEC_length (aix_ld_info_t, info_list) < 1)
+    {
+      /* This should never happen, as there should always be
+	 at least one entry for the main executable.  The best
+	 we can do in this case is emit a warning, and pretend
+	 there is no relocation needed.  */
+      warning (_("unable to determine main executable relocation"));
+      VEC_free (aix_ld_info_t, info_list);
+      return;
+    }
+  exec_info = VEC_index (aix_ld_info_t, info_list, 0);
+
+  if (symfile_objfile != NULL)
+    {
+      struct section_offsets *offsets
+	= solib_aix_get_section_offsets (symfile_objfile, exec_info);
+      struct cleanup *cleanup = make_cleanup (xfree, offsets);
+
+      objfile_relocate (symfile_objfile, offsets);
+      do_cleanups (cleanup);
+    }
+}
+
+/* Implement the "special_symbol_handling" target_so_ops method.  */
+
+static void
+solib_aix_special_symbol_handling (void)
+{
+  /* Nothing needed.  */
+}
+
+/* Implement the "current_sos" target_so_ops method.  */
+
+static struct so_list *
+solib_aix_current_sos (void)
+{
+  VEC (aix_ld_info_t) *info_list;
+  struct aix_ld_info *info;
+  int ix;
+  struct so_list *start = NULL, *last = NULL;
+
+  info_list = get_ld_info_list (ptid_get_pid (inferior_ptid));
+  /* get_ld_info_list returns the loader info for all objects,
+     including the info for the main executable, which is always
+     the first element of the list.  That's why we iterate over
+     that list starting from the second element (ix = 1).  */
+  for (ix = 1; VEC_iterate (aix_ld_info_t, info_list, ix, info); ix++)
+    {
+      struct so_list *new_solib = XZALLOC (struct so_list);
+      char *so_name;
+
+      if (info->object_filename[0] == '\0')
+	{
+	  /* archive_filename is probably not an archive, but rather
+	     a shared object.  Unusual, but it should be possible
+	     to link a program against a shared object directory,
+	     without having to put it in an archive first.  */
+	  so_name = xstrdup (info->archive_filename);
+	}
+      else
+	{
+	  /* This is the usual case on AIX, where the shared object
+	     is a member of an archive.  Create a synthetic so_name
+	     that follows the same convention as AIX's ldd tool
+	     (Eg: "/lib/libc.a(shr.o)").  */
+	  so_name = xstrprintf ("%s(%s)",
+				info->archive_filename,
+				info->object_filename);
+	}
+
+      new_solib->lm_info = XZALLOC (struct lm_info);
+      new_solib->lm_info->info = *info;
+
+      strncpy (new_solib->so_original_name, so_name,
+	       SO_NAME_MAX_PATH_SIZE - 1);
+      new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
+      memcpy (new_solib->so_name, new_solib->so_original_name,
+	      SO_NAME_MAX_PATH_SIZE);
+
+      /* Add it to the list.  */
+      if (!start)
+	last = start = new_solib;
+      else
+	{
+	  last->next = new_solib;
+	  last = new_solib;
+	}
+
+      xfree (so_name);
+    }
+
+  /* FIXME: We need to free the various filenames.
+     Actually, maybe not, because the data is copied inside
+     the lm_info data, so it still has a ref to those strings.  */
+  VEC_free (aix_ld_info_t, info_list);
+  return start;
+}
+
+/* Implement the "open_symbol_file_object" target_so_ops method.  */
+
+static int
+solib_aix_open_symbol_file_object (void *from_ttyp)
+{
+  return 0;
+}
+
+/* Implement the "in_dynsym_resolve_code" target_so_ops method.  */
+
+static int
+solib_aix_in_dynsym_resolve_code (CORE_ADDR pc)
+{
+  return 0;
+}
+
+/* Implement the "bfd_open" target_so_ops method.  */
+
+static bfd *
+solib_aix_bfd_open (char *pathname)
+{
+  /* The pathname is actually a synthetic filename with the following
+     form: "/path/to/sharedlib(member.o)" (double-quotes excluded).
+     split this into archive name and member name.
+
+     FIXME: This is a little hacky.  Perhaps we should provide access
+     to the solib's lm_info here?  */
+  const int path_len = strlen(pathname);
+  int len;
+  char *archive_filename;
+  char *object_filename;
+  bfd *archive_bfd, *object_bfd;
+  struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
+
+  if (pathname[path_len - 1] != ')')
+    return solib_bfd_open (pathname);
+
+  /* Search for the associated parens.  */
+  len = path_len - 2;
+  while (len > 1 && pathname[len] != '(')
+    len--;
+
+  if (pathname[len] != '(')
+    {
+      /* Should never happen, but recover as best as we can (trying
+	 to open pathname without decoding, possibly leading to
+	 a failure), rather than triggering an assert failure).  */
+      warning (_("unable shared object pathname: %s"), pathname);
+      return solib_bfd_open (pathname);
+    }
+
+  archive_filename = xstrprintf ("%.*s", len, pathname);
+  make_cleanup (xfree, archive_filename);
+  object_filename = xstrprintf ("%.*s", path_len - len - 2,
+				pathname + len + 1);
+  make_cleanup (xfree, object_filename);
+
+  archive_bfd = gdb_bfd_open (archive_filename, gnutarget, -1);
+  if (archive_bfd == NULL)
+    {
+      warning (_("Could not open `%s' as an executable file: %s"),
+	       archive_filename, bfd_errmsg (bfd_get_error ()));
+      do_cleanups (cleanup);
+      return NULL;
+    }
+
+  if (bfd_check_format (archive_bfd, bfd_object))
+    {
+      do_cleanups (cleanup);
+      return archive_bfd;
+    }
+
+  if (! bfd_check_format (archive_bfd, bfd_archive))
+    {
+      warning (_("\"%s\": not in executable format: %s."),
+	       archive_filename, bfd_errmsg (bfd_get_error ()));
+      gdb_bfd_unref (archive_bfd);
+      do_cleanups (cleanup);
+      return NULL;
+    }
+
+  object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd, NULL);
+  while (object_bfd != NULL)
+    {
+      bfd *next;
+
+      if (strcmp (object_filename, object_bfd->filename) == 0)
+	break;
+
+      next = gdb_bfd_openr_next_archived_file (archive_bfd, object_bfd);
+      gdb_bfd_unref (object_bfd);
+      object_bfd = next;
+    }
+
+  if (object_bfd == NULL)
+    {
+      warning (_("\"%s\": member \"%s\" missing."),
+	       archive_filename, object_filename);
+      gdb_bfd_unref (archive_bfd);
+      do_cleanups (cleanup);
+      return NULL;
+    }
+
+  if (! bfd_check_format (object_bfd, bfd_object))
+    {
+      warning (_("%s(%s): not in object format: %s."),
+	       archive_filename, object_filename,
+	       bfd_errmsg (bfd_get_error ()));
+      gdb_bfd_unref (archive_bfd);
+      gdb_bfd_unref (object_bfd);
+      do_cleanups (cleanup);
+      return NULL;
+    }
+
+  gdb_bfd_unref (archive_bfd);
+  do_cleanups (cleanup);
+  return object_bfd;
+}
+
+/* FIXME: Define in a more general location? */
+
+static struct obj_section *
+data_obj_section_from_objfile (struct objfile *objfile)
+{
+  struct obj_section *osect;
+
+  ALL_OBJFILE_OSECTIONS (objfile, osect)
+    if (strcmp (bfd_section_name (objfile->obfd, osect->the_bfd_section),
+		".data") == 0)
+      return osect;
+
+  return NULL;
+}
+
+CORE_ADDR
+solib_aix_get_toc_value (CORE_ADDR pc)
+{
+  struct obj_section *pc_osect = find_pc_section (pc);
+  struct obj_section *data_osect;
+
+  if (pc_osect == NULL)
+    error (_("unable to find TOC entry for pc %s "
+	     "(no section contains this PC)"),
+	   core_addr_to_string (pc));
+
+  data_osect = data_obj_section_from_objfile (pc_osect->objfile);
+  if (data_osect == NULL)
+    error (_("unable to find TOC entry for pc %s "
+	     "(%s has no data section)"),
+	   core_addr_to_string (pc), pc_osect->objfile->name);
+
+  return (obj_section_addr (data_osect)
+	  + xcoff_get_toc_offset (pc_osect->objfile));
+}
+
+/* The target_so_ops for AIX targets.  */
+struct target_so_ops solib_aix_so_ops;
+
+/* -Wmissing-prototypes */
+extern initialize_file_ftype _initialize_solib_aix;
+
+void
+_initialize_solib_aix (void)
+{
+  solib_aix_so_ops.relocate_section_addresses
+    = solib_aix_relocate_section_addresses;
+  solib_aix_so_ops.free_so = solib_aix_free_so;
+  solib_aix_so_ops.clear_solib = solib_aix_clear_solib;
+  solib_aix_so_ops.solib_create_inferior_hook
+    = solib_aix_solib_create_inferior_hook;
+  solib_aix_so_ops.special_symbol_handling
+    = solib_aix_special_symbol_handling;
+  solib_aix_so_ops.current_sos = solib_aix_current_sos;
+  solib_aix_so_ops.open_symbol_file_object
+    = solib_aix_open_symbol_file_object;
+  solib_aix_so_ops.in_dynsym_resolve_code
+    = solib_aix_in_dynsym_resolve_code;
+  solib_aix_so_ops.bfd_open = solib_aix_bfd_open;
+}
diff --git a/gdb/solib-aix.h b/gdb/solib-aix.h
new file mode 100644
index 0000000..305d97a
--- /dev/null
+++ b/gdb/solib-aix.h
@@ -0,0 +1,52 @@
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef SOLIB_AIX_H
+#define SOLIB_AIX_H
+
+struct target_so_ops;
+extern struct target_so_ops solib_aix_so_ops;
+
+/* FIXME: This might be temporary - until we dissociate the direct
+   dependency of the "solib" part from the "nat" part.  */
+
+#include "vec.h"
+
+typedef struct aix_ld_info
+{
+  /* The name of the shared library (which, on AIX, is an archive
+     library file, usually created using the "ar" command).  */
+  const char *archive_filename;
+
+  /* The name of the shared object file with the actual dynamic
+     loading dependency.  This should never be NULL, but may be
+     the empty string (main executable).  */
+  const char *object_filename;
+
+  CORE_ADDR text_addr;
+  ULONGEST text_size;
+
+  CORE_ADDR data_addr;
+  ULONGEST data_size;
+} aix_ld_info_t;
+
+DEF_VEC_O (aix_ld_info_t);
+
+extern VEC (aix_ld_info_t) *get_ld_info_list (int pid);
+extern CORE_ADDR solib_aix_get_toc_value (CORE_ADDR pc);
+
+#endif
diff --git a/gdb/solib.c b/gdb/solib.c
index 8129c0f..d43e8d9 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -469,7 +469,14 @@ solib_map_sections (struct so_list *so)
      can find it.  */
   if (strlen (bfd_get_filename (abfd)) >= SO_NAME_MAX_PATH_SIZE)
     error (_("Shared library file name is too long."));
+#ifdef FIXME_CAUSES_US_TO_DISPLAY_MEMBER_NAME_ONLY
+  /* FIXME: Why are we overwritting the so_name, here?
+     Because of that, "info sharedlibrary" prints shared object name
+     as "shr.o" instead of what we set it to ("/lib/libc.a(shr.o)").
+     Perhaps we can use abfd->my_archive??? But this would affect
+     Darwin, I believe, so to be checked.  */
   strcpy (so->so_name, bfd_get_filename (abfd));
+#endif
 
   if (build_section_table (abfd, &so->sections, &so->sections_end))
     {
@@ -1299,11 +1306,7 @@ reload_shared_libraries (char *ignored, int from_tty,
 	 we're not really starting up the inferior here.  */
       remove_solib_event_breakpoints ();
 
-#ifdef SOLIB_CREATE_INFERIOR_HOOK
-      SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
-#else
       solib_create_inferior_hook (from_tty);
-#endif
     }
 
   /* Sometimes the platform-specific hook loads initial shared
diff --git a/gdb/stack.c b/gdb/stack.c
index ccdab00..5a2a244 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1202,12 +1202,9 @@ print_frame (struct frame_info *frame, int print_level,
 
   if (pc_p && (funname == NULL || sal.symtab == NULL))
     {
-#ifdef PC_SOLIB
-      char *lib = PC_SOLIB (get_frame_pc (frame));
-#else
       char *lib = solib_name_from_address (get_frame_program_space (frame),
 					   get_frame_pc (frame));
-#endif
+
       if (lib)
 	{
 	  annotate_frame_where ();
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index 896b817..2821b91 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -907,11 +907,16 @@ enter_line_range (struct subfile *subfile, unsigned beginoffset,
 
 /* Create a new minimal symbol (using prim_record_minimal_symbol_and_info).
 
+   Creation of all new minimal symbols should go through this function
+   rather than calling the various prim_record_[...] functions in order
+   to make sure that all symbol addresses get properly relocated.
+
    Arguments are:
 
    NAME - the symbol's name (but if NAME starts with a period, that
    leading period is discarded).
-   ADDRESS - the symbol's address.
+   ADDRESS - the symbol's address, prior to relocation.  This function
+      relocates the address before recording the minimal symbol.
    MS_TYPE - the symbol's type.
    N_SCNUM - the symbol's XCOFF section number.
    OBJFILE - the objfile associated with the minimal symbol.  */
@@ -929,6 +934,7 @@ record_minimal_symbol (const char *name, CORE_ADDR address,
     ++name;
 
   xcoff_secnum_to_sections (n_scnum, objfile, &bfd_sect, &secnum);
+  address += ANOFFSET (objfile->section_offsets, secnum);
   prim_record_minimal_symbol_and_info (name, address, ms_type,
 				       secnum, bfd_sect, objfile);
 }
@@ -2342,12 +2348,10 @@ scan_xcoff_symtab (struct objfile *objfile)
 		    /* Data variables are recorded in the minimal symbol
 		       table, except for section symbols.  */
 		    if (*namestring != '.')
-		      prim_record_minimal_symbol_and_info
+		      record_minimal_symbol
 			(namestring, symbol.n_value,
 			 sclass == C_HIDEXT ? mst_file_data : mst_data,
-			 secnum_to_section (symbol.n_scnum, objfile),
-			 secnum_to_bfd_section (symbol.n_scnum, objfile),
-			 objfile);
+			 symbol.n_scnum, objfile);
 		    break;
 
 		  case XMC_TC0:
@@ -2420,12 +2424,10 @@ scan_xcoff_symtab (struct objfile *objfile)
 		       typically be XMC_RW; I suspect XMC_RO and
 		       XMC_BS might be possible too.  */
 		    if (*namestring != '.')
-		      prim_record_minimal_symbol_and_info
+		      record_minimal_symbol
 			(namestring, symbol.n_value,
 			 sclass == C_HIDEXT ? mst_file_data : mst_data,
-			 secnum_to_section (symbol.n_scnum, objfile),
-			 secnum_to_bfd_section (symbol.n_scnum, objfile),
-			 objfile);
+			 symbol.n_scnum, objfile);
 		    break;
 		  }
 		break;
@@ -2438,12 +2440,10 @@ scan_xcoff_symtab (struct objfile *objfile)
 		    /* Common variables are recorded in the minimal symbol
 		       table, except for section symbols.  */
 		    if (*namestring != '.')
-		      prim_record_minimal_symbol_and_info
+		      record_minimal_symbol
 			(namestring, symbol.n_value,
 			 sclass == C_HIDEXT ? mst_file_bss : mst_bss,
-			 secnum_to_section (symbol.n_scnum, objfile),
-			 secnum_to_bfd_section (symbol.n_scnum, objfile),
-			 objfile);
+			 symbol.n_scnum, objfile);
 		    break;
 		  }
 		break;
@@ -3041,44 +3041,38 @@ static void
 xcoff_symfile_offsets (struct objfile *objfile,
 		       struct section_addr_info *addrs)
 {
-  asection *sect = NULL;
-  int i;
+  const char *first_section_name;
 
-  objfile->num_sections = bfd_count_sections (objfile->obfd);
-  objfile->section_offsets = (struct section_offsets *)
-    obstack_alloc (&objfile->objfile_obstack, 
-		   SIZEOF_N_SECTION_OFFSETS (objfile->num_sections));
+  default_symfile_offsets (objfile, addrs);
 
-  /* Initialize the section indexes for future use.  */
-  sect = bfd_get_section_by_name (objfile->obfd, ".text");
-  if (sect) 
-    objfile->sect_index_text = sect->index;
+  /* Oneof the weird side-effects of default_symfile_offsets is that
+     it sometimes sets some section indices to zero for sections that,
+     in fact do not exist. See the body of default_symfile_offsets
+     for more info on when that happens. Undo that, as this then allows
+     us to test whether the associated section exists or not, and then
+     access it quickly (without searching it again).  */
 
-  sect = bfd_get_section_by_name (objfile->obfd, ".data");
-  if (sect) 
-    objfile->sect_index_data = sect->index;
+  if (objfile->num_sections == 0)
+    return; /* Is that even possible?  Better safe than sorry.  */
 
-  sect = bfd_get_section_by_name (objfile->obfd, ".bss");
-  if (sect) 
-    objfile->sect_index_bss = sect->index;
+  first_section_name
+    = bfd_section_name (objfile->obfd, objfile->sections[0].the_bfd_section);
 
-  sect = bfd_get_section_by_name (objfile->obfd, ".rodata");
-  if (sect) 
-    objfile->sect_index_rodata = sect->index;
+  if (objfile->sect_index_text == 0
+      && strcmp (first_section_name, ".text") != 0)
+    objfile->sect_index_text = -1;
 
-  for (i = 0; i < objfile->num_sections; ++i)
-    {
-      /* syms_from_objfile kindly subtracts from addr the
-	 bfd_section_vma of the .text section.  This strikes me as
-	 wrong--whether the offset to be applied to symbol reading is
-	 relative to the start address of the section depends on the
-	 symbol format.  In any event, this whole "addr" concept is
-	 pretty broken (it doesn't handle any section but .text
-	 sensibly), so just ignore the addr parameter and use 0.
-	 rs6000-nat.c will set the correct section offsets via
-	 objfile_relocate.  */
-	(objfile->section_offsets)->offsets[i] = 0;
-    }
+  if (objfile->sect_index_data == 0
+      && strcmp (first_section_name, ".data") != 0)
+    objfile->sect_index_data = -1;
+
+  if (objfile->sect_index_bss == 0
+      && strcmp (first_section_name, ".bss") != 0)
+    objfile->sect_index_bss = -1;
+
+  if (objfile->sect_index_rodata == 0
+      && strcmp (first_section_name, ".rodata") != 0)
+    objfile->sect_index_rodata = -1;
 }
 
 /* Register our ability to parse symbols for xcoff BFD files.  */
diff --git a/gdb/xcoffsolib.c b/gdb/xcoffsolib.c
deleted file mode 100644
index 069b016..0000000
--- a/gdb/xcoffsolib.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/* Shared library support for RS/6000 (xcoff) object files, for GDB.
-   Copyright (C) 1991-2013 Free Software Foundation, Inc.
-   Contributed by IBM Corporation.
-
-   This file is part of GDB.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#include "defs.h"
-#include "bfd.h"
-#include "xcoffsolib.h"
-#include "inferior.h"
-#include "gdbcmd.h"
-#include "symfile.h"
-#include "frame.h"
-#include "gdb_regex.h"
-
-
-/* If ADDR lies in a shared library, return its name.
-   Note that returned name points to static data whose content is overwritten
-   by each call.  */
-
-char *
-xcoff_solib_address (CORE_ADDR addr)
-{
-  static char *buffer = NULL;
-  struct vmap *vp = vmap;
-
-  /* The first vmap entry is for the exec file.  */
-
-  if (vp == NULL)
-    return NULL;
-  for (vp = vp->nxt; vp; vp = vp->nxt)
-    if (vp->tstart <= addr && addr < vp->tend)
-      {
-	xfree (buffer);
-	buffer = xstrprintf ("%s%s%s%s",
-			     vp->name,
-			     *vp->member ? "(" : "",
-			     vp->member,
-			     *vp->member ? ")" : "");
-	return buffer;
-      }
-  return NULL;
-}
-
-static void solib_info (char *, int);
-static void sharedlibrary_command (char *pattern, int from_tty);
-
-static void
-solib_info (char *args, int from_tty)
-{
-  int addr_size = gdbarch_addr_bit (target_gdbarch ()) / 8;
-  struct vmap *vp = vmap;
-
-  /* Check for new shared libraries loaded with load ().  */
-  if (! ptid_equal (inferior_ptid, null_ptid))
-    xcoff_relocate_symtab (PIDGET (inferior_ptid));
-
-  if (vp == NULL || vp->nxt == NULL)
-    {
-      printf_unfiltered ("No shared libraries loaded at this time.\n");
-      return;
-    }
-
-  /* Skip over the first vmap, it is the main program, always loaded.  */
-  vp = vp->nxt;
-
-  printf_unfiltered ("Text Range		Data Range		"
-		     "Syms	Shared Object Library\n");
-
-  for (; vp != NULL; vp = vp->nxt)
-    {
-      printf_unfiltered ("0x%s-0x%s	0x%s-0x%s	%s	%s%s%s%s\n",
-			 phex (vp->tstart, addr_size),
-			 phex (vp->tend, addr_size),
-			 phex (vp->dstart, addr_size),
-			 phex (vp->dend, addr_size),
-			 vp->loaded ? "Yes" : "No ",
-			 vp->name,
-			 *vp->member ? "(" : "",
-			 vp->member,
-			 *vp->member ? ")" : "");
-    }
-}
-
-static void
-sharedlibrary_command (char *pattern, int from_tty)
-{
-  dont_repeat ();
-
-  /* Check for new shared libraries loaded with load ().  */
-  if (! ptid_equal (inferior_ptid, null_ptid))
-    xcoff_relocate_symtab (PIDGET (inferior_ptid));
-
-  if (pattern)
-    {
-      char *re_err = re_comp (pattern);
-
-      if (re_err)
-	error (_("Invalid regexp: %s"), re_err);
-    }
-
-  /* Walk the list of currently loaded shared libraries, and read
-     symbols for any that match the pattern --- or any whose symbols
-     aren't already loaded, if no pattern was given.  */
-  {
-    int any_matches = 0;
-    int loaded_any_symbols = 0;
-    struct vmap *vp = vmap;
-
-    if (!vp)
-      return;
-
-    /* skip over the first vmap, it is the main program, always loaded.  */
-    for (vp = vp->nxt; vp; vp = vp->nxt)
-      if (! pattern
-	    || re_exec (vp->name)
-	    || (*vp->member && re_exec (vp->member)))
-	{
-	  any_matches = 1;
-
-	  if (vp->loaded)
-	    {
-	      if (from_tty)
-		printf_unfiltered ("Symbols already loaded for %s\n",
-				   vp->name);
-	    }
-	  else
-	    {
-	      if (vmap_add_symbols (vp))
-		loaded_any_symbols = 1;
-	    }
-	}
-
-    if (from_tty && pattern && ! any_matches)
-      printf_unfiltered
-	("No loaded shared libraries match the pattern `%s'.\n", pattern);
-
-    if (loaded_any_symbols)
-      {
-	/* Getting new symbols may change our opinion about what is
-	   frameless.  */
-	reinit_frame_cache ();
-      }
-  }
-}
-
-void _initialize_xcoffsolib (void);
-
-void
-_initialize_xcoffsolib (void)
-{
-  add_com ("sharedlibrary", class_files, sharedlibrary_command,
-	   _("Load shared object library symbols for files matching REGEXP."));
-  add_info ("sharedlibrary", solib_info,
-	    _("Status of loaded shared object libraries"));
-
-  add_setshow_boolean_cmd ("auto-solib-add", class_support,
-			   &auto_solib_add, _("\
-Set autoloading of shared library symbols."), _("\
-Show autoloading of shared library symbols."), _("\
-If \"on\", symbols from all shared object libraries will be loaded\n\
-automatically when the inferior begins execution, when the dynamic linker\n\
-informs gdb that a new library has been loaded, or when attaching to the\n\
-inferior.  Otherwise, symbols must be loaded manually, using \
-`sharedlibrary'."),
-			   NULL,
-			   NULL, /* FIXME: i18n: */
-			   &setlist, &showlist);
-}
diff --git a/gdb/xcoffsolib.h b/gdb/xcoffsolib.h
deleted file mode 100644
index 7dcdb60..0000000
--- a/gdb/xcoffsolib.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Data structures for RS/6000 shared libraries, for GDB.
-   Copyright (C) 1991-2013 Free Software Foundation, Inc.
-
-   This file is part of GDB.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/* The vmap struct is used to describe the virtual address space of
-   the target we are manipulating.  The first entry is always the "exec"
-   file.  Subsequent entries correspond to other objects that are
-   mapped into the address space of a process created from the "exec" file.
-   These are either in response to exec()ing the file, in which case all
-   shared libraries are loaded, or a "load" system call, followed by the
-   user's issuance of a "load" command.  */
-
-#ifndef XCOFFSOLIB_H
-#define XCOFFSOLIB_H
-
-struct vmap
-  {
-    struct vmap *nxt;		/* ptr to next in chain                 */
-    bfd *bfd;			/* BFD for mappable object library      */
-    char *name;			/* ptr to object file name              */
-    char *member;		/* ptr to member name                   */
-    CORE_ADDR tstart;		/* virtual addr where member is mapped  */
-    CORE_ADDR tend;		/* virtual upper bound of member        */
-    CORE_ADDR tvma;		/* virtual addr of text section in
-				   object file */
-    CORE_ADDR toffs;		/* offset of text section in object file */
-    CORE_ADDR dstart;		/* virtual address of data start        */
-    CORE_ADDR dend;		/* virtual address of data end          */
-    CORE_ADDR dvma;		/* virtual addr of data section in
-				   object file */
-
-    /* This is NULL for the exec-file.  */
-    struct objfile *objfile;
-
-    unsigned loaded:1;		/* True if symbols are loaded           */
-    unsigned padding:15;
-  };
-
-
-struct vmap_and_bfd
-  {
-    bfd *pbfd;
-    struct vmap *pvmap;
-  };
-
-extern struct vmap *vmap;
-
-/* Add symbols for a vmap.  */
-extern int vmap_add_symbols (struct vmap *vp);
-
-#endif
-- 
1.7.0.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]