* infrun.c (IN_SOLIB_TRAMPOLINE): Correct comment, trampolines
are in the .plt section. * minsyms.c (lookup_solib_trampoline_symbol_by_pc, find_solib_trampoline_target): New functions for handling stepping into -g compiled shared libraries. * symtab.h (lookup_solib_trampoline_symbol_by_pc, find_solib_trampoline_target): Add prototypes. * config/tm-sunos.h (IN_SOLIB_TRAMPOLINE, SKIP_TRAMPOLINE_CODE): Define to handle stepping into -g compiled shared libraries. * config/tm-sysv4.h (SKIP_TRAMPOLINE_CODE): Define to handle stepping into -g compiled shared libraries. * configure.in: Add mips-*-sysv4* support. * config/mips/mipsv4.mh, config/mips/mipsv4.mt, config/mips/tm-mipsv4.h, config/mips/xm-mipsv4.h, mipsv4-nat.c: New files for MIPS SVR4 support. * Makefile.in: Update for new mipsv4 files. * alpha-tdep.c (heuristic_proc_desc, find_proc_desc): Use read_next_frame_reg to obtain the frame relative stack pointer. * mips-tdep.c (heuristic_proc_desc): Use read_next_frame_reg to obtain the frame relative stack pointer. * mdebugread.c (parse_partial_symbols, psymtab_to_symtab1): Handle stStatic and stStaticProc symbols in stabs-in-ecoff output by entering them into the minimal symbol table. * printcmd.c (print_scalar_formatted): Do not try to unpack to a long for float formats. * solib.c: Include "elf/mips.h" only if DT_MIPS_RLD_MAP does not get defined in <link.h>. * solib.c (solib_add): Add shared library sections to the section table of the target before adding the symbols. * partial-stab.h: Relocate static and global functions. * dbxread.c (read_dbx_symtab): Remove unused variable end_of_text_address. Relocate text_addr when passing it to end_psymtab. For Alpha OSF/1 targets, enable gdb to set breakpoints in shared library functions before the executable is run. Retrieve dynamic symbols from stripped executables. * mipsread.c (read_alphacoff_dynamic_symtab): New function. * mipsread.c (mipscoff_symfile_read): Use it. Issue warning message if no debugging symbols were found. * alpha-tdep.c (alpha_skip_prologue): Silently return the unaltered pc if memory at the pc is not accessible and GDB_TARGET_HAS_SHARED_LIBS is defined. * config/alpha/nm-alpha.h (GDB_TARGET_HAS_SHARED_LIBS): Define, OSF/1 has shared libraries.
This commit is contained in:
parent
44c1515dc7
commit
2fe3b329f6
14 changed files with 772 additions and 225 deletions
|
@ -203,6 +203,7 @@ mips-nat.c
|
|||
mips-pinsn.c
|
||||
mips-tdep.c
|
||||
mipsm3-nat.c
|
||||
mipsv4-nat.c
|
||||
mipsread.c
|
||||
monitor.h
|
||||
news-xdep.c
|
||||
|
|
|
@ -1,3 +1,55 @@
|
|||
Thu Apr 7 17:25:21 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
|
||||
Jim Kingdon (kingdon@cygnus.com)
|
||||
|
||||
* infrun.c (IN_SOLIB_TRAMPOLINE): Correct comment, trampolines
|
||||
are in the .plt section.
|
||||
* minsyms.c (lookup_solib_trampoline_symbol_by_pc,
|
||||
find_solib_trampoline_target): New functions for handling
|
||||
stepping into -g compiled shared libraries.
|
||||
* symtab.h (lookup_solib_trampoline_symbol_by_pc,
|
||||
find_solib_trampoline_target): Add prototypes.
|
||||
* config/tm-sunos.h (IN_SOLIB_TRAMPOLINE, SKIP_TRAMPOLINE_CODE):
|
||||
Define to handle stepping into -g compiled shared libraries.
|
||||
* config/tm-sysv4.h (SKIP_TRAMPOLINE_CODE): Define to handle
|
||||
stepping into -g compiled shared libraries.
|
||||
|
||||
Thu Apr 7 17:22:54 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
|
||||
|
||||
* configure.in: Add mips-*-sysv4* support.
|
||||
* config/mips/mipsv4.mh, config/mips/mipsv4.mt,
|
||||
config/mips/tm-mipsv4.h, config/mips/xm-mipsv4.h, mipsv4-nat.c:
|
||||
New files for MIPS SVR4 support.
|
||||
* Makefile.in: Update for new mipsv4 files.
|
||||
* alpha-tdep.c (heuristic_proc_desc, find_proc_desc): Use
|
||||
read_next_frame_reg to obtain the frame relative stack pointer.
|
||||
* mips-tdep.c (heuristic_proc_desc): Use read_next_frame_reg to
|
||||
obtain the frame relative stack pointer.
|
||||
* mdebugread.c (parse_partial_symbols, psymtab_to_symtab1):
|
||||
Handle stStatic and stStaticProc symbols in stabs-in-ecoff output
|
||||
by entering them into the minimal symbol table.
|
||||
* printcmd.c (print_scalar_formatted): Do not try to unpack to
|
||||
a long for float formats.
|
||||
* solib.c: Include "elf/mips.h" only if DT_MIPS_RLD_MAP does not
|
||||
get defined in <link.h>.
|
||||
* solib.c (solib_add): Add shared library sections to the section
|
||||
table of the target before adding the symbols.
|
||||
* partial-stab.h: Relocate static and global functions.
|
||||
* dbxread.c (read_dbx_symtab): Remove unused variable
|
||||
end_of_text_address. Relocate text_addr when passing it
|
||||
to end_psymtab.
|
||||
|
||||
For Alpha OSF/1 targets, enable gdb to set breakpoints in shared
|
||||
library functions before the executable is run. Retrieve dynamic
|
||||
symbols from stripped executables.
|
||||
* mipsread.c (read_alphacoff_dynamic_symtab): New function.
|
||||
* mipsread.c (mipscoff_symfile_read): Use it. Issue warning message
|
||||
if no debugging symbols were found.
|
||||
* alpha-tdep.c (alpha_skip_prologue): Silently return the unaltered
|
||||
pc if memory at the pc is not accessible and GDB_TARGET_HAS_SHARED_LIBS
|
||||
is defined.
|
||||
* config/alpha/nm-alpha.h (GDB_TARGET_HAS_SHARED_LIBS): Define,
|
||||
OSF/1 has shared libraries.
|
||||
|
||||
Thu Apr 7 15:11:11 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
|
||||
|
||||
* dbxread.c (read_dbx_dynamic_symtab): Adjust for recent changes
|
||||
|
|
|
@ -329,7 +329,7 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame)
|
|||
CORE_ADDR start_pc, limit_pc;
|
||||
FRAME next_frame;
|
||||
{
|
||||
CORE_ADDR sp = next_frame ? next_frame->frame : read_register (SP_REGNUM);
|
||||
CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
|
||||
CORE_ADDR cur_pc;
|
||||
int frame_size;
|
||||
int has_frame_reg = 0;
|
||||
|
@ -456,7 +456,7 @@ find_proc_desc(pc, next_frame)
|
|||
if (PC_IN_CALL_DUMMY (pc, 0, 0))
|
||||
{
|
||||
struct linked_proc_info *link;
|
||||
CORE_ADDR sp = next_frame ? next_frame->frame : read_register (SP_REGNUM);
|
||||
CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
|
||||
alpha_extra_func_info_t found_proc_desc = NULL;
|
||||
long min_distance = LONG_MAX;
|
||||
|
||||
|
@ -913,6 +913,18 @@ alpha_skip_prologue (pc, lenient)
|
|||
unsigned long inst;
|
||||
int offset;
|
||||
CORE_ADDR post_prologue_pc;
|
||||
char buf[4];
|
||||
|
||||
#ifdef GDB_TARGET_HAS_SHARED_LIBS
|
||||
/* Silently return the unaltered pc upon memory errors.
|
||||
This could happen on OSF/1 if decode_line_1 tries to skip the
|
||||
prologue for quickstarted shared library functions when the
|
||||
shared library is not yet mapped in.
|
||||
Reading target memory is slow over serial lines, so we perform
|
||||
this check only if the target has shared libraries. */
|
||||
if (target_read_memory (pc, buf, 4))
|
||||
return pc;
|
||||
#endif
|
||||
|
||||
/* See if we can determine the end of the prologue via the symbol table.
|
||||
If so, then return either PC, or the PC after the prologue, whichever
|
||||
|
@ -931,7 +943,6 @@ alpha_skip_prologue (pc, lenient)
|
|||
or in the gcc frame. */
|
||||
for (offset = 0; offset < 100; offset += 4)
|
||||
{
|
||||
char buf[4];
|
||||
int status;
|
||||
|
||||
status = read_memory_nobpt (pc + offset, buf, 4);
|
||||
|
|
|
@ -94,6 +94,7 @@ mips-sgi-irix3*) gdb_host=irix3 ;;
|
|||
mips-sgi-irix4*) gdb_host=irix4 ;;
|
||||
mips-sgi-irix5*) gdb_host=irix5 ;;
|
||||
mips-sony-*) gdb_host=news-mips ;;
|
||||
mips-*-sysv4*) gdb_host=mipsv4 ;;
|
||||
mips-*-sysv*) gdb_host=riscos ;;
|
||||
mips-*-riscos*) gdb_host=riscos ;;
|
||||
mips-*-mach*) gdb_host=mipsm3 ;;
|
||||
|
@ -280,6 +281,7 @@ mips*-little-*) gdb_target=littlemips ;;
|
|||
mips*-sgi-irix5*) gdb_target=irix5 ;;
|
||||
mips*-sgi-*) gdb_target=irix3 ;;
|
||||
mips*-sony-*) gdb_target=bigmips ;;
|
||||
mips*-*-sysv4*) gdb_target=mipsv4 ;;
|
||||
mips*-*-sysv*) gdb_target=bigmips ;;
|
||||
mips*-*-riscos*) gdb_target=bigmips ;;
|
||||
mips*-*-mach*) gdb_target=mipsm3 ;;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Read dbx symbol tables and convert to internal format, for GDB.
|
||||
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993
|
||||
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
@ -984,9 +984,6 @@ read_dbx_symtab (section_offsets, objfile, text_addr, text_size)
|
|||
struct cleanup *back_to;
|
||||
bfd *abfd;
|
||||
|
||||
/* End of the text segment of the executable file. */
|
||||
CORE_ADDR end_of_text_addr;
|
||||
|
||||
/* Current partial symtab */
|
||||
struct partial_symtab *pst;
|
||||
|
||||
|
@ -1100,7 +1097,8 @@ read_dbx_symtab (section_offsets, objfile, text_addr, text_size)
|
|||
end_psymtab (pst, psymtab_include_list, includes_used,
|
||||
symnum * symbol_size,
|
||||
(lowest_text_address == (CORE_ADDR)-1
|
||||
? text_addr : lowest_text_address)
|
||||
? (text_addr + section_offsets->offsets[SECT_OFF_TEXT])
|
||||
: lowest_text_address)
|
||||
+ text_size,
|
||||
dependency_list, dependencies_used);
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ hook_stop_stub PARAMS ((char *));
|
|||
#endif
|
||||
|
||||
/* For SVR4 shared libraries, each call goes through a small piece of
|
||||
trampoline code in the ".init" section. IN_SOLIB_TRAMPOLINE evaluates
|
||||
trampoline code in the ".plt" section. IN_SOLIB_TRAMPOLINE evaluates
|
||||
to nonzero if we are current stopped in one of these. */
|
||||
#ifndef IN_SOLIB_TRAMPOLINE
|
||||
#define IN_SOLIB_TRAMPOLINE(pc,name) 0
|
||||
|
@ -1714,7 +1714,7 @@ signals_info (signum_exp, from_tty)
|
|||
|
||||
printf_filtered ("\n");
|
||||
/* These ugly casts brought to you by the native VAX compiler. */
|
||||
for (oursig = 0;
|
||||
for (oursig = TARGET_SIGNAL_FIRST;
|
||||
(int)oursig < (int)TARGET_SIGNAL_LAST;
|
||||
oursig = (enum target_signal)((int)oursig + 1))
|
||||
{
|
||||
|
|
|
@ -2332,6 +2332,16 @@ parse_partial_symbols (objfile, section_offsets)
|
|||
long isym;
|
||||
|
||||
sh.value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
|
||||
if (sh.st == stStaticProc)
|
||||
{
|
||||
namestring = debug_info->ss + fh->issBase + sh.iss;
|
||||
prim_record_minimal_symbol_and_info (namestring,
|
||||
sh.value,
|
||||
mst_file_text,
|
||||
NULL,
|
||||
SECT_OFF_TEXT,
|
||||
objfile);
|
||||
}
|
||||
procaddr = sh.value;
|
||||
|
||||
isym = AUX_GET_ISYM (fh->fBigendian,
|
||||
|
@ -2350,6 +2360,42 @@ parse_partial_symbols (objfile, section_offsets)
|
|||
pst->texthigh = high;
|
||||
}
|
||||
}
|
||||
else if (sh.st == stStatic)
|
||||
{
|
||||
switch (sh.sc)
|
||||
{
|
||||
case scUndefined:
|
||||
case scNil:
|
||||
case scAbs:
|
||||
break;
|
||||
|
||||
case scData:
|
||||
case scSData:
|
||||
case scRData:
|
||||
case scPData:
|
||||
case scXData:
|
||||
namestring = debug_info->ss + fh->issBase + sh.iss;
|
||||
sh.value += ANOFFSET (section_offsets, SECT_OFF_DATA);
|
||||
prim_record_minimal_symbol_and_info (namestring,
|
||||
sh.value,
|
||||
mst_file_data,
|
||||
NULL,
|
||||
SECT_OFF_DATA,
|
||||
objfile);
|
||||
break;
|
||||
|
||||
default:
|
||||
namestring = debug_info->ss + fh->issBase + sh.iss;
|
||||
sh.value += ANOFFSET (section_offsets, SECT_OFF_BSS);
|
||||
prim_record_minimal_symbol_and_info (namestring,
|
||||
sh.value,
|
||||
mst_file_bss,
|
||||
NULL,
|
||||
SECT_OFF_BSS,
|
||||
objfile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
#define SET_NAMESTRING() \
|
||||
|
@ -2913,7 +2959,8 @@ psymtab_to_symtab_1 (pst, filename)
|
|||
/* Handle encoded stab line number. */
|
||||
record_line (current_subfile, sh.index, valu);
|
||||
}
|
||||
else if (sh.st == stProc || sh.st == stStaticProc || sh.st == stEnd)
|
||||
else if (sh.st == stProc || sh.st == stStaticProc
|
||||
|| sh.st == stStatic || sh.st == stEnd)
|
||||
/* These are generated by gcc-2.x, do not complain */
|
||||
;
|
||||
else
|
||||
|
|
|
@ -601,3 +601,48 @@ install_minimal_symbols (objfile)
|
|||
}
|
||||
}
|
||||
|
||||
/* Check if PC is in a shared library trampoline code stub.
|
||||
Return minimal symbol for the trampoline entry or NULL if PC is not
|
||||
in a trampoline code stub. */
|
||||
|
||||
struct minimal_symbol *
|
||||
lookup_solib_trampoline_symbol_by_pc (pc)
|
||||
CORE_ADDR pc;
|
||||
{
|
||||
struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc);
|
||||
|
||||
if (msymbol != NULL && MSYMBOL_TYPE (msymbol) == mst_solib_trampoline)
|
||||
return msymbol;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If PC is in a shared library trampoline code stub, return the
|
||||
address of the `real' function belonging to the stub.
|
||||
Return 0 if PC is not in a trampoline code stub or if the real
|
||||
function is not found in the minimal symbol table.
|
||||
|
||||
We may fail to find the right function if a function with the
|
||||
same name is defined in more than one shared library, but this
|
||||
is considered bad programming style. We could return 0 if we find
|
||||
a duplicate function in case this matters someday. */
|
||||
|
||||
CORE_ADDR
|
||||
find_solib_trampoline_target (pc)
|
||||
CORE_ADDR pc;
|
||||
{
|
||||
struct objfile *objfile;
|
||||
struct minimal_symbol *msymbol;
|
||||
struct minimal_symbol *tsymbol = lookup_solib_trampoline_symbol_by_pc (pc);
|
||||
|
||||
if (tsymbol != NULL)
|
||||
{
|
||||
ALL_MSYMBOLS (objfile, msymbol)
|
||||
{
|
||||
if (MSYMBOL_TYPE (msymbol) == mst_text
|
||||
&& STREQ (SYMBOL_NAME (msymbol), SYMBOL_NAME (tsymbol)))
|
||||
return SYMBOL_VALUE_ADDRESS (msymbol);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
311
gdb/mipsread.c
311
gdb/mipsread.c
|
@ -1,6 +1,6 @@
|
|||
/* Read a symbol table in MIPS' format (Third-Eye).
|
||||
Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993 Free Software
|
||||
Foundation, Inc.
|
||||
Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Alessandro Forin (af@cs.cmu.edu) at CMU. Major work
|
||||
by Per Bothner, John Gilmore and Ian Lance Taylor at Cygnus Support.
|
||||
|
||||
|
@ -24,6 +24,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
mdebugread.c. */
|
||||
|
||||
#include "defs.h"
|
||||
#include <string.h>
|
||||
#include "bfd.h"
|
||||
#include "symtab.h"
|
||||
#include "symfile.h"
|
||||
#include "objfiles.h"
|
||||
|
@ -31,10 +33,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
#include "stabsread.h"
|
||||
#include "gdb-stabs.h"
|
||||
|
||||
#include "coff/sym.h"
|
||||
#include "coff/internal.h"
|
||||
#include "coff/ecoff.h"
|
||||
#include "libcoff.h" /* Private BFD COFF information. */
|
||||
#include "libecoff.h" /* Private BFD ECOFF information. */
|
||||
#include "elf/common.h"
|
||||
#include "elf/mips.h"
|
||||
|
||||
static void
|
||||
mipscoff_new_init PARAMS ((struct objfile *));
|
||||
|
@ -52,6 +57,10 @@ mipscoff_symfile_finish PARAMS ((struct objfile *));
|
|||
static struct section_offsets *
|
||||
mipscoff_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR));
|
||||
|
||||
static void
|
||||
read_alphacoff_dynamic_symtab PARAMS ((struct section_offsets *,
|
||||
struct objfile *objfile));
|
||||
|
||||
/* Initialize anything that needs initializing when a completely new
|
||||
symbol file is specified (not just adding some symbols from another
|
||||
file, e.g. a shared library). */
|
||||
|
@ -93,11 +102,23 @@ mipscoff_symfile_read (objfile, section_offsets, mainline)
|
|||
process it and define symbols accordingly. */
|
||||
|
||||
if (ecoff_slurp_symbolic_info (abfd) == false)
|
||||
error ("Error reading symbol table: %s", bfd_errmsg (bfd_error));
|
||||
error ("Error reading symbol table: %s", bfd_errmsg (bfd_get_error ()));
|
||||
|
||||
mdebug_build_psymtabs (objfile, &ecoff_backend (abfd)->debug_swap,
|
||||
&ecoff_data (abfd)->debug_info, section_offsets);
|
||||
|
||||
/* Add the dynamic symbols if we are reading the main symbol table. */
|
||||
|
||||
if (mainline)
|
||||
read_alphacoff_dynamic_symtab (section_offsets, objfile);
|
||||
|
||||
if (!have_partial_symbols ())
|
||||
{
|
||||
wrap_here ("");
|
||||
printf_filtered ("(no debugging symbols found)...");
|
||||
wrap_here ("");
|
||||
}
|
||||
|
||||
/* Install any minimal symbols that have been collected as the current
|
||||
minimal symbols for this objfile. */
|
||||
|
||||
|
@ -138,6 +159,290 @@ mipscoff_symfile_offsets (objfile, addr)
|
|||
return section_offsets;
|
||||
}
|
||||
|
||||
/* Alpha OSF/1 encapsulates the dynamic symbols in ELF format in a
|
||||
standard coff section. The ELF format for the symbols differs from
|
||||
the format defined in elf/external.h. It seems that a normal ELF 32 bit
|
||||
format is used, and the representation only changes because longs are
|
||||
64 bit on the alpha. In addition, the handling of text/data section
|
||||
indices for symbols is different from the ELF ABI.
|
||||
As the BFD linker currently does not support dynamic linking on the alpha,
|
||||
there seems to be no reason to pollute BFD with another mixture of object
|
||||
file formats for now. */
|
||||
|
||||
/* Format of an alpha external ELF symbol. */
|
||||
|
||||
typedef struct {
|
||||
unsigned char st_name[4]; /* Symbol name, index in string tbl */
|
||||
unsigned char st_pad[4]; /* Pad to long word boundary */
|
||||
unsigned char st_value[8]; /* Value of the symbol */
|
||||
unsigned char st_size[4]; /* Associated symbol size */
|
||||
unsigned char st_info[1]; /* Type and binding attributes */
|
||||
unsigned char st_other[1]; /* No defined meaning, 0 */
|
||||
unsigned char st_shndx[2]; /* Associated section index */
|
||||
} Elfalpha_External_Sym;
|
||||
|
||||
/* Format of an alpha external ELF dynamic info structure. */
|
||||
|
||||
typedef struct {
|
||||
unsigned char d_tag[4]; /* Tag */
|
||||
unsigned char d_pad[4]; /* Pad to long word boundary */
|
||||
union {
|
||||
unsigned char d_ptr[8]; /* Pointer value */
|
||||
unsigned char d_val[4]; /* Integer value */
|
||||
} d_un;
|
||||
} Elfalpha_External_Dyn;
|
||||
|
||||
/* Struct to obtain the section pointers for alpha dynamic symbol info. */
|
||||
|
||||
struct alphacoff_dynsecinfo {
|
||||
asection *sym_sect; /* Section pointer for .dynsym section */
|
||||
asection *str_sect; /* Section pointer for .dynstr section */
|
||||
asection *dyninfo_sect; /* Section pointer for .dynamic section */
|
||||
asection *got_sect; /* Section pointer for .got section */
|
||||
};
|
||||
|
||||
static void
|
||||
alphacoff_locate_sections PARAMS ((bfd *, asection *, void *));
|
||||
|
||||
/* We are called once per section from read_alphacoff_dynamic_symtab.
|
||||
We need to examine each section we are passed, check to see
|
||||
if it is something we are interested in processing, and
|
||||
if so, stash away some access information for the section. */
|
||||
|
||||
static void
|
||||
alphacoff_locate_sections (ignore_abfd, sectp, sip)
|
||||
bfd *ignore_abfd;
|
||||
asection *sectp;
|
||||
PTR sip;
|
||||
{
|
||||
register struct alphacoff_dynsecinfo *si;
|
||||
|
||||
si = (struct alphacoff_dynsecinfo *) sip;
|
||||
|
||||
if (STREQ (sectp->name, ".dynsym"))
|
||||
{
|
||||
si->sym_sect = sectp;
|
||||
}
|
||||
else if (STREQ (sectp->name, ".dynstr"))
|
||||
{
|
||||
si->str_sect = sectp;
|
||||
}
|
||||
else if (STREQ (sectp->name, ".dynamic"))
|
||||
{
|
||||
si->dyninfo_sect = sectp;
|
||||
}
|
||||
else if (STREQ (sectp->name, ".got"))
|
||||
{
|
||||
si->got_sect = sectp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Scan an alpha dynamic symbol table for symbols of interest and
|
||||
add them to the minimal symbol table. */
|
||||
|
||||
static void
|
||||
read_alphacoff_dynamic_symtab (section_offsets, objfile)
|
||||
struct section_offsets *section_offsets;
|
||||
struct objfile *objfile;
|
||||
{
|
||||
bfd *abfd = objfile->obfd;
|
||||
struct alphacoff_dynsecinfo si;
|
||||
char *sym_secptr;
|
||||
char *str_secptr;
|
||||
char *dyninfo_secptr;
|
||||
char *got_secptr;
|
||||
bfd_size_type sym_secsize;
|
||||
bfd_size_type str_secsize;
|
||||
bfd_size_type dyninfo_secsize;
|
||||
bfd_size_type got_secsize;
|
||||
int sym_count;
|
||||
int i;
|
||||
int stripped;
|
||||
Elfalpha_External_Sym *x_symp;
|
||||
char *dyninfo_p;
|
||||
char *dyninfo_end;
|
||||
int got_entry_size = 8;
|
||||
int dt_mips_local_gotno = -1;
|
||||
int dt_mips_gotsym = -1;
|
||||
|
||||
|
||||
/* We currently only know how to handle alpha dynamic symbols. */
|
||||
if (bfd_get_arch (abfd) != bfd_arch_alpha)
|
||||
return;
|
||||
|
||||
/* Locate the dynamic symbols sections and read them in. */
|
||||
memset ((char *) &si, 0, sizeof (si));
|
||||
bfd_map_over_sections (abfd, alphacoff_locate_sections, (PTR) &si);
|
||||
if (si.sym_sect == NULL
|
||||
|| si.str_sect == NULL
|
||||
|| si.dyninfo_sect == NULL
|
||||
|| si.got_sect == NULL)
|
||||
return;
|
||||
|
||||
sym_secsize = bfd_get_section_size_before_reloc (si.sym_sect);
|
||||
str_secsize = bfd_get_section_size_before_reloc (si.str_sect);
|
||||
dyninfo_secsize = bfd_get_section_size_before_reloc (si.dyninfo_sect);
|
||||
got_secsize = bfd_get_section_size_before_reloc (si.got_sect);
|
||||
sym_secptr = alloca (sym_secsize);
|
||||
str_secptr = alloca (str_secsize);
|
||||
dyninfo_secptr = alloca (dyninfo_secsize);
|
||||
got_secptr = alloca (got_secsize);
|
||||
|
||||
if (!bfd_get_section_contents (abfd, si.sym_sect, sym_secptr,
|
||||
(file_ptr)0, sym_secsize))
|
||||
return;
|
||||
if (!bfd_get_section_contents (abfd, si.str_sect, str_secptr,
|
||||
(file_ptr)0, str_secsize))
|
||||
return;
|
||||
if (!bfd_get_section_contents (abfd, si.dyninfo_sect, dyninfo_secptr,
|
||||
(file_ptr)0, dyninfo_secsize))
|
||||
return;
|
||||
if (!bfd_get_section_contents (abfd, si.got_sect, got_secptr,
|
||||
(file_ptr)0, got_secsize))
|
||||
return;
|
||||
|
||||
/* Find the number of local GOT entries and the index for the
|
||||
the first dynamic symbol in the GOT. */
|
||||
for (dyninfo_p = dyninfo_secptr, dyninfo_end = dyninfo_p + dyninfo_secsize;
|
||||
dyninfo_p < dyninfo_end;
|
||||
dyninfo_p += sizeof (Elfalpha_External_Dyn))
|
||||
{
|
||||
Elfalpha_External_Dyn *x_dynp = (Elfalpha_External_Dyn *)dyninfo_p;
|
||||
long dyn_tag;
|
||||
|
||||
dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_tag);
|
||||
if (dyn_tag == DT_NULL)
|
||||
break;
|
||||
else if (dyn_tag == DT_MIPS_LOCAL_GOTNO)
|
||||
{
|
||||
dt_mips_local_gotno = bfd_h_get_32 (abfd,
|
||||
(bfd_byte *) x_dynp->d_un.d_val);
|
||||
}
|
||||
else if (dyn_tag == DT_MIPS_GOTSYM)
|
||||
{
|
||||
dt_mips_gotsym = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
|
||||
}
|
||||
}
|
||||
if (dt_mips_local_gotno < 0 || dt_mips_gotsym < 0)
|
||||
return;
|
||||
|
||||
/* Scan all dynamic symbols and enter them into the minimal symbol table
|
||||
if appropriate. */
|
||||
sym_count = sym_secsize / sizeof (Elfalpha_External_Sym);
|
||||
stripped = (bfd_get_symcount (abfd) == 0);
|
||||
|
||||
/* Skip first symbol, which is a null dummy. */
|
||||
for (i = 1, x_symp = (Elfalpha_External_Sym *) sym_secptr + 1;
|
||||
i < sym_count;
|
||||
i++, x_symp++)
|
||||
{
|
||||
unsigned long strx;
|
||||
char *name;
|
||||
bfd_vma sym_value;
|
||||
unsigned char sym_info;
|
||||
unsigned int sym_shndx;
|
||||
int isglobal;
|
||||
enum minimal_symbol_type ms_type;
|
||||
|
||||
strx = bfd_h_get_32 (abfd, (bfd_byte *) x_symp->st_name);
|
||||
if (strx >= str_secsize)
|
||||
continue;
|
||||
name = str_secptr + strx;
|
||||
if (*name == '\0' || *name == '.')
|
||||
continue;
|
||||
|
||||
sym_value = bfd_h_get_64 (abfd, (bfd_byte *) x_symp->st_value);
|
||||
sym_info = bfd_h_get_8 (abfd, (bfd_byte *) x_symp->st_info);
|
||||
sym_shndx = bfd_h_get_16 (abfd, (bfd_byte *) x_symp->st_shndx);
|
||||
isglobal = (ELF_ST_BIND (sym_info) == STB_GLOBAL);
|
||||
|
||||
if (sym_shndx == SHN_UNDEF)
|
||||
{
|
||||
/* Handle undefined functions which are defined in a shared
|
||||
library. */
|
||||
if (ELF_ST_TYPE (sym_info) != STT_FUNC
|
||||
|| ELF_ST_BIND (sym_info) != STB_GLOBAL)
|
||||
continue;
|
||||
|
||||
ms_type = mst_solib_trampoline;
|
||||
|
||||
/* If sym_value is nonzero, it points to the shared library
|
||||
trampoline entry, which is what we are looking for.
|
||||
|
||||
If sym_value is zero, then we have to get the GOT entry
|
||||
for the symbol.
|
||||
If the GOT entry is nonzero, it represents the quickstart
|
||||
address of the function and we use that as the symbol value.
|
||||
|
||||
If the GOT entry is zero, the function address has to be resolved
|
||||
by the runtime loader before the executable is started.
|
||||
We are unable to find any meaningful address for these
|
||||
functions in the executable file, so we skip them. */
|
||||
if (sym_value == 0)
|
||||
{
|
||||
int got_entry_offset =
|
||||
(i - dt_mips_gotsym + dt_mips_local_gotno) * got_entry_size;
|
||||
|
||||
if (got_entry_offset < 0 || got_entry_offset >= got_secsize)
|
||||
continue;
|
||||
sym_value =
|
||||
bfd_h_get_64 (abfd,
|
||||
(bfd_byte *) (got_secptr + got_entry_offset));
|
||||
if (sym_value == 0)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Symbols defined in the executable itself. We only care about
|
||||
them if this is a stripped executable, otherwise they have
|
||||
been retrieved from the normal symbol table already. */
|
||||
if (!stripped)
|
||||
continue;
|
||||
|
||||
if (sym_shndx == SHN_MIPS_TEXT)
|
||||
{
|
||||
if (isglobal)
|
||||
ms_type = mst_text;
|
||||
else
|
||||
ms_type = mst_file_text;
|
||||
sym_value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
|
||||
}
|
||||
else if (sym_shndx == SHN_MIPS_DATA)
|
||||
{
|
||||
if (isglobal)
|
||||
ms_type = mst_data;
|
||||
else
|
||||
ms_type = mst_file_data;
|
||||
sym_value += ANOFFSET (section_offsets, SECT_OFF_DATA);
|
||||
}
|
||||
else if (sym_shndx == SHN_MIPS_ACOMMON)
|
||||
{
|
||||
if (isglobal)
|
||||
ms_type = mst_bss;
|
||||
else
|
||||
ms_type = mst_file_bss;
|
||||
sym_value += ANOFFSET (section_offsets, SECT_OFF_BSS);
|
||||
}
|
||||
else if (sym_shndx == SHN_ABS)
|
||||
{
|
||||
ms_type = mst_abs;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
prim_record_minimal_symbol (obsavestring (name,
|
||||
strlen (name),
|
||||
&objfile -> symbol_obstack),
|
||||
sym_value,
|
||||
ms_type,
|
||||
objfile);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialization */
|
||||
|
||||
static struct sym_fns ecoff_sym_fns =
|
||||
|
|
148
gdb/mipsv4-nat.c
Normal file
148
gdb/mipsv4-nat.c
Normal file
|
@ -0,0 +1,148 @@
|
|||
/* Native support for MIPS running SVR4, for GDB.
|
||||
Copyright 1994 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "inferior.h"
|
||||
#include "gdbcore.h"
|
||||
#include "target.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/procfs.h>
|
||||
#include <setjmp.h> /* For JB_XXX. */
|
||||
|
||||
/* Size of elements in jmpbuf */
|
||||
|
||||
#define JB_ELEMENT_SIZE 4
|
||||
|
||||
/*
|
||||
* See the comment in m68k-tdep.c regarding the utility of these functions.
|
||||
*
|
||||
* These definitions are from the MIPS SVR4 ABI, so they may work for
|
||||
* any MIPS SVR4 target.
|
||||
*/
|
||||
|
||||
void
|
||||
supply_gregset (gregsetp)
|
||||
gregset_t *gregsetp;
|
||||
{
|
||||
register int regi;
|
||||
register greg_t *regp = &(*gregsetp)[0];
|
||||
|
||||
for(regi = 0; regi <= CXT_RA; regi++)
|
||||
supply_register (regi, (char *)(regp + regi));
|
||||
|
||||
supply_register (PC_REGNUM, (char *)(regp + CXT_EPC));
|
||||
supply_register (HI_REGNUM, (char *)(regp + CXT_MDHI));
|
||||
supply_register (LO_REGNUM, (char *)(regp + CXT_MDLO));
|
||||
supply_register (CAUSE_REGNUM, (char *)(regp + CXT_CAUSE));
|
||||
}
|
||||
|
||||
void
|
||||
fill_gregset (gregsetp, regno)
|
||||
gregset_t *gregsetp;
|
||||
int regno;
|
||||
{
|
||||
int regi;
|
||||
register greg_t *regp = &(*gregsetp)[0];
|
||||
|
||||
for (regi = 0; regi <= 32; regi++)
|
||||
if ((regno == -1) || (regno == regi))
|
||||
*(regp + regi) = *(greg_t *) ®isters[REGISTER_BYTE (regi)];
|
||||
|
||||
if ((regno == -1) || (regno == PC_REGNUM))
|
||||
*(regp + CXT_EPC) = *(greg_t *) ®isters[REGISTER_BYTE (PC_REGNUM)];
|
||||
|
||||
if ((regno == -1) || (regno == CAUSE_REGNUM))
|
||||
*(regp + CXT_CAUSE) = *(greg_t *) ®isters[REGISTER_BYTE (PS_REGNUM)];
|
||||
|
||||
if ((regno == -1) || (regno == HI_REGNUM))
|
||||
*(regp + CXT_MDHI) = *(greg_t *) ®isters[REGISTER_BYTE (HI_REGNUM)];
|
||||
|
||||
if ((regno == -1) || (regno == LO_REGNUM))
|
||||
*(regp + CXT_MDLO) = *(greg_t *) ®isters[REGISTER_BYTE (LO_REGNUM)];
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we do the same thing for floating-point registers.
|
||||
* We don't bother to condition on FP0_REGNUM since any
|
||||
* reasonable MIPS configuration has an R3010 in it.
|
||||
*
|
||||
* Again, see the comments in m68k-tdep.c.
|
||||
*/
|
||||
|
||||
void
|
||||
supply_fpregset (fpregsetp)
|
||||
fpregset_t *fpregsetp;
|
||||
{
|
||||
register int regi;
|
||||
|
||||
for (regi = 0; regi < 32; regi++)
|
||||
supply_register (FP0_REGNUM + regi,
|
||||
(char *)&fpregsetp->fp_r.fp_regs[regi]);
|
||||
|
||||
supply_register (FCRCS_REGNUM, (char *)&fpregsetp->fp_csr);
|
||||
|
||||
/* FIXME: how can we supply FCRIR_REGNUM? The ABI doesn't tell us. */
|
||||
}
|
||||
|
||||
void
|
||||
fill_fpregset (fpregsetp, regno)
|
||||
fpregset_t *fpregsetp;
|
||||
int regno;
|
||||
{
|
||||
int regi;
|
||||
char *from, *to;
|
||||
|
||||
for (regi = FP0_REGNUM; regi < FP0_REGNUM + 32; regi++)
|
||||
{
|
||||
if ((regno == -1) || (regno == regi))
|
||||
{
|
||||
from = (char *) ®isters[REGISTER_BYTE (regi)];
|
||||
to = (char *) &(fpregsetp->fp_r.fp_regs[regi - FP0_REGNUM]);
|
||||
memcpy(to, from, REGISTER_RAW_SIZE (regi));
|
||||
}
|
||||
}
|
||||
|
||||
if ((regno == -1) || (regno == FCRCS_REGNUM))
|
||||
fpregsetp->fp_csr = *(unsigned *) ®isters[REGISTER_BYTE(FCRCS_REGNUM)];
|
||||
}
|
||||
|
||||
|
||||
/* Figure out where the longjmp will land.
|
||||
We expect the first arg to be a pointer to the jmp_buf structure from which
|
||||
we extract the pc (_JB_PC) that we will land at. The pc is copied into PC.
|
||||
This routine returns true on success. */
|
||||
|
||||
int
|
||||
get_longjmp_target (pc)
|
||||
CORE_ADDR *pc;
|
||||
{
|
||||
char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
|
||||
CORE_ADDR jb_addr;
|
||||
|
||||
jb_addr = read_register (A0_REGNUM);
|
||||
|
||||
if (target_read_memory (jb_addr + _JB_PC * JB_ELEMENT_SIZE, buf,
|
||||
TARGET_PTR_BIT / TARGET_CHAR_BIT))
|
||||
return 0;
|
||||
|
||||
*pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/* Shared code to pre-read a stab (dbx-style), when building a psymtab.
|
||||
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993
|
||||
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
@ -496,6 +496,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
continue;
|
||||
|
||||
case 'f':
|
||||
CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_TEXT);
|
||||
#ifdef DBXREAD_ONLY
|
||||
/* Kludges for ELF/STABS with Sun ACC */
|
||||
last_function_name = namestring;
|
||||
|
@ -517,6 +518,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
are put into the global psymtab like one would expect.
|
||||
They're also in the minimal symbol table. */
|
||||
case 'F':
|
||||
CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_TEXT);
|
||||
#ifdef DBXREAD_ONLY
|
||||
/* Kludges for ELF/STABS with Sun ACC */
|
||||
last_function_name = namestring;
|
||||
|
|
|
@ -74,11 +74,6 @@ static unsigned int max_symbolic_offset = UINT_MAX;
|
|||
printing a symbolic value as `<symbol at filename:linenum>' if set. */
|
||||
static int print_symbol_filename = 0;
|
||||
|
||||
/* Switch for quick display of symbolic addresses -- only uses minsyms,
|
||||
not full search of symtabs. */
|
||||
|
||||
int fast_symbolic_addr = 1;
|
||||
|
||||
/* Number of auto-display expression currently being displayed.
|
||||
So that we can disable it if we get an error or a signal within it.
|
||||
-1 when not doing one. */
|
||||
|
@ -374,7 +369,8 @@ print_scalar_formatted (valaddr, type, format, size, stream)
|
|||
return;
|
||||
}
|
||||
|
||||
val_long = unpack_long (type, valaddr);
|
||||
if (format != 'f')
|
||||
val_long = unpack_long (type, valaddr);
|
||||
|
||||
/* If we are printing it as unsigned, truncate it in case it is actually
|
||||
a negative signed value (e.g. "print/u (short)-1" should print 65535
|
||||
|
@ -533,15 +529,15 @@ print_address_symbolic (addr, stream, do_demangle, leadin)
|
|||
/* First try to find the address in the symbol table, then
|
||||
in the minsyms. Take the closest one. */
|
||||
|
||||
if (fast_symbolic_addr)
|
||||
{
|
||||
/* This is defective in the sense that it only finds text symbols. */
|
||||
symbol = find_pc_function (addr);
|
||||
if (symbol)
|
||||
name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (symbol));
|
||||
}
|
||||
else
|
||||
find_addr_symbol (addr, &symtab, &name_location);
|
||||
/* This is defective in the sense that it only finds text symbols. So
|
||||
really this is kind of pointless--we should make sure that the
|
||||
minimal symbols have everything we need (by changing that we could
|
||||
save some memory, but for many debug format--ELF/DWARF or
|
||||
anything/stabs--it would be inconvenient to eliminate those minimal
|
||||
symbols anyway). */
|
||||
symbol = find_pc_function (addr);
|
||||
if (symbol)
|
||||
name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (symbol));
|
||||
|
||||
if (symbol)
|
||||
{
|
||||
|
@ -2183,13 +2179,6 @@ environment, the value is printed in its own window.");
|
|||
&setprintlist),
|
||||
&showprintlist);
|
||||
|
||||
add_show_from_set (
|
||||
add_set_cmd ("fast-symbolic-addr", no_class, var_boolean,
|
||||
(char *)&fast_symbolic_addr,
|
||||
"Set fast printing of symbolic addresses (using minimal symbols).",
|
||||
&setprintlist),
|
||||
&showprintlist);
|
||||
|
||||
examine_b_type = init_type (TYPE_CODE_INT, 1, 0, NULL, NULL);
|
||||
examine_h_type = init_type (TYPE_CODE_INT, 2, 0, NULL, NULL);
|
||||
examine_w_type = init_type (TYPE_CODE_INT, 4, 0, NULL, NULL);
|
||||
|
|
294
gdb/solib.c
294
gdb/solib.c
|
@ -1,5 +1,5 @@
|
|||
/* Handle SunOS and SVR4 shared libraries for GDB, the GNU Debugger.
|
||||
Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
|
||||
Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
@ -30,6 +30,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
#ifndef SVR4_SHARED_LIBS
|
||||
/* SunOS shared libs need the nlist structure. */
|
||||
#include <a.out.h>
|
||||
#else
|
||||
#include "libelf.h"
|
||||
#ifndef DT_MIPS_RLD_MAP
|
||||
#include "elf/mips.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "symtab.h"
|
||||
|
@ -71,15 +76,12 @@ static char *bkpt_names[] = {
|
|||
|
||||
/* Symbols which are used to locate the base of the link map structures. */
|
||||
|
||||
#ifndef SVR4_SHARED_LIBS
|
||||
static char *debug_base_symbols[] = {
|
||||
#ifdef SVR4_SHARED_LIBS
|
||||
"_r_debug", /* Most SVR4 systems, Solaris 2.1, 2.2 */
|
||||
"r_debug", /* Solaris 2.3 */
|
||||
#else
|
||||
"_DYNAMIC", /* SunOS */
|
||||
#endif
|
||||
"_DYNAMIC",
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
/* local data declarations */
|
||||
|
||||
|
@ -164,11 +166,8 @@ solib_map_sections PARAMS ((struct so_list *));
|
|||
|
||||
#ifdef SVR4_SHARED_LIBS
|
||||
|
||||
static int
|
||||
look_for_base PARAMS ((int, CORE_ADDR));
|
||||
|
||||
static CORE_ADDR
|
||||
bfd_lookup_symbol PARAMS ((bfd *, char *));
|
||||
elf_locate_base PARAMS ((void));
|
||||
|
||||
#else
|
||||
|
||||
|
@ -250,7 +249,7 @@ solib_map_sections (so)
|
|||
if (build_section_table (abfd, &so -> sections, &so -> sections_end))
|
||||
{
|
||||
error ("Can't find the file sections in `%s': %s",
|
||||
bfd_get_filename (exec_bfd), bfd_errmsg (bfd_get_error ()));
|
||||
bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
|
||||
}
|
||||
|
||||
for (p = so -> sections; p < so -> sections_end; p++)
|
||||
|
@ -261,7 +260,7 @@ solib_map_sections (so)
|
|||
p -> addr += (CORE_ADDR) LM_ADDR (so);
|
||||
p -> endaddr += (CORE_ADDR) LM_ADDR (so);
|
||||
so -> lmend = (CORE_ADDR) max (p -> endaddr, so -> lmend);
|
||||
if (STREQ (p -> sec_ptr -> name, ".text"))
|
||||
if (STREQ (p -> the_bfd_section -> name, ".text"))
|
||||
{
|
||||
so -> textsection = p;
|
||||
}
|
||||
|
@ -355,162 +354,95 @@ solib_add_common_symbols (rtc_symp, objfile)
|
|||
|
||||
#endif /* SVR4_SHARED_LIBS */
|
||||
|
||||
|
||||
#ifdef SVR4_SHARED_LIBS
|
||||
|
||||
/*
|
||||
|
||||
LOCAL FUNCTION
|
||||
|
||||
bfd_lookup_symbol -- lookup the value for a specific symbol
|
||||
elf_locate_base -- locate the base address of dynamic linker structs
|
||||
for SVR4 elf targets.
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname)
|
||||
CORE_ADDR elf_locate_base (void)
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
An expensive way to lookup the value of a single symbol for
|
||||
bfd's that are only temporary anyway. This is used by the
|
||||
shared library support to find the address of the debugger
|
||||
interface structures in the shared library.
|
||||
For SVR4 elf targets the address of the dynamic linker's runtime
|
||||
structure is contained within the dynamic info section in the
|
||||
executable file. The dynamic section is also mapped into the
|
||||
inferior address space. Because the runtime loader fills in the
|
||||
real address before starting the inferior, we have to read in the
|
||||
dynamic info section from the inferior address space.
|
||||
If there are any errors while trying to find the address, we
|
||||
silently return 0, otherwise the found address is returned.
|
||||
|
||||
Note that 0 is specifically allowed as an error return (no
|
||||
such symbol).
|
||||
|
||||
FIXME: See if there is a less "expensive" way of doing this.
|
||||
Also see if there is already another bfd or gdb function
|
||||
that specifically does this, and if so, use it.
|
||||
*/
|
||||
|
||||
static CORE_ADDR
|
||||
bfd_lookup_symbol (abfd, symname)
|
||||
bfd *abfd;
|
||||
char *symname;
|
||||
{
|
||||
unsigned int storage_needed;
|
||||
asymbol *sym;
|
||||
asymbol **symbol_table;
|
||||
unsigned int number_of_symbols;
|
||||
unsigned int i;
|
||||
struct cleanup *back_to;
|
||||
CORE_ADDR symaddr = 0;
|
||||
|
||||
storage_needed = get_symtab_upper_bound (abfd);
|
||||
|
||||
if (storage_needed > 0)
|
||||
{
|
||||
symbol_table = (asymbol **) xmalloc (storage_needed);
|
||||
back_to = make_cleanup (free, (PTR)symbol_table);
|
||||
number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
|
||||
|
||||
for (i = 0; i < number_of_symbols; i++)
|
||||
{
|
||||
sym = *symbol_table++;
|
||||
if (STREQ (sym -> name, symname))
|
||||
{
|
||||
/* Bfd symbols are section relative. */
|
||||
symaddr = sym -> value + sym -> section -> vma;
|
||||
break;
|
||||
}
|
||||
}
|
||||
do_cleanups (back_to);
|
||||
}
|
||||
return (symaddr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
LOCAL FUNCTION
|
||||
|
||||
look_for_base -- examine file for each mapped address segment
|
||||
|
||||
SYNOPSYS
|
||||
|
||||
static int look_for_base (int fd, CORE_ADDR baseaddr)
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
This function is passed to proc_iterate_over_mappings, which
|
||||
causes it to get called once for each mapped address space, with
|
||||
an open file descriptor for the file mapped to that space, and the
|
||||
base address of that mapped space.
|
||||
|
||||
Our job is to find the debug base symbol in the file that this
|
||||
fd is open on, if it exists, and if so, initialize the dynamic
|
||||
linker structure base address debug_base.
|
||||
|
||||
Note that this is a computationally expensive proposition, since
|
||||
we basically have to open a bfd on every call, so we specifically
|
||||
avoid opening the exec file.
|
||||
*/
|
||||
|
||||
static int
|
||||
look_for_base (fd, baseaddr)
|
||||
int fd;
|
||||
CORE_ADDR baseaddr;
|
||||
static CORE_ADDR
|
||||
elf_locate_base ()
|
||||
{
|
||||
bfd *interp_bfd;
|
||||
CORE_ADDR address;
|
||||
char **symbolp;
|
||||
struct elf_internal_shdr *dyninfo_sect;
|
||||
int dyninfo_sect_size;
|
||||
CORE_ADDR dyninfo_addr;
|
||||
char *buf;
|
||||
char *bufend;
|
||||
|
||||
/* If the fd is -1, then there is no file that corresponds to this
|
||||
mapped memory segment, so skip it. Also, if the fd corresponds
|
||||
to the exec file, skip it as well. */
|
||||
/* Find the start address of the .dynamic section. */
|
||||
if (exec_bfd == NULL || bfd_get_flavour (exec_bfd) != bfd_target_elf_flavour)
|
||||
return 0;
|
||||
dyninfo_sect = bfd_elf_find_section (exec_bfd, ".dynamic");
|
||||
if (dyninfo_sect == NULL)
|
||||
return 0;
|
||||
dyninfo_addr = dyninfo_sect->sh_addr;
|
||||
|
||||
if ((fd == -1) || fdmatch (fileno ((GDB_FILE *)(exec_bfd -> iostream)), fd))
|
||||
/* Read in .dynamic section, silently ignore errors. */
|
||||
dyninfo_sect_size = dyninfo_sect->sh_size;
|
||||
buf = alloca (dyninfo_sect_size);
|
||||
if (target_read_memory (dyninfo_addr, buf, dyninfo_sect_size))
|
||||
return 0;
|
||||
|
||||
/* Find the DT_DEBUG entry in the the .dynamic section.
|
||||
For mips elf we look for DT_MIPS_RLD_MAP, mips elf apparently has
|
||||
no DT_DEBUG entries. */
|
||||
/* FIXME: In lack of a 64 bit ELF ABI the following code assumes
|
||||
a 32 bit ELF ABI target. */
|
||||
for (bufend = buf + dyninfo_sect_size;
|
||||
buf < bufend;
|
||||
buf += sizeof (Elf32_External_Dyn))
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
Elf32_External_Dyn *x_dynp = (Elf32_External_Dyn *)buf;
|
||||
long dyn_tag;
|
||||
CORE_ADDR dyn_ptr;
|
||||
|
||||
/* Try to open whatever random file this fd corresponds to. Note that
|
||||
we have no way currently to find the filename. Don't gripe about
|
||||
any problems we might have, just fail. */
|
||||
|
||||
if ((interp_bfd = bfd_fdopenr ("unnamed", gnutarget, fd)) == NULL)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
if (!bfd_check_format (interp_bfd, bfd_object))
|
||||
{
|
||||
bfd_close (interp_bfd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Now try to find our debug base symbol in this file, which we at
|
||||
least know to be a valid ELF executable or shared library. */
|
||||
|
||||
for (symbolp = debug_base_symbols; *symbolp != NULL; symbolp++)
|
||||
{
|
||||
address = bfd_lookup_symbol (interp_bfd, *symbolp);
|
||||
if (address != 0)
|
||||
dyn_tag = bfd_h_get_32 (exec_bfd, (bfd_byte *) x_dynp->d_tag);
|
||||
if (dyn_tag == DT_NULL)
|
||||
break;
|
||||
else if (dyn_tag == DT_DEBUG)
|
||||
{
|
||||
break;
|
||||
dyn_ptr = bfd_h_get_32 (exec_bfd, (bfd_byte *) x_dynp->d_un.d_ptr);
|
||||
return dyn_ptr;
|
||||
}
|
||||
else if (dyn_tag == DT_MIPS_RLD_MAP)
|
||||
{
|
||||
char pbuf[TARGET_PTR_BIT / HOST_CHAR_BIT];
|
||||
|
||||
/* DT_MIPS_RLD_MAP contains a pointer to the address
|
||||
of the dynamic link structure. */
|
||||
dyn_ptr = bfd_h_get_32 (exec_bfd, (bfd_byte *) x_dynp->d_un.d_ptr);
|
||||
if (target_read_memory (dyn_ptr, pbuf, sizeof (pbuf)))
|
||||
return 0;
|
||||
return extract_unsigned_integer (pbuf, sizeof (pbuf));
|
||||
}
|
||||
}
|
||||
if (address == 0)
|
||||
{
|
||||
bfd_close (interp_bfd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Eureka! We found the symbol. But now we may need to relocate it
|
||||
by the base address. If the symbol's value is less than the base
|
||||
address of the shared library, then it hasn't yet been relocated
|
||||
by the dynamic linker, and we have to do it ourself. FIXME: Note
|
||||
that we make the assumption that the first segment that corresponds
|
||||
to the shared library has the base address to which the library
|
||||
was relocated. */
|
||||
|
||||
if (address < baseaddr)
|
||||
{
|
||||
address += baseaddr;
|
||||
}
|
||||
debug_base = address;
|
||||
bfd_close (interp_bfd);
|
||||
return (1);
|
||||
/* DT_DEBUG entry not found. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* SVR4_SHARED_LIBS */
|
||||
|
||||
/*
|
||||
|
||||
|
@ -540,20 +472,13 @@ DESCRIPTION
|
|||
have to do is look it up there. Note that we explicitly do NOT want
|
||||
to find the copies in the shared library.
|
||||
|
||||
The SVR4 version is much more complicated because the dynamic linker
|
||||
and it's structures are located in the shared C library, which gets
|
||||
run as the executable's "interpreter" by the kernel. We have to go
|
||||
The SVR4 version is a bit more complicated because the address
|
||||
is contained somewhere in the dynamic info section. We have to go
|
||||
to a lot more work to discover the address of the debug base symbol.
|
||||
Because of this complexity, we cache the value we find and return that
|
||||
value on subsequent invocations. Note there is no copy in the
|
||||
executable symbol tables.
|
||||
|
||||
Note that we can assume nothing about the process state at the time
|
||||
we need to find this address. We may be stopped on the first instruc-
|
||||
tion of the interpreter (C shared library), the first instruction of
|
||||
the executable itself, or somewhere else entirely (if we attached
|
||||
to the process for example).
|
||||
|
||||
*/
|
||||
|
||||
static CORE_ADDR
|
||||
|
@ -585,14 +510,12 @@ locate_base ()
|
|||
|
||||
/* Check to see if we have a currently valid address, and if so, avoid
|
||||
doing all this work again and just return the cached address. If
|
||||
we have no cached address, ask the /proc support interface to iterate
|
||||
over the list of mapped address segments, calling look_for_base() for
|
||||
each segment. When we are done, we will have either found the base
|
||||
address or not. */
|
||||
we have no cached address, try to locate it in the dynamic info
|
||||
section. */
|
||||
|
||||
if (debug_base == 0)
|
||||
{
|
||||
proc_iterate_over_mappings (look_for_base);
|
||||
debug_base = elf_locate_base ();
|
||||
}
|
||||
return (debug_base);
|
||||
|
||||
|
@ -808,35 +731,10 @@ solib_add (arg_string, from_tty, target)
|
|||
error ("Invalid regexp: %s", re_err);
|
||||
}
|
||||
|
||||
/* Getting new symbols may change our opinion about what is
|
||||
frameless. */
|
||||
reinit_frame_cache ();
|
||||
|
||||
while ((so = find_solib (so)) != NULL)
|
||||
{
|
||||
if (so -> so_name[0] && re_exec (so -> so_name))
|
||||
{
|
||||
so -> from_tty = from_tty;
|
||||
if (so -> symbols_loaded)
|
||||
{
|
||||
if (from_tty)
|
||||
{
|
||||
printf_unfiltered ("Symbols already loaded for %s\n", so -> so_name);
|
||||
}
|
||||
}
|
||||
else if (catch_errors
|
||||
(symbol_add_stub, (char *) so,
|
||||
"Error while reading shared library symbols:\n",
|
||||
RETURN_MASK_ALL))
|
||||
{
|
||||
so_last = so;
|
||||
so -> symbols_loaded = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now add the shared library sections to the section table of the
|
||||
specified target, if any. */
|
||||
/* Add the shared library sections to the section table of the
|
||||
specified target, if any. We have to do this before reading the
|
||||
symbol files as symbol_file_add calls reinit_frame_cache and
|
||||
creating a new frame might access memory in the shared library. */
|
||||
if (target)
|
||||
{
|
||||
/* Count how many new section_table entries there are. */
|
||||
|
@ -882,6 +780,30 @@ solib_add (arg_string, from_tty, target)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now add the symbol files. */
|
||||
while ((so = find_solib (so)) != NULL)
|
||||
{
|
||||
if (so -> so_name[0] && re_exec (so -> so_name))
|
||||
{
|
||||
so -> from_tty = from_tty;
|
||||
if (so -> symbols_loaded)
|
||||
{
|
||||
if (from_tty)
|
||||
{
|
||||
printf_unfiltered ("Symbols already loaded for %s\n", so -> so_name);
|
||||
}
|
||||
}
|
||||
else if (catch_errors
|
||||
(symbol_add_stub, (char *) so,
|
||||
"Error while reading shared library symbols:\n",
|
||||
RETURN_MASK_ALL))
|
||||
{
|
||||
so_last = so;
|
||||
so -> symbols_loaded = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Calling this once at the end means that we put all the minimal
|
||||
symbols for commons into the objfile for the last shared library.
|
||||
|
|
29
gdb/symtab.h
29
gdb/symtab.h
|
@ -26,8 +26,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
#define obstack_chunk_alloc xmalloc
|
||||
#define obstack_chunk_free free
|
||||
|
||||
/* GNU C supports enums that are bitfields. Some old compilers don't. */
|
||||
#if defined(__GNUC__) && !defined(BYTE_BITFIELD)
|
||||
/* Don't do this; it means that if some .o's are compiled with GNU C
|
||||
and some are not (easy to do accidentally the way we configure
|
||||
things; also it is a pain to have to "make clean" every time you
|
||||
want to switch compilers), then GDB dies a horrible death. */
|
||||
/* GNU C supports enums that are bitfields. Some compilers don't. */
|
||||
#if 0 && defined(__GNUC__) && !defined(BYTE_BITFIELD)
|
||||
#define BYTE_BITFIELD :8;
|
||||
#else
|
||||
#define BYTE_BITFIELD /*nothing*/
|
||||
|
@ -57,6 +61,9 @@ struct general_symbol_info
|
|||
|
||||
union
|
||||
{
|
||||
/* The fact that this is a long not a LONGEST mainly limits the
|
||||
range of a LOC_CONST. Since LOC_CONST_BYTES exists, I'm not
|
||||
sure that is a big deal. */
|
||||
long value;
|
||||
|
||||
struct block *block;
|
||||
|
@ -299,6 +306,15 @@ struct minimal_symbol
|
|||
mst_data, /* Generally initialized data */
|
||||
mst_bss, /* Generally uninitialized data */
|
||||
mst_abs, /* Generally absolute (nonrelocatable) */
|
||||
/* GDB uses mst_solib_trampoline for the start address of a shared
|
||||
library trampoline entry. Breakpoints for shared library functions
|
||||
are put there if the shared library is not yet loaded.
|
||||
After the shared library is loaded, lookup_minimal_symbol will
|
||||
prefer the minimal symbol from the shared library (usually
|
||||
a mst_text symbol) over the mst_solib_trampoline symbol, and the
|
||||
breakpoints will be moved to their true address in the shared
|
||||
library via breakpoint_re_set. */
|
||||
mst_solib_trampoline, /* Shared library trampoline code */
|
||||
/* For the mst_file* types, the names are only guaranteed to be unique
|
||||
within a given .o file. */
|
||||
mst_file_text, /* Static version of mst_text */
|
||||
|
@ -1016,6 +1032,12 @@ lookup_minimal_symbol PARAMS ((const char *, struct objfile *));
|
|||
extern struct minimal_symbol *
|
||||
lookup_minimal_symbol_by_pc PARAMS ((CORE_ADDR));
|
||||
|
||||
extern struct minimal_symbol *
|
||||
lookup_solib_trampoline_symbol_by_pc PARAMS ((CORE_ADDR));
|
||||
|
||||
extern CORE_ADDR
|
||||
find_solib_trampoline_target PARAMS ((CORE_ADDR));
|
||||
|
||||
extern void
|
||||
init_minimal_symbol_collection PARAMS ((void));
|
||||
|
||||
|
@ -1097,6 +1119,9 @@ maintenance_print_msymbols PARAMS ((char *, int));
|
|||
void
|
||||
maintenance_print_objfiles PARAMS ((char *, int));
|
||||
|
||||
void
|
||||
maintenance_check_symtabs PARAMS ((char *, int));
|
||||
|
||||
#endif
|
||||
|
||||
extern void
|
||||
|
|
Loading…
Reference in a new issue