Reimplement shared library support on ppc-aix...

... using the target_so_ops framework.

gdb/ChangeLog:

        * target.h (TARGET_OBJECT_AIX_LIBRARIES): New target_object enum.
        * features/library-list-aix.dtd: New file.
        * solib-aix.h, solib-aix.c: New file.
        * rs6000-aix-tdep.c: #include "solib.h" and "solib-aix.h".
        (rs6000_find_toc_address_hook): Delete.
        (rs6000_push_dummy_call): Rewrite code setting the TOC value.
        (rs6000_aix_init_osabi): Register solib_aix_so_ops.
        * rs6000-nat.c: Remove "xcoffsolib.h" include.  Include
        "xml-utils.h".
        (map_vmap, vmap_exec, vmap_ldinfo, add_vmap, objfile_symbol_add)
        (vmap_symtab, fixup_breakpoints): Delete.
        (rs6000_xfer_shared_libraries): New function.
        (rs6000_xfer_partial): Add TARGET_OBJECT_AIX_LIBRARIES handling.
        (vmap_secs, bss_data_overlap, vmap_add_symbols): Delete.
        (xcoff_relocate_symtab, xcoff_relocate_core): Delete.
        (rs6000_ptrace_ldinfo, rs6000_core_ldinfo)
        (rs6000_xfer_shared_library): New function.
        (find_toc_address): Delete.
        (_initialize_rs6000_nat): Do not set rs6000_find_toc_address_hook.
        * rs6000-tdep.h (rs6000_find_toc_address_hook): Remove.
        * xcoffread.c (record_minimal_symbol): Reloate symbol address
        before creating minimal symbol.  Adjust function description
        accordingly.
        (scan_xcoff_symtab): Replace call to
        prim_record_minimal_symbol_and_info by call to
        record_minimal_symbol.
        (xcoff_symfile_offsets): Reimplement mostly as a wrapper
        around default_symfile_offsets.
        * configure.tgt: Add solib-aix.o to gdb_target_obs for
        powerpc-aix targets.
        * config/rs6000/nm-rs6000.h: Delete.
        * config/powerpc/aix.mh (NAT_FILE): Delete.
        (NATDEPFILES): Remove xcoffsolib.o.
        * Makefile.in (XMLFILES): Add library-list-aix.dtd.
        (ALL_TARGET_OBS): Add solib-aix.o.
        (HFILES_NO_SRCDIR): Remove xcoffsolib.h and
        config/rs6000/nm-rs6000.h.  Add solib-aix.h.
        (ALLDEPFILES): Add solib-aix.c.  Remove xcoffsolib.c.
        * xcoffsolib.h, xcoffsolib.c: Delete.

        * solib.c (reload_shared_libraries): Remove reference to
        SOLIB_CREATE_INFERIOR_HOOK.
        * breakpoint.c (handle_solib_event): Remove reference to SOLIB_ADD.
        (disable_breakpoints_in_shlibs): Remove reference to PC_SOLIB.
        (momentary_bkpt_re_set): Replace SOLIB_ADD by solib_add in
        comment.
        * corelow.c (deprecated_core_resize_section_table): Delete.
        * exec.c: Remove include of xcoffsolib.h".
        (map_vmap, vmap): Delete.
        (exec_close_1): Remove references to vmap.
        (exec_file_attach): Remove vmap handling code, and reference
        to DEPRECATED_IBM6000_TARGET.
        (bfdsec_to_vmap): Delete.
        (exec_files_info): Remove block of code handling VMAP.
        * infcmd.c (post_create_inferior): Remove reference to
        SOLIB_CREATE_INFERIOR_HOOK and SOLIB_ADD.
        * infrun.c (follow_exec): Remove reference to
        SOLIB_CREATE_INFERIOR_HOOK.
        * stack.c (print_frame): Remove reference to PC_SOLIB.
        * solib-dsbt.c (dsbt_current_sos): Adjust comment.
        (dsbt_relocate_main_executable): Likewise.
        * solib-frv.c (frv_current_sos): Likewise.

gdb/doc/ChangeLog:

        * gdbint.texinfo (Algorithms): Remove entries documenting
        DEPRECATED_IBM6000_TARGET, SOLIB_ADD, and
        SOLIB_CREATE_INFERIOR_HOOK.
This commit is contained in:
Joel Brobecker 2013-05-06 14:15:50 +00:00
parent 0c4f667cfe
commit 4d1eb6b4d2
26 changed files with 1205 additions and 1173 deletions

View File

@ -1,3 +1,69 @@
2013-05-06 Joel Brobecker <brobecker@adacore.com>
Reimplement shared library support on ppc-aix...
* target.h (TARGET_OBJECT_AIX_LIBRARIES): New target_object enum.
* features/library-list-aix.dtd: New file.
* solib-aix.h, solib-aix.c: New file.
* rs6000-aix-tdep.c: #include "solib.h" and "solib-aix.h".
(rs6000_find_toc_address_hook): Delete.
(rs6000_push_dummy_call): Rewrite code setting the TOC value.
(rs6000_aix_init_osabi): Register solib_aix_so_ops.
* rs6000-nat.c: Remove "xcoffsolib.h" include. Include
"xml-utils.h".
(map_vmap, vmap_exec, vmap_ldinfo, add_vmap, objfile_symbol_add)
(vmap_symtab, fixup_breakpoints): Delete.
(rs6000_xfer_shared_libraries): New function.
(rs6000_xfer_partial): Add TARGET_OBJECT_AIX_LIBRARIES handling.
(vmap_secs, bss_data_overlap, vmap_add_symbols): Delete.
(xcoff_relocate_symtab, xcoff_relocate_core): Delete.
(rs6000_ptrace_ldinfo, rs6000_core_ldinfo)
(rs6000_xfer_shared_library): New function.
(find_toc_address): Delete.
(_initialize_rs6000_nat): Do not set rs6000_find_toc_address_hook.
* rs6000-tdep.h (rs6000_find_toc_address_hook): Remove.
* xcoffread.c (record_minimal_symbol): Reloate symbol address
before creating minimal symbol. Adjust function description
accordingly.
(scan_xcoff_symtab): Replace call to
prim_record_minimal_symbol_and_info by call to
record_minimal_symbol.
(xcoff_symfile_offsets): Reimplement mostly as a wrapper
around default_symfile_offsets.
* configure.tgt: Add solib-aix.o to gdb_target_obs for
powerpc-aix targets.
* config/rs6000/nm-rs6000.h: Delete.
* config/powerpc/aix.mh (NAT_FILE): Delete.
(NATDEPFILES): Remove xcoffsolib.o.
* Makefile.in (XMLFILES): Add library-list-aix.dtd.
(ALL_TARGET_OBS): Add solib-aix.o.
(HFILES_NO_SRCDIR): Remove xcoffsolib.h and
config/rs6000/nm-rs6000.h. Add solib-aix.h.
(ALLDEPFILES): Add solib-aix.c. Remove xcoffsolib.c.
* xcoffsolib.h, xcoffsolib.c: Delete.
* solib.c (reload_shared_libraries): Remove reference to
SOLIB_CREATE_INFERIOR_HOOK.
* breakpoint.c (handle_solib_event): Remove reference to SOLIB_ADD.
(disable_breakpoints_in_shlibs): Remove reference to PC_SOLIB.
(momentary_bkpt_re_set): Replace SOLIB_ADD by solib_add in
comment.
* corelow.c (deprecated_core_resize_section_table): Delete.
* exec.c: Remove include of xcoffsolib.h".
(map_vmap, vmap): Delete.
(exec_close_1): Remove references to vmap.
(exec_file_attach): Remove vmap handling code, and reference
to DEPRECATED_IBM6000_TARGET.
(bfdsec_to_vmap): Delete.
(exec_files_info): Remove block of code handling VMAP.
* infcmd.c (post_create_inferior): Remove reference to
SOLIB_CREATE_INFERIOR_HOOK and SOLIB_ADD.
* infrun.c (follow_exec): Remove reference to
SOLIB_CREATE_INFERIOR_HOOK.
* stack.c (print_frame): Remove reference to PC_SOLIB.
* solib-dsbt.c (dsbt_current_sos): Adjust comment.
(dsbt_relocate_main_executable): Likewise.
* solib-frv.c (frv_current_sos): Likewise.
2013-05-06 Joel Brobecker <brobecker@adacore.com>
* sol-thread.c (rw_common): Cast BUF to "gdb_byte *" in calls

View File

@ -501,6 +501,7 @@ RUNTESTFLAGS=
# XML files to build in to GDB.
XMLFILES = $(srcdir)/features/gdb-target.dtd $(srcdir)/features/xinclude.dtd \
$(srcdir)/features/library-list.dtd \
$(srcdir)/features/library-list-aix.dtd \
$(srcdir)/features/library-list-svr4.dtd $(srcdir)/features/osdata.dtd \
$(srcdir)/features/threads.dtd $(srcdir)/features/traceframe-info.dtd \
$(srcdir)/features/btrace.dtd
@ -573,7 +574,7 @@ ALL_TARGET_OBS = \
nto-tdep.o \
ppc-linux-tdep.o ppcnbsd-tdep.o ppcobsd-tdep.o ppc-sysv-tdep.o \
ppc64-tdep.o rl78-tdep.o \
rs6000-aix-tdep.o rs6000-tdep.o ppc-ravenscar-thread.o \
rs6000-aix-tdep.o rs6000-tdep.o solib-aix.o ppc-ravenscar-thread.o \
rs6000-lynx178-tdep.o \
rx-tdep.o \
s390-tdep.o \
@ -805,7 +806,7 @@ target.h prologue-value.h cp-abi.h tui/tui-hooks.h tui/tui.h \
tui/tui-file.h tui/tui-command.h tui/tui-disasm.h tui/tui-wingeneral.h \
tui/tui-windata.h tui/tui-data.h tui/tui-win.h tui/tui-stack.h \
tui/tui-winsource.h tui/tui-regs.h tui/tui-io.h tui/tui-layout.h \
tui/tui-source.h xcoffsolib.h sol2-tdep.h gregset.h sh-tdep.h sh64-tdep.h \
tui/tui-source.h sol2-tdep.h gregset.h sh-tdep.h sh64-tdep.h \
expression.h score-tdep.h gdb_select.h ser-tcp.h buildsym.h valprint.h \
typeprint.h mi/mi-getopt.h mi/mi-parse.h mi/mi-console.h \
mi/mi-out.h mi/mi-main.h mi/mi-common.h mi/mi-cmds.h linux-nat.h \
@ -824,7 +825,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 \
@ -836,7 +837,7 @@ dicos-tdep.h filesystem.h gcore.h gdb_wchar.h hppabsd-tdep.h \
i386-darwin-tdep.h i386-nat.h linux-record.h moxie-tdep.h \
osdata.h procfs.h python/py-event.h python/py-events.h python/py-stopevent.h \
python/python-internal.h python/python.h ravenscar-thread.h record.h \
record-full.h \
record-full.h solib-aix.h \
solib-darwin.h solib-ia64-hpux.h solib-spu.h windows-nat.h xcoffread.h \
gnulib/import/extra/snippet/arg-nonnull.h gnulib/import/extra/snippet/c++defs.h \
gnulib/import/extra/snippet/warn-on-use.h \
@ -1528,7 +1529,7 @@ ALLDEPFILES = \
remote-sim.c \
dcache.c \
rl78-tdep.c \
rs6000-nat.c rs6000-tdep.c ppc-ravenscar-thread.c \
rs6000-nat.c rs6000-tdep.c solib-aix.c ppc-ravenscar-thread.c \
rs6000-lynx178-tdep.c \
rx-tdep.c \
s390-tdep.c s390-nat.c \
@ -1549,7 +1550,7 @@ ALLDEPFILES = \
v850-tdep.c \
vax-nat.c vax-tdep.c vaxbsd-nat.c vaxnbsd-tdep.c \
windows-nat.c windows-tdep.c \
xcoffread.c xcoffsolib.c \
xcoffread.c \
xstormy16-tdep.c \
xtensa-tdep.c xtensa-config.c \
xtensa-linux-tdep.c xtensa-linux-nat.c xtensa-xtregs.c

View File

@ -5367,11 +5367,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 ();
}
@ -7417,11 +7413,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;
@ -13077,7 +13069,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. */
}

View File

@ -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.

View File

@ -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

View File

@ -419,7 +419,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*)

View File

@ -467,24 +467,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.

View File

@ -1,3 +1,9 @@
2013-05-06 Joel Brobecker <brobecker@adacore.com>
* gdbint.texinfo (Algorithms): Remove entries documenting
DEPRECATED_IBM6000_TARGET, SOLIB_ADD, and
SOLIB_CREATE_INFERIOR_HOOK.
2013-04-29 Tom Tromey <tromey@redhat.com>
PR python/14204:

View File

@ -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

View File

@ -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 (void)
{
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
@ -506,62 +467,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) *
@ -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

View File

@ -0,0 +1,18 @@
<!-- Copyright (C) 2013 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!-- library-list: Root element with versioning -->
<!ELEMENT library-list (library)*>
<!ATTLIST library-list version CDATA #FIXED "1.0">
<!ELEMENT library (name, member, text_addr, text_size, data_addr, data_size)>
<!ATTLIST library name CDATA #REQUIRED>
<!ATTLIST library member CDATA #REQUIRED>
<!ATTLIST library text_addr CDATA #REQUIRED>
<!ATTLIST library text_size CDATA #REQUIRED>
<!ATTLIST library data_addr CDATA #REQUIRED>
<!ATTLIST library data_size CDATA #REQUIRED>

View File

@ -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);
}
}

View File

@ -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 ();

View File

@ -36,12 +36,8 @@
#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 "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
@ -412,13 +408,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;
@ -793,6 +785,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. */

View File

@ -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) */
@ -58,6 +57,7 @@
#define __LDINFO_PTRACE64__ /* for __ld_info64 */
#include <sys/ldr.h>
#include <sys/systemcfg.h>
#include "xml-utils.h"
/* On AIX4.3+, sys/ldr.h provides different versions of struct ld_info for
debugging 32-bit and 64-bit processes. Define a typedef and macros for
@ -118,20 +118,13 @@ 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 *);
static LONGEST rs6000_xfer_shared_libraries
(struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, LONGEST len);
/* Given REGNO, a gdb register number, return the corresponding
number suitable for use as a ptrace() parameter. Return -1 if
there's no suitable mapping. Also, set the int pointed to by
@ -431,6 +424,10 @@ rs6000_xfer_partial (struct target_ops *ops, enum target_object object,
switch (object)
{
case TARGET_OBJECT_AIX_LIBRARIES:
return rs6000_xfer_shared_libraries (ops, object, annex,
readbuf, writebuf,
offset, len);
case TARGET_OBJECT_MEMORY:
{
union
@ -621,431 +618,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. */
@ -1101,195 +673,209 @@ 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)
/* Shared Object support. */
/* Return the LdInfo data for the given process. Raises an error
if the data could not be obtained.
The returned value must be deallocated after use. */
static LdInfo *
rs6000_ptrace_ldinfo (ptid_t ptid)
{
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;
const int pid = ptid_get_pid (ptid);
int ldi_size = 1024;
LdInfo *ldi = xmalloc (ldi_size);
int rc = -1;
/* Nothing to do if we are debugging a core file. */
if (!target_has_execution)
return;
do
while (1)
{
size = load_segs * ldisize;
ldi = (void *) xrealloc (ldi, size);
#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 (arch64)
rc = rs6000_ptrace64 (PT_LDINFO, pid, (unsigned long) ldi, size, NULL);
if (ARCH64 ())
rc = rs6000_ptrace64 (PT_LDINFO, pid, (unsigned long) ldi, ldi_size,
NULL);
else
rc = rs6000_ptrace32 (PT_LDINFO, pid, (int *) ldi, size, NULL);
rc = rs6000_ptrace32 (PT_LDINFO, pid, (int *) ldi, 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);
if (rc != -1)
break; /* Success, we got the entire ld_info data. */
if (errno != ENOMEM)
perror_with_name (_("ptrace ldinfo"));
/* ldi is not big enough. Double it and try again. */
ldi_size *= 2;
ldi = xrealloc (ldi, ldi_size);
}
return ldi;
}
/* Core file stuff. */
/* Relocate symtabs and read in shared library info, based on symbols
from the core file. */
/* Assuming ABFD refers to a core file, return the LdInfo data
stored in that core file. Raises an error if the data could
not be read or extracted.
void
xcoff_relocate_core (struct target_ops *target)
The returned value much be deallocated after use. */
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;
error (_("cannot find .ldinfo section from core file: %s\n"),
bfd_errmsg (bfd_get_error ()));
ldinfo_size = bfd_get_section_size (ldinfo_sec);
/* Read in everything but the name. */
if (bfd_get_section_contents (core_bfd, ldinfo_sec, buffer,
offset, nonfilesz) == 0)
goto bfd_err;
ldinfo_buf = xmalloc (ldinfo_size);
cleanup = make_cleanup (xfree, ldinfo_buf);
/* 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);
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 ()));
ldi = (LdInfo *) buffer;
/* 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;
/* The first ldinfo is for the exec file, allocated elsewhere. */
if (offset == 0 && vmap != NULL)
vp = vmap;
else
vp = add_vmap (ldi);
/* Process next shared library upon error. */
offset += LDI_NEXT (ldi, arch64);
if (vp == NULL)
continue;
vmap_secs (vp, ldi, arch64);
/* Unless this is the exec file,
add our sections to the section table for the core target. */
if (vp != vmap)
{
struct target_section *stp;
stp = deprecated_core_resize_section_table (2);
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++;
stp->bfd = vp->bfd;
stp->the_bfd_section = bfd_get_section_by_name (stp->bfd, ".data");
stp->addr = vp->dstart;
stp->endaddr = vp->dend;
}
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);
discard_cleanups (cleanup);
return (LdInfo *) ldinfo_buf;
}
/* 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)
/* Append to OBJSTACK an XML string description of the shared library
corresponding to LDI, following the TARGET_OBJECT_AIX_LIBRARIES
format. */
static void
rs6000_xfer_shared_library (LdInfo *ldi, struct obstack *obstack)
{
struct vmap *vp;
const int arch64 = ARCH64 ();
const char *archive_name = LDI_FILENAME (ldi, arch64);
const char *member_name = archive_name + strlen (archive_name) + 1;
CORE_ADDR text_addr, data_addr;
ULONGEST text_size, data_size;
char *p;
for (vp = vmap; vp; vp = vp->nxt)
if (arch64)
{
if (pc >= vp->tstart && pc < vp->tend)
{
/* vp->objfile is only NULL for the exec file. */
return vp->dstart + xcoff_get_toc_offset (vp->objfile == NULL
? symfile_objfile
: vp->objfile);
}
text_addr = ldi->l64.ldinfo_textorg;
text_size = ldi->l64.ldinfo_textsize;
data_addr = ldi->l64.ldinfo_dataorg;
data_size = ldi->l64.ldinfo_datasize;
}
error (_("Unable to find TOC entry for pc %s."), hex_string (pc));
else
{
/* The text and data addresses are defined as pointers.
To avoid sign-extending their value in the assignments
below, we cast their value to unsigned long first. */
text_addr = (unsigned long) ldi->l32.ldinfo_textorg;
text_size = ldi->l32.ldinfo_textsize;
data_addr = (unsigned long) ldi->l32.ldinfo_dataorg;
data_size = ldi->l32.ldinfo_datasize;
}
obstack_grow_str (obstack, "<library name=\"");
p = xml_escape_text (archive_name);
obstack_grow_str (obstack, p);
xfree (p);
obstack_grow_str (obstack, "\"");
if (member_name[0] != '\0')
{
obstack_grow_str (obstack, " member=\"");
p = xml_escape_text (member_name);
obstack_grow_str (obstack, p);
xfree (p);
obstack_grow_str (obstack, "\"");
}
obstack_grow_str (obstack, " text_addr=\"");
obstack_grow_str (obstack, core_addr_to_string (text_addr));
obstack_grow_str (obstack, "\"");
obstack_grow_str (obstack, " text_size=\"");
obstack_grow_str (obstack, pulongest (text_size));
obstack_grow_str (obstack, "\"");
obstack_grow_str (obstack, " data_addr=\"");
obstack_grow_str (obstack, core_addr_to_string (data_addr));
obstack_grow_str (obstack, "\"");
obstack_grow_str (obstack, " data_size=\"");
obstack_grow_str (obstack, pulongest (data_size));
obstack_grow_str (obstack, "\"");
obstack_grow_str (obstack, "></library>");
}
/* Implement the to_xfer_partial target_ops method for
TARGET_OBJECT_AIX_LIBRARIES objects. */
static LONGEST
rs6000_xfer_shared_libraries
(struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, LONGEST len)
{
const int arch64 = ARCH64 ();
LdInfo *ldi_data;
LdInfo *ldi;
struct obstack obstack;
const char *buf;
LONGEST len_avail;
if (writebuf)
return -1;
/* 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. */
if (target_has_execution)
ldi_data = rs6000_ptrace_ldinfo (inferior_ptid);
else
ldi_data = rs6000_core_ldinfo (core_bfd);
/* Convert the raw data into an XML representation. */
obstack_init (&obstack);
obstack_grow_str (&obstack, "<library-list version=\"1.0\">\n");
ldi = ldi_data;
while (1)
{
/* 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));
rs6000_xfer_shared_library (ldi, &obstack);
if (!LDI_NEXT (ldi, arch64))
break;
ldi = (LdInfo *) ((char *) ldi + LDI_NEXT (ldi, arch64));
}
xfree (ldi_data);
obstack_grow_str0 (&obstack, "</library-list>\n");
buf = obstack_finish (&obstack);
len_avail = strlen (buf);
if (offset >= len_avail)
len= 0;
else
{
if (len > len_avail - offset)
len = len_avail - offset;
memcpy (readbuf, buf + offset, len);
}
obstack_free (&obstack, NULL);
return len;
}
void _initialize_rs6000_nat (void);
@ -1309,8 +895,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;
}

View File

@ -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

830
gdb/solib-aix.c Normal file
View File

@ -0,0 +1,830 @@
/* 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"
#include "observer.h"
#include "gdbcmd.h"
/* Variable controlling the output of the debugging traces for
this module. */
static int solib_aix_debug;
/* Our private data in struct so_list. */
struct lm_info
{
/* The name of the file mapped by the loader. Apart from the entry
for the main executable, this is usually a shared library (which,
on AIX, is an archive library file, created using the "ar"
command). */
char *filename;
/* The name of the shared object file with the actual dynamic
loading dependency. This may be NULL (Eg. main executable). */
char *member_name;
/* The address in inferior memory where the text section got mapped. */
CORE_ADDR text_addr;
/* The size of the text section, obtained via the loader data. */
ULONGEST text_size;
/* The address in inferior memory where the data section got mapped. */
CORE_ADDR data_addr;
/* The size of the data section, obtained via the loader data. */
ULONGEST data_size;
};
typedef struct lm_info *lm_info_p;
DEF_VEC_P(lm_info_p);
/* Return a deep copy of the given struct lm_info object. */
static struct lm_info *
solib_aix_new_lm_info (struct lm_info *info)
{
struct lm_info *result = xmalloc (sizeof (struct lm_info));
memcpy (result, info, sizeof (struct lm_info));
result->filename = xstrdup (info->filename);
if (info->member_name != NULL)
result->member_name = xstrdup (info->member_name);
return result;
}
/* Free the memory allocated for the given lm_info. */
static void
solib_aix_xfree_lm_info (struct lm_info *info)
{
xfree (info->filename);
xfree (info->member_name);
xfree (info);
}
/* This module's per-inferior data. */
struct solib_aix_inferior_data
{
/* The list of shared libraries. NULL if not computed yet.
Note that the first element of this list is always the main
executable, which is not technically a shared library. But
we need that information to perform its relocation, and
the same principles applied to shared libraries also apply
to the main executable. So it's simpler to keep it as part
of this list. */
VEC (lm_info_p) *library_list;
};
/* Key to our per-inferior data. */
static const struct inferior_data *solib_aix_inferior_data_handle;
/* Return this module's data for the given inferior.
If none is found, add a zero'ed one now. */
static struct solib_aix_inferior_data *
get_solib_aix_inferior_data (struct inferior *inf)
{
struct solib_aix_inferior_data *data;
data = inferior_data (inf, solib_aix_inferior_data_handle);
if (data == NULL)
{
data = XZALLOC (struct solib_aix_inferior_data);
set_inferior_data (inf, solib_aix_inferior_data_handle, data);
}
return data;
}
#if !defined(HAVE_LIBEXPAT)
/* Dummy implementation if XML support is not compiled in. */
static VEC (lm_info_p) *
solib_aix_parse_libraries (const char *library)
{
static int have_warned;
if (!have_warned)
{
have_warned = 1;
warning (_("Can not parse XML library list; XML support was disabled "
"at compile time"));
}
return NULL;
}
#else /* HAVE_LIBEXPAT */
#include "xml-support.h"
/* Handle the start of a <library> element. */
static void
library_list_start_library (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
void *user_data,
VEC (gdb_xml_value_s) *attributes)
{
VEC (lm_info_p) **list = user_data;
struct lm_info *item = XZALLOC (struct lm_info);
struct gdb_xml_value *attr;
attr = xml_find_attribute (attributes, "name");
item->filename = xstrdup (attr->value);
attr = xml_find_attribute (attributes, "member");
if (attr != NULL)
item->member_name = xstrdup (attr->value);
attr = xml_find_attribute (attributes, "text_addr");
item->text_addr = * (ULONGEST *) attr->value;
attr = xml_find_attribute (attributes, "text_size");
item->text_size = * (ULONGEST *) attr->value;
attr = xml_find_attribute (attributes, "data_addr");
item->data_addr = * (ULONGEST *) attr->value;
attr = xml_find_attribute (attributes, "data_size");
item->data_size = * (ULONGEST *) attr->value;
VEC_safe_push (lm_info_p, *list, item);
}
/* Handle the start of a <library-list> element. */
static void
library_list_start_list (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
void *user_data, VEC (gdb_xml_value_s) *attributes)
{
char *version = xml_find_attribute (attributes, "version")->value;
if (strcmp (version, "1.0") != 0)
gdb_xml_error (parser,
_("Library list has unsupported version \"%s\""),
version);
}
/* Discard the constructed library list. */
static void
solib_aix_free_library_list (void *p)
{
VEC (lm_info_p) **result = p;
struct lm_info *info;
int ix;
if (solib_aix_debug)
fprintf_unfiltered (gdb_stdlog, "DEBUG: solib_aix_free_library_list\n");
for (ix = 0; VEC_iterate (lm_info_p, *result, ix, info); ix++)
solib_aix_xfree_lm_info (info);
VEC_free (lm_info_p, *result);
*result = NULL;
}
/* The allowed elements and attributes for an AIX library list
described in XML format. The root element is a <library-list>. */
static const struct gdb_xml_attribute library_attributes[] =
{
{ "name", GDB_XML_AF_NONE, NULL, NULL },
{ "member", GDB_XML_AF_OPTIONAL, NULL, NULL },
{ "text_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
{ "text_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
{ "data_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
{ "data_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
static const struct gdb_xml_element library_list_children[] =
{
{ "library", library_attributes, NULL,
GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
library_list_start_library, NULL},
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};
static const struct gdb_xml_attribute library_list_attributes[] =
{
{ "version", GDB_XML_AF_NONE, NULL, NULL },
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
static const struct gdb_xml_element library_list_elements[] =
{
{ "library-list", library_list_attributes, library_list_children,
GDB_XML_EF_NONE, library_list_start_list, NULL },
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};
/* Parse LIBRARY, a string containing the loader info in XML format,
and return an lm_info_p vector.
Return NULL if the parsing failed. */
static VEC (lm_info_p) *
solib_aix_parse_libraries (const char *library)
{
VEC (lm_info_p) *result = NULL;
struct cleanup *back_to = make_cleanup (solib_aix_free_library_list,
&result);
if (gdb_xml_parse_quick (_("aix library list"), "library-list-aix.dtd",
library_list_elements, library, &result) == 0)
{
/* Parsed successfully, keep the result. */
discard_cleanups (back_to);
return result;
}
do_cleanups (back_to);
return NULL;
}
#endif /* HAVE_LIBEXPAT */
/* Return the loader info for the given inferior (INF), or NULL if
the list could not be computed.
Cache the result in per-inferior data, so as to avoid recomputing it
each time this function is called.
If an error occurs while computing this list, and WARNING_MSG
is not NULL, then print a warning including WARNING_MSG and
a description of the error. */
static VEC (lm_info_p) *
solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
{
struct solib_aix_inferior_data *data;
char *library_document;
struct cleanup *cleanup;
/* If already computed, return the cached value. */
data = get_solib_aix_inferior_data (inf);
if (data->library_list != NULL)
return data->library_list;
library_document = target_read_stralloc (&current_target,
TARGET_OBJECT_AIX_LIBRARIES,
NULL);
if (library_document == NULL && warning_msg != NULL)
{
warning (_("%s (failed to read TARGET_OBJECT_AIX_LIBRARIES)"),
warning_msg);
return NULL;
}
cleanup = make_cleanup (xfree, library_document);
if (solib_aix_debug)
fprintf_unfiltered (gdb_stdlog,
"DEBUG: TARGET_OBJECT_AIX_LIBRARIES = \n%s\n",
library_document);
data->library_list = solib_aix_parse_libraries (library_document);
if (data->library_list == NULL && warning_msg != NULL)
{
warning (_("%s (missing XML support?)"), warning_msg);
do_cleanups (cleanup);
return NULL;
}
do_cleanups (cleanup);
return data->library_list;
}
/* 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 lm_info *info = so->lm_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)
{
if (solib_aix_debug)
fprintf_unfiltered (gdb_stdlog, "DEBUG: solib_aix_free_so (%s)\n",
so->so_name);
solib_aix_xfree_lm_info (so->lm_info);
}
/* Implement the "clear_solib" target_so_ops method. */
static void
solib_aix_clear_solib (void)
{
/* Nothing needed. */
}
/* Compute and return the OBJFILE's section_offset array, using
the associated loader info (INFO).
The resulting array is computed on the heap and must be
deallocated after use. */
static struct section_offsets *
solib_aix_get_section_offsets (struct objfile *objfile,
struct lm_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);
}
/* .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)
{
const char *warning_msg = "unable to relocate main executable";
VEC (lm_info_p) *library_list;
struct lm_info *exec_info;
/* We need to relocate the main executable... */
library_list = solib_aix_get_library_list (current_inferior (),
warning_msg);
if (library_list == NULL)
return; /* Warning already printed. */
if (VEC_length (lm_info_p, library_list) < 1)
{
warning (_("unable to relocate main executable (no info from loader)"));
return;
}
exec_info = VEC_index (lm_info_p, library_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)
{
struct so_list *start = NULL, *last = NULL;
VEC (lm_info_p) *library_list;
struct lm_info *info;
int ix;
library_list = solib_aix_get_library_list (current_inferior (), NULL);
if (library_list == NULL)
return NULL;
/* Build a struct so_list for each entry on the list.
We skip the first entry, since this is the entry corresponding
to the main executable, not a shared library. */
for (ix = 1; VEC_iterate (lm_info_p, library_list, ix, info); ix++)
{
struct so_list *new_solib = XZALLOC (struct so_list);
char *so_name;
if (info->member_name == NULL)
{
/* INFO->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->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->filename, info->member_name);
}
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);
new_solib->lm_info = solib_aix_new_lm_info (info);
/* Add it to the list. */
if (!start)
last = start = new_solib;
else
{
last->next = new_solib;
last = new_solib;
}
}
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);
char *sep;
char *filename;
int filename_len;
char *member_name;
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. */
sep = strrchr (pathname, '(');
if (sep == NULL)
{
/* 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 (_("missing '(' in shared object pathname: %s"), pathname);
return solib_bfd_open (pathname);
}
filename_len = sep - pathname;
filename = xstrprintf ("%.*s", filename_len, pathname);
make_cleanup (xfree, filename);
member_name = xstrprintf ("%.*s", path_len - filename_len - 2, sep + 1);
make_cleanup (xfree, member_name);
archive_bfd = gdb_bfd_open (filename, gnutarget, -1);
if (archive_bfd == NULL)
{
warning (_("Could not open `%s' as an executable file: %s"),
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."),
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 (member_name, 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."), filename, member_name);
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."),
filename, member_name, 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;
}
/* Return the obj_section corresponding to OBJFILE's data section,
or NULL if not found. */
/* 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;
}
/* Return the TOC value corresponding to the given PC address,
or raise an error if the value could not be determined. */
CORE_ADDR
solib_aix_get_toc_value (CORE_ADDR pc)
{
struct obj_section *pc_osect = find_pc_section (pc);
struct obj_section *data_osect;
CORE_ADDR result;
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);
result = (obj_section_addr (data_osect)
+ xcoff_get_toc_offset (pc_osect->objfile));
if (solib_aix_debug)
fprintf_unfiltered (gdb_stdlog,
"DEBUG: solib_aix_get_toc_value (pc=%s) -> %s\n",
core_addr_to_string (pc),
core_addr_to_string (result));
return result;
}
/* This module's normal_stop observer. */
static void
solib_aix_normal_stop_observer (struct bpstats *unused_1, int unused_2)
{
struct solib_aix_inferior_data *data
= get_solib_aix_inferior_data (current_inferior ());
/* The inferior execution has been resumed, and it just stopped
again. This means that the list of shared libraries may have
evolved. Reset our cached value. */
solib_aix_free_library_list (&data->library_list);
}
/* Implements the "show debug aix-solib" command. */
static void
show_solib_aix_debug (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("solib-aix debugging is %s.\n"), value);
}
/* 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;
solib_aix_inferior_data_handle = register_inferior_data ();
observer_attach_normal_stop (solib_aix_normal_stop_observer);
/* Debug this file's internals. */
add_setshow_boolean_cmd ("aix-solib", class_maintenance,
&solib_aix_debug, _("\
Control the debugging traces for the solib-aix module."), _("\
Show whether solib-aix debugging traces are enabled."), _("\
When on, solib-aix debugging traces are enabled."),
NULL,
show_solib_aix_debug,
&setdebuglist, &showdebuglist);
}

26
gdb/solib-aix.h Normal file
View File

@ -0,0 +1,26 @@
/* 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;
extern CORE_ADDR solib_aix_get_toc_value (CORE_ADDR pc);
#endif

View File

@ -647,11 +647,11 @@ dsbt_current_sos (void)
for details.)
Note that the relocation of the main executable is also performed
by SOLIB_CREATE_INFERIOR_HOOK, however, in the case of core
by solib_create_inferior_hook, however, in the case of core
files, this hook is called too late in order to be of benefit to
SOLIB_ADD. SOLIB_ADD eventually calls this function,
solib_add. solib_add eventually calls this function,
dsbt_current_sos, and also precedes the call to
SOLIB_CREATE_INFERIOR_HOOK. (See post_create_inferior in
solib_create_inferior_hook. (See post_create_inferior in
infcmd.c.) */
if (info->main_executable_lm_info == 0 && core_bfd != NULL)
dsbt_relocate_main_executable ();
@ -1089,12 +1089,10 @@ dsbt_relocate_main_executable (void)
/* When gdb starts up the inferior, it nurses it along (through the
shell) until it is ready to execute it's first instruction. At this
point, this function gets called via expansion of the macro
SOLIB_CREATE_INFERIOR_HOOK.
point, this function gets called via solib_create_inferior_hook.
For the DSBT shared library, the main executable needs to be relocated.
The shared library breakpoints also need to be enabled.
*/
The shared library breakpoints also need to be enabled. */
static void
dsbt_solib_create_inferior_hook (int from_tty)

View File

@ -328,11 +328,11 @@ frv_current_sos (void)
for details.)
Note that the relocation of the main executable is also performed
by SOLIB_CREATE_INFERIOR_HOOK(), however, in the case of core
by solib_create_inferior_hook(), however, in the case of core
files, this hook is called too late in order to be of benefit to
SOLIB_ADD. SOLIB_ADD eventually calls this this function,
solib_add. solib_add eventually calls this this function,
frv_current_sos, and also precedes the call to
SOLIB_CREATE_INFERIOR_HOOK(). (See post_create_inferior() in
solib_create_inferior_hook(). (See post_create_inferior() in
infcmd.c.) */
if (main_executable_lm_info == 0 && core_bfd != NULL)
frv_relocate_main_executable ();

View File

@ -1294,11 +1294,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

View File

@ -1205,12 +1205,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 ();

View File

@ -261,6 +261,8 @@ enum target_object
TARGET_OBJECT_LIBRARIES,
/* Currently loaded libraries specific for SVR4 systems, in XML format. */
TARGET_OBJECT_LIBRARIES_SVR4,
/* Currently loaded libraries specific to AIX systems, in XML format. */
TARGET_OBJECT_AIX_LIBRARIES,
/* Get OS specific data. The ANNEX specifies the type (running
processes, etc.). The data being transfered is expected to follow
the DTD specified in features/osdata.dtd. */

View File

@ -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. */
@ -922,9 +927,12 @@ record_minimal_symbol (const char *name, CORE_ADDR address,
int n_scnum,
struct objfile *objfile)
{
int section = secnum_to_section (n_scnum, objfile);
if (name[0] == '.')
++name;
address += ANOFFSET (objfile->section_offsets, section);
prim_record_minimal_symbol_and_info (name, address, ms_type,
secnum_to_section (n_scnum, objfile),
objfile);
@ -2339,11 +2347,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),
objfile);
symbol.n_scnum, objfile);
break;
case XMC_TC0:
@ -2416,11 +2423,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),
objfile);
symbol.n_scnum, objfile);
break;
}
break;
@ -2433,11 +2439,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),
objfile);
symbol.n_scnum, objfile);
break;
}
break;
@ -3035,44 +3040,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. */

View File

@ -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);
}

View File

@ -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