This file has been removed from HEAD when it should (also) have been

removed from the vendor branch.
This commit is contained in:
Marcel Moolenaar 2004-06-19 03:39:16 +00:00
parent f0f8ce0889
commit 90184f6712
30 changed files with 0 additions and 32873 deletions

View File

@ -1,167 +0,0 @@
/* Remote debugging interface for ABug Rom monitor for GDB, the GNU debugger.
Copyright 1995, 1996, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
Written by Rob Savoye of Cygnus Support
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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "gdbcore.h"
#include "target.h"
#include "monitor.h"
#include "serial.h"
#include "regcache.h"
/* Prototypes for local functions. */
static void abug_open (char *args, int from_tty);
static void
abug_supply_register (char *regname, int regnamelen, char *val, int vallen)
{
int regno;
if (regnamelen != 2)
return;
switch (regname[0])
{
case 'S':
if (regname[1] != 'R')
return;
regno = PS_REGNUM;
break;
case 'P':
if (regname[1] != 'C')
return;
regno = PC_REGNUM;
break;
case 'D':
if (regname[1] < '0' || regname[1] > '7')
return;
regno = regname[1] - '0' + D0_REGNUM;
break;
case 'A':
if (regname[1] < '0' || regname[1] > '7')
return;
regno = regname[1] - '0' + A0_REGNUM;
break;
default:
return;
}
monitor_supply_register (regno, val);
}
/*
* This array of registers needs to match the indexes used by GDB. The
* whole reason this exists is because the various ROM monitors use
* different names than GDB does, and don't support all the
* registers either. So, typing "info reg sp" becomes an "A7".
*/
static char *abug_regnames[NUM_REGS] =
{
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
"PC",
};
/*
* Define the monitor command strings. Since these are passed directly
* through to a printf style function, we need can include formatting
* strings. We also need a CR or LF on the end.
*/
static struct target_ops abug_ops;
static char *abug_inits[] =
{"\r", NULL};
static struct monitor_ops abug_cmds;
static void
init_abug_cmds (void)
{
abug_cmds.flags = MO_CLR_BREAK_USES_ADDR;
abug_cmds.init = abug_inits; /* Init strings */
abug_cmds.cont = "g\r"; /* continue command */
abug_cmds.step = "t\r"; /* single step */
abug_cmds.stop = NULL; /* interrupt command */
abug_cmds.set_break = "br %x\r"; /* set a breakpoint */
abug_cmds.clr_break = "nobr %x\r"; /* clear a breakpoint */
abug_cmds.clr_all_break = "nobr\r"; /* clear all breakpoints */
abug_cmds.fill = "bf %x:%x %x;b\r"; /* fill (start count val) */
abug_cmds.setmem.cmdb = "ms %x %02x\r"; /* setmem.cmdb (addr, value) */
abug_cmds.setmem.cmdw = "ms %x %04x\r"; /* setmem.cmdw (addr, value) */
abug_cmds.setmem.cmdl = "ms %x %08x\r"; /* setmem.cmdl (addr, value) */
abug_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
abug_cmds.setmem.resp_delim = NULL; /* setreg.resp_delim */
abug_cmds.setmem.term = NULL; /* setreg.term */
abug_cmds.setmem.term_cmd = NULL; /* setreg.term_cmd */
abug_cmds.getmem.cmdb = "md %x:%x;b\r"; /* getmem.cmdb (addr, len) */
abug_cmds.getmem.cmdw = "md %x:%x;b\r"; /* getmem.cmdw (addr, len) */
abug_cmds.getmem.cmdl = "md %x:%x;b\r"; /* getmem.cmdl (addr, len) */
abug_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
abug_cmds.getmem.resp_delim = " "; /* getmem.resp_delim */
abug_cmds.getmem.term = NULL; /* getmem.term */
abug_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
abug_cmds.setreg.cmd = "rm %s %x\r"; /* setreg.cmd (name, value) */
abug_cmds.setreg.resp_delim = "="; /* setreg.resp_delim */
abug_cmds.setreg.term = "? "; /* setreg.term */
abug_cmds.setreg.term_cmd = ".\r"; /* setreg.term_cmd */
abug_cmds.getreg.cmd = "rm %s\r"; /* getreg.cmd (name) */
abug_cmds.getreg.resp_delim = "="; /* getreg.resp_delim */
abug_cmds.getreg.term = "? "; /* getreg.term */
abug_cmds.getreg.term_cmd = ".\r"; /* getreg.term_cmd */
abug_cmds.dump_registers = "rd\r"; /* dump_registers */
abug_cmds.register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
abug_cmds.supply_register = abug_supply_register; /* supply_register */
abug_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
abug_cmds.load = "lo 0\r"; /* download command */
abug_cmds.loadresp = "\n"; /* load response */
abug_cmds.prompt = "135Bug>"; /* monitor command prompt */
abug_cmds.line_term = "\r"; /* end-of-line terminator */
abug_cmds.cmd_end = NULL; /* optional command terminator */
abug_cmds.target = &abug_ops; /* target operations */
abug_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
abug_cmds.regnames = abug_regnames; /* registers names */
abug_cmds.magic = MONITOR_OPS_MAGIC; /* magic */
};
static void
abug_open (char *args, int from_tty)
{
monitor_open (args, &abug_cmds, from_tty);
}
void
_initialize_abug_rom (void)
{
init_abug_cmds ();
init_monitor_ops (&abug_ops);
abug_ops.to_shortname = "abug";
abug_ops.to_longname = "ABug monitor";
abug_ops.to_doc = "Debug via the ABug monitor.\n\
Specify the serial device it is connected to (e.g. /dev/ttya).";
abug_ops.to_open = abug_open;
add_target (&abug_ops);
}

View File

@ -1,175 +0,0 @@
/* Define if compiling on Solaris 7. */
#undef _MSE_INT_H
/* Define if your struct reg has r_fs. */
#undef HAVE_STRUCT_REG_R_FS
/* Define if your struct reg has r_gs. */
#undef HAVE_STRUCT_REG_R_GS
/* Define if pstatus_t type is available */
#undef HAVE_PSTATUS_T
/* Define if prrun_t type is available */
#undef HAVE_PRRUN_T
/* Define if fpregset_t type is available. */
#undef HAVE_FPREGSET_T
/* Define if gregset_t type is available. */
#undef HAVE_GREGSET_T
/* Define if <sys/procfs.h> has prgregset_t. */
#undef HAVE_PRGREGSET_T
/* Define if <sys/procfs.h> has prfpregset_t. */
#undef HAVE_PRFPREGSET_T
/* Define if <sys/procfs.h> has lwpid_t. */
#undef HAVE_LWPID_T
/* Define if <sys/procfs.h> has psaddr_t. */
#undef HAVE_PSADDR_T
/* Define if <sys/procfs.h> has prgregset32_t. */
#undef HAVE_PRGREGSET32_T
/* Define if <sys/procfs.h> has prfpregset32_t. */
#undef HAVE_PRFPREGSET32_T
/* Define if <sys/procfs.h> has prsysent_t */
#undef HAVE_PRSYSENT_T
/* Define if <sys/procfs.h> has pr_sigset_t */
#undef HAVE_PR_SIGSET_T
/* Define if <sys/procfs.h> has pr_sigaction64_t */
#undef HAVE_PR_SIGACTION64_T
/* Define if <sys/procfs.h> has pr_siginfo64_t */
#undef HAVE_PR_SIGINFO64_T
/* Define if <link.h> exists and defines struct link_map which has
members with an ``l_'' prefix. (For Solaris, SVR4, and
SVR4-like systems.) */
#undef HAVE_STRUCT_LINK_MAP_WITH_L_MEMBERS
/* Define if <link.h> exists and defines struct link_map which has
members with an ``lm_'' prefix. (For SunOS.) */
#undef HAVE_STRUCT_LINK_MAP_WITH_LM_MEMBERS
/* Define if <link.h> exists and defines a struct so_map which has
members with an ``som_'' prefix. (Found on older *BSD systems.) */
#undef HAVE_STRUCT_SO_MAP_WITH_SOM_MEMBERS
/* Define if <sys/link.h> has struct link_map32 */
#undef HAVE_STRUCT_LINK_MAP32
/* Define if the prfpregset_t type is broken. */
#undef PRFPREGSET_T_BROKEN
/* Define if you want to use new multi-fd /proc interface
(replaces HAVE_MULTIPLE_PROC_FDS as well as other macros). */
#undef NEW_PROC_API
/* Define if ioctl argument PIOCSET is available. */
#undef HAVE_PROCFS_PIOCSET
/* Define if the `long long' type works. */
#undef CC_HAS_LONG_LONG
/* Define if the "ll" format works to print long long ints. */
#undef PRINTF_HAS_LONG_LONG
/* Define if the "%Lg" format works to print long doubles. */
#undef PRINTF_HAS_LONG_DOUBLE
/* Define if the "%Lg" format works to scan long doubles. */
#undef SCANF_HAS_LONG_DOUBLE
/* Define if using Solaris thread debugging. */
#undef HAVE_THREAD_DB_LIB
/* Define on a GNU/Linux system to work around problems in sys/procfs.h. */
#undef START_INFERIOR_TRAPS_EXPECTED
#undef sys_quotactl
/* Define if you have HPUX threads */
#undef HAVE_HPUX_THREAD_SUPPORT
/* Define if you want to use the memory mapped malloc package (mmalloc). */
#undef USE_MMALLOC
/* Define if the runtime uses a routine from mmalloc before gdb has a chance
to initialize mmalloc, and we want to force checking to be used anyway.
This may cause spurious memory corruption messages if the runtime tries
to explicitly deallocate that memory when gdb calls exit. */
#undef MMCHECK_FORCE
/* Define to 1 if NLS is requested. */
#undef ENABLE_NLS
/* Define as 1 if you have catgets and don't want to use GNU gettext. */
#undef HAVE_CATGETS
/* Define as 1 if you have gettext and don't want to use GNU gettext. */
#undef HAVE_GETTEXT
/* Define as 1 if you have the stpcpy function. */
#undef HAVE_STPCPY
/* Define if your locale.h file contains LC_MESSAGES. */
#undef HAVE_LC_MESSAGES
/* Define if you want to use the full-screen terminal user interface. */
#undef TUI
/* Define if <proc_service.h> on solaris uses int instead of
size_t, and assorted other type changes. */
#undef PROC_SERVICE_IS_OLD
/* If you want to specify a default CPU variant, define this to be its
name, as a C string. */
#undef TARGET_CPU_DEFAULT
/* Define if the simulator is being linked in. */
#undef WITH_SIM
/* Set to true if the save_state_t structure is present */
#undef HAVE_STRUCT_SAVE_STATE_T
/* Set to true if the save_state_t structure has the ss_wide member */
#undef HAVE_STRUCT_MEMBER_SS_WIDE
/* Define if <sys/ptrace.h> defines the PTRACE_GETREGS request. */
#undef HAVE_PTRACE_GETREGS
/* Define if <sys/ptrace.h> defines the PTRACE_GETFPXREGS request. */
#undef HAVE_PTRACE_GETFPXREGS
/* Define if <sys/ptrace.h> defines the PT_GETDBREGS request. */
#undef HAVE_PT_GETDBREGS
/* Define if <sys/ptrace.h> defines the PT_GETXMMREGS request. */
#undef HAVE_PT_GETXMMREGS
/* Define if gnu-regex.c included with GDB should be used. */
#undef USE_INCLUDED_REGEX
/* BFD's default architecture. */
#undef DEFAULT_BFD_ARCH
/* BFD's default target vector. */
#undef DEFAULT_BFD_VEC
/* Multi-arch enabled. */
#undef GDB_MULTI_ARCH
/* hostfile */
#undef GDB_XM_FILE
/* targetfile */
#undef GDB_TM_FILE
/* nativefile */
#undef GDB_NM_FILE

View File

@ -1,308 +0,0 @@
/* Low level Alpha interface, for GDB when running native.
Copyright 1993, 1995, 1996, 1998, 1999, 2000, 2001
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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "inferior.h"
#include "gdbcore.h"
#include "target.h"
#include "regcache.h"
#include <sys/ptrace.h>
#ifdef __linux__
#include <asm/reg.h>
#include <alpha/ptrace.h>
#else
#include <alpha/coreregs.h>
#endif
#include <sys/user.h>
/* Prototypes for local functions. */
static void fetch_osf_core_registers (char *, unsigned, int, CORE_ADDR);
static void fetch_elf_core_registers (char *, unsigned, int, CORE_ADDR);
/* Size of elements in jmpbuf */
#define JB_ELEMENT_SIZE 8
/* The definition for JB_PC in machine/reg.h is wrong.
And we can't get at the correct definition in setjmp.h as it is
not always available (eg. if _POSIX_SOURCE is defined which is the
default). As the defintion is unlikely to change (see comment
in <setjmp.h>, define the correct value here. */
#undef JB_PC
#define JB_PC 2
/* 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 (CORE_ADDR *pc)
{
CORE_ADDR jb_addr;
char raw_buffer[MAX_REGISTER_RAW_SIZE];
jb_addr = read_register (A0_REGNUM);
if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, raw_buffer,
sizeof (CORE_ADDR)))
return 0;
*pc = extract_address (raw_buffer, sizeof (CORE_ADDR));
return 1;
}
/* Extract the register values out of the core file and store
them where `read_register' will find them.
CORE_REG_SECT points to the register values themselves, read into memory.
CORE_REG_SIZE is the size of that area.
WHICH says which set of registers we are handling (0 = int, 2 = float
on machines where they are discontiguous).
REG_ADDR is the offset from u.u_ar0 to the register values relative to
core_reg_sect. This is used with old-fashioned core files to
locate the registers in a large upage-plus-stack ".reg" section.
Original upage address X is at location core_reg_sect+x+reg_addr.
*/
static void
fetch_osf_core_registers (char *core_reg_sect, unsigned core_reg_size,
int which, CORE_ADDR reg_addr)
{
register int regno;
register int addr;
int bad_reg = -1;
/* Table to map a gdb regnum to an index in the core register
section. The floating point register values are garbage in
OSF/1.2 core files. OSF5 uses different names for the register
enum list, need to handle two cases. The actual values are the
same. */
static int core_reg_mapping[NUM_REGS] =
{
#ifdef NCF_REGS
#define EFL NCF_REGS
CF_V0, CF_T0, CF_T1, CF_T2, CF_T3, CF_T4, CF_T5, CF_T6,
CF_T7, CF_S0, CF_S1, CF_S2, CF_S3, CF_S4, CF_S5, CF_S6,
CF_A0, CF_A1, CF_A2, CF_A3, CF_A4, CF_A5, CF_T8, CF_T9,
CF_T10, CF_T11, CF_RA, CF_T12, CF_AT, CF_GP, CF_SP, -1,
EFL + 0, EFL + 1, EFL + 2, EFL + 3, EFL + 4, EFL + 5, EFL + 6, EFL + 7,
EFL + 8, EFL + 9, EFL + 10, EFL + 11, EFL + 12, EFL + 13, EFL + 14, EFL + 15,
EFL + 16, EFL + 17, EFL + 18, EFL + 19, EFL + 20, EFL + 21, EFL + 22, EFL + 23,
EFL + 24, EFL + 25, EFL + 26, EFL + 27, EFL + 28, EFL + 29, EFL + 30, EFL + 31,
CF_PC, -1
#else
#define EFL (EF_SIZE / 8)
EF_V0, EF_T0, EF_T1, EF_T2, EF_T3, EF_T4, EF_T5, EF_T6,
EF_T7, EF_S0, EF_S1, EF_S2, EF_S3, EF_S4, EF_S5, EF_S6,
EF_A0, EF_A1, EF_A2, EF_A3, EF_A4, EF_A5, EF_T8, EF_T9,
EF_T10, EF_T11, EF_RA, EF_T12, EF_AT, EF_GP, EF_SP, -1,
EFL + 0, EFL + 1, EFL + 2, EFL + 3, EFL + 4, EFL + 5, EFL + 6, EFL + 7,
EFL + 8, EFL + 9, EFL + 10, EFL + 11, EFL + 12, EFL + 13, EFL + 14, EFL + 15,
EFL + 16, EFL + 17, EFL + 18, EFL + 19, EFL + 20, EFL + 21, EFL + 22, EFL + 23,
EFL + 24, EFL + 25, EFL + 26, EFL + 27, EFL + 28, EFL + 29, EFL + 30, EFL + 31,
EF_PC, -1
#endif
};
static char zerobuf[MAX_REGISTER_RAW_SIZE] =
{0};
for (regno = 0; regno < NUM_REGS; regno++)
{
if (CANNOT_FETCH_REGISTER (regno))
{
supply_register (regno, zerobuf);
continue;
}
addr = 8 * core_reg_mapping[regno];
if (addr < 0 || addr >= core_reg_size)
{
if (bad_reg < 0)
bad_reg = regno;
}
else
{
supply_register (regno, core_reg_sect + addr);
}
}
if (bad_reg >= 0)
{
error ("Register %s not found in core file.", REGISTER_NAME (bad_reg));
}
}
static void
fetch_elf_core_registers (char *core_reg_sect, unsigned core_reg_size,
int which, CORE_ADDR reg_addr)
{
if (core_reg_size < 32 * 8)
{
error ("Core file register section too small (%u bytes).", core_reg_size);
return;
}
if (which == 2)
{
/* The FPU Registers. */
memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], core_reg_sect, 31 * 8);
memset (&registers[REGISTER_BYTE (FP0_REGNUM + 31)], 0, 8);
memset (&register_valid[FP0_REGNUM], 1, 32);
}
else
{
/* The General Registers. */
memcpy (&registers[REGISTER_BYTE (V0_REGNUM)], core_reg_sect, 31 * 8);
memcpy (&registers[REGISTER_BYTE (PC_REGNUM)], core_reg_sect + 31 * 8, 8);
memset (&registers[REGISTER_BYTE (ZERO_REGNUM)], 0, 8);
memset (&register_valid[V0_REGNUM], 1, 32);
register_valid[PC_REGNUM] = 1;
}
}
/* Map gdb internal register number to a ptrace ``address''.
These ``addresses'' are defined in <sys/ptrace.h> */
#define REGISTER_PTRACE_ADDR(regno) \
(regno < FP0_REGNUM ? GPR_BASE + (regno) \
: regno == PC_REGNUM ? PC \
: regno >= FP0_REGNUM ? FPR_BASE + ((regno) - FP0_REGNUM) \
: 0)
/* Return the ptrace ``address'' of register REGNO. */
CORE_ADDR
register_addr (int regno, CORE_ADDR blockend)
{
return REGISTER_PTRACE_ADDR (regno);
}
int
kernel_u_size (void)
{
return (sizeof (struct user));
}
#if defined(USE_PROC_FS) || defined(HAVE_GREGSET_T)
#include <sys/procfs.h>
/* Prototypes for supply_gregset etc. */
#include "gregset.h"
/*
* See the comment in m68k-tdep.c regarding the utility of these functions.
*/
void
supply_gregset (gdb_gregset_t *gregsetp)
{
register int regi;
register long *regp = ALPHA_REGSET_BASE (gregsetp);
static char zerobuf[MAX_REGISTER_RAW_SIZE] =
{0};
for (regi = 0; regi < 31; regi++)
supply_register (regi, (char *) (regp + regi));
supply_register (PC_REGNUM, (char *) (regp + 31));
/* Fill inaccessible registers with zero. */
supply_register (ZERO_REGNUM, zerobuf);
supply_register (FP_REGNUM, zerobuf);
}
void
fill_gregset (gdb_gregset_t *gregsetp, int regno)
{
int regi;
register long *regp = ALPHA_REGSET_BASE (gregsetp);
for (regi = 0; regi < 31; regi++)
if ((regno == -1) || (regno == regi))
*(regp + regi) = *(long *) &registers[REGISTER_BYTE (regi)];
if ((regno == -1) || (regno == PC_REGNUM))
*(regp + 31) = *(long *) &registers[REGISTER_BYTE (PC_REGNUM)];
}
/*
* Now we do the same thing for floating-point registers.
* Again, see the comments in m68k-tdep.c.
*/
void
supply_fpregset (gdb_fpregset_t *fpregsetp)
{
register int regi;
register long *regp = ALPHA_REGSET_BASE (fpregsetp);
for (regi = 0; regi < 32; regi++)
supply_register (regi + FP0_REGNUM, (char *) (regp + regi));
}
void
fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
{
int regi;
register long *regp = ALPHA_REGSET_BASE (fpregsetp);
for (regi = FP0_REGNUM; regi < FP0_REGNUM + 32; regi++)
{
if ((regno == -1) || (regno == regi))
{
*(regp + regi - FP0_REGNUM) =
*(long *) &registers[REGISTER_BYTE (regi)];
}
}
}
#endif
/* Register that we are able to handle alpha core file formats. */
static struct core_fns alpha_osf_core_fns =
{
/* This really is bfd_target_unknown_flavour. */
bfd_target_unknown_flavour, /* core_flavour */
default_check_format, /* check_format */
default_core_sniffer, /* core_sniffer */
fetch_osf_core_registers, /* core_read_registers */
NULL /* next */
};
static struct core_fns alpha_elf_core_fns =
{
bfd_target_elf_flavour, /* core_flavour */
default_check_format, /* check_format */
default_core_sniffer, /* core_sniffer */
fetch_elf_core_registers, /* core_read_registers */
NULL /* next */
};
void
_initialize_core_alpha (void)
{
add_core_fns (&alpha_osf_core_fns);
add_core_fns (&alpha_elf_core_fns);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,134 +0,0 @@
/* Handle COFF SVR3 shared libraries for GDB, the GNU Debugger.
Copyright 1993, 1994, 1998, 1999, 2000 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "frame.h"
#include "bfd.h"
#include "gdbcore.h"
#include "symtab.h"
#include "symfile.h"
#include "objfiles.h"
/*
GLOBAL FUNCTION
coff_solib_add -- add a shared library files to the symtab list. We
examine the `.lib' section of the exec file and determine the names of
the shared libraries.
This function is responsible for discovering those names and
addresses, and saving sufficient information about them to allow
their symbols to be read at a later time.
SYNOPSIS
void coff_solib_add (char *arg_string, int from_tty,
struct target_ops *target, int readsyms)
DESCRIPTION
*/
void
coff_solib_add (char *arg_string, int from_tty, struct target_ops *target, int readsyms)
{
asection *libsect;
if (!readsyms)
return;
libsect = bfd_get_section_by_name (exec_bfd, ".lib");
if (libsect)
{
int libsize;
unsigned char *lib;
struct libent
{
bfd_byte len[4];
bfd_byte nameoffset[4];
};
libsize = bfd_section_size (exec_bfd, libsect);
lib = (unsigned char *) alloca (libsize);
bfd_get_section_contents (exec_bfd, libsect, lib, 0, libsize);
while (libsize > 0)
{
struct libent *ent;
struct objfile *objfile;
int len, nameoffset;
char *filename;
ent = (struct libent *) lib;
len = bfd_get_32 (exec_bfd, ent->len);
nameoffset = bfd_get_32 (exec_bfd, ent->nameoffset);
if (len <= 0)
break;
filename = (char *) ent + nameoffset * 4;
objfile = symbol_file_add (filename, from_tty,
NULL, /* no offsets */
0, /* not mainline */
OBJF_SHARED); /* flags */
libsize -= len * 4;
lib += len * 4;
}
/* Getting new symbols may change our opinion about what is
frameless. */
reinit_frame_cache ();
}
}
/*
GLOBAL FUNCTION
coff_solib_create_inferior_hook -- shared library startup support
SYNOPSIS
void coff_solib_create_inferior_hook()
DESCRIPTION
When gdb starts up the inferior, the kernel maps in the shared
libraries. We get here with the target stopped at it's first
instruction, and the libraries already mapped. At this point, this
function gets called via expansion of the macro
SOLIB_CREATE_INFERIOR_HOOK.
*/
void
coff_solib_create_inferior_hook (void)
{
coff_solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add);
}

View File

@ -1,186 +0,0 @@
/* COFF (SVR3) Shared library declarations for GDB, the GNU Debugger.
Copyright 1992, 1993, 1998, 1999, 2000 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Forward decl's for prototypes */
struct target_ops;
/* Called when we free all symtabs, to free the shared library information
as well. */
#if 0
#define CLEAR_SOLIB coff_clear_solib
extern void coff_clear_solib (void);
#endif
/* Called to add symbols from a shared library to gdb's symbol table. */
#define SOLIB_ADD(filename, from_tty, targ, readsyms) \
coff_solib_add (filename, from_tty, targ, readsyms)
extern void coff_solib_add (char *, int, struct target_ops *, int);
/* Function to be called when the inferior starts up, to discover the names
of shared libraries that are dynamically linked, the base addresses to
which they are linked, and sufficient information to read in their symbols
at a later time. */
#define SOLIB_CREATE_INFERIOR_HOOK(PID) coff_solib_create_inferior_hook()
extern void coff_solib_create_inferior_hook (void); /* solib.c */
/* Function to be called to remove the connection between debugger and
dynamic linker that was established by SOLIB_CREATE_INFERIOR_HOOK.
(This operation does not remove shared library information from
the debugger, as CLEAR_SOLIB does.)
This functionality is presently not implemented for this target.
*/
#define SOLIB_REMOVE_INFERIOR_HOOK(PID) (0)
/* This function is called by the "catch load" command. It allows
the debugger to be notified by the dynamic linker when a specified
library file (or any library file, if filename is NULL) is loaded.
Presently, this functionality is not implemented.
*/
#define SOLIB_CREATE_CATCH_LOAD_HOOK(pid,tempflag,filename,cond_string) \
error("catch of library loads/unloads not yet implemented on this platform")
/* This function is called by the "catch unload" command. It allows
the debugger to be notified by the dynamic linker when a specified
library file (or any library file, if filename is NULL) is unloaded.
Presently, this functionality is not implemented.
*/
#define SOLIB_CREATE_CATCH_UNLOAD_HOOK(pid,tempflag,filename,cond_string) \
error("catch of library loads/unloads not yet implemented on this platform")
/* This function returns TRUE if the dynamic linker has just reported
a load of a library.
This function must be used only when the inferior has stopped in
the dynamic linker hook, or undefined results are guaranteed.
Presently, this functionality is not implemented.
*/
/*
#define SOLIB_HAVE_LOAD_EVENT(pid) \
error("catch of library loads/unloads not yet implemented on this platform")
*/
#define SOLIB_HAVE_LOAD_EVENT(pid) \
(0)
/* This function returns a pointer to the string representation of the
pathname of the dynamically-linked library that has just been loaded.
This function must be used only when SOLIB_HAVE_LOAD_EVENT is TRUE,
or undefined results are guaranteed.
This string's contents are only valid immediately after the inferior
has stopped in the dynamic linker hook, and becomes invalid as soon
as the inferior is continued. Clients should make a copy of this
string if they wish to continue the inferior and then access the string.
Presently, this functionality is not implemented.
*/
/*
#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) \
error("catch of library loads/unloads not yet implemented on this platform")
*/
#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) \
(0)
/* This function returns TRUE if the dynamic linker has just reported
an unload of a library.
This function must be used only when the inferior has stopped in
the dynamic linker hook, or undefined results are guaranteed.
Presently, this functionality is not implemented.
*/
/*
#define SOLIB_HAVE_UNLOAD_EVENT(pid) \
error("catch of library loads/unloads not yet implemented on this platform")
*/
#define SOLIB_HAVE_UNLOAD_EVENT(pid) \
(0)
/* This function returns a pointer to the string representation of the
pathname of the dynamically-linked library that has just been unloaded.
This function must be used only when SOLIB_HAVE_UNLOAD_EVENT is TRUE,
or undefined results are guaranteed.
This string's contents are only valid immediately after the inferior
has stopped in the dynamic linker hook, and becomes invalid as soon
as the inferior is continued. Clients should make a copy of this
string if they wish to continue the inferior and then access the string.
Presently, this functionality is not implemented.
*/
/*
#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) \
error("catch of library loads/unloads not yet implemented on this platform")
*/
#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) \
(0)
/* This function returns TRUE if pc is the address of an instruction that
lies within the dynamic linker (such as the event hook, or the dld
itself).
This function must be used only when a dynamic linker event has been
caught, and the inferior is being stepped out of the hook, or undefined
results are guaranteed.
Presently, this functionality is not implemented.
*/
/*
#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) \
error("catch of library loads/unloads not yet implemented on this platform")
*/
#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) \
(0)
/* This function must be called when the inferior is killed, and the program
restarted. This is not the same as CLEAR_SOLIB, in that it doesn't discard
any symbol tables.
Presently, this functionality is not implemented.
*/
#define SOLIB_RESTART() \
(0)
/* If we can't set a breakpoint, and it's in a shared library, just
disable it. */
#if 0
#define DISABLE_UNSETTABLE_BREAK(addr) coff_solib_address(addr)
extern int solib_address (CORE_ADDR); /* solib.c */
#endif

View File

@ -1,196 +0,0 @@
/* Machine independent support for Solaris 2 core files for GDB.
Copyright 1994, 1995, 1996, 1998, 1999, 2000, 2001
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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Solaris comes with two flavours of core files, cores generated by
an ELF executable and cores generated by programs that were
run under BCP (the part of Solaris which allows it to run SunOS4
a.out files).
This file combines the core register fetching from core-regset.c
and sparc-nat.c to be able to read both flavours. */
/* for Sparc64 cross Sparc32 */
#define _SYSCALL32
#include "defs.h"
#if defined (__sparcv9)
/* Fails to get included by the Solaris system header files. */
# include <v9/sys/privregs.h>
#endif
#include <time.h>
#include <sys/types.h>
#include <sys/regset.h>
#include <sys/procfs.h>
#include <fcntl.h>
#include <errno.h>
#include "gdb_string.h"
#include "regcache.h"
#include "inferior.h"
#include "target.h"
#include "command.h"
#include "gdbcore.h"
/* Prototypes for supply_gregset etc. */
#include "gregset.h"
static void fetch_core_registers (char *, unsigned, int, CORE_ADDR);
/* Fetch registers from core file data pointed to by CORE_REG_SECT. When
WHICH is 0, the the general register set is fetched; when WHICH is
2, the floating point registers are fetched. CORE_REG_SIZE is used
to validate the size of the data pointed to by CORE_REG_SECT. REG_ADDR
is unused. */
static void
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
CORE_ADDR reg_addr)
{
int i;
if (which == 0)
{
prgregset_t prgregset;
if (core_reg_size == sizeof (prgregset_t))
{
memcpy ((char *) &prgregset, core_reg_sect, sizeof (prgregset));
supply_gregset (&prgregset);
}
#if defined (HAVE_PRGREGSET32_T)
/* 32-bit corefile, 64-bit debugger. */
else if (core_reg_size == sizeof (prgregset32_t))
{
prgreg32_t *core_gregs;
/* Can't use memcpy here, because the core file contains
32-bit regs; supply_register expects 64-bit regs. */
core_gregs = (prgreg32_t *) core_reg_sect;
for (i = 0; i < NPRGREG; i++)
prgregset[i] = core_gregs[i];
supply_gregset (&prgregset);
}
#endif /* HAVE_PRGREGSET32_T */
else if (core_reg_size == sizeof (struct regs))
{
struct regs *gregs = (struct regs *) core_reg_sect;
/* G0 *always* holds 0. */
*(int *) &registers[REGISTER_BYTE (0)] = 0;
/* The globals and output registers. */
memcpy (&registers[REGISTER_BYTE (G1_REGNUM)], &gregs->r_g1,
15 * REGISTER_RAW_SIZE (G1_REGNUM));
*(int *) &registers[REGISTER_BYTE (PS_REGNUM)] = gregs->r_ps;
*(int *) &registers[REGISTER_BYTE (PC_REGNUM)] = gregs->r_pc;
*(int *) &registers[REGISTER_BYTE (NPC_REGNUM)] = gregs->r_npc;
*(int *) &registers[REGISTER_BYTE (Y_REGNUM)] = gregs->r_y;
/* My best guess at where to get the locals and input
registers is exactly where they usually are, right above
the stack pointer. If the core dump was caused by a bus error
from blowing away the stack pointer (as is possible) then this
won't work, but it's worth the try. */
{
int sp;
sp = *(int *) &registers[REGISTER_BYTE (SP_REGNUM)];
if (0 != target_read_memory (sp,
&registers[REGISTER_BYTE (L0_REGNUM)],
16 * REGISTER_RAW_SIZE (L0_REGNUM)))
{
warning ("couldn't read input and local registers from core file\n");
}
}
}
else
{
warning ("wrong size gregset struct in core file");
}
}
else if (which == 2)
{
prfpregset_t prfpregset;
if (core_reg_size == sizeof (prfpregset_t))
{
memcpy ((char *) &prfpregset, core_reg_sect, sizeof (prfpregset));
supply_fpregset (&prfpregset);
}
#if defined (HAVE_PRFPREGSET32_T)
/* 32-bit corefile, 64-bit debugger. */
else if (core_reg_size == sizeof (prfpregset32_t))
{
prfpregset32_t *core_fpregset;
/* Can't use memcpy here, because the core file contains
32-bit regs; supply_fpregset expects 64-bit regs. */
core_fpregset = (prfpregset32_t *) core_reg_sect;
for (i = 0; i < 16; i++)
prfpregset.pr_fr.pr_dregs[i] = core_fpregset->pr_fr.pr_dregs[i];
while (i < 32)
prfpregset.pr_fr.pr_dregs[i++] = 0;
prfpregset.pr_fsr = core_fpregset->pr_fsr;
prfpregset.pr_qcnt = core_fpregset->pr_qcnt;
prfpregset.pr_q_entrysize = core_fpregset->pr_q_entrysize;
prfpregset.pr_en = core_fpregset->pr_en;
/* We will not use the pr_q array. */
supply_fpregset (&prfpregset);
}
#endif /* HAVE_PRFPREGSET32_T */
else if (core_reg_size >= sizeof (struct fpu))
{
struct fpu *fpuregs = (struct fpu *) core_reg_sect;
memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], &fpuregs->fpu_fr,
sizeof (fpuregs->fpu_fr));
memcpy (&registers[REGISTER_BYTE (FPS_REGNUM)], &fpuregs->fpu_fsr,
sizeof (FPU_FSR_TYPE));
}
else
{
warning ("wrong size fpregset struct in core file");
}
}
}
/* Register that we are able to handle solaris core file formats. */
static struct core_fns solaris_core_fns =
{
bfd_target_elf_flavour, /* core_flavour */
default_check_format, /* check_format */
default_core_sniffer, /* core_sniffer */
fetch_core_registers, /* core_read_registers */
NULL /* next */
};
void
_initialize_core_solaris (void)
{
add_core_fns (&solaris_core_fns);
}

View File

@ -1,601 +0,0 @@
/* Target-dependent code for the Fujitsu FR30.
Copyright 1999, 2000, 2001 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include "obstack.h"
#include "target.h"
#include "value.h"
#include "bfd.h"
#include "gdb_string.h"
#include "gdbcore.h"
#include "symfile.h"
#include "regcache.h"
/* An expression that tells us whether the function invocation represented
by FI does not have a frame on the stack associated with it. */
int
fr30_frameless_function_invocation (struct frame_info *fi)
{
int frameless;
CORE_ADDR func_start, after_prologue;
func_start = (get_pc_function_start ((fi)->pc) +
FUNCTION_START_OFFSET);
after_prologue = func_start;
after_prologue = SKIP_PROLOGUE (after_prologue);
frameless = (after_prologue == func_start);
return frameless;
}
/* Function: pop_frame
This routine gets called when either the user uses the `return'
command, or the call dummy breakpoint gets hit. */
void
fr30_pop_frame (void)
{
struct frame_info *frame = get_current_frame ();
int regnum;
CORE_ADDR sp = read_register (SP_REGNUM);
if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
generic_pop_dummy_frame ();
else
{
write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
for (regnum = 0; regnum < NUM_REGS; regnum++)
if (frame->fsr.regs[regnum] != 0)
{
write_register (regnum,
read_memory_unsigned_integer (frame->fsr.regs[regnum],
REGISTER_RAW_SIZE (regnum)));
}
write_register (SP_REGNUM, sp + frame->framesize);
}
flush_cached_frames ();
}
/* Function: fr30_store_return_value
Put a value where a caller expects to see it. Used by the 'return'
command. */
void
fr30_store_return_value (struct type *type,
char *valbuf)
{
/* Here's how the FR30 returns values (gleaned from gcc/config/
fr30/fr30.h):
If the return value is 32 bits long or less, it goes in r4.
If the return value is 64 bits long or less, it goes in r4 (most
significant word) and r5 (least significant word.
If the function returns a structure, of any size, the caller
passes the function an invisible first argument where the callee
should store the value. But GDB doesn't let you do that anyway.
If you're returning a value smaller than a word, it's not really
necessary to zero the upper bytes of the register; the caller is
supposed to ignore them. However, the FR30 typically keeps its
values extended to the full register width, so we should emulate
that. */
/* The FR30 is big-endian, so if we return a small value (like a
short or a char), we need to position it correctly within the
register. We round the size up to a register boundary, and then
adjust the offset so as to place the value at the right end. */
int value_size = TYPE_LENGTH (type);
int returned_size = (value_size + FR30_REGSIZE - 1) & ~(FR30_REGSIZE - 1);
int offset = (REGISTER_BYTE (RETVAL_REG)
+ (returned_size - value_size));
char *zeros = alloca (returned_size);
memset (zeros, 0, returned_size);
write_register_bytes (REGISTER_BYTE (RETVAL_REG), zeros, returned_size);
write_register_bytes (offset, valbuf, value_size);
}
/* Function: skip_prologue
Return the address of the first code past the prologue of the function. */
CORE_ADDR
fr30_skip_prologue (CORE_ADDR pc)
{
CORE_ADDR func_addr, func_end;
/* See what the symbol table says */
if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
{
struct symtab_and_line sal;
sal = find_pc_line (func_addr, 0);
if (sal.line != 0 && sal.end < func_end)
{
return sal.end;
}
}
/* Either we didn't find the start of this function (nothing we can do),
or there's no line info, or the line after the prologue is after
the end of the function (there probably isn't a prologue). */
return pc;
}
/* Function: push_arguments
Setup arguments and RP for a call to the target. First four args
go in FIRST_ARGREG -> LAST_ARGREG, subsequent args go on stack...
Structs are passed by reference. XXX not right now Z.R.
64 bit quantities (doubles and long longs) may be split between
the regs and the stack.
When calling a function that returns a struct, a pointer to the struct
is passed in as a secret first argument (always in FIRST_ARGREG).
Stack space for the args has NOT been allocated: that job is up to us.
*/
CORE_ADDR
fr30_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
int struct_return, CORE_ADDR struct_addr)
{
int argreg;
int argnum;
int stack_offset;
struct stack_arg
{
char *val;
int len;
int offset;
};
struct stack_arg *stack_args =
(struct stack_arg *) alloca (nargs * sizeof (struct stack_arg));
int nstack_args = 0;
argreg = FIRST_ARGREG;
/* the struct_return pointer occupies the first parameter-passing reg */
if (struct_return)
write_register (argreg++, struct_addr);
stack_offset = 0;
/* Process args from left to right. Store as many as allowed in
registers, save the rest to be pushed on the stack */
for (argnum = 0; argnum < nargs; argnum++)
{
char *val;
struct value *arg = args[argnum];
struct type *arg_type = check_typedef (VALUE_TYPE (arg));
struct type *target_type = TYPE_TARGET_TYPE (arg_type);
int len = TYPE_LENGTH (arg_type);
enum type_code typecode = TYPE_CODE (arg_type);
CORE_ADDR regval;
int newarg;
val = (char *) VALUE_CONTENTS (arg);
{
/* Copy the argument to general registers or the stack in
register-sized pieces. Large arguments are split between
registers and stack. */
while (len > 0)
{
if (argreg <= LAST_ARGREG)
{
int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE;
regval = extract_address (val, partial_len);
/* It's a simple argument being passed in a general
register. */
write_register (argreg, regval);
argreg++;
len -= partial_len;
val += partial_len;
}
else
{
/* keep for later pushing */
stack_args[nstack_args].val = val;
stack_args[nstack_args++].len = len;
break;
}
}
}
}
/* now do the real stack pushing, process args right to left */
while (nstack_args--)
{
sp -= stack_args[nstack_args].len;
write_memory (sp, stack_args[nstack_args].val,
stack_args[nstack_args].len);
}
/* Return adjusted stack pointer. */
return sp;
}
void _initialize_fr30_tdep (void);
void
_initialize_fr30_tdep (void)
{
extern int print_insn_fr30 (bfd_vma, disassemble_info *);
tm_print_insn = print_insn_fr30;
}
/* Function: check_prologue_cache
Check if prologue for this frame's PC has already been scanned.
If it has, copy the relevant information about that prologue and
return non-zero. Otherwise do not copy anything and return zero.
The information saved in the cache includes:
* the frame register number;
* the size of the stack frame;
* the offsets of saved regs (relative to the old SP); and
* the offset from the stack pointer to the frame pointer
The cache contains only one entry, since this is adequate
for the typical sequence of prologue scan requests we get.
When performing a backtrace, GDB will usually ask to scan
the same function twice in a row (once to get the frame chain,
and once to fill in the extra frame information).
*/
static struct frame_info prologue_cache;
static int
check_prologue_cache (struct frame_info *fi)
{
int i;
if (fi->pc == prologue_cache.pc)
{
fi->framereg = prologue_cache.framereg;
fi->framesize = prologue_cache.framesize;
fi->frameoffset = prologue_cache.frameoffset;
for (i = 0; i <= NUM_REGS; i++)
fi->fsr.regs[i] = prologue_cache.fsr.regs[i];
return 1;
}
else
return 0;
}
/* Function: save_prologue_cache
Copy the prologue information from fi to the prologue cache.
*/
static void
save_prologue_cache (struct frame_info *fi)
{
int i;
prologue_cache.pc = fi->pc;
prologue_cache.framereg = fi->framereg;
prologue_cache.framesize = fi->framesize;
prologue_cache.frameoffset = fi->frameoffset;
for (i = 0; i <= NUM_REGS; i++)
{
prologue_cache.fsr.regs[i] = fi->fsr.regs[i];
}
}
/* Function: scan_prologue
Scan the prologue of the function that contains PC, and record what
we find in PI. PI->fsr must be zeroed by the called. Returns the
pc after the prologue. Note that the addresses saved in pi->fsr
are actually just frame relative (negative offsets from the frame
pointer). This is because we don't know the actual value of the
frame pointer yet. In some circumstances, the frame pointer can't
be determined till after we have scanned the prologue. */
static void
fr30_scan_prologue (struct frame_info *fi)
{
int sp_offset, fp_offset;
CORE_ADDR prologue_start, prologue_end, current_pc;
/* Check if this function is already in the cache of frame information. */
if (check_prologue_cache (fi))
return;
/* Assume there is no frame until proven otherwise. */
fi->framereg = SP_REGNUM;
fi->framesize = 0;
fi->frameoffset = 0;
/* Find the function prologue. If we can't find the function in
the symbol table, peek in the stack frame to find the PC. */
if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
{
/* Assume the prologue is everything between the first instruction
in the function and the first source line. */
struct symtab_and_line sal = find_pc_line (prologue_start, 0);
if (sal.line == 0) /* no line info, use current PC */
prologue_end = fi->pc;
else if (sal.end < prologue_end) /* next line begins after fn end */
prologue_end = sal.end; /* (probably means no prologue) */
}
else
{
/* XXX Z.R. What now??? The following is entirely bogus */
prologue_start = (read_memory_integer (fi->frame, 4) & 0x03fffffc) - 12;
prologue_end = prologue_start + 40;
}
/* Now search the prologue looking for instructions that set up the
frame pointer, adjust the stack pointer, and save registers. */
sp_offset = fp_offset = 0;
for (current_pc = prologue_start; current_pc < prologue_end; current_pc += 2)
{
unsigned int insn;
insn = read_memory_unsigned_integer (current_pc, 2);
if ((insn & 0xfe00) == 0x8e00) /* stm0 or stm1 */
{
int reg, mask = insn & 0xff;
/* scan in one sweep - create virtual 16-bit mask from either insn's mask */
if ((insn & 0x0100) == 0)
{
mask <<= 8; /* stm0 - move to upper byte in virtual mask */
}
/* Calculate offsets of saved registers (to be turned later into addresses). */
for (reg = R4_REGNUM; reg <= R11_REGNUM; reg++)
if (mask & (1 << (15 - reg)))
{
sp_offset -= 4;
fi->fsr.regs[reg] = sp_offset;
}
}
else if ((insn & 0xfff0) == 0x1700) /* st rx,@-r15 */
{
int reg = insn & 0xf;
sp_offset -= 4;
fi->fsr.regs[reg] = sp_offset;
}
else if ((insn & 0xff00) == 0x0f00) /* enter */
{
fp_offset = fi->fsr.regs[FP_REGNUM] = sp_offset - 4;
sp_offset -= 4 * (insn & 0xff);
fi->framereg = FP_REGNUM;
}
else if (insn == 0x1781) /* st rp,@-sp */
{
sp_offset -= 4;
fi->fsr.regs[RP_REGNUM] = sp_offset;
}
else if (insn == 0x170e) /* st fp,@-sp */
{
sp_offset -= 4;
fi->fsr.regs[FP_REGNUM] = sp_offset;
}
else if (insn == 0x8bfe) /* mov sp,fp */
{
fi->framereg = FP_REGNUM;
}
else if ((insn & 0xff00) == 0xa300) /* addsp xx */
{
sp_offset += 4 * (signed char) (insn & 0xff);
}
else if ((insn & 0xff0f) == 0x9b00 && /* ldi:20 xx,r0 */
read_memory_unsigned_integer (current_pc + 4, 2)
== 0xac0f) /* sub r0,sp */
{
/* large stack adjustment */
sp_offset -= (((insn & 0xf0) << 12) | read_memory_unsigned_integer (current_pc + 2, 2));
current_pc += 4;
}
else if (insn == 0x9f80 && /* ldi:32 xx,r0 */
read_memory_unsigned_integer (current_pc + 6, 2)
== 0xac0f) /* sub r0,sp */
{
/* large stack adjustment */
sp_offset -=
(read_memory_unsigned_integer (current_pc + 2, 2) << 16 |
read_memory_unsigned_integer (current_pc + 4, 2));
current_pc += 6;
}
}
/* The frame size is just the negative of the offset (from the original SP)
of the last thing thing we pushed on the stack. The frame offset is
[new FP] - [new SP]. */
fi->framesize = -sp_offset;
fi->frameoffset = fp_offset - sp_offset;
save_prologue_cache (fi);
}
/* Function: init_extra_frame_info
Setup the frame's frame pointer, pc, and frame addresses for saved
registers. Most of the work is done in scan_prologue().
Note that when we are called for the last frame (currently active frame),
that fi->pc and fi->frame will already be setup. However, fi->frame will
be valid only if this routine uses FP. For previous frames, fi-frame will
always be correct (since that is derived from fr30_frame_chain ()).
We can be called with the PC in the call dummy under two circumstances.
First, during normal backtracing, second, while figuring out the frame
pointer just prior to calling the target function (see run_stack_dummy). */
void
fr30_init_extra_frame_info (struct frame_info *fi)
{
int reg;
if (fi->next)
fi->pc = FRAME_SAVED_PC (fi->next);
memset (fi->fsr.regs, '\000', sizeof fi->fsr.regs);
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
{
/* We need to setup fi->frame here because run_stack_dummy gets it wrong
by assuming it's always FP. */
fi->frame = generic_read_register_dummy (fi->pc, fi->frame, SP_REGNUM);
fi->framesize = 0;
fi->frameoffset = 0;
return;
}
fr30_scan_prologue (fi);
if (!fi->next) /* this is the innermost frame? */
fi->frame = read_register (fi->framereg);
else
/* not the innermost frame */
/* If we have an FP, the callee saved it. */
if (fi->framereg == FP_REGNUM)
if (fi->next->fsr.regs[fi->framereg] != 0)
fi->frame = read_memory_integer (fi->next->fsr.regs[fi->framereg], 4);
/* Calculate actual addresses of saved registers using offsets determined
by fr30_scan_prologue. */
for (reg = 0; reg < NUM_REGS; reg++)
if (fi->fsr.regs[reg] != 0)
{
fi->fsr.regs[reg] += fi->frame + fi->framesize - fi->frameoffset;
}
}
/* Function: find_callers_reg
Find REGNUM on the stack. Otherwise, it's in an active register.
One thing we might want to do here is to check REGNUM against the
clobber mask, and somehow flag it as invalid if it isn't saved on
the stack somewhere. This would provide a graceful failure mode
when trying to get the value of caller-saves registers for an inner
frame. */
CORE_ADDR
fr30_find_callers_reg (struct frame_info *fi, int regnum)
{
for (; fi; fi = fi->next)
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
return generic_read_register_dummy (fi->pc, fi->frame, regnum);
else if (fi->fsr.regs[regnum] != 0)
return read_memory_unsigned_integer (fi->fsr.regs[regnum],
REGISTER_RAW_SIZE (regnum));
return read_register (regnum);
}
/* Function: frame_chain
Figure out the frame prior to FI. Unfortunately, this involves
scanning the prologue of the caller, which will also be done
shortly by fr30_init_extra_frame_info. For the dummy frame, we
just return the stack pointer that was in use at the time the
function call was made. */
CORE_ADDR
fr30_frame_chain (struct frame_info *fi)
{
CORE_ADDR fn_start, callers_pc, fp;
struct frame_info caller_fi;
int framereg;
/* is this a dummy frame? */
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
return fi->frame; /* dummy frame same as caller's frame */
/* is caller-of-this a dummy frame? */
callers_pc = FRAME_SAVED_PC (fi); /* find out who called us: */
fp = fr30_find_callers_reg (fi, FP_REGNUM);
if (PC_IN_CALL_DUMMY (callers_pc, fp, fp))
return fp; /* dummy frame's frame may bear no relation to ours */
if (find_pc_partial_function (fi->pc, 0, &fn_start, 0))
if (fn_start == entry_point_address ())
return 0; /* in _start fn, don't chain further */
framereg = fi->framereg;
/* If the caller is the startup code, we're at the end of the chain. */
if (find_pc_partial_function (callers_pc, 0, &fn_start, 0))
if (fn_start == entry_point_address ())
return 0;
memset (&caller_fi, 0, sizeof (caller_fi));
caller_fi.pc = callers_pc;
fr30_scan_prologue (&caller_fi);
framereg = caller_fi.framereg;
/* If the caller used a frame register, return its value.
Otherwise, return the caller's stack pointer. */
if (framereg == FP_REGNUM)
return fr30_find_callers_reg (fi, framereg);
else
return fi->frame + fi->framesize;
}
/* Function: frame_saved_pc
Find the caller of this frame. We do this by seeing if RP_REGNUM
is saved in the stack anywhere, otherwise we get it from the
registers. If the inner frame is a dummy frame, return its PC
instead of RP, because that's where "caller" of the dummy-frame
will be found. */
CORE_ADDR
fr30_frame_saved_pc (struct frame_info *fi)
{
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
return generic_read_register_dummy (fi->pc, fi->frame, PC_REGNUM);
else
return fr30_find_callers_reg (fi, RP_REGNUM);
}
/* Function: fix_call_dummy
Pokes the callee function's address into the CALL_DUMMY assembly stub.
Assumes that the CALL_DUMMY looks like this:
jarl <offset24>, r31
trap
*/
int
fr30_fix_call_dummy (char *dummy, CORE_ADDR sp, CORE_ADDR fun, int nargs,
struct value **args, struct type *type, int gcc_p)
{
long offset24;
offset24 = (long) fun - (long) entry_point_address ();
offset24 &= 0x3fffff;
offset24 |= 0xff800000; /* jarl <offset24>, r31 */
store_unsigned_integer ((unsigned int *) &dummy[2], 2, offset24 & 0xffff);
store_unsigned_integer ((unsigned int *) &dummy[0], 2, offset24 >> 16);
return 0;
}

View File

@ -1,952 +0,0 @@
/****************************************************************************
THIS SOFTWARE IS NOT COPYRIGHTED
HP offers the following for use in the public domain. HP makes no
warranty with regard to the software or it's performance and the
user accepts the software "AS IS" with all faults.
HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
****************************************************************************/
/****************************************************************************
* Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
*
* Module name: remcom.c $
* Revision: 1.34 $
* Date: 91/03/09 12:29:49 $
* Contributor: Lake Stevens Instrument Division$
*
* Description: low level support for gdb debugger. $
*
* Considerations: only works on target hardware $
*
* Written by: Glenn Engel $
* ModuleState: Experimental $
*
* NOTES: See Below $
*
* Modified for 386 by Jim Kingdon, Cygnus Support.
*
* To enable debugger support, two things need to happen. One, a
* call to set_debug_traps() is necessary in order to allow any breakpoints
* or error conditions to be properly intercepted and reported to gdb.
* Two, a breakpoint needs to be generated to begin communication. This
* is most easily accomplished by a call to breakpoint(). Breakpoint()
* simulates a breakpoint by executing a trap #1.
*
* The external function exceptionHandler() is
* used to attach a specific handler to a specific 386 vector number.
* It should use the same privilege level it runs at. It should
* install it as an interrupt gate so that interrupts are masked
* while the handler runs.
*
* Because gdb will sometimes write to the stack area to execute function
* calls, this program cannot rely on using the supervisor stack so it
* uses it's own stack area reserved in the int array remcomStack.
*
*************
*
* The following gdb commands are supported:
*
* command function Return value
*
* g return the value of the CPU registers hex data or ENN
* G set the value of the CPU registers OK or ENN
*
* mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
* MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
*
* c Resume at current address SNN ( signal NN)
* cAA..AA Continue at address AA..AA SNN
*
* s Step one instruction SNN
* sAA..AA Step one instruction from AA..AA SNN
*
* k kill
*
* ? What was the last sigval ? SNN (signal NN)
*
* All commands and responses are sent with a packet which includes a
* checksum. A packet consists of
*
* $<packet info>#<checksum>.
*
* where
* <packet info> :: <characters representing the command or response>
* <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
*
* When a packet is received, it is first acknowledged with either '+' or '-'.
* '+' indicates a successful transfer. '-' indicates a failed transfer.
*
* Example:
*
* Host: Reply:
* $m0,10#2a +$00010203040506070809101112131415#42
*
****************************************************************************/
#include <stdio.h>
#include <string.h>
/************************************************************************
*
* external low-level support routines
*/
extern void putDebugChar(); /* write a single character */
extern int getDebugChar(); /* read and return a single char */
extern void exceptionHandler(); /* assign an exception handler */
/************************************************************************/
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
/* at least NUMREGBYTES*2 are needed for register packets */
#define BUFMAX 400
static char initialized; /* boolean flag. != 0 means we've been initialized */
int remote_debug;
/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
static const char hexchars[]="0123456789abcdef";
/* Number of registers. */
#define NUMREGS 16
/* Number of bytes of registers. */
#define NUMREGBYTES (NUMREGS * 4)
enum regnames {EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
PC /* also known as eip */,
PS /* also known as eflags */,
CS, SS, DS, ES, FS, GS};
/*
* these should not be static cuz they can be used outside this module
*/
int registers[NUMREGS];
#define STACKSIZE 10000
int remcomStack[STACKSIZE/sizeof(int)];
static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
/*************************** ASSEMBLY CODE MACROS *************************/
/* */
extern void
return_to_prog ();
/* Restore the program's registers (including the stack pointer, which
means we get the right stack and don't have to worry about popping our
return address and any stack frames and so on) and return. */
asm(".text");
asm(".globl _return_to_prog");
asm("_return_to_prog:");
asm(" movw _registers+44, %ss");
asm(" movl _registers+16, %esp");
asm(" movl _registers+4, %ecx");
asm(" movl _registers+8, %edx");
asm(" movl _registers+12, %ebx");
asm(" movl _registers+20, %ebp");
asm(" movl _registers+24, %esi");
asm(" movl _registers+28, %edi");
asm(" movw _registers+48, %ds");
asm(" movw _registers+52, %es");
asm(" movw _registers+56, %fs");
asm(" movw _registers+60, %gs");
asm(" movl _registers+36, %eax");
asm(" pushl %eax"); /* saved eflags */
asm(" movl _registers+40, %eax");
asm(" pushl %eax"); /* saved cs */
asm(" movl _registers+32, %eax");
asm(" pushl %eax"); /* saved eip */
asm(" movl _registers, %eax");
/* use iret to restore pc and flags together so
that trace flag works right. */
asm(" iret");
#define BREAKPOINT() asm(" int $3");
/* Put the error code here just in case the user cares. */
int gdb_i386errcode;
/* Likewise, the vector number here (since GDB only gets the signal
number through the usual means, and that's not very specific). */
int gdb_i386vector = -1;
/* GDB stores segment registers in 32-bit words (that's just the way
m-i386v.h is written). So zero the appropriate areas in registers. */
#define SAVE_REGISTERS1() \
asm ("movl %eax, _registers"); \
asm ("movl %ecx, _registers+4"); \
asm ("movl %edx, _registers+8"); \
asm ("movl %ebx, _registers+12"); \
asm ("movl %ebp, _registers+20"); \
asm ("movl %esi, _registers+24"); \
asm ("movl %edi, _registers+28"); \
asm ("movw $0, %ax"); \
asm ("movw %ds, _registers+48"); \
asm ("movw %ax, _registers+50"); \
asm ("movw %es, _registers+52"); \
asm ("movw %ax, _registers+54"); \
asm ("movw %fs, _registers+56"); \
asm ("movw %ax, _registers+58"); \
asm ("movw %gs, _registers+60"); \
asm ("movw %ax, _registers+62");
#define SAVE_ERRCODE() \
asm ("popl %ebx"); \
asm ("movl %ebx, _gdb_i386errcode");
#define SAVE_REGISTERS2() \
asm ("popl %ebx"); /* old eip */ \
asm ("movl %ebx, _registers+32"); \
asm ("popl %ebx"); /* old cs */ \
asm ("movl %ebx, _registers+40"); \
asm ("movw %ax, _registers+42"); \
asm ("popl %ebx"); /* old eflags */ \
asm ("movl %ebx, _registers+36"); \
/* Now that we've done the pops, we can save the stack pointer."); */ \
asm ("movw %ss, _registers+44"); \
asm ("movw %ax, _registers+46"); \
asm ("movl %esp, _registers+16");
/* See if mem_fault_routine is set, if so just IRET to that address. */
#define CHECK_FAULT() \
asm ("cmpl $0, _mem_fault_routine"); \
asm ("jne mem_fault");
asm (".text");
asm ("mem_fault:");
/* OK to clobber temp registers; we're just going to end up in set_mem_err. */
/* Pop error code from the stack and save it. */
asm (" popl %eax");
asm (" movl %eax, _gdb_i386errcode");
asm (" popl %eax"); /* eip */
/* We don't want to return there, we want to return to the function
pointed to by mem_fault_routine instead. */
asm (" movl _mem_fault_routine, %eax");
asm (" popl %ecx"); /* cs (low 16 bits; junk in hi 16 bits). */
asm (" popl %edx"); /* eflags */
/* Remove this stack frame; when we do the iret, we will be going to
the start of a function, so we want the stack to look just like it
would after a "call" instruction. */
asm (" leave");
/* Push the stuff that iret wants. */
asm (" pushl %edx"); /* eflags */
asm (" pushl %ecx"); /* cs */
asm (" pushl %eax"); /* eip */
/* Zero mem_fault_routine. */
asm (" movl $0, %eax");
asm (" movl %eax, _mem_fault_routine");
asm ("iret");
#define CALL_HOOK() asm("call _remcomHandler");
/* This function is called when a i386 exception occurs. It saves
* all the cpu regs in the _registers array, munges the stack a bit,
* and invokes an exception handler (remcom_handler).
*
* stack on entry: stack on exit:
* old eflags vector number
* old cs (zero-filled to 32 bits)
* old eip
*
*/
extern void _catchException3();
asm(".text");
asm(".globl __catchException3");
asm("__catchException3:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $3");
CALL_HOOK();
/* Same thing for exception 1. */
extern void _catchException1();
asm(".text");
asm(".globl __catchException1");
asm("__catchException1:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $1");
CALL_HOOK();
/* Same thing for exception 0. */
extern void _catchException0();
asm(".text");
asm(".globl __catchException0");
asm("__catchException0:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $0");
CALL_HOOK();
/* Same thing for exception 4. */
extern void _catchException4();
asm(".text");
asm(".globl __catchException4");
asm("__catchException4:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $4");
CALL_HOOK();
/* Same thing for exception 5. */
extern void _catchException5();
asm(".text");
asm(".globl __catchException5");
asm("__catchException5:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $5");
CALL_HOOK();
/* Same thing for exception 6. */
extern void _catchException6();
asm(".text");
asm(".globl __catchException6");
asm("__catchException6:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $6");
CALL_HOOK();
/* Same thing for exception 7. */
extern void _catchException7();
asm(".text");
asm(".globl __catchException7");
asm("__catchException7:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $7");
CALL_HOOK();
/* Same thing for exception 8. */
extern void _catchException8();
asm(".text");
asm(".globl __catchException8");
asm("__catchException8:");
SAVE_REGISTERS1();
SAVE_ERRCODE();
SAVE_REGISTERS2();
asm ("pushl $8");
CALL_HOOK();
/* Same thing for exception 9. */
extern void _catchException9();
asm(".text");
asm(".globl __catchException9");
asm("__catchException9:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $9");
CALL_HOOK();
/* Same thing for exception 10. */
extern void _catchException10();
asm(".text");
asm(".globl __catchException10");
asm("__catchException10:");
SAVE_REGISTERS1();
SAVE_ERRCODE();
SAVE_REGISTERS2();
asm ("pushl $10");
CALL_HOOK();
/* Same thing for exception 12. */
extern void _catchException12();
asm(".text");
asm(".globl __catchException12");
asm("__catchException12:");
SAVE_REGISTERS1();
SAVE_ERRCODE();
SAVE_REGISTERS2();
asm ("pushl $12");
CALL_HOOK();
/* Same thing for exception 16. */
extern void _catchException16();
asm(".text");
asm(".globl __catchException16");
asm("__catchException16:");
SAVE_REGISTERS1();
SAVE_REGISTERS2();
asm ("pushl $16");
CALL_HOOK();
/* For 13, 11, and 14 we have to deal with the CHECK_FAULT stuff. */
/* Same thing for exception 13. */
extern void _catchException13 ();
asm (".text");
asm (".globl __catchException13");
asm ("__catchException13:");
CHECK_FAULT();
SAVE_REGISTERS1();
SAVE_ERRCODE();
SAVE_REGISTERS2();
asm ("pushl $13");
CALL_HOOK();
/* Same thing for exception 11. */
extern void _catchException11 ();
asm (".text");
asm (".globl __catchException11");
asm ("__catchException11:");
CHECK_FAULT();
SAVE_REGISTERS1();
SAVE_ERRCODE();
SAVE_REGISTERS2();
asm ("pushl $11");
CALL_HOOK();
/* Same thing for exception 14. */
extern void _catchException14 ();
asm (".text");
asm (".globl __catchException14");
asm ("__catchException14:");
CHECK_FAULT();
SAVE_REGISTERS1();
SAVE_ERRCODE();
SAVE_REGISTERS2();
asm ("pushl $14");
CALL_HOOK();
/*
* remcomHandler is a front end for handle_exception. It moves the
* stack pointer into an area reserved for debugger use.
*/
asm("_remcomHandler:");
asm(" popl %eax"); /* pop off return address */
asm(" popl %eax"); /* get the exception number */
asm(" movl _stackPtr, %esp"); /* move to remcom stack area */
asm(" pushl %eax"); /* push exception onto stack */
asm(" call _handle_exception"); /* this never returns */
void
_returnFromException ()
{
return_to_prog ();
}
int
hex (ch)
char ch;
{
if ((ch >= 'a') && (ch <= 'f'))
return (ch - 'a' + 10);
if ((ch >= '0') && (ch <= '9'))
return (ch - '0');
if ((ch >= 'A') && (ch <= 'F'))
return (ch - 'A' + 10);
return (-1);
}
static char remcomInBuffer[BUFMAX];
static char remcomOutBuffer[BUFMAX];
/* scan for the sequence $<data>#<checksum> */
unsigned char *
getpacket (void)
{
unsigned char *buffer = &remcomInBuffer[0];
unsigned char checksum;
unsigned char xmitcsum;
int count;
char ch;
while (1)
{
/* wait around for the start character, ignore all other characters */
while ((ch = getDebugChar ()) != '$')
;
retry:
checksum = 0;
xmitcsum = -1;
count = 0;
/* now, read until a # or end of buffer is found */
while (count < BUFMAX)
{
ch = getDebugChar ();
if (ch == '$')
goto retry;
if (ch == '#')
break;
checksum = checksum + ch;
buffer[count] = ch;
count = count + 1;
}
buffer[count] = 0;
if (ch == '#')
{
ch = getDebugChar ();
xmitcsum = hex (ch) << 4;
ch = getDebugChar ();
xmitcsum += hex (ch);
if (checksum != xmitcsum)
{
if (remote_debug)
{
fprintf (stderr,
"bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
checksum, xmitcsum, buffer);
}
putDebugChar ('-'); /* failed checksum */
}
else
{
putDebugChar ('+'); /* successful transfer */
/* if a sequence char is present, reply the sequence ID */
if (buffer[2] == ':')
{
putDebugChar (buffer[0]);
putDebugChar (buffer[1]);
return &buffer[3];
}
return &buffer[0];
}
}
}
}
/* send the packet in buffer. */
void
putpacket (unsigned char *buffer)
{
unsigned char checksum;
int count;
char ch;
/* $<packet info>#<checksum>. */
do
{
putDebugChar ('$');
checksum = 0;
count = 0;
while (ch = buffer[count])
{
putDebugChar (ch);
checksum += ch;
count += 1;
}
putDebugChar ('#');
putDebugChar (hexchars[checksum >> 4]);
putDebugChar (hexchars[checksum % 16]);
}
while (getDebugChar () != '+');
}
void
debug_error (format, parm)
char *format;
char *parm;
{
if (remote_debug)
fprintf (stderr, format, parm);
}
/* Address of a routine to RTE to if we get a memory fault. */
static void (*volatile mem_fault_routine) () = NULL;
/* Indicate to caller of mem2hex or hex2mem that there has been an
error. */
static volatile int mem_err = 0;
void
set_mem_err (void)
{
mem_err = 1;
}
/* These are separate functions so that they are so short and sweet
that the compiler won't save any registers (if there is a fault
to mem_fault, they won't get restored, so there better not be any
saved). */
int
get_char (char *addr)
{
return *addr;
}
void
set_char (char *addr, int val)
{
*addr = val;
}
/* convert the memory pointed to by mem into hex, placing result in buf */
/* return a pointer to the last char put in buf (null) */
/* If MAY_FAULT is non-zero, then we should set mem_err in response to
a fault; if zero treat a fault like any other fault in the stub. */
char *
mem2hex (mem, buf, count, may_fault)
char *mem;
char *buf;
int count;
int may_fault;
{
int i;
unsigned char ch;
if (may_fault)
mem_fault_routine = set_mem_err;
for (i = 0; i < count; i++)
{
ch = get_char (mem++);
if (may_fault && mem_err)
return (buf);
*buf++ = hexchars[ch >> 4];
*buf++ = hexchars[ch % 16];
}
*buf = 0;
if (may_fault)
mem_fault_routine = NULL;
return (buf);
}
/* convert the hex array pointed to by buf into binary to be placed in mem */
/* return a pointer to the character AFTER the last byte written */
char *
hex2mem (buf, mem, count, may_fault)
char *buf;
char *mem;
int count;
int may_fault;
{
int i;
unsigned char ch;
if (may_fault)
mem_fault_routine = set_mem_err;
for (i = 0; i < count; i++)
{
ch = hex (*buf++) << 4;
ch = ch + hex (*buf++);
set_char (mem++, ch);
if (may_fault && mem_err)
return (mem);
}
if (may_fault)
mem_fault_routine = NULL;
return (mem);
}
/* this function takes the 386 exception vector and attempts to
translate this number into a unix compatible signal value */
int
computeSignal (int exceptionVector)
{
int sigval;
switch (exceptionVector)
{
case 0:
sigval = 8;
break; /* divide by zero */
case 1:
sigval = 5;
break; /* debug exception */
case 3:
sigval = 5;
break; /* breakpoint */
case 4:
sigval = 16;
break; /* into instruction (overflow) */
case 5:
sigval = 16;
break; /* bound instruction */
case 6:
sigval = 4;
break; /* Invalid opcode */
case 7:
sigval = 8;
break; /* coprocessor not available */
case 8:
sigval = 7;
break; /* double fault */
case 9:
sigval = 11;
break; /* coprocessor segment overrun */
case 10:
sigval = 11;
break; /* Invalid TSS */
case 11:
sigval = 11;
break; /* Segment not present */
case 12:
sigval = 11;
break; /* stack exception */
case 13:
sigval = 11;
break; /* general protection */
case 14:
sigval = 11;
break; /* page fault */
case 16:
sigval = 7;
break; /* coprocessor error */
default:
sigval = 7; /* "software generated" */
}
return (sigval);
}
/**********************************************/
/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
/* RETURN NUMBER OF CHARS PROCESSED */
/**********************************************/
int
hexToInt (char **ptr, int *intValue)
{
int numChars = 0;
int hexValue;
*intValue = 0;
while (**ptr)
{
hexValue = hex (**ptr);
if (hexValue >= 0)
{
*intValue = (*intValue << 4) | hexValue;
numChars++;
}
else
break;
(*ptr)++;
}
return (numChars);
}
/*
* This function does all command procesing for interfacing to gdb.
*/
void
handle_exception (int exceptionVector)
{
int sigval, stepping;
int addr, length;
char *ptr;
int newPC;
gdb_i386vector = exceptionVector;
if (remote_debug)
{
printf ("vector=%d, sr=0x%x, pc=0x%x\n",
exceptionVector, registers[PS], registers[PC]);
}
/* reply to host that an exception has occurred */
sigval = computeSignal (exceptionVector);
ptr = remcomOutBuffer;
*ptr++ = 'T'; /* notify gdb with signo, PC, FP and SP */
*ptr++ = hexchars[sigval >> 4];
*ptr++ = hexchars[sigval & 0xf];
*ptr++ = hexchars[ESP];
*ptr++ = ':';
ptr = mem2hex((char *)&registers[ESP], ptr, 4, 0); /* SP */
*ptr++ = ';';
*ptr++ = hexchars[EBP];
*ptr++ = ':';
ptr = mem2hex((char *)&registers[EBP], ptr, 4, 0); /* FP */
*ptr++ = ';';
*ptr++ = hexchars[PC];
*ptr++ = ':';
ptr = mem2hex((char *)&registers[PC], ptr, 4, 0); /* PC */
*ptr++ = ';';
*ptr = '\0'
putpacket (remcomOutBuffer);
stepping = 0;
while (1 == 1)
{
remcomOutBuffer[0] = 0;
ptr = getpacket ();
switch (*ptr++)
{
case '?':
remcomOutBuffer[0] = 'S';
remcomOutBuffer[1] = hexchars[sigval >> 4];
remcomOutBuffer[2] = hexchars[sigval % 16];
remcomOutBuffer[3] = 0;
break;
case 'd':
remote_debug = !(remote_debug); /* toggle debug flag */
break;
case 'g': /* return the value of the CPU registers */
mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES, 0);
break;
case 'G': /* set the value of the CPU registers - return OK */
hex2mem (ptr, (char *) registers, NUMREGBYTES, 0);
strcpy (remcomOutBuffer, "OK");
break;
case 'P': /* set the value of a single CPU register - return OK */
{
int regno;
if (hexToInt (&ptr, &regno) && *ptr++ == '=')
if (regno >= 0 && regno < NUMREGS)
{
hex2mem (ptr, (char *) &registers[regno], 4, 0);
strcpy (remcomOutBuffer, "OK");
break;
}
strcpy (remcomOutBuffer, "E01");
break;
}
/* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
case 'm':
/* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
if (hexToInt (&ptr, &addr))
if (*(ptr++) == ',')
if (hexToInt (&ptr, &length))
{
ptr = 0;
mem_err = 0;
mem2hex ((char *) addr, remcomOutBuffer, length, 1);
if (mem_err)
{
strcpy (remcomOutBuffer, "E03");
debug_error ("memory fault");
}
}
if (ptr)
{
strcpy (remcomOutBuffer, "E01");
}
break;
/* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
case 'M':
/* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
if (hexToInt (&ptr, &addr))
if (*(ptr++) == ',')
if (hexToInt (&ptr, &length))
if (*(ptr++) == ':')
{
mem_err = 0;
hex2mem (ptr, (char *) addr, length, 1);
if (mem_err)
{
strcpy (remcomOutBuffer, "E03");
debug_error ("memory fault");
}
else
{
strcpy (remcomOutBuffer, "OK");
}
ptr = 0;
}
if (ptr)
{
strcpy (remcomOutBuffer, "E02");
}
break;
/* cAA..AA Continue at address AA..AA(optional) */
/* sAA..AA Step one instruction from AA..AA(optional) */
case 's':
stepping = 1;
case 'c':
/* try to read optional parameter, pc unchanged if no parm */
if (hexToInt (&ptr, &addr))
registers[PC] = addr;
newPC = registers[PC];
/* clear the trace bit */
registers[PS] &= 0xfffffeff;
/* set the trace bit if we're stepping */
if (stepping)
registers[PS] |= 0x100;
_returnFromException (); /* this is a jump */
break;
/* kill the program */
case 'k': /* do nothing */
#if 0
/* Huh? This doesn't look like "nothing".
m68k-stub.c and sparc-stub.c don't have it. */
BREAKPOINT ();
#endif
break;
} /* switch */
/* reply to the request */
putpacket (remcomOutBuffer);
}
}
/* this function is used to set up exception handlers for tracing and
breakpoints */
void
set_debug_traps (void)
{
stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1];
exceptionHandler (0, _catchException0);
exceptionHandler (1, _catchException1);
exceptionHandler (3, _catchException3);
exceptionHandler (4, _catchException4);
exceptionHandler (5, _catchException5);
exceptionHandler (6, _catchException6);
exceptionHandler (7, _catchException7);
exceptionHandler (8, _catchException8);
exceptionHandler (9, _catchException9);
exceptionHandler (10, _catchException10);
exceptionHandler (11, _catchException11);
exceptionHandler (12, _catchException12);
exceptionHandler (13, _catchException13);
exceptionHandler (14, _catchException14);
exceptionHandler (16, _catchException16);
initialized = 1;
}
/* This function will generate a breakpoint exception. It is used at the
beginning of a program to sync up with a debugger and can be used
otherwise as a quick means to stop program execution and "break" into
the debugger. */
void
breakpoint (void)
{
if (initialized)
BREAKPOINT ();
}

View File

@ -1,377 +0,0 @@
/* Intel 386 native support.
Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999,
2000, 2001 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include "language.h"
#include "gdbcore.h"
#include "regcache.h"
#ifdef USG
#include <sys/types.h>
#endif
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/user.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/file.h>
#include "gdb_stat.h"
#include <stddef.h>
#include <sys/ptrace.h>
/* Does AIX define this in <errno.h>? */
extern int errno;
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>
#endif
#include "floatformat.h"
#include "target.h"
static void fetch_core_registers (char *, unsigned, int, CORE_ADDR);
/* this table must line up with REGISTER_NAMES in tm-i386v.h */
/* symbols like 'EAX' come from <sys/reg.h> */
static int regmap[] =
{
EAX, ECX, EDX, EBX,
USP, EBP, ESI, EDI,
EIP, EFL, CS, SS,
DS, ES, FS, GS,
};
/* blockend is the value of u.u_ar0, and points to the
* place where GS is stored
*/
int
i386_register_u_addr (int blockend, int regnum)
{
#if 0
/* this will be needed if fp registers are reinstated */
/* for now, you can look at them with 'info float'
* sys5 wont let you change them with ptrace anyway
*/
if (regnum >= FP0_REGNUM && regnum <= FP7_REGNUM)
{
int ubase, fpstate;
struct user u;
ubase = blockend + 4 * (SS + 1) - KSTKSZ;
fpstate = ubase + ((char *) &u.u_fpstate - (char *) &u);
return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
}
else
#endif
return (blockend + 4 * regmap[regnum]);
}
/* The code below only work on the aix ps/2 (i386-ibm-aix) -
* mtranle@paris - Sat Apr 11 10:34:12 1992
*/
struct env387
{
unsigned short control;
unsigned short r0;
unsigned short status;
unsigned short r1;
unsigned short tag;
unsigned short r2;
unsigned long eip;
unsigned short code_seg;
unsigned short opcode;
unsigned long operand;
unsigned short operand_seg;
unsigned short r3;
unsigned char regs[8][10];
};
static
print_387_status (unsigned short status, struct env387 *ep)
{
int i;
int bothstatus;
int top;
int fpreg;
unsigned char *p;
bothstatus = ((status != 0) && (ep->status != 0));
if (status != 0)
{
if (bothstatus)
printf_unfiltered ("u: ");
print_387_status_word (status);
}
if (ep->status != 0)
{
if (bothstatus)
printf_unfiltered ("e: ");
print_387_status_word (ep->status);
}
print_387_control_word (ep->control);
printf_unfiltered ("last exception: ");
printf_unfiltered ("opcode %s; ", local_hex_string (ep->opcode));
printf_unfiltered ("pc %s:", local_hex_string (ep->code_seg));
printf_unfiltered ("%s; ", local_hex_string (ep->eip));
printf_unfiltered ("operand %s", local_hex_string (ep->operand_seg));
printf_unfiltered (":%s\n", local_hex_string (ep->operand));
top = ((ep->status >> 11) & 7);
printf_unfiltered ("regno tag msb lsb value\n");
for (fpreg = 7; fpreg >= 0; fpreg--)
{
double val;
printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
switch ((ep->tag >> ((7 - fpreg) * 2)) & 3)
{
case 0:
printf_unfiltered ("valid ");
break;
case 1:
printf_unfiltered ("zero ");
break;
case 2:
printf_unfiltered ("trap ");
break;
case 3:
printf_unfiltered ("empty ");
break;
}
for (i = 9; i >= 0; i--)
printf_unfiltered ("%02x", ep->regs[fpreg][i]);
i387_to_double ((char *) ep->regs[fpreg], (char *) &val);
printf_unfiltered (" %#g\n", val);
}
}
static struct env387 core_env387;
void
i386_float_info (void)
{
struct env387 fps;
int fpsaved = 0;
/* We need to reverse the order of the registers. Apparently AIX stores
the highest-numbered ones first. */
struct env387 fps_fixed;
int i;
if (! ptid_equal (inferior_ptid, null_ptid))
{
char buf[10];
unsigned short status;
ptrace (PT_READ_FPR, PIDGET (inferior_ptid), buf,
offsetof (struct env387, status));
memcpy (&status, buf, sizeof (status));
fpsaved = status;
}
else
{
if ((fpsaved = core_env387.status) != 0)
memcpy (&fps, &core_env387, sizeof (fps));
}
if (fpsaved == 0)
{
printf_unfiltered ("no floating point status saved\n");
return;
}
if (! ptid_equal (inferior_ptid, null_ptid))
{
int offset;
for (offset = 0; offset < sizeof (fps); offset += 10)
{
char buf[10];
ptrace (PT_READ_FPR, PIDGET (inferior_ptid), buf, offset);
memcpy ((char *) &fps.control + offset, buf,
MIN (10, sizeof (fps) - offset));
}
}
fps_fixed = fps;
for (i = 0; i < 8; ++i)
memcpy (fps_fixed.regs[i], fps.regs[7 - i], 10);
print_387_status (0, &fps_fixed);
}
/* Fetch one register. */
static void
fetch_register (int regno)
{
char buf[MAX_REGISTER_RAW_SIZE];
if (regno < FP0_REGNUM)
*(int *) buf = ptrace (PT_READ_GPR, PIDGET (inferior_ptid),
PT_REG (regmap[regno]), 0, 0);
else
ptrace (PT_READ_FPR, PIDGET (inferior_ptid), buf,
(regno - FP0_REGNUM) * 10 + offsetof (struct env387, regs));
supply_register (regno, buf);
}
void
fetch_inferior_registers (int regno)
{
if (regno < 0)
for (regno = 0; regno < NUM_REGS; regno++)
fetch_register (regno);
else
fetch_register (regno);
}
/* store one register */
static void
store_register (int regno)
{
char buf[80];
errno = 0;
if (regno < FP0_REGNUM)
ptrace (PT_WRITE_GPR, PIDGET (inferior_ptid), PT_REG (regmap[regno]),
*(int *) &registers[REGISTER_BYTE (regno)], 0);
else
ptrace (PT_WRITE_FPR, PIDGET (inferior_ptid),
&registers[REGISTER_BYTE (regno)],
(regno - FP0_REGNUM) * 10 + offsetof (struct env387, regs));
if (errno != 0)
{
sprintf (buf, "writing register number %d", regno);
perror_with_name (buf);
}
}
/* Store our register values back into the inferior.
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
void
store_inferior_registers (int regno)
{
if (regno < 0)
for (regno = 0; regno < NUM_REGS; regno++)
store_register (regno);
else
store_register (regno);
}
#ifndef CD_AX /* defined in sys/i386/coredump.h */
#define CD_AX 0
#define CD_BX 1
#define CD_CX 2
#define CD_DX 3
#define CD_SI 4
#define CD_DI 5
#define CD_BP 6
#define CD_SP 7
#define CD_FL 8
#define CD_IP 9
#define CD_CS 10
#define CD_DS 11
#define CD_ES 12
#define CD_FS 13
#define CD_GS 14
#define CD_SS 15
#endif
/*
* The order here in core_regmap[] has to be the same as in
* regmap[] above.
*/
static int core_regmap[] =
{
CD_AX, CD_CX, CD_DX, CD_BX,
CD_SP, CD_BP, CD_SI, CD_DI,
CD_IP, CD_FL, CD_CS, CD_SS,
CD_DS, CD_ES, CD_FS, CD_GS,
};
/* Provide registers to GDB from a core file.
CORE_REG_SECT points to an array of bytes, which were obtained from
a core file which BFD thinks might contain register contents.
CORE_REG_SIZE is its size.
WHICH says which register set corelow suspects this is:
0 --- the general-purpose register set
2 --- the floating-point register set
REG_ADDR isn't used. */
static void
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
int which, CORE_ADDR reg_addr)
{
if (which == 0)
{
/* Integer registers */
#define cd_regs(n) ((int *)core_reg_sect)[n]
#define regs(n) *((int *) &registers[REGISTER_BYTE (n)])
int i;
for (i = 0; i < FP0_REGNUM; i++)
regs (i) = cd_regs (core_regmap[i]);
}
else if (which == 2)
{
/* Floating point registers */
if (core_reg_size >= sizeof (core_env387))
memcpy (&core_env387, core_reg_sect, core_reg_size);
else
fprintf_unfiltered (gdb_stderr, "Couldn't read float regs from core file\n");
}
}
/* Register that we are able to handle i386aix core file formats.
FIXME: is this really bfd_target_unknown_flavour? */
static struct core_fns i386aix_core_fns =
{
bfd_target_unknown_flavour, /* core_flavour */
default_check_format, /* check_format */
default_core_sniffer, /* core_sniffer */
fetch_core_registers, /* core_read_registers */
NULL /* next */
};
void
_initialize_core_i386aix (void)
{
add_core_fns (&i386aix_core_fns);
}

View File

@ -1,45 +0,0 @@
/* Target-dependent code for Intel 386 running LynxOS.
Copyright 1993, 1996, 2000, 2001 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "inferior.h"
#include "target.h"
#include "gdbcore.h"
#include "regcache.h"
/* Return the PC of the caller from the call frame. Assumes the subr prologue
has already been executed, and the frame pointer setup. If this is the
outermost frame, we check to see if we are in a system call by examining the
previous instruction. If so, then the return PC is actually at SP+4 because
system calls use a different calling sequence. */
CORE_ADDR
i386lynx_saved_pc_after_call (struct frame_info *frame)
{
char opcode[7];
static const unsigned char call_inst[] =
{0x9a, 0, 0, 0, 0, 8, 0}; /* lcall 0x8,0x0 */
read_memory (frame->pc - 7, opcode, 7);
if (memcmp (opcode, call_inst, 7) == 0)
return read_memory_integer (read_register (SP_REGNUM) + 4, 4);
return read_memory_integer (read_register (SP_REGNUM), 4);
}

View File

@ -1,426 +0,0 @@
/* Low level interface to I386 running mach 3.0.
Copyright 1992, 1993, 1994, 1996, 2000, 2001
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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "inferior.h"
#include "floatformat.h"
#include "regcache.h"
#include <stdio.h>
#include <mach.h>
#include <mach/message.h>
#include <mach/exception.h>
#include <mach_error.h>
/* Hmmm... Should this not be here?
* Now for i386_float_info() target_has_execution
*/
#include <target.h>
/* This mess is duplicated in bfd/i386mach3.h
* This is an ugly way to hack around the incorrect
* definition of UPAGES in i386/machparam.h.
*
* The definition should specify the size reserved
* for "struct user" in core files in PAGES,
* but instead it gives it in 512-byte core-clicks
* for i386 and i860.
*/
#include <sys/param.h>
#if UPAGES == 16
#define UAREA_SIZE ctob(UPAGES)
#elif UPAGES == 2
#define UAREA_SIZE (NBPG*UPAGES)
#else
FIXME ! !UPAGES is neither 2 nor 16
#endif
/* @@@ Should move print_387_status() to i387-tdep.c */
extern void print_387_control_word (); /* i387-tdep.h */
extern void print_387_status_word ();
#define private static
/* Find offsets to thread states at compile time.
* If your compiler does not grok this, calculate offsets
* offsets yourself and use them (or get a compatible compiler :-)
*/
#define REG_OFFSET(reg) (int)(&((struct i386_thread_state *)0)->reg)
/* at reg_offset[i] is the offset to the i386_thread_state
* location where the gdb registers[i] is stored.
*/
static int reg_offset[] =
{
REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
};
#define REG_ADDRESS(state,regnum) ((char *)(state)+reg_offset[regnum])
/* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
* Caller knows that the regs handled in one transaction are of same size.
*/
#define FETCH_REGS(state, regnum, count) \
memcpy (&registers[REGISTER_BYTE (regnum)], \
REG_ADDRESS (state, regnum), \
count*REGISTER_SIZE)
/* Store COUNT contiguous registers to thread STATE starting from REGNUM */
#define STORE_REGS(state, regnum, count) \
memcpy (REG_ADDRESS (state, regnum), \
&registers[REGISTER_BYTE (regnum)], \
count*REGISTER_SIZE)
/*
* Fetch inferiors registers for gdb.
* REGNO specifies which (as gdb views it) register, -1 for all.
*/
void
fetch_inferior_registers (int regno)
{
kern_return_t ret;
thread_state_data_t state;
unsigned int stateCnt = i386_THREAD_STATE_COUNT;
int index;
if (!MACH_PORT_VALID (current_thread))
error ("fetch inferior registers: Invalid thread");
if (must_suspend_thread)
setup_thread (current_thread, 1);
ret = thread_get_state (current_thread,
i386_THREAD_STATE,
state,
&stateCnt);
if (ret != KERN_SUCCESS)
warning ("fetch_inferior_registers: %s ",
mach_error_string (ret));
#if 0
/* It may be more effective to store validate all of them,
* since we fetched them all anyway
*/
else if (regno != -1)
supply_register (regno, (char *) state + reg_offset[regno]);
#endif
else
{
for (index = 0; index < NUM_REGS; index++)
supply_register (index, (char *) state + reg_offset[index]);
}
if (must_suspend_thread)
setup_thread (current_thread, 0);
}
/* Store our register values back into the inferior.
* If REGNO is -1, do this for all registers.
* Otherwise, REGNO specifies which register
*
* On mach3 all registers are always saved in one call.
*/
void
store_inferior_registers (int regno)
{
kern_return_t ret;
thread_state_data_t state;
unsigned int stateCnt = i386_THREAD_STATE_COUNT;
register int index;
if (!MACH_PORT_VALID (current_thread))
error ("store inferior registers: Invalid thread");
if (must_suspend_thread)
setup_thread (current_thread, 1);
/* Fetch the state of the current thread */
ret = thread_get_state (current_thread,
i386_THREAD_STATE,
state,
&stateCnt);
if (ret != KERN_SUCCESS)
{
warning ("store_inferior_registers (get): %s",
mach_error_string (ret));
if (must_suspend_thread)
setup_thread (current_thread, 0);
return;
}
/* move gdb's registers to thread's state
* Since we save all registers anyway, save the ones
* that gdb thinks are valid (e.g. ignore the regno
* parameter)
*/
#if 0
if (regno != -1)
STORE_REGS (state, regno, 1);
else
#endif
{
for (index = 0; index < NUM_REGS; index++)
STORE_REGS (state, index, 1);
}
/* Write gdb's current view of register to the thread
*/
ret = thread_set_state (current_thread,
i386_THREAD_STATE,
state,
i386_THREAD_STATE_COUNT);
if (ret != KERN_SUCCESS)
warning ("store_inferior_registers (set): %s",
mach_error_string (ret));
if (must_suspend_thread)
setup_thread (current_thread, 0);
}
/* Return the address in the core dump or inferior of register REGNO.
* BLOCKEND should be the address of the end of the UPAGES area read
* in memory, but it's not?
*
* Currently our UX server dumps the whole thread state to the
* core file. If your UX does something else, adapt the routine
* below to return the offset to the given register.
*
* Called by core-aout.c(fetch_core_registers)
*/
CORE_ADDR
register_addr (int regno, CORE_ADDR blockend)
{
CORE_ADDR addr;
if (regno < 0 || regno >= NUM_REGS)
error ("Invalid register number %d.", regno);
/* UAREA_SIZE == 8 kB in i386 */
addr = (unsigned int) REG_ADDRESS (UAREA_SIZE - sizeof (struct i386_thread_state), regno);
return addr;
}
/* jtv@hut.fi: I copied and modified this 387 code from
* gdb/i386-xdep.c. Modifications for Mach 3.0.
*
* i387 status dumper. See also i387-tdep.c
*/
struct env387
{
unsigned short control;
unsigned short r0;
unsigned short status;
unsigned short r1;
unsigned short tag;
unsigned short r2;
unsigned long eip;
unsigned short code_seg;
unsigned short opcode;
unsigned long operand;
unsigned short operand_seg;
unsigned short r3;
unsigned char regs[8][10];
};
/* This routine is machine independent?
* Should move it to i387-tdep.c but you need to export struct env387
*/
private
print_387_status (unsigned short status, struct env387 *ep)
{
int i;
int bothstatus;
int top;
int fpreg;
unsigned char *p;
bothstatus = ((status != 0) && (ep->status != 0));
if (status != 0)
{
if (bothstatus)
printf_unfiltered ("u: ");
print_387_status_word (status);
}
if (ep->status != 0)
{
if (bothstatus)
printf_unfiltered ("e: ");
print_387_status_word (ep->status);
}
print_387_control_word (ep->control);
printf_unfiltered ("last exception: ");
printf_unfiltered ("opcode %s; ", local_hex_string (ep->opcode));
printf_unfiltered ("pc %s:", local_hex_string (ep->code_seg));
printf_unfiltered ("%s; ", local_hex_string (ep->eip));
printf_unfiltered ("operand %s", local_hex_string (ep->operand_seg));
printf_unfiltered (":%s\n", local_hex_string (ep->operand));
top = (ep->status >> 11) & 7;
printf_unfiltered ("regno tag msb lsb value\n");
for (fpreg = 7; fpreg >= 0; fpreg--)
{
double val;
printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
switch ((ep->tag >> (fpreg * 2)) & 3)
{
case 0:
printf_unfiltered ("valid ");
break;
case 1:
printf_unfiltered ("zero ");
break;
case 2:
printf_unfiltered ("trap ");
break;
case 3:
printf_unfiltered ("empty ");
break;
}
for (i = 9; i >= 0; i--)
printf_unfiltered ("%02x", ep->regs[fpreg][i]);
floatformat_to_double (&floatformat_i387_ext, (char *) ep->regs[fpreg],
&val);
printf_unfiltered (" %g\n", val);
}
if (ep->r0)
printf_unfiltered ("warning: reserved0 is %s\n", local_hex_string (ep->r0));
if (ep->r1)
printf_unfiltered ("warning: reserved1 is %s\n", local_hex_string (ep->r1));
if (ep->r2)
printf_unfiltered ("warning: reserved2 is %s\n", local_hex_string (ep->r2));
if (ep->r3)
printf_unfiltered ("warning: reserved3 is %s\n", local_hex_string (ep->r3));
}
/*
* values that go into fp_kind (from <i386/fpreg.h>)
*/
#define FP_NO 0 /* no fp chip, no emulator (no fp support) */
#define FP_SW 1 /* no fp chip, using software emulator */
#define FP_HW 2 /* chip present bit */
#define FP_287 2 /* 80287 chip present */
#define FP_387 3 /* 80387 chip present */
typedef struct fpstate
{
#if 1
unsigned char state[FP_STATE_BYTES]; /* "hardware" state */
#else
struct env387 state; /* Actually this */
#endif
int status; /* Duplicate status */
}
*fpstate_t;
/* Mach 3 specific routines.
*/
private boolean_t
get_i387_state (struct fpstate *fstate)
{
kern_return_t ret;
thread_state_data_t state;
unsigned int fsCnt = i386_FLOAT_STATE_COUNT;
struct i386_float_state *fsp;
ret = thread_get_state (current_thread,
i386_FLOAT_STATE,
state,
&fsCnt);
if (ret != KERN_SUCCESS)
{
warning ("Can not get live floating point state: %s",
mach_error_string (ret));
return FALSE;
}
fsp = (struct i386_float_state *) state;
/* The 387 chip (also 486 counts) or a software emulator? */
if (!fsp->initialized || (fsp->fpkind != FP_387 && fsp->fpkind != FP_SW))
return FALSE;
/* Clear the target then copy thread's float state there.
Make a copy of the status word, for some reason?
*/
memset (fstate, 0, sizeof (struct fpstate));
fstate->status = fsp->exc_status;
memcpy (fstate->state, (char *) &fsp->hw_state, FP_STATE_BYTES);
return TRUE;
}
private boolean_t
get_i387_core_state (struct fpstate *fstate)
{
/* Not implemented yet. Core files do not contain float state. */
return FALSE;
}
/*
* This is called by "info float" command
*/
void
i386_mach3_float_info (void)
{
char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
boolean_t valid = FALSE;
fpstate_t fps;
if (target_has_execution)
valid = get_i387_state (buf);
#if 0
else if (WE HAVE CORE FILE) /* @@@@ Core files not supported */
valid = get_i387_core_state (buf);
#endif
if (!valid)
{
warning ("no floating point status saved");
return;
}
fps = (fpstate_t) buf;
print_387_status (fps->status, (struct env387 *) fps->state);
}

View File

@ -1,172 +0,0 @@
/* Native dependent code for Mach 386's for GDB, the GNU debugger.
Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1995, 1996, 1999, 2000,
2001 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include "gdbcore.h"
#include "regcache.h"
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/ptrace.h>
#include <machine/reg.h>
#include <sys/file.h>
#include "gdb_stat.h"
#include <sys/core.h>
static void fetch_core_registers (char *, unsigned, int, CORE_ADDR);
void
fetch_inferior_registers (int regno)
{
struct regs inferior_registers;
struct fp_state inferior_fp_registers;
registers_fetched ();
ptrace (PTRACE_GETREGS, PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) & inferior_registers);
ptrace (PTRACE_GETFPREGS, PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) & inferior_fp_registers);
memcpy (registers, &inferior_registers, sizeof inferior_registers);
memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)],
inferior_fp_registers.f_st,
sizeof inferior_fp_registers.f_st);
memcpy (&registers[REGISTER_BYTE (FPC_REGNUM)],
&inferior_fp_registers.f_ctrl,
sizeof inferior_fp_registers - sizeof inferior_fp_registers.f_st);
}
/* Store our register values back into the inferior.
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
void
store_inferior_registers (int regno)
{
struct regs inferior_registers;
struct fp_state inferior_fp_registers;
memcpy (&inferior_registers, registers, 20 * 4);
memcpy (inferior_fp_registers.f_st, &registers[REGISTER_BYTE (FP0_REGNUM)],
sizeof inferior_fp_registers.f_st);
memcpy (&inferior_fp_registers.f_ctrl,
&registers[REGISTER_BYTE (FPC_REGNUM)],
sizeof inferior_fp_registers - sizeof inferior_fp_registers.f_st);
#ifdef PTRACE_FP_BUG
if (regno == FP_REGNUM || regno == -1)
/* Storing the frame pointer requires a gross hack, in which an
instruction that moves eax into ebp gets single-stepped. */
{
int stack = inferior_registers.r_reg[SP_REGNUM];
int stuff = ptrace (PTRACE_PEEKDATA, PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) stack);
int reg = inferior_registers.r_reg[EAX];
inferior_registers.r_reg[EAX] =
inferior_registers.r_reg[FP_REGNUM];
ptrace (PTRACE_SETREGS, PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) & inferior_registers);
ptrace (PTRACE_POKEDATA, PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) stack, 0xc589);
ptrace (PTRACE_SINGLESTEP, PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) stack, 0);
wait (0);
ptrace (PTRACE_POKEDATA, PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) stack, stuff);
inferior_registers.r_reg[EAX] = reg;
}
#endif
ptrace (PTRACE_SETREGS, PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) & inferior_registers);
ptrace (PTRACE_SETFPREGS, PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) & inferior_fp_registers);
}
/* Provide registers to GDB from a core file.
CORE_REG_SECT points to an array of bytes, which were obtained from
a core file which BFD thinks might contain register contents.
CORE_REG_SIZE is its size.
WHICH says which register set corelow suspects this is:
0 --- the general-purpose register set
2 --- the floating-point register set
REG_ADDR isn't used. */
static void
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
int which, CORE_ADDR reg_addr)
{
int val;
switch (which)
{
case 0:
case 1:
memcpy (registers, core_reg_sect, core_reg_size);
break;
case 2:
memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)],
core_reg_sect,
core_reg_size); /* FIXME, probably bogus */
#ifdef FPC_REGNUM
memcpy (&registers[REGISTER_BYTE (FPC_REGNUM)],
&corestr.c_fpu.f_fpstatus.f_ctrl,
sizeof corestr.c_fpu.f_fpstatus -
sizeof corestr.c_fpu.f_fpstatus.f_st);
#endif
break;
}
}
/* Register that we are able to handle i386mach core file formats.
FIXME: is this really bfd_target_unknown_flavour? */
static struct core_fns i386mach_core_fns =
{
bfd_target_unknown_flavour, /* core_flavour */
default_check_format, /* check_format */
default_core_sniffer, /* core_sniffer */
fetch_core_registers, /* core_read_registers */
NULL /* next */
};
void
_initialize_core_i386mach (void)
{
add_core_fns (&i386mach_core_fns);
}

View File

@ -1,289 +0,0 @@
/* Intel 386 native support for SYSV systems (pre-SVR4).
Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
1999, 2000, 2002 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#ifdef HAVE_PTRACE_H
#include <ptrace.h>
#else
#ifdef HAVE_SYS_PTRACE_H
#include <sys/ptrace.h>
#endif
#endif
#include "frame.h"
#include "inferior.h"
#include "language.h"
#include "gdbcore.h"
#ifdef USG
#include <sys/types.h>
#endif
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/user.h>
#include <sys/ioctl.h>
#include <fcntl.h>
/* FIXME: 1998-10-21/jsm: The following used to be just "#include
<sys/debugreg.h>", but the the Linux kernel (version 2.1.x) and
glibc 2.0.x are not in sync; including <sys/debugreg.h> will result
in an error. With luck, these losers will get their act together
and we can trash this hack in the near future. */
#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
#ifdef HAVE_ASM_DEBUGREG_H
#include <asm/debugreg.h>
#else
#include <sys/debugreg.h>
#endif
#endif
#include <sys/file.h>
#include "gdb_stat.h"
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>
#endif
#include "floatformat.h"
#include "target.h"
/* this table must line up with REGISTER_NAMES in tm-i386v.h */
/* symbols like 'EAX' come from <sys/reg.h> */
static int regmap[] =
{
EAX, ECX, EDX, EBX,
UESP, EBP, ESI, EDI,
EIP, EFL, CS, SS,
DS, ES, FS, GS,
};
/* blockend is the value of u.u_ar0, and points to the
* place where GS is stored
*/
int
i386_register_u_addr (int blockend, int regnum)
{
struct user u;
int fpstate;
int ubase;
ubase = blockend;
/* FIXME: Should have better way to test floating point range */
if (regnum >= FP0_REGNUM && regnum <= (FP0_REGNUM + 7))
{
#ifdef KSTKSZ /* SCO, and others? */
ubase += 4 * (SS + 1) - KSTKSZ;
fpstate = ubase + ((char *) &u.u_fps.u_fpstate - (char *) &u);
return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
#else
fpstate = ubase + ((char *) &u.i387.st_space - (char *) &u);
return (fpstate + 10 * (regnum - FP0_REGNUM));
#endif
}
else
{
return (ubase + 4 * regmap[regnum]);
}
}
int
kernel_u_size (void)
{
return (sizeof (struct user));
}
#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
#if !defined (offsetof)
#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
#endif
/* Record the value of the debug control register. */
static int debug_control_mirror;
/* Record which address associates with which register. */
static CORE_ADDR address_lookup[DR_LASTADDR - DR_FIRSTADDR + 1];
static int
i386_insert_aligned_watchpoint (int, CORE_ADDR, CORE_ADDR, int, int);
static int
i386_insert_nonaligned_watchpoint (int, CORE_ADDR, CORE_ADDR, int, int);
/* Insert a watchpoint. */
int
i386_insert_watchpoint (int pid, CORE_ADDR addr, int len, int rw)
{
return i386_insert_aligned_watchpoint (pid, addr, addr, len, rw);
}
static int
i386_insert_aligned_watchpoint (int pid, CORE_ADDR waddr, CORE_ADDR addr,
int len, int rw)
{
int i;
int read_write_bits, len_bits;
int free_debug_register;
int register_number;
/* Look for a free debug register. */
for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
{
if (address_lookup[i - DR_FIRSTADDR] == 0)
break;
}
/* No more debug registers! */
if (i > DR_LASTADDR)
return -1;
read_write_bits = (rw & 1) ? DR_RW_READ : DR_RW_WRITE;
if (len == 1)
len_bits = DR_LEN_1;
else if (len == 2)
{
if (addr % 2)
return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
len_bits = DR_LEN_2;
}
else if (len == 4)
{
if (addr % 4)
return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
len_bits = DR_LEN_4;
}
else
return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
free_debug_register = i;
register_number = free_debug_register - DR_FIRSTADDR;
debug_control_mirror |=
((read_write_bits | len_bits)
<< (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * register_number));
debug_control_mirror |=
(1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
debug_control_mirror |= DR_LOCAL_SLOWDOWN;
debug_control_mirror &= ~DR_CONTROL_RESERVED;
ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
debug_control_mirror);
ptrace (6, pid, offsetof (struct user, u_debugreg[free_debug_register]),
addr);
/* Record where we came from. */
address_lookup[register_number] = addr;
return 0;
}
static int
i386_insert_nonaligned_watchpoint (int pid, CORE_ADDR waddr, CORE_ADDR addr,
int len, int rw)
{
int align;
int size;
int rv;
static int size_try_array[4][4] =
{
{ 1, 1, 1, 1 }, /* trying size one */
{ 2, 1, 2, 1 }, /* trying size two */
{ 2, 1, 2, 1 }, /* trying size three */
{ 4, 1, 2, 1 } /* trying size four */
};
rv = 0;
while (len > 0)
{
align = addr % 4;
/* Four is the maximum length for 386. */
size = size_try_array[len > 4 ? 3 : len - 1][align];
rv = i386_insert_aligned_watchpoint (pid, waddr, addr, size, rw);
if (rv)
{
i386_remove_watchpoint (pid, waddr, size);
return rv;
}
addr += size;
len -= size;
}
return rv;
}
/* Remove a watchpoint. */
int
i386_remove_watchpoint (int pid, CORE_ADDR addr, int len)
{
int i;
int register_number;
for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
{
register_number = i - DR_FIRSTADDR;
if (address_lookup[register_number] == addr)
{
debug_control_mirror &=
~(1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
address_lookup[register_number] = 0;
}
}
ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
debug_control_mirror);
ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
return 0;
}
/* Check if stopped by a watchpoint. */
CORE_ADDR
i386_stopped_by_watchpoint (int pid)
{
int i;
int status;
status = ptrace (3, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
{
if (status & (1 << (i - DR_FIRSTADDR)))
return address_lookup[i - DR_FIRSTADDR];
}
return 0;
}
#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */

View File

@ -1,184 +0,0 @@
/* Native-dependent code for SVR4 Unix running on i386's, for GDB.
Copyright 1988, 1989, 1991, 1992, 1996, 1997, 1998, 1999, 2000, 2001
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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "value.h"
#include "inferior.h"
#include "regcache.h"
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>
#endif
#include "i387-nat.h"
#ifdef HAVE_SYS_PROCFS_H
#include <sys/procfs.h>
/* Prototypes for supply_gregset etc. */
#include "gregset.h"
/* The /proc interface divides the target machine's register set up into
two different sets, the general register set (gregset) and the floating
point register set (fpregset). For each set, there is an ioctl to get
the current register set and another ioctl to set the current values.
The actual structure passed through the ioctl interface is, of course,
naturally machine dependent, and is different for each set of registers.
For the i386 for example, the general register set is typically defined
by:
typedef int gregset_t[19]; (in <sys/regset.h>)
#define GS 0 (in <sys/reg.h>)
#define FS 1
...
#define UESP 17
#define SS 18
and the floating point set by:
typedef struct fpregset
{
union
{
struct fpchip_state // fp extension state //
{
int state[27]; // 287/387 saved state //
int status; // status word saved at exception //
} fpchip_state;
struct fp_emul_space // for emulators //
{
char fp_emul[246];
char fp_epad[2];
} fp_emul_space;
int f_fpregs[62]; // union of the above //
} fp_reg_set;
long f_wregs[33]; // saved weitek state //
} fpregset_t;
These routines provide the packing and unpacking of gregset_t and
fpregset_t formatted data.
*/
#ifdef HAVE_GREGSET_T
/* This is a duplicate of the table in i386-xdep.c. */
static int regmap[] =
{
EAX, ECX, EDX, EBX,
UESP, EBP, ESI, EDI,
EIP, EFL, CS, SS,
DS, ES, FS, GS,
};
/* Prototypes for local functions */
void fill_gregset (gregset_t *, int);
void supply_gregset (gregset_t *);
void supply_fpregset (fpregset_t *);
void fill_fpregset (fpregset_t *, int);
/* FIXME: These routine absolutely depends upon (NUM_REGS - NUM_FREGS)
being less than or equal to the number of registers that can be stored
in a gregset_t. Note that with the current scheme there will typically
be more registers actually stored in a gregset_t that what we know
about. This is bogus and should be fixed. */
/* Given a pointer to a general register set in /proc format (gregset_t *),
unpack the register contents and supply them as gdb's idea of the current
register values. */
void
supply_gregset (gregset_t *gregsetp)
{
register int regi;
register greg_t *regp = (greg_t *) gregsetp;
extern int regmap[];
for (regi = 0; regi < (NUM_REGS - NUM_FREGS); regi++)
{
supply_register (regi, (char *) (regp + regmap[regi]));
}
}
void
fill_gregset (gregset_t *gregsetp, int regno)
{
int regi;
register greg_t *regp = (greg_t *) gregsetp;
extern int regmap[];
for (regi = 0; regi < (NUM_REGS - NUM_FREGS); regi++)
{
if ((regno == -1) || (regno == regi))
{
*(regp + regmap[regi]) = *(int *) &registers[REGISTER_BYTE (regi)];
}
}
}
#endif /* HAVE_GREGSET_T */
#if defined (HAVE_FPREGSET_T)
/* Given a pointer to a floating point register set in /proc format
(fpregset_t *), unpack the register contents and supply them as gdb's
idea of the current floating point register values. */
/* FIXME: Assumes that fpregsetp contains an i387 FSAVE area. */
#if !defined(FPREGSET_FSAVE_OFFSET)
#define FPREGSET_FSAVE_OFFSET 0
#endif
void
supply_fpregset (fpregset_t *fpregsetp)
{
if (NUM_FREGS == 0)
return;
i387_supply_fsave ((char *) fpregsetp + FPREGSET_FSAVE_OFFSET);
}
/* Given a pointer to a floating point register set in /proc format
(fpregset_t *), update the register specified by REGNO from gdb's idea
of the current floating point register set. If REGNO is -1, update
them all. */
void
fill_fpregset (fpregset_t *fpregsetp, int regno)
{
if (NUM_FREGS == 0)
return;
i387_fill_fsave ((char *) fpregsetp + FPREGSET_FSAVE_OFFSET, regno);
}
#endif /* defined (HAVE_FPREGSET_T) */
#endif /* HAVE_SYS_PROCFS_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,601 +0,0 @@
/* Definitions and macros for support of AMD's remote debugger, MiniMON.
Copyright 1990, 1991 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/*
* Some basic types. FIXME, this should be done by declaring bitfield
* sizes in the structs. We can't portably depend on a "long int" being
* 32 bits, etc.
*/
typedef long int INT32; /* 32 bit integer */
typedef unsigned long int UINT32; /* 32 bit integer (unsigned) */
typedef unsigned long int ADDR32; /* 32 bit address */
typedef unsigned long int INST32; /* 32 bit instruction */
typedef long int BOOLEAN; /* Boolean value (32 bit) */
typedef unsigned char BYTE; /* byte (8 bit) */
typedef short int INT16; /* 16 bit integer */
typedef unsigned short int UINT16; /* 16 bit integer (unsigned) */
/****************************************************************************/
/************************* Message Information ******************************/
/****************************************************************************/
/*
* Error codes
*/
/* General errors */
#define EMUSAGE 1 /* Bad args / flags */
#define EMFAIL 2 /* Unrecoverable error */
#define EMBADADDR 3 /* Illegal address */
#define EMBADREG 4 /* Illegal register */
#define EMSYNTAX 5 /* Illegal command syntax */
#define EMACCESS 6 /* Could not access memory */
#define EMALLOC 7 /* Could not allocate memory */
#define EMTARGET 8 /* Unknown target type */
#define EMHINIT 9 /* Could not initialize host */
#define EMCOMM 10 /* Could not open communication channel */
/* Message errors */
#define EMBADMSG 11 /* Unknown message type */
#define EMMSG2BIG 12 /* Message to large for buffer */
#define EMNOSEND 13 /* Could not send message */
#define EMNORECV 14 /* Could not receive message */
#define EMRESET 15 /* Could not RESET target */
#define EMCONFIG 16 /* Could not get target CONFIG */
#define EMSTATUS 17 /* Could not get target STATUS */
#define EMREAD 18 /* Could not READ target memory */
#define EMWRITE 19 /* Could not WRITE target memory */
#define EMBKPTSET 20 /* Could not set breakpoint */
#define EMBKPTRM 21 /* Could not remove breakpoint */
#define EMBKPTSTAT 22 /* Could not get breakpoint status */
#define EMBKPTNONE 23 /* All breakpoints in use */
#define EMBKPTUSED 24 /* Breakpoints already in use */
#define EMCOPY 25 /* Could not COPY target memory */
#define EMFILL 26 /* Could not FILL target memory */
#define EMINIT 27 /* Could not initialize target memory */
#define EMGO 28 /* Could not start execution */
#define EMSTEP 29 /* Could not single step */
#define EMBREAK 30 /* Could not BREAK */
#define EMHIF 31 /* Could not perform HIF service */
#define EMCHANNEL0 32 /* Could not read CHANNEL0 */
#define EMCHANNEL1 33 /* Could not write CHANNEL1 */
/* COFF file loader errors */
#define EMOPEN 34 /* Could not open COFF file */
#define EMHDR 35 /* Could not read COFF header */
#define EMMAGIC 36 /* Bad magic number */
#define EMAOUT 37 /* Could not read COFF a.out header */
#define EMSCNHDR 38 /* Could not read COFF section header */
#define EMSCN 39 /* Could not read COFF section */
#define EMCLOSE 40 /* Could not close COFF file */
/* Log file errors */
#define EMLOGOPEN 41 /* Could not open log file */
#define EMLOGREAD 42 /* Could not read log file */
#define EMLOGWRITE 43 /* Could not write to log file */
#define EMLOGCLOSE 44 /* Could not close log file */
/* Command file errors */
#define EMCMDOPEN 45 /* Could not open command file */
#define EMCMDREAD 46 /* Could not read command file */
#define EMCMDWRITE 47 /* Could not write to command file */
#define EMCMDCLOSE 48 /* Could not close comand file */
#define EMTIMEOUT 49 /* Host timed out waiting for a message */
#define EMCOMMTYPE 50 /* A '-t' flag must be specified */
#define EMCOMMERR 51 /* Communication error */
#define EMBAUD 52 /* Invalid baud rate specified */
/*
* Memory Spaces
*/
#define LOCAL_REG 0 /* Local processor register */
#define GLOBAL_REG 1 /* Global processor register */
#define SPECIAL_REG 2 /* Special processor register */
#define TLB_REG 3 /* Translation Lookaside Buffer */
#define COPROC_REG 4 /* Coprocessor register */
#define I_MEM 5 /* Instruction Memory */
#define D_MEM 6 /* Data Memory */
#define I_ROM 7 /* Instruction ROM */
#define D_ROM 8 /* Data ROM */
#define I_O 9 /* Input/Output */
#define I_CACHE 10 /* Instruction Cache */
#define D_CACHE 11 /* Data Cache */
/* To supress warnings for zero length array definitions */
#define DUMMY 1
/*
** Host to target definitions
*/
#define RESET 0
#define CONFIG_REQ 1
#define STATUS_REQ 2
#define READ_REQ 3
#define WRITE_REQ 4
#define BKPT_SET 5
#define BKPT_RM 6
#define BKPT_STAT 7
#define COPY 8
#define FILL 9
#define INIT 10
#define GO 11
#define STEP 12
#define BREAK 13
#define HIF_CALL_RTN 64
#define CHANNEL0 65
#define CHANNEL1_ACK 66
/*
** Target to host definitions
*/
#define RESET_ACK 32
#define CONFIG 33
#define STATUS 34
#define READ_ACK 35
#define WRITE_ACK 36
#define BKPT_SET_ACK 37
#define BKPT_RM_ACK 38
#define BKPT_STAT_ACK 39
#define COPY_ACK 40
#define FILL_ACK 41
#define INIT_ACK 42
#define HALT 43
#define ERROR 63
#define HIF_CALL 96
#define CHANNEL0_ACK 97
#define CHANNEL1 98
/* A "generic" message */
struct generic_msg_t
{
INT32 code; /* generic */
INT32 length;
BYTE byte[DUMMY];
};
/* A "generic" message (with an INT32 array) */
struct generic_int32_msg_t
{
INT32 code; /* generic */
INT32 length;
INT32 int32[DUMMY];
};
/*
** Host to target messages
*/
struct reset_msg_t
{
INT32 code; /* 0 */
INT32 length;
};
struct config_req_msg_t
{
INT32 code; /* 1 */
INT32 length;
};
struct status_req_msg_t
{
INT32 code; /* 2 */
INT32 length;
};
struct read_req_msg_t
{
INT32 code; /* 3 */
INT32 length;
INT32 memory_space;
ADDR32 address;
INT32 byte_count;
};
struct write_req_msg_t
{
INT32 code; /* 4 */
INT32 length;
INT32 memory_space;
ADDR32 address;
INT32 byte_count;
BYTE data[DUMMY];
};
struct write_r_msg_t
{
INT32 code; /* 4 */
INT32 length;
INT32 memory_space;
ADDR32 address;
INT32 byte_count;
INT32 data[DUMMY];
};
struct bkpt_set_msg_t
{
INT32 code; /* 5 */
INT32 length;
INT32 memory_space;
ADDR32 bkpt_addr;
INT32 pass_count;
INT32 bkpt_type;
};
struct bkpt_rm_msg_t
{
INT32 code; /* 6 */
INT32 length;
INT32 memory_space;
ADDR32 bkpt_addr;
};
struct bkpt_stat_msg_t
{
INT32 code; /* 7 */
INT32 length;
INT32 memory_space;
ADDR32 bkpt_addr;
};
struct copy_msg_t
{
INT32 code; /* 8 */
INT32 length;
INT32 source_space;
ADDR32 source_addr;
INT32 dest_space;
ADDR32 dest_addr;
INT32 byte_count;
};
struct fill_msg_t
{
INT32 code; /* 9 */
INT32 length;
INT32 memory_space;
ADDR32 start_addr;
INT32 fill_count;
INT32 byte_count;
BYTE fill_data[DUMMY];
};
struct init_msg_t
{
INT32 code; /* 10 */
INT32 length;
ADDR32 text_start;
ADDR32 text_end;
ADDR32 data_start;
ADDR32 data_end;
ADDR32 entry_point;
INT32 mem_stack_size;
INT32 reg_stack_size;
ADDR32 arg_start;
INT32 os_control;
};
struct go_msg_t
{
INT32 code; /* 11 */
INT32 length;
};
struct step_msg_t
{
INT32 code; /* 12 */
INT32 length;
INT32 count;
};
struct break_msg_t
{
INT32 code; /* 13 */
INT32 length;
};
struct hif_call_rtn_msg_t
{
INT32 code; /* 64 */
INT32 length;
INT32 service_number;
INT32 gr121;
INT32 gr96;
INT32 gr97;
};
struct channel0_msg_t
{
INT32 code; /* 65 */
INT32 length;
BYTE data;
};
struct channel1_ack_msg_t
{
INT32 code; /* 66 */
INT32 length;
};
/*
** Target to host messages
*/
struct reset_ack_msg_t
{
INT32 code; /* 32 */
INT32 length;
};
struct config_msg_t
{
INT32 code; /* 33 */
INT32 length;
INT32 processor_id;
INT32 version;
ADDR32 I_mem_start;
INT32 I_mem_size;
ADDR32 D_mem_start;
INT32 D_mem_size;
ADDR32 ROM_start;
INT32 ROM_size;
INT32 max_msg_size;
INT32 max_bkpts;
INT32 coprocessor;
INT32 reserved;
};
struct status_msg_t
{
INT32 code; /* 34 */
INT32 length;
INT32 msgs_sent;
INT32 msgs_received;
INT32 errors;
INT32 bkpts_hit;
INT32 bkpts_free;
INT32 traps;
INT32 fills;
INT32 spills;
INT32 cycles;
INT32 reserved;
};
struct read_ack_msg_t
{
INT32 code; /* 35 */
INT32 length;
INT32 memory_space;
ADDR32 address;
INT32 byte_count;
BYTE data[DUMMY];
};
struct read_r_ack_msg_t
{
INT32 code; /* 35 */
INT32 length;
INT32 memory_space;
ADDR32 address;
INT32 byte_count;
INT32 data[DUMMY];
};
struct write_ack_msg_t
{
INT32 code; /* 36 */
INT32 length;
INT32 memory_space;
ADDR32 address;
INT32 byte_count;
};
struct bkpt_set_ack_msg_t
{
INT32 code; /* 37 */
INT32 length;
INT32 memory_space;
ADDR32 address;
INT32 pass_count;
INT32 bkpt_type;
};
struct bkpt_rm_ack_msg_t
{
INT32 code; /* 38 */
INT32 length;
INT32 memory_space;
ADDR32 address;
};
struct bkpt_stat_ack_msg_t
{
INT32 code; /* 39 */
INT32 length;
INT32 memory_space;
ADDR32 address;
INT32 pass_count;
INT32 bkpt_type;
};
struct copy_ack_msg_t
{
INT32 code; /* 40 */
INT32 length;
INT32 source_space;
ADDR32 source_addr;
INT32 dest_space;
ADDR32 dest_addr;
INT32 byte_count;
};
struct fill_ack_msg_t
{
INT32 code; /* 41 */
INT32 length;
INT32 memory_space;
ADDR32 start_addr;
INT32 fill_count;
INT32 byte_count;
};
struct init_ack_msg_t
{
INT32 code; /* 42 */
INT32 length;
};
struct halt_msg_t
{
INT32 code; /* 43 */
INT32 length;
INT32 memory_space;
ADDR32 pc0;
ADDR32 pc1;
INT32 trap_number;
};
struct error_msg_t
{
INT32 code; /* 63 */
INT32 length;
INT32 error_code;
INT32 memory_space;
ADDR32 address;
};
struct hif_call_msg_t
{
INT32 code; /* 96 */
INT32 length;
INT32 service_number;
INT32 lr2;
INT32 lr3;
INT32 lr4;
};
struct channel0_ack_msg_t
{
INT32 code; /* 97 */
INT32 length;
};
struct channel1_msg_t
{
INT32 code; /* 98 */
INT32 length;
BYTE data[DUMMY];
};
/*
** Union all of the message types together
*/
union msg_t
{
struct generic_msg_t generic_msg;
struct generic_int32_msg_t generic_int32_msg;
struct reset_msg_t reset_msg;
struct config_req_msg_t config_req_msg;
struct status_req_msg_t status_req_msg;
struct read_req_msg_t read_req_msg;
struct write_req_msg_t write_req_msg;
struct write_r_msg_t write_r_msg;
struct bkpt_set_msg_t bkpt_set_msg;
struct bkpt_rm_msg_t bkpt_rm_msg;
struct bkpt_stat_msg_t bkpt_stat_msg;
struct copy_msg_t copy_msg;
struct fill_msg_t fill_msg;
struct init_msg_t init_msg;
struct go_msg_t go_msg;
struct step_msg_t step_msg;
struct break_msg_t break_msg;
struct hif_call_rtn_msg_t hif_call_rtn_msg;
struct channel0_msg_t channel0_msg;
struct channel1_ack_msg_t channel1_ack_msg;
struct reset_ack_msg_t reset_ack_msg;
struct config_msg_t config_msg;
struct status_msg_t status_msg;
struct read_ack_msg_t read_ack_msg;
struct read_r_ack_msg_t read_r_ack_msg;
struct write_ack_msg_t write_ack_msg;
struct bkpt_set_ack_msg_t bkpt_set_ack_msg;
struct bkpt_rm_ack_msg_t bkpt_rm_ack_msg;
struct bkpt_stat_ack_msg_t bkpt_stat_ack_msg;
struct copy_ack_msg_t copy_ack_msg;
struct fill_ack_msg_t fill_ack_msg;
struct init_ack_msg_t init_ack_msg;
struct halt_msg_t halt_msg;
struct error_msg_t error_msg;
struct hif_call_msg_t hif_call_msg;
struct channel0_ack_msg_t channel0_ack_msg;
struct channel1_msg_t channel1_msg;
};

File diff suppressed because it is too large Load Diff

View File

@ -1,254 +0,0 @@
/* Definitions for remote debugging interface for ROM monitors.
Copyright 1990, 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000
Free Software Foundation, Inc.
Contributed by Cygnus Support. Written by Rob Savoye for Cygnus.
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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef MONITOR_H
#define MONITOR_H
struct serial;
/* This structure describes the strings necessary to give small command
sequences to the monitor, and parse the response.
CMD is the actual command typed at the monitor. Usually this has
embedded sequences ala printf, which are substituted with the
arguments appropriate to that type of command. Ie: to examine a
register, we substitute the register name for the first arg. To
modify memory, we substitute the memory location and the new
contents for the first and second args, etc...
RESP_DELIM used to home in on the response string, and is used to
disambiguate the answer within the pile of text returned by the
monitor. This should be a unique string that immediately precedes
the answer. Ie: if your monitor prints out `PC: 00000001= ' in
response to asking for the PC, you should use `: ' as the
RESP_DELIM. RESP_DELIM may be NULL if the res- ponse is going to
be ignored, or has no particular leading text.
TERM is the string that the monitor outputs to indicate that it is
idle, and waiting for input. This is usually a prompt of some
sort. In the previous example, it would be `= '. It is important
that TERM really means that the monitor is idle, otherwise GDB may
try to type at it when it isn't ready for input. This is a problem
because many monitors cannot deal with type-ahead. TERM may be
NULL if the normal prompt is output.
TERM_CMD is used to quit out of the subcommand mode and get back to
the main prompt. TERM_CMD may be NULL if it isn't necessary. It
will also be ignored if TERM is NULL. */
struct memrw_cmd
{
char *cmdb; /* Command to send for byte read/write */
char *cmdw; /* Command for word (16 bit) read/write */
char *cmdl; /* Command for long (32 bit) read/write */
char *cmdll; /* Command for long long (64 bit) read/write */
char *resp_delim; /* String just prior to the desired value */
char *term; /* Terminating string to search for */
char *term_cmd; /* String to get out of sub-mode (if necessary) */
};
struct regrw_cmd
{
char *cmd; /* Command to send for reg read/write */
char *resp_delim; /* String (actually a regexp if getmem) just
prior to the desired value */
char *term; /* Terminating string to search for */
char *term_cmd; /* String to get out of sub-mode (if necessary) */
};
struct monitor_ops
{
int flags; /* See below */
char **init; /* List of init commands. NULL terminated. */
char *cont; /* continue command */
char *step; /* single step */
char *stop; /* Interrupt program string */
char *set_break; /* set a breakpoint. If NULL, monitor implementation
sets its own to_insert_breakpoint method. */
char *clr_break; /* clear a breakpoint */
char *clr_all_break; /* Clear all breakpoints */
char *fill; /* Memory fill cmd (addr len val) */
struct memrw_cmd setmem; /* set memory to a value */
struct memrw_cmd getmem; /* display memory */
struct regrw_cmd setreg; /* set a register */
struct regrw_cmd getreg; /* get a register */
/* Some commands can dump a bunch of registers
at once. This comes as a set of REG=VAL
pairs. This should be called for each pair
of registers that we can parse to supply
GDB with the value of a register. */
char *dump_registers; /* Command to dump all regs at once */
char *register_pattern; /* Pattern that picks out register from reg dump */
void (*supply_register) (char *name, int namelen, char *val, int vallen);
void (*load_routine) (struct serial *desc, char *file,
int hashmark); /* Download routine */
int (*dumpregs) (void); /* routine to dump all registers */
int (*continue_hook) (void); /* Emit the continue command */
int (*wait_filter) (char *buf, /* Maybe contains registers */
int bufmax,
int *response_length,
struct target_waitstatus * status);
char *load; /* load command */
char *loadresp; /* Response to load command */
char *prompt; /* monitor command prompt */
char *line_term; /* end-of-command delimitor */
char *cmd_end; /* optional command terminator */
struct target_ops *target; /* target operations */
int stopbits; /* number of stop bits */
char **regnames; /* array of register names in ascii */
int num_breakpoints; /* If set_break != NULL, number of supported
breakpoints */
int magic; /* Check value */
};
/* The monitor ops magic number, used to detect if an ops structure doesn't
have the right number of entries filled in. */
#define MONITOR_OPS_MAGIC 600925
/* Flag definitions. */
/* If set, then clear breakpoint command uses address, otherwise it
uses an index returned by the monitor. */
#define MO_CLR_BREAK_USES_ADDR 0x1
/* If set, then memory fill command uses STARTADDR, ENDADDR+1, VALUE
as args, else it uses STARTADDR, LENGTH, VALUE as args. */
#define MO_FILL_USES_ADDR 0x2
/* If set, then monitor doesn't automatically supply register dump
when coming back after a continue. */
#define MO_NEED_REGDUMP_AFTER_CONT 0x4
/* getmem needs start addr and end addr */
#define MO_GETMEM_NEEDS_RANGE 0x8
/* getmem can only read one loc at a time */
#define MO_GETMEM_READ_SINGLE 0x10
/* handle \r\n combinations */
#define MO_HANDLE_NL 0x20
/* don't expect echos in monitor_open */
#define MO_NO_ECHO_ON_OPEN 0x40
/* If set, send break to stop monitor */
#define MO_SEND_BREAK_ON_STOP 0x80
/* If set, target sends an ACK after each S-record */
#define MO_SREC_ACK 0x100
/* Allow 0x prefix on addresses retured from monitor */
#define MO_HEX_PREFIX 0x200
/* Some monitors require a different command when starting a program */
#define MO_RUN_FIRST_TIME 0x400
/* Don't expect echos when getting memory */
#define MO_NO_ECHO_ON_SETMEM 0x800
/* If set, then register store command expects value BEFORE regname */
#define MO_REGISTER_VALUE_FIRST 0x1000
/* If set, then the monitor displays registers as pairs. */
#define MO_32_REGS_PAIRED 0x2000
/* If set, then register setting happens interactively. */
#define MO_SETREG_INTERACTIVE 0x4000
/* If set, then memory setting happens interactively. */
#define MO_SETMEM_INTERACTIVE 0x8000
/* If set, then memory dumps are always on 16-byte boundaries, even
when less is desired. */
#define MO_GETMEM_16_BOUNDARY 0x10000
/* If set, then the monitor numbers its breakpoints starting from 1. */
#define MO_CLR_BREAK_1_BASED 0x20000
/* If set, then the monitor acks srecords with a plus sign. */
#define MO_SREC_ACK_PLUS 0x40000
/* If set, then the monitor "acks" srecords with rotating lines. */
#define MO_SREC_ACK_ROTATE 0x80000
/* If set, then remove useless address bits from memory addresses. */
#define MO_ADDR_BITS_REMOVE 0x100000
/* If set, then display target program output if prefixed by ^O. */
#define MO_PRINT_PROGRAM_OUTPUT 0x200000
/* Some dump bytes commands align the first data with the preceeding
16 byte boundary. Some print blanks and start at the exactly the
requested boundary. */
#define MO_EXACT_DUMPADDR 0x400000
/* Rather entering and exiting the write memory dialog for each word byte,
we can save time by transferring the whole block without exiting
the memory editing mode. You only need to worry about this
if you are doing memory downloading.
This engages a new write function registered with dcache.
*/
#define MO_HAS_BLOCKWRITES 0x800000
#define SREC_SIZE 160
extern void monitor_open (char *args, struct monitor_ops *ops, int from_tty);
extern void monitor_close (int quitting);
extern char *monitor_supply_register (int regno, char *valstr);
extern int monitor_expect (char *prompt, char *buf, int buflen);
extern int monitor_expect_prompt (char *buf, int buflen);
extern void monitor_printf (char *, ...) ATTR_FORMAT (printf, 1, 2);
extern void
monitor_printf_noecho (char *, ...)
ATTR_FORMAT (printf, 1, 2);
extern void monitor_write (char *buf, int buflen);
extern int monitor_readchar (void);
extern char *monitor_get_dev_name (void);
extern void init_monitor_ops (struct target_ops *);
extern int monitor_dump_reg_block (char *dump_cmd);
#endif

View File

@ -1,938 +0,0 @@
/* Handle OSF/1 shared libraries for GDB, the GNU Debugger.
Copyright 1993, 1994, 1995, 1996, 1998, 1999, 2000
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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* FIXME: Most of this code could be merged with solib.c by using
next_link_map_member and xfer_link_map_member in solib.c. */
#include "defs.h"
#include <sys/types.h>
#include <signal.h>
#include "gdb_string.h"
#include <fcntl.h>
#include "symtab.h"
#include "bfd.h"
#include "symfile.h"
#include "objfiles.h"
#include "gdbcore.h"
#include "command.h"
#include "target.h"
#include "frame.h"
#include "gdb_regex.h"
#include "inferior.h"
#include "language.h"
#include "gdbcmd.h"
#define MAX_PATH_SIZE 1024 /* FIXME: Should be dynamic */
/* When handling shared libraries, GDB has to find out the pathnames
of all shared libraries that are currently loaded (to read in their
symbols) and where the shared libraries are loaded in memory
(to relocate them properly from their prelinked addresses to the
current load address).
Under OSF/1 there are two possibilities to get at this information:
1) Peek around in the runtime loader structures.
These are not documented, and they are not defined in the system
header files. The definitions below were obtained by experimentation,
but they seem stable enough.
2) Use the undocumented libxproc.a library, which contains the
equivalent ldr_* routines.
This approach is somewhat cleaner, but it requires that the GDB
executable is dynamically linked. In addition it requires a
NAT_CLIBS= -lxproc -Wl,-expect_unresolved,ldr_process_context
linker specification for GDB and all applications that are using
libgdb.
We will use the peeking approach until it becomes unwieldy. */
#ifndef USE_LDR_ROUTINES
/* Definition of runtime loader structures, found by experimentation. */
#define RLD_CONTEXT_ADDRESS 0x3ffc0000000
typedef struct
{
CORE_ADDR next;
CORE_ADDR previous;
CORE_ADDR unknown1;
char *module_name;
CORE_ADDR modinfo_addr;
long module_id;
CORE_ADDR unknown2;
CORE_ADDR unknown3;
long region_count;
CORE_ADDR regioninfo_addr;
}
ldr_module_info_t;
typedef struct
{
long unknown1;
CORE_ADDR regionname_addr;
long protection;
CORE_ADDR vaddr;
CORE_ADDR mapaddr;
long size;
long unknown2[5];
}
ldr_region_info_t;
typedef struct
{
CORE_ADDR unknown1;
CORE_ADDR unknown2;
CORE_ADDR head;
CORE_ADDR tail;
}
ldr_context_t;
static ldr_context_t ldr_context;
#else
#include <loader.h>
static ldr_process_t fake_ldr_process;
/* Called by ldr_* routines to read memory from the current target. */
static int ldr_read_memory (CORE_ADDR, char *, int, int);
static int
ldr_read_memory (CORE_ADDR memaddr, char *myaddr, int len, int readstring)
{
int result;
char *buffer;
if (readstring)
{
target_read_string (memaddr, &buffer, len, &result);
if (result == 0)
strcpy (myaddr, buffer);
xfree (buffer);
}
else
result = target_read_memory (memaddr, myaddr, len);
if (result != 0)
result = -result;
return result;
}
#endif
/* Define our own link_map structure.
This will help to share code with solib.c. */
struct link_map
{
CORE_ADDR l_offset; /* prelink to load address offset */
char *l_name; /* full name of loaded object */
ldr_module_info_t module_info; /* corresponding module info */
};
#define LM_OFFSET(so) ((so) -> lm.l_offset)
#define LM_NAME(so) ((so) -> lm.l_name)
struct so_list
{
struct so_list *next; /* next structure in linked list */
struct link_map lm; /* copy of link map from inferior */
struct link_map *lmaddr; /* addr in inferior lm was read from */
CORE_ADDR lmend; /* upper addr bound of mapped object */
char so_name[MAX_PATH_SIZE]; /* shared object lib name (FIXME) */
char symbols_loaded; /* flag: symbols read in yet? */
char from_tty; /* flag: print msgs? */
struct objfile *objfile; /* objfile for loaded lib */
struct section_table *sections;
struct section_table *sections_end;
struct section_table *textsection;
bfd *abfd;
};
static struct so_list *so_list_head; /* List of known shared objects */
extern int fdmatch (int, int); /* In libiberty */
/* Local function prototypes */
static void sharedlibrary_command (char *, int);
static void info_sharedlibrary_command (char *, int);
static int symbol_add_stub (char *);
static struct so_list *find_solib (struct so_list *);
static struct link_map *first_link_map_member (void);
static struct link_map *next_link_map_member (struct so_list *);
static void xfer_link_map_member (struct so_list *, struct link_map *);
static int solib_map_sections (char *);
/*
LOCAL FUNCTION
solib_map_sections -- open bfd and build sections for shared lib
SYNOPSIS
static int solib_map_sections (struct so_list *so)
DESCRIPTION
Given a pointer to one of the shared objects in our list
of mapped objects, use the recorded name to open a bfd
descriptor for the object, build a section table, and then
relocate all the section addresses by the base address at
which the shared object was mapped.
FIXMES
In most (all?) cases the shared object file name recorded in the
dynamic linkage tables will be a fully qualified pathname. For
cases where it isn't, do we really mimic the systems search
mechanism correctly in the below code (particularly the tilde
expansion stuff?).
*/
static int
solib_map_sections (char *arg)
{
struct so_list *so = (struct so_list *) arg; /* catch_errors bogon */
char *filename;
char *scratch_pathname;
int scratch_chan;
struct section_table *p;
struct cleanup *old_chain;
bfd *abfd;
filename = tilde_expand (so->so_name);
old_chain = make_cleanup (xfree, filename);
scratch_chan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
&scratch_pathname);
if (scratch_chan < 0)
{
scratch_chan = openp (getenv ("LD_LIBRARY_PATH"), 1, filename,
O_RDONLY, 0, &scratch_pathname);
}
if (scratch_chan < 0)
{
perror_with_name (filename);
}
/* Leave scratch_pathname allocated. bfd->name will point to it. */
abfd = bfd_fdopenr (scratch_pathname, gnutarget, scratch_chan);
if (!abfd)
{
close (scratch_chan);
error ("Could not open `%s' as an executable file: %s",
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
/* Leave bfd open, core_xfer_memory and "info files" need it. */
so->abfd = abfd;
abfd->cacheable = 1;
if (!bfd_check_format (abfd, bfd_object))
{
error ("\"%s\": not in executable format: %s.",
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
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 ()));
}
for (p = so->sections; p < so->sections_end; p++)
{
/* Relocate the section binding addresses as recorded in the shared
object's file by the offset to get the address to which the
object was actually mapped. */
p->addr += LM_OFFSET (so);
p->endaddr += LM_OFFSET (so);
so->lmend = (CORE_ADDR) max (p->endaddr, so->lmend);
if (STREQ (p->the_bfd_section->name, ".text"))
{
so->textsection = p;
}
}
/* Free the file names, close the file now. */
do_cleanups (old_chain);
return (1);
}
/*
LOCAL FUNCTION
first_link_map_member -- locate first member in dynamic linker's map
SYNOPSIS
static struct link_map *first_link_map_member (void)
DESCRIPTION
Read in a copy of the first member in the inferior's dynamic
link map from the inferior's dynamic linker structures, and return
a pointer to the copy in our address space.
*/
static struct link_map *
first_link_map_member (void)
{
struct link_map *lm = NULL;
static struct link_map first_lm;
#ifdef USE_LDR_ROUTINES
ldr_module_t mod_id = LDR_NULL_MODULE;
size_t retsize;
fake_ldr_process = ldr_core_process ();
ldr_set_core_reader (ldr_read_memory);
ldr_xdetach (fake_ldr_process);
if (ldr_xattach (fake_ldr_process) != 0
|| ldr_next_module (fake_ldr_process, &mod_id) != 0
|| mod_id == LDR_NULL_MODULE
|| ldr_inq_module (fake_ldr_process, mod_id,
&first_lm.module_info, sizeof (ldr_module_info_t),
&retsize) != 0)
return lm;
#else
CORE_ADDR ldr_context_addr;
if (target_read_memory ((CORE_ADDR) RLD_CONTEXT_ADDRESS,
(char *) &ldr_context_addr,
sizeof (CORE_ADDR)) != 0
|| target_read_memory (ldr_context_addr,
(char *) &ldr_context,
sizeof (ldr_context_t)) != 0
|| target_read_memory ((CORE_ADDR) ldr_context.head,
(char *) &first_lm.module_info,
sizeof (ldr_module_info_t)) != 0)
return lm;
#endif
lm = &first_lm;
/* The first entry is for the main program and should be skipped. */
lm->l_name = NULL;
return lm;
}
static struct link_map *
next_link_map_member (struct so_list *so_list_ptr)
{
struct link_map *lm = NULL;
static struct link_map next_lm;
#ifdef USE_LDR_ROUTINES
ldr_module_t mod_id = so_list_ptr->lm.module_info.lmi_modid;
size_t retsize;
if (ldr_next_module (fake_ldr_process, &mod_id) != 0
|| mod_id == LDR_NULL_MODULE
|| ldr_inq_module (fake_ldr_process, mod_id,
&next_lm.module_info, sizeof (ldr_module_info_t),
&retsize) != 0)
return lm;
lm = &next_lm;
lm->l_name = lm->module_info.lmi_name;
#else
CORE_ADDR ldr_context_addr;
/* Reread context in case ldr_context.tail was updated. */
if (target_read_memory ((CORE_ADDR) RLD_CONTEXT_ADDRESS,
(char *) &ldr_context_addr,
sizeof (CORE_ADDR)) != 0
|| target_read_memory (ldr_context_addr,
(char *) &ldr_context,
sizeof (ldr_context_t)) != 0
|| so_list_ptr->lm.module_info.modinfo_addr == ldr_context.tail
|| target_read_memory (so_list_ptr->lm.module_info.next,
(char *) &next_lm.module_info,
sizeof (ldr_module_info_t)) != 0)
return lm;
lm = &next_lm;
lm->l_name = lm->module_info.module_name;
#endif
return lm;
}
static void
xfer_link_map_member (struct so_list *so_list_ptr, struct link_map *lm)
{
int i;
so_list_ptr->lm = *lm;
/* OSF/1 shared libraries are pre-linked to particular addresses,
but the runtime loader may have to relocate them if the
address ranges of the libraries used by the target executable clash,
or if the target executable is linked with the -taso option.
The offset is the difference between the address where the shared
library is mapped and the pre-linked address of the shared library.
FIXME: GDB is currently unable to relocate the shared library
sections by different offsets. If sections are relocated by
different offsets, put out a warning and use the offset of the
first section for all remaining sections. */
LM_OFFSET (so_list_ptr) = 0;
/* There is one entry that has no name (for the inferior executable)
since it is not a shared object. */
if (LM_NAME (so_list_ptr) != 0)
{
#ifdef USE_LDR_ROUTINES
int len = strlen (LM_NAME (so_list_ptr) + 1);
if (len > MAX_PATH_SIZE)
len = MAX_PATH_SIZE;
strncpy (so_list_ptr->so_name, LM_NAME (so_list_ptr), MAX_PATH_SIZE);
so_list_ptr->so_name[MAX_PATH_SIZE - 1] = '\0';
for (i = 0; i < lm->module_info.lmi_nregion; i++)
{
ldr_region_info_t region_info;
size_t retsize;
CORE_ADDR region_offset;
if (ldr_inq_region (fake_ldr_process, lm->module_info.lmi_modid,
i, &region_info, sizeof (region_info),
&retsize) != 0)
break;
region_offset = (CORE_ADDR) region_info.lri_mapaddr
- (CORE_ADDR) region_info.lri_vaddr;
if (i == 0)
LM_OFFSET (so_list_ptr) = region_offset;
else if (LM_OFFSET (so_list_ptr) != region_offset)
warning ("cannot handle shared library relocation for %s (%s)",
so_list_ptr->so_name, region_info.lri_name);
}
#else
int errcode;
char *buffer;
target_read_string ((CORE_ADDR) LM_NAME (so_list_ptr), &buffer,
MAX_PATH_SIZE - 1, &errcode);
if (errcode != 0)
error ("xfer_link_map_member: Can't read pathname for load map: %s\n",
safe_strerror (errcode));
strncpy (so_list_ptr->so_name, buffer, MAX_PATH_SIZE - 1);
xfree (buffer);
so_list_ptr->so_name[MAX_PATH_SIZE - 1] = '\0';
for (i = 0; i < lm->module_info.region_count; i++)
{
ldr_region_info_t region_info;
CORE_ADDR region_offset;
if (target_read_memory (lm->module_info.regioninfo_addr
+ i * sizeof (region_info),
(char *) &region_info,
sizeof (region_info)) != 0)
break;
region_offset = region_info.mapaddr - region_info.vaddr;
if (i == 0)
LM_OFFSET (so_list_ptr) = region_offset;
else if (LM_OFFSET (so_list_ptr) != region_offset)
{
char *region_name;
target_read_string (region_info.regionname_addr, &buffer,
MAX_PATH_SIZE - 1, &errcode);
if (errcode == 0)
region_name = buffer;
else
region_name = "??";
warning ("cannot handle shared library relocation for %s (%s)",
so_list_ptr->so_name, region_name);
xfree (buffer);
}
}
#endif
catch_errors (solib_map_sections, (char *) so_list_ptr,
"Error while mapping shared library sections:\n",
RETURN_MASK_ALL);
}
}
/*
LOCAL FUNCTION
find_solib -- step through list of shared objects
SYNOPSIS
struct so_list *find_solib (struct so_list *so_list_ptr)
DESCRIPTION
This module contains the routine which finds the names of any
loaded "images" in the current process. The argument in must be
NULL on the first call, and then the returned value must be passed
in on subsequent calls. This provides the capability to "step" down
the list of loaded objects. On the last object, a NULL value is
returned.
The arg and return value are "struct link_map" pointers, as defined
in <link.h>.
*/
static struct so_list *
find_solib (struct so_list *so_list_ptr)
{
struct so_list *so_list_next = NULL;
struct link_map *lm = NULL;
struct so_list *new;
if (so_list_ptr == NULL)
{
/* We are setting up for a new scan through the loaded images. */
if ((so_list_next = so_list_head) == NULL)
{
/* Find the first link map list member. */
lm = first_link_map_member ();
}
}
else
{
/* We have been called before, and are in the process of walking
the shared library list. Advance to the next shared object. */
lm = next_link_map_member (so_list_ptr);
so_list_next = so_list_ptr->next;
}
if ((so_list_next == NULL) && (lm != NULL))
{
/* Get next link map structure from inferior image and build a local
abbreviated load_map structure */
new = (struct so_list *) xmalloc (sizeof (struct so_list));
memset ((char *) new, 0, sizeof (struct so_list));
new->lmaddr = lm;
/* Add the new node as the next node in the list, or as the root
node if this is the first one. */
if (so_list_ptr != NULL)
{
so_list_ptr->next = new;
}
else
{
so_list_head = new;
}
so_list_next = new;
xfer_link_map_member (new, lm);
}
return (so_list_next);
}
/* A small stub to get us past the arg-passing pinhole of catch_errors. */
static int
symbol_add_stub (char *arg)
{
register struct so_list *so = (struct so_list *) arg; /* catch_errs bogon */
CORE_ADDR text_addr = 0;
struct section_addr_info section_addrs;
memset (&section_addrs, 0, sizeof (section_addrs));
if (so->textsection)
text_addr = so->textsection->addr;
else if (so->abfd != NULL)
{
asection *lowest_sect;
/* If we didn't find a mapped non zero sized .text section, set up
text_addr so that the relocation in symbol_file_add does no harm. */
lowest_sect = bfd_get_section_by_name (so->abfd, ".text");
if (lowest_sect == NULL)
bfd_map_over_sections (so->abfd, find_lowest_section,
(PTR) &lowest_sect);
if (lowest_sect)
text_addr = bfd_section_vma (so->abfd, lowest_sect) + LM_OFFSET (so);
}
section_addrs.other[0].addr = text_addr;
section_addrs.other[0].name = ".text";
so->objfile = symbol_file_add (so->so_name, so->from_tty,
&section_addrs, 0, OBJF_SHARED);
return (1);
}
/*
GLOBAL FUNCTION
solib_add -- add a shared library file to the symtab and section list
SYNOPSIS
void solib_add (char *arg_string, int from_tty,
struct target_ops *target, int readsyms)
DESCRIPTION
*/
void
solib_add (char *arg_string, int from_tty, struct target_ops *target, int readsyms)
{
register struct so_list *so = NULL; /* link map state variable */
/* Last shared library that we read. */
struct so_list *so_last = NULL;
char *re_err;
int count;
int old;
if (!readsyms)
return;
if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL)
{
error ("Invalid regexp: %s", re_err);
}
/* Add the shared library sections to the section table of the
specified target, if any. */
if (target)
{
/* Count how many new section_table entries there are. */
so = NULL;
count = 0;
while ((so = find_solib (so)) != NULL)
{
if (so->so_name[0])
{
count += so->sections_end - so->sections;
}
}
if (count)
{
/* Add these section table entries to the target's table. */
old = target_resize_to_sections (target, count);
while ((so = find_solib (so)) != NULL)
{
if (so->so_name[0])
{
count = so->sections_end - so->sections;
memcpy ((char *) (target->to_sections + old),
so->sections,
(sizeof (struct section_table)) * count);
old += count;
}
}
}
}
/* Now add the symbol files. */
so = NULL;
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;
}
}
}
/* Getting new symbols may change our opinion about what is
frameless. */
if (so_last)
reinit_frame_cache ();
}
/*
LOCAL FUNCTION
info_sharedlibrary_command -- code for "info sharedlibrary"
SYNOPSIS
static void info_sharedlibrary_command ()
DESCRIPTION
Walk through the shared library list and print information
about each attached library.
*/
static void
info_sharedlibrary_command (char *ignore, int from_tty)
{
register struct so_list *so = NULL; /* link map state variable */
int header_done = 0;
if (exec_bfd == NULL)
{
printf_unfiltered ("No executable file.\n");
return;
}
while ((so = find_solib (so)) != NULL)
{
if (so->so_name[0])
{
unsigned long txt_start = 0;
unsigned long txt_end = 0;
if (!header_done)
{
printf_unfiltered ("%-20s%-20s%-12s%s\n", "From", "To", "Syms Read",
"Shared Object Library");
header_done++;
}
if (so->textsection)
{
txt_start = (unsigned long) so->textsection->addr;
txt_end = (unsigned long) so->textsection->endaddr;
}
printf_unfiltered ("%-20s", local_hex_string_custom (txt_start, "08l"));
printf_unfiltered ("%-20s", local_hex_string_custom (txt_end, "08l"));
printf_unfiltered ("%-12s", so->symbols_loaded ? "Yes" : "No");
printf_unfiltered ("%s\n", so->so_name);
}
}
if (so_list_head == NULL)
{
printf_unfiltered ("No shared libraries loaded at this time.\n");
}
}
/*
GLOBAL FUNCTION
solib_address -- check to see if an address is in a shared lib
SYNOPSIS
char *solib_address (CORE_ADDR address)
DESCRIPTION
Provides a hook for other gdb routines to discover whether or
not a particular address is within the mapped address space of
a shared library. Any address between the base mapping address
and the first address beyond the end of the last mapping, is
considered to be within the shared library address space, for
our purposes.
For example, this routine is called at one point to disable
breakpoints which are in shared libraries that are not currently
mapped in.
*/
char *
solib_address (CORE_ADDR address)
{
register struct so_list *so = 0; /* link map state variable */
while ((so = find_solib (so)) != NULL)
{
if (so->so_name[0] && so->textsection)
{
if ((address >= (CORE_ADDR) so->textsection->addr) &&
(address < (CORE_ADDR) so->textsection->endaddr))
return (so->so_name);
}
}
return (0);
}
/* Called by free_all_symtabs */
void
clear_solib (void)
{
struct so_list *next;
char *bfd_filename;
disable_breakpoints_in_shlibs (1);
while (so_list_head)
{
if (so_list_head->sections)
{
xfree (so_list_head->sections);
}
if (so_list_head->abfd)
{
remove_target_sections (so_list_head->abfd);
bfd_filename = bfd_get_filename (so_list_head->abfd);
if (!bfd_close (so_list_head->abfd))
warning ("cannot close \"%s\": %s",
bfd_filename, bfd_errmsg (bfd_get_error ()));
}
else
/* This happens for the executable on SVR4. */
bfd_filename = NULL;
next = so_list_head->next;
if (bfd_filename)
xfree (bfd_filename);
xfree (so_list_head);
so_list_head = next;
}
}
/*
GLOBAL FUNCTION
solib_create_inferior_hook -- shared library startup support
SYNOPSIS
void solib_create_inferior_hook()
DESCRIPTION
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.
For a statically bound executable, this first instruction is the
one at "_start", or a similar text label. No further processing is
needed in that case.
For a dynamically bound executable, this first instruction is somewhere
in the rld, and the actual user executable is not yet mapped in.
We continue the inferior again, rld then maps in the actual user
executable and any needed shared libraries and then sends
itself a SIGTRAP.
At that point we discover the names of all shared libraries and
read their symbols in.
FIXME
This code does not properly handle hitting breakpoints which the
user might have set in the rld itself. Proper handling would have
to check if the SIGTRAP happened due to a kill call.
Also, what if child has exit()ed? Must exit loop somehow.
*/
void
solib_create_inferior_hook (void)
{
/* Nothing to do for statically bound executables. */
if (symfile_objfile == NULL
|| symfile_objfile->obfd == NULL
|| ((bfd_get_file_flags (symfile_objfile->obfd) & DYNAMIC) == 0))
return;
/* Now run the target. It will eventually get a SIGTRAP, at
which point all of the libraries will have been mapped in and we
can go groveling around in the rld structures to find
out what we need to know about them. */
clear_proceed_status ();
stop_soon_quietly = 1;
stop_signal = TARGET_SIGNAL_0;
do
{
target_resume (minus_one_ptid, 0, stop_signal);
wait_for_inferior ();
}
while (stop_signal != TARGET_SIGNAL_TRAP);
/* solib_add will call reinit_frame_cache.
But we are stopped in the runtime loader and we do not have symbols
for the runtime loader. So heuristic_proc_start will be called
and will put out an annoying warning.
Delaying the resetting of stop_soon_quietly until after symbol loading
suppresses the warning. */
solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add);
stop_soon_quietly = 0;
}
/*
LOCAL FUNCTION
sharedlibrary_command -- handle command to explicitly add library
SYNOPSIS
static void sharedlibrary_command (char *args, int from_tty)
DESCRIPTION
*/
static void
sharedlibrary_command (char *args, int from_tty)
{
dont_repeat ();
solib_add (args, from_tty, (struct target_ops *) 0, 1);
}
void
_initialize_solib (void)
{
add_com ("sharedlibrary", class_files, sharedlibrary_command,
"Load shared object library symbols for files matching REGEXP.");
add_info ("sharedlibrary", info_sharedlibrary_command,
"Status of loaded shared object libraries.");
add_show_from_set
(add_set_cmd ("auto-solib-add", class_support, var_boolean,
(char *) &auto_solib_add,
"Set autoloading of shared library symbols.\n\
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'.",
&setlist),
&showlist);
}

View File

@ -1,223 +0,0 @@
/* Remote debugging interface for PPCbug (PowerPC) Rom monitor
for GDB, the GNU debugger.
Copyright 1995, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
Written by Stu Grossman of Cygnus Support
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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "gdbcore.h"
#include "target.h"
#include "monitor.h"
#include "serial.h"
#include "regcache.h"
static void
ppcbug_supply_register (char *regname, int regnamelen, char *val, int vallen)
{
int regno = 0;
if (regnamelen < 2 || regnamelen > 4)
return;
switch (regname[0])
{
case 'R':
if (regname[1] < '0' || regname[1] > '9')
return;
if (regnamelen == 2)
regno = regname[1] - '0';
else if (regnamelen == 3 && regname[2] >= '0' && regname[2] <= '9')
regno = (regname[1] - '0') * 10 + (regname[2] - '0');
else
return;
break;
case 'F':
if (regname[1] != 'R' || regname[2] < '0' || regname[2] > '9')
return;
if (regnamelen == 3)
regno = 32 + regname[2] - '0';
else if (regnamelen == 4 && regname[3] >= '0' && regname[3] <= '9')
regno = 32 + (regname[2] - '0') * 10 + (regname[3] - '0');
else
return;
break;
case 'I':
if (regnamelen != 2 || regname[1] != 'P')
return;
regno = 64;
break;
case 'M':
if (regnamelen != 3 || regname[1] != 'S' || regname[2] != 'R')
return;
regno = 65;
break;
case 'C':
if (regnamelen != 2 || regname[1] != 'R')
return;
regno = 66;
break;
case 'S':
if (regnamelen != 4 || regname[1] != 'P' || regname[2] != 'R')
return;
else if (regname[3] == '8')
regno = 67;
else if (regname[3] == '9')
regno = 68;
else if (regname[3] == '1')
regno = 69;
else if (regname[3] == '0')
regno = 70;
else
return;
break;
default:
return;
}
monitor_supply_register (regno, val);
}
/*
* This array of registers needs to match the indexes used by GDB. The
* whole reason this exists is because the various ROM monitors use
* different names than GDB does, and don't support all the
* registers either. So, typing "info reg sp" becomes an "A7".
*/
static char *ppcbug_regnames[] =
{
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
"fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7",
"fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
"fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",
"fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31",
/* pc ps cnd lr cnt xer mq */
"ip", "msr", "cr", "spr8", "spr9", "spr1", "spr0"
};
/*
* Define the monitor command strings. Since these are passed directly
* through to a printf style function, we need can include formatting
* strings. We also need a CR or LF on the end.
*/
static struct target_ops ppcbug_ops0;
static struct target_ops ppcbug_ops1;
static char *ppcbug_inits[] =
{"\r", NULL};
static void
init_ppc_cmds (char *LOAD_CMD,
struct monitor_ops *OPS,
struct target_ops *targops)
{
OPS->flags = MO_CLR_BREAK_USES_ADDR | MO_HANDLE_NL;
OPS->init = ppcbug_inits; /* Init strings */
OPS->cont = "g\r"; /* continue command */
OPS->step = "t\r"; /* single step */
OPS->stop = NULL; /* interrupt command */
OPS->set_break = "br %x\r"; /* set a breakpoint */
OPS->clr_break = "nobr %x\r"; /* clear a breakpoint */
OPS->clr_all_break = "nobr\r"; /* clear all breakpoints */
OPS->fill = "bf %x:%x %x;b\r"; /* fill (start count val) */
OPS->setmem.cmdb = "ms %x %02x\r"; /* setmem.cmdb (addr, value) */
OPS->setmem.cmdw = "ms %x %04x\r"; /* setmem.cmdw (addr, value) */
OPS->setmem.cmdl = "ms %x %08x\r"; /* setmem.cmdl (addr, value) */
OPS->setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
OPS->setmem.resp_delim = NULL; /* setreg.resp_delim */
OPS->setmem.term = NULL; /* setreg.term */
OPS->setmem.term_cmd = NULL; /* setreg.term_cmd */
OPS->getmem.cmdb = "md %x:%x;b\r"; /* getmem.cmdb (addr, len) */
OPS->getmem.cmdw = "md %x:%x;b\r"; /* getmem.cmdw (addr, len) */
OPS->getmem.cmdl = "md %x:%x;b\r"; /* getmem.cmdl (addr, len) */
OPS->getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
OPS->getmem.resp_delim = " "; /* getmem.resp_delim */
OPS->getmem.term = NULL; /* getmem.term */
OPS->getmem.term_cmd = NULL; /* getmem.term_cmd */
OPS->setreg.cmd = "rs %s %x\r"; /* setreg.cmd (name, value) */
OPS->setreg.resp_delim = NULL; /* setreg.resp_delim */
OPS->setreg.term = NULL; /* setreg.term */
OPS->setreg.term_cmd = NULL; /* setreg.term_cmd */
OPS->getreg.cmd = "rs %s\r"; /* getreg.cmd (name) */
OPS->getreg.resp_delim = "="; /* getreg.resp_delim */
OPS->getreg.term = NULL; /* getreg.term */
OPS->getreg.term_cmd = NULL; /* getreg.term_cmd */
OPS->register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
OPS->supply_register = ppcbug_supply_register; /* supply_register */
OPS->dump_registers = "rd\r"; /* dump all registers */
OPS->load_routine = NULL; /* load_routine (defaults to SRECs) */
OPS->load = LOAD_CMD; /* download command */
OPS->loadresp = NULL; /* load response */
OPS->prompt = "PPC1-Bug>"; /* monitor command prompt */
OPS->line_term = "\r"; /* end-of-line terminator */
OPS->cmd_end = NULL; /* optional command terminator */
OPS->target = targops; /* target operations */
OPS->stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
OPS->regnames = ppcbug_regnames; /* registers names */
OPS->magic = MONITOR_OPS_MAGIC; /* magic */
}
static struct monitor_ops ppcbug_cmds0;
static struct monitor_ops ppcbug_cmds1;
static void
ppcbug_open0 (char *args, int from_tty)
{
monitor_open (args, &ppcbug_cmds0, from_tty);
}
static void
ppcbug_open1 (char *args, int from_tty)
{
monitor_open (args, &ppcbug_cmds1, from_tty);
}
void
_initialize_ppcbug_rom (void)
{
init_ppc_cmds ("lo 0\r", &ppcbug_cmds0, &ppcbug_ops0);
init_ppc_cmds ("lo 1\r", &ppcbug_cmds1, &ppcbug_ops1);
init_monitor_ops (&ppcbug_ops0);
ppcbug_ops0.to_shortname = "ppcbug";
ppcbug_ops0.to_longname = "PowerPC PPCBug monitor on port 0";
ppcbug_ops0.to_doc = "Debug via the PowerPC PPCBug monitor using port 0.\n\
Specify the serial device it is connected to (e.g. /dev/ttya).";
ppcbug_ops0.to_open = ppcbug_open0;
add_target (&ppcbug_ops0);
init_monitor_ops (&ppcbug_ops1);
ppcbug_ops1.to_shortname = "ppcbug1";
ppcbug_ops1.to_longname = "PowerPC PPCBug monitor on port 1";
ppcbug_ops1.to_doc = "Debug via the PowerPC PPCBug monitor using port 1.\n\
Specify the serial device it is connected to (e.g. /dev/ttya).";
ppcbug_ops1.to_open = ppcbug_open1;
add_target (&ppcbug_ops1);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,941 +0,0 @@
/* Generic remote debugging interface for simulators.
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
2002 Free Software Foundation, Inc.
Contributed by Cygnus Support.
Steve Chamberlain (sac@cygnus.com).
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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "inferior.h"
#include "value.h"
#include "gdb_string.h"
#include <ctype.h>
#include <fcntl.h>
#include <signal.h>
#include <setjmp.h>
#include <errno.h>
#include "terminal.h"
#include "target.h"
#include "gdbcore.h"
#include "callback.h"
#include "remote-sim.h"
#include "remote-utils.h"
#include "command.h"
#include "regcache.h"
/* Prototypes */
extern void _initialize_remote_sim (void);
extern int (*ui_loop_hook) (int signo);
static void dump_mem (char *buf, int len);
static void init_callbacks (void);
static void end_callbacks (void);
static int gdb_os_write_stdout (host_callback *, const char *, int);
static void gdb_os_flush_stdout (host_callback *);
static int gdb_os_write_stderr (host_callback *, const char *, int);
static void gdb_os_flush_stderr (host_callback *);
static int gdb_os_poll_quit (host_callback *);
/* printf_filtered is depreciated */
static void gdb_os_printf_filtered (host_callback *, const char *, ...);
static void gdb_os_vprintf_filtered (host_callback *, const char *, va_list);
static void gdb_os_evprintf_filtered (host_callback *, const char *, va_list);
static void gdb_os_error (host_callback *, const char *, ...);
static void gdbsim_fetch_register (int regno);
static void gdbsim_store_register (int regno);
static void gdbsim_kill (void);
static void gdbsim_load (char *prog, int fromtty);
static void gdbsim_create_inferior (char *exec_file, char *args, char **env);
static void gdbsim_open (char *args, int from_tty);
static void gdbsim_close (int quitting);
static void gdbsim_detach (char *args, int from_tty);
static void gdbsim_resume (ptid_t ptid, int step, enum target_signal siggnal);
static ptid_t gdbsim_wait (ptid_t ptid, struct target_waitstatus *status);
static void gdbsim_prepare_to_store (void);
static int gdbsim_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr,
int len, int write,
struct mem_attrib *attrib,
struct target_ops *target);
static void gdbsim_files_info (struct target_ops *target);
static void gdbsim_mourn_inferior (void);
static void gdbsim_stop (void);
void simulator_command (char *args, int from_tty);
/* Naming convention:
sim_* are the interface to the simulator (see remote-sim.h).
gdbsim_* are stuff which is internal to gdb. */
/* Forward data declarations */
extern struct target_ops gdbsim_ops;
static int program_loaded = 0;
/* We must keep track of whether the simulator has been opened or not because
GDB can call a target's close routine twice, but sim_close doesn't allow
this. We also need to record the result of sim_open so we can pass it
back to the other sim_foo routines. */
static SIM_DESC gdbsim_desc = 0;
static void
dump_mem (char *buf, int len)
{
if (len <= 8)
{
if (len == 8 || len == 4)
{
long l[2];
memcpy (l, buf, len);
printf_filtered ("\t0x%lx", l[0]);
if (len == 8)
printf_filtered (" 0x%lx", l[1]);
printf_filtered ("\n");
}
else
{
int i;
printf_filtered ("\t");
for (i = 0; i < len; i++)
printf_filtered ("0x%x ", buf[i]);
printf_filtered ("\n");
}
}
}
static host_callback gdb_callback;
static int callbacks_initialized = 0;
/* Initialize gdb_callback. */
static void
init_callbacks (void)
{
if (!callbacks_initialized)
{
gdb_callback = default_callback;
gdb_callback.init (&gdb_callback);
gdb_callback.write_stdout = gdb_os_write_stdout;
gdb_callback.flush_stdout = gdb_os_flush_stdout;
gdb_callback.write_stderr = gdb_os_write_stderr;
gdb_callback.flush_stderr = gdb_os_flush_stderr;
gdb_callback.printf_filtered = gdb_os_printf_filtered;
gdb_callback.vprintf_filtered = gdb_os_vprintf_filtered;
gdb_callback.evprintf_filtered = gdb_os_evprintf_filtered;
gdb_callback.error = gdb_os_error;
gdb_callback.poll_quit = gdb_os_poll_quit;
gdb_callback.magic = HOST_CALLBACK_MAGIC;
callbacks_initialized = 1;
}
}
/* Release callbacks (free resources used by them). */
static void
end_callbacks (void)
{
if (callbacks_initialized)
{
gdb_callback.shutdown (&gdb_callback);
callbacks_initialized = 0;
}
}
/* GDB version of os_write_stdout callback. */
static int
gdb_os_write_stdout (host_callback *p, const char *buf, int len)
{
int i;
char b[2];
ui_file_write (gdb_stdtarg, buf, len);
return len;
}
/* GDB version of os_flush_stdout callback. */
static void
gdb_os_flush_stdout (host_callback *p)
{
gdb_flush (gdb_stdtarg);
}
/* GDB version of os_write_stderr callback. */
static int
gdb_os_write_stderr (host_callback *p, const char *buf, int len)
{
int i;
char b[2];
for (i = 0; i < len; i++)
{
b[0] = buf[i];
b[1] = 0;
fputs_unfiltered (b, gdb_stdtarg);
}
return len;
}
/* GDB version of os_flush_stderr callback. */
static void
gdb_os_flush_stderr (host_callback *p)
{
gdb_flush (gdb_stderr);
}
/* GDB version of printf_filtered callback. */
static void
gdb_os_printf_filtered (host_callback * p, const char *format,...)
{
va_list args;
va_start (args, format);
vfprintf_filtered (gdb_stdout, format, args);
va_end (args);
}
/* GDB version of error vprintf_filtered. */
static void
gdb_os_vprintf_filtered (host_callback * p, const char *format, va_list ap)
{
vfprintf_filtered (gdb_stdout, format, ap);
}
/* GDB version of error evprintf_filtered. */
static void
gdb_os_evprintf_filtered (host_callback * p, const char *format, va_list ap)
{
vfprintf_filtered (gdb_stderr, format, ap);
}
/* GDB version of error callback. */
static void
gdb_os_error (host_callback * p, const char *format,...)
{
if (error_hook)
(*error_hook) ();
else
{
va_list args;
va_start (args, format);
verror (format, args);
va_end (args);
}
}
static void
gdbsim_fetch_register (int regno)
{
static int warn_user = 1;
if (regno == -1)
{
for (regno = 0; regno < NUM_REGS; regno++)
gdbsim_fetch_register (regno);
}
else if (REGISTER_NAME (regno) != NULL
&& *REGISTER_NAME (regno) != '\0')
{
char buf[MAX_REGISTER_RAW_SIZE];
int nr_bytes;
if (REGISTER_SIM_REGNO (regno) >= 0)
nr_bytes = sim_fetch_register (gdbsim_desc,
REGISTER_SIM_REGNO (regno),
buf, REGISTER_RAW_SIZE (regno));
else
nr_bytes = 0;
if (nr_bytes == 0)
/* register not applicable, supply zero's */
memset (buf, 0, MAX_REGISTER_RAW_SIZE);
else if (nr_bytes > 0 && nr_bytes != REGISTER_RAW_SIZE (regno)
&& warn_user)
{
fprintf_unfiltered (gdb_stderr,
"Size of register %s (%d/%d) incorrect (%d instead of %d))",
REGISTER_NAME (regno),
regno, REGISTER_SIM_REGNO (regno),
nr_bytes, REGISTER_RAW_SIZE (regno));
warn_user = 0;
}
supply_register (regno, buf);
if (sr_get_debug ())
{
printf_filtered ("gdbsim_fetch_register: %d", regno);
/* FIXME: We could print something more intelligible. */
dump_mem (buf, REGISTER_RAW_SIZE (regno));
}
}
}
static void
gdbsim_store_register (int regno)
{
if (regno == -1)
{
for (regno = 0; regno < NUM_REGS; regno++)
gdbsim_store_register (regno);
}
else if (REGISTER_NAME (regno) != NULL
&& *REGISTER_NAME (regno) != '\0'
&& REGISTER_SIM_REGNO (regno) >= 0)
{
char tmp[MAX_REGISTER_RAW_SIZE];
int nr_bytes;
read_register_gen (regno, tmp);
nr_bytes = sim_store_register (gdbsim_desc,
REGISTER_SIM_REGNO (regno),
tmp, REGISTER_RAW_SIZE (regno));
if (nr_bytes > 0 && nr_bytes != REGISTER_RAW_SIZE (regno))
internal_error (__FILE__, __LINE__,
"Register size different to expected");
if (sr_get_debug ())
{
printf_filtered ("gdbsim_store_register: %d", regno);
/* FIXME: We could print something more intelligible. */
dump_mem (tmp, REGISTER_RAW_SIZE (regno));
}
}
}
/* Kill the running program. This may involve closing any open files
and releasing other resources acquired by the simulated program. */
static void
gdbsim_kill (void)
{
if (sr_get_debug ())
printf_filtered ("gdbsim_kill\n");
/* There is no need to `kill' running simulator - the simulator is
not running */
inferior_ptid = null_ptid;
}
/* Load an executable file into the target process. This is expected to
not only bring new code into the target process, but also to update
GDB's symbol tables to match. */
static void
gdbsim_load (char *prog, int fromtty)
{
if (sr_get_debug ())
printf_filtered ("gdbsim_load: prog \"%s\"\n", prog);
inferior_ptid = null_ptid;
/* FIXME: We will print two messages on error.
Need error to either not print anything if passed NULL or need
another routine that doesn't take any arguments. */
if (sim_load (gdbsim_desc, prog, NULL, fromtty) == SIM_RC_FAIL)
error ("unable to load program");
/* FIXME: If a load command should reset the targets registers then
a call to sim_create_inferior() should go here. */
program_loaded = 1;
}
/* Start an inferior process and set inferior_ptid to its pid.
EXEC_FILE is the file to run.
ARGS is a string containing the arguments to the program.
ENV is the environment vector to pass. Errors reported with error().
On VxWorks and various standalone systems, we ignore exec_file. */
/* This is called not only when we first attach, but also when the
user types "run" after having attached. */
static void
gdbsim_create_inferior (char *exec_file, char *args, char **env)
{
int len;
char *arg_buf, **argv;
if (exec_file == 0 || exec_bfd == 0)
warning ("No executable file specified.");
if (!program_loaded)
warning ("No program loaded.");
if (sr_get_debug ())
printf_filtered ("gdbsim_create_inferior: exec_file \"%s\", args \"%s\"\n",
(exec_file ? exec_file : "(NULL)"),
args);
gdbsim_kill ();
remove_breakpoints ();
init_wait_for_inferior ();
if (exec_file != NULL)
{
len = strlen (exec_file) + 1 + strlen (args) + 1 + /*slop */ 10;
arg_buf = (char *) alloca (len);
arg_buf[0] = '\0';
strcat (arg_buf, exec_file);
strcat (arg_buf, " ");
strcat (arg_buf, args);
argv = buildargv (arg_buf);
make_cleanup_freeargv (argv);
}
else
argv = NULL;
sim_create_inferior (gdbsim_desc, exec_bfd, argv, env);
inferior_ptid = pid_to_ptid (42);
insert_breakpoints (); /* Needed to get correct instruction in cache */
clear_proceed_status ();
/* NB: Entry point already set by sim_create_inferior. */
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
}
/* The open routine takes the rest of the parameters from the command,
and (if successful) pushes a new target onto the stack.
Targets should supply this routine, if only to provide an error message. */
/* Called when selecting the simulator. EG: (gdb) target sim name. */
static void
gdbsim_open (char *args, int from_tty)
{
int len;
char *arg_buf;
char **argv;
if (sr_get_debug ())
printf_filtered ("gdbsim_open: args \"%s\"\n", args ? args : "(null)");
/* Remove current simulator if one exists. Only do this if the simulator
has been opened because sim_close requires it.
This is important because the call to push_target below will cause
sim_close to be called if the simulator is already open, but push_target
is called after sim_open! We can't move the call to push_target before
the call to sim_open because sim_open may invoke `error'. */
if (gdbsim_desc != NULL)
unpush_target (&gdbsim_ops);
len = (7 + 1 /* gdbsim */
+ strlen (" -E little")
+ strlen (" --architecture=xxxxxxxxxx")
+ (args ? strlen (args) : 0)
+ 50) /* slack */ ;
arg_buf = (char *) alloca (len);
strcpy (arg_buf, "gdbsim"); /* 7 */
/* Specify the byte order for the target when it is both selectable
and explicitly specified by the user (not auto detected). */
if (!TARGET_BYTE_ORDER_AUTO)
{
switch (TARGET_BYTE_ORDER)
{
case BFD_ENDIAN_BIG:
strcat (arg_buf, " -E big");
break;
case BFD_ENDIAN_LITTLE:
strcat (arg_buf, " -E little");
break;
default:
internal_error (__FILE__, __LINE__,
"Value of TARGET_BYTE_ORDER unknown");
}
}
/* Specify the architecture of the target when it has been
explicitly specified */
if (!TARGET_ARCHITECTURE_AUTO)
{
strcat (arg_buf, " --architecture=");
strcat (arg_buf, TARGET_ARCHITECTURE->printable_name);
}
/* finally, any explicit args */
if (args)
{
strcat (arg_buf, " "); /* 1 */
strcat (arg_buf, args);
}
argv = buildargv (arg_buf);
if (argv == NULL)
error ("Insufficient memory available to allocate simulator arg list.");
make_cleanup_freeargv (argv);
init_callbacks ();
gdbsim_desc = sim_open (SIM_OPEN_DEBUG, &gdb_callback, exec_bfd, argv);
if (gdbsim_desc == 0)
error ("unable to create simulator instance");
push_target (&gdbsim_ops);
target_fetch_registers (-1);
printf_filtered ("Connected to the simulator.\n");
}
/* Does whatever cleanup is required for a target that we are no longer
going to be calling. Argument says whether we are quitting gdb and
should not get hung in case of errors, or whether we want a clean
termination even if it takes a while. This routine is automatically
always called just before a routine is popped off the target stack.
Closing file descriptors and freeing memory are typical things it should
do. */
/* Close out all files and local state before this target loses control. */
static void
gdbsim_close (int quitting)
{
if (sr_get_debug ())
printf_filtered ("gdbsim_close: quitting %d\n", quitting);
program_loaded = 0;
if (gdbsim_desc != NULL)
{
sim_close (gdbsim_desc, quitting);
gdbsim_desc = NULL;
}
end_callbacks ();
generic_mourn_inferior ();
}
/* Takes a program previously attached to and detaches it.
The program may resume execution (some targets do, some don't) and will
no longer stop on signals, etc. We better not have left any breakpoints
in the program or it'll die when it hits one. ARGS is arguments
typed by the user (e.g. a signal to send the process). FROM_TTY
says whether to be verbose or not. */
/* Terminate the open connection to the remote debugger.
Use this when you want to detach and do something else with your gdb. */
static void
gdbsim_detach (char *args, int from_tty)
{
if (sr_get_debug ())
printf_filtered ("gdbsim_detach: args \"%s\"\n", args);
pop_target (); /* calls gdbsim_close to do the real work */
if (from_tty)
printf_filtered ("Ending simulator %s debugging\n", target_shortname);
}
/* Resume execution of the target process. STEP says whether to single-step
or to run free; SIGGNAL is the signal value (e.g. SIGINT) to be given
to the target, or zero for no signal. */
static enum target_signal resume_siggnal;
static int resume_step;
static void
gdbsim_resume (ptid_t ptid, int step, enum target_signal siggnal)
{
if (PIDGET (inferior_ptid) != 42)
error ("The program is not being run.");
if (sr_get_debug ())
printf_filtered ("gdbsim_resume: step %d, signal %d\n", step, siggnal);
resume_siggnal = siggnal;
resume_step = step;
}
/* Notify the simulator of an asynchronous request to stop.
The simulator shall ensure that the stop request is eventually
delivered to the simulator. If the call is made while the
simulator is not running then the stop request is processed when
the simulator is next resumed.
For simulators that do not support this operation, just abort */
static void
gdbsim_stop (void)
{
if (!sim_stop (gdbsim_desc))
{
quit ();
}
}
/* GDB version of os_poll_quit callback.
Taken from gdb/util.c - should be in a library */
static int
gdb_os_poll_quit (host_callback *p)
{
if (ui_loop_hook != NULL)
ui_loop_hook (0);
if (quit_flag) /* gdb's idea of quit */
{
quit_flag = 0; /* we've stolen it */
return 1;
}
else if (immediate_quit)
{
return 1;
}
return 0;
}
/* Wait for inferior process to do something. Return pid of child,
or -1 in case of error; store status through argument pointer STATUS,
just as `wait' would. */
static void
gdbsim_cntrl_c (int signo)
{
gdbsim_stop ();
}
static ptid_t
gdbsim_wait (ptid_t ptid, struct target_waitstatus *status)
{
static RETSIGTYPE (*prev_sigint) ();
int sigrc = 0;
enum sim_stop reason = sim_running;
if (sr_get_debug ())
printf_filtered ("gdbsim_wait\n");
#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
{
struct sigaction sa, osa;
sa.sa_handler = gdbsim_cntrl_c;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
sigaction (SIGINT, &sa, &osa);
prev_sigint = osa.sa_handler;
}
#else
prev_sigint = signal (SIGINT, gdbsim_cntrl_c);
#endif
sim_resume (gdbsim_desc, resume_step,
target_signal_to_host (resume_siggnal));
signal (SIGINT, prev_sigint);
resume_step = 0;
sim_stop_reason (gdbsim_desc, &reason, &sigrc);
switch (reason)
{
case sim_exited:
status->kind = TARGET_WAITKIND_EXITED;
status->value.integer = sigrc;
break;
case sim_stopped:
switch (sigrc)
{
case SIGABRT:
quit ();
break;
case SIGINT:
case SIGTRAP:
default:
status->kind = TARGET_WAITKIND_STOPPED;
/* The signal in sigrc is a host signal. That probably
should be fixed. */
status->value.sig = target_signal_from_host (sigrc);
break;
}
break;
case sim_signalled:
status->kind = TARGET_WAITKIND_SIGNALLED;
/* The signal in sigrc is a host signal. That probably
should be fixed. */
status->value.sig = target_signal_from_host (sigrc);
break;
case sim_running:
case sim_polling:
/* FIXME: Is this correct? */
break;
}
return inferior_ptid;
}
/* Get ready to modify the registers array. On machines which store
individual registers, this doesn't need to do anything. On machines
which store all the registers in one fell swoop, this makes sure
that registers contains all the registers from the program being
debugged. */
static void
gdbsim_prepare_to_store (void)
{
/* Do nothing, since we can store individual regs */
}
/* Transfer LEN bytes between GDB address MYADDR and target address
MEMADDR. If WRITE is non-zero, transfer them to the target,
otherwise transfer them from the target. TARGET is unused.
Returns the number of bytes transferred. */
static int
gdbsim_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len,
int write, struct mem_attrib *attrib,
struct target_ops *target)
{
if (!program_loaded)
error ("No program loaded.");
if (sr_get_debug ())
{
/* FIXME: Send to something other than STDOUT? */
printf_filtered ("gdbsim_xfer_inferior_memory: myaddr 0x");
gdb_print_host_address (myaddr, gdb_stdout);
printf_filtered (", memaddr 0x%s, len %d, write %d\n",
paddr_nz (memaddr), len, write);
if (sr_get_debug () && write)
dump_mem (myaddr, len);
}
if (write)
{
len = sim_write (gdbsim_desc, memaddr, myaddr, len);
}
else
{
len = sim_read (gdbsim_desc, memaddr, myaddr, len);
if (sr_get_debug () && len > 0)
dump_mem (myaddr, len);
}
return len;
}
static void
gdbsim_files_info (struct target_ops *target)
{
char *file = "nothing";
if (exec_bfd)
file = bfd_get_filename (exec_bfd);
if (sr_get_debug ())
printf_filtered ("gdbsim_files_info: file \"%s\"\n", file);
if (exec_bfd)
{
printf_filtered ("\tAttached to %s running program %s\n",
target_shortname, file);
sim_info (gdbsim_desc, 0);
}
}
/* Clear the simulator's notion of what the break points are. */
static void
gdbsim_mourn_inferior (void)
{
if (sr_get_debug ())
printf_filtered ("gdbsim_mourn_inferior:\n");
remove_breakpoints ();
generic_mourn_inferior ();
}
static int
gdbsim_insert_breakpoint (CORE_ADDR addr, char *contents_cache)
{
#ifdef SIM_HAS_BREAKPOINTS
SIM_RC retcode;
retcode = sim_set_breakpoint (gdbsim_desc, addr);
switch (retcode)
{
case SIM_RC_OK:
return 0;
case SIM_RC_INSUFFICIENT_RESOURCES:
return ENOMEM;
default:
return EIO;
}
#else
return memory_insert_breakpoint (addr, contents_cache);
#endif
}
static int
gdbsim_remove_breakpoint (CORE_ADDR addr, char *contents_cache)
{
#ifdef SIM_HAS_BREAKPOINTS
SIM_RC retcode;
retcode = sim_clear_breakpoint (gdbsim_desc, addr);
switch (retcode)
{
case SIM_RC_OK:
case SIM_RC_UNKNOWN_BREAKPOINT:
return 0;
case SIM_RC_INSUFFICIENT_RESOURCES:
return ENOMEM;
default:
return EIO;
}
#else
return memory_remove_breakpoint (addr, contents_cache);
#endif
}
/* Pass the command argument through to the simulator verbatim. The
simulator must do any command interpretation work. */
void
simulator_command (char *args, int from_tty)
{
if (gdbsim_desc == NULL)
{
/* PREVIOUSLY: The user may give a command before the simulator
is opened. [...] (??? assuming of course one wishes to
continue to allow commands to be sent to unopened simulators,
which isn't entirely unreasonable). */
/* The simulator is a builtin abstraction of a remote target.
Consistent with that model, access to the simulator, via sim
commands, is restricted to the period when the channel to the
simulator is open. */
error ("Not connected to the simulator target");
}
sim_do_command (gdbsim_desc, args);
/* Invalidate the register cache, in case the simulator command does
something funny. */
registers_changed ();
}
/* Define the target subroutine names */
struct target_ops gdbsim_ops;
static void
init_gdbsim_ops (void)
{
gdbsim_ops.to_shortname = "sim";
gdbsim_ops.to_longname = "simulator";
gdbsim_ops.to_doc = "Use the compiled-in simulator.";
gdbsim_ops.to_open = gdbsim_open;
gdbsim_ops.to_close = gdbsim_close;
gdbsim_ops.to_attach = NULL;
gdbsim_ops.to_post_attach = NULL;
gdbsim_ops.to_require_attach = NULL;
gdbsim_ops.to_detach = gdbsim_detach;
gdbsim_ops.to_require_detach = NULL;
gdbsim_ops.to_resume = gdbsim_resume;
gdbsim_ops.to_wait = gdbsim_wait;
gdbsim_ops.to_post_wait = NULL;
gdbsim_ops.to_fetch_registers = gdbsim_fetch_register;
gdbsim_ops.to_store_registers = gdbsim_store_register;
gdbsim_ops.to_prepare_to_store = gdbsim_prepare_to_store;
gdbsim_ops.to_xfer_memory = gdbsim_xfer_inferior_memory;
gdbsim_ops.to_files_info = gdbsim_files_info;
gdbsim_ops.to_insert_breakpoint = gdbsim_insert_breakpoint;
gdbsim_ops.to_remove_breakpoint = gdbsim_remove_breakpoint;
gdbsim_ops.to_terminal_init = NULL;
gdbsim_ops.to_terminal_inferior = NULL;
gdbsim_ops.to_terminal_ours_for_output = NULL;
gdbsim_ops.to_terminal_ours = NULL;
gdbsim_ops.to_terminal_info = NULL;
gdbsim_ops.to_kill = gdbsim_kill;
gdbsim_ops.to_load = gdbsim_load;
gdbsim_ops.to_lookup_symbol = NULL;
gdbsim_ops.to_create_inferior = gdbsim_create_inferior;
gdbsim_ops.to_post_startup_inferior = NULL;
gdbsim_ops.to_acknowledge_created_inferior = NULL;
gdbsim_ops.to_clone_and_follow_inferior = NULL;
gdbsim_ops.to_post_follow_inferior_by_clone = NULL;
gdbsim_ops.to_insert_fork_catchpoint = NULL;
gdbsim_ops.to_remove_fork_catchpoint = NULL;
gdbsim_ops.to_insert_vfork_catchpoint = NULL;
gdbsim_ops.to_remove_vfork_catchpoint = NULL;
gdbsim_ops.to_has_forked = NULL;
gdbsim_ops.to_has_vforked = NULL;
gdbsim_ops.to_can_follow_vfork_prior_to_exec = NULL;
gdbsim_ops.to_post_follow_vfork = NULL;
gdbsim_ops.to_insert_exec_catchpoint = NULL;
gdbsim_ops.to_remove_exec_catchpoint = NULL;
gdbsim_ops.to_has_execd = NULL;
gdbsim_ops.to_reported_exec_events_per_exec_call = NULL;
gdbsim_ops.to_has_exited = NULL;
gdbsim_ops.to_mourn_inferior = gdbsim_mourn_inferior;
gdbsim_ops.to_can_run = 0;
gdbsim_ops.to_notice_signals = 0;
gdbsim_ops.to_thread_alive = 0;
gdbsim_ops.to_stop = gdbsim_stop;
gdbsim_ops.to_pid_to_exec_file = NULL;
gdbsim_ops.to_stratum = process_stratum;
gdbsim_ops.DONT_USE = NULL;
gdbsim_ops.to_has_all_memory = 1;
gdbsim_ops.to_has_memory = 1;
gdbsim_ops.to_has_stack = 1;
gdbsim_ops.to_has_registers = 1;
gdbsim_ops.to_has_execution = 1;
gdbsim_ops.to_sections = NULL;
gdbsim_ops.to_sections_end = NULL;
gdbsim_ops.to_magic = OPS_MAGIC;
#ifdef TARGET_REDEFINE_DEFAULT_OPS
TARGET_REDEFINE_DEFAULT_OPS (&gdbsim_ops);
#endif
}
void
_initialize_remote_sim (void)
{
init_gdbsim_ops ();
add_target (&gdbsim_ops);
add_com ("sim <command>", class_obscure, simulator_command,
"Send a command to the simulator.");
}

View File

@ -1,837 +0,0 @@
/* Remote debugging interface for Tandem ST2000 phone switch, for GDB.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000,
2001, 2002 Free Software Foundation, Inc.
Contributed by Cygnus Support. Written by Jim Kingdon for Cygnus.
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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* This file was derived from remote-eb.c, which did a similar job, but for
an AMD-29K running EBMON. That file was in turn derived from remote.c
as mentioned in the following comment (left in for comic relief):
"This is like remote.c but is for an esoteric situation--
having an a29k board in a PC hooked up to a unix machine with
a serial line, and running ctty com1 on the PC, through which
the unix machine can run ebmon. Not to mention that the PC
has PC/NFS, so it can access the same executables that gdb can,
over the net in real time."
In reality, this module talks to a debug monitor called 'STDEBUG', which
runs in a phone switch. We communicate with STDEBUG via either a direct
serial line, or a TCP (or possibly TELNET) stream to a terminal multiplexor,
which in turn talks to the phone switch. */
#include "defs.h"
#include "gdbcore.h"
#include "target.h"
#include "gdb_string.h"
#include <sys/types.h>
#include "serial.h"
#include "regcache.h"
extern struct target_ops st2000_ops; /* Forward declaration */
static void st2000_close ();
static void st2000_fetch_register ();
static void st2000_store_register ();
#define LOG_FILE "st2000.log"
#if defined (LOG_FILE)
FILE *log_file;
#endif
static int timeout = 24;
/* Descriptor for I/O to remote machine. Initialize it to -1 so that
st2000_open knows that we don't have a file open when the program
starts. */
static struct serial *st2000_desc;
/* Send data to stdebug. Works just like printf. */
static void
printf_stdebug (char *pattern,...)
{
va_list args;
char buf[200];
va_start (args, pattern);
vsprintf (buf, pattern, args);
va_end (args);
if (serial_write (st2000_desc, buf, strlen (buf)))
fprintf (stderr, "serial_write failed: %s\n", safe_strerror (errno));
}
/* Read a character from the remote system, doing all the fancy timeout
stuff. */
static int
readchar (int timeout)
{
int c;
c = serial_readchar (st2000_desc, timeout);
#ifdef LOG_FILE
putc (c & 0x7f, log_file);
#endif
if (c >= 0)
return c & 0x7f;
if (c == SERIAL_TIMEOUT)
{
if (timeout == 0)
return c; /* Polls shouldn't generate timeout errors */
error ("Timeout reading from remote system.");
}
perror_with_name ("remote-st2000");
}
/* Scan input from the remote system, until STRING is found. If DISCARD is
non-zero, then discard non-matching input, else print it out.
Let the user break out immediately. */
static void
expect (char *string, int discard)
{
char *p = string;
int c;
immediate_quit++;
while (1)
{
c = readchar (timeout);
if (c == *p++)
{
if (*p == '\0')
{
immediate_quit--;
return;
}
}
else
{
if (!discard)
{
fwrite (string, 1, (p - 1) - string, stdout);
putchar ((char) c);
fflush (stdout);
}
p = string;
}
}
}
/* Keep discarding input until we see the STDEBUG prompt.
The convention for dealing with the prompt is that you
o give your command
o *then* wait for the prompt.
Thus the last thing that a procedure does with the serial line
will be an expect_prompt(). Exception: st2000_resume does not
wait for the prompt, because the terminal is being handed over
to the inferior. However, the next thing which happens after that
is a st2000_wait which does wait for the prompt.
Note that this includes abnormal exit, e.g. error(). This is
necessary to prevent getting into states from which we can't
recover. */
static void
expect_prompt (int discard)
{
#if defined (LOG_FILE)
/* This is a convenient place to do this. The idea is to do it often
enough that we never lose much data if we terminate abnormally. */
fflush (log_file);
#endif
expect ("dbug> ", discard);
}
/* Get a hex digit from the remote system & return its value.
If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
static int
get_hex_digit (int ignore_space)
{
int ch;
while (1)
{
ch = readchar (timeout);
if (ch >= '0' && ch <= '9')
return ch - '0';
else if (ch >= 'A' && ch <= 'F')
return ch - 'A' + 10;
else if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
else if (ch == ' ' && ignore_space)
;
else
{
expect_prompt (1);
error ("Invalid hex digit from remote system.");
}
}
}
/* Get a byte from stdebug and put it in *BYT. Accept any number
leading spaces. */
static void
get_hex_byte (char *byt)
{
int val;
val = get_hex_digit (1) << 4;
val |= get_hex_digit (0);
*byt = val;
}
/* Get N 32-bit words from remote, each preceded by a space,
and put them in registers starting at REGNO. */
static void
get_hex_regs (int n, int regno)
{
long val;
int i;
for (i = 0; i < n; i++)
{
int j;
val = 0;
for (j = 0; j < 8; j++)
val = (val << 4) + get_hex_digit (j == 0);
supply_register (regno++, (char *) &val);
}
}
/* This is called not only when we first attach, but also when the
user types "run" after having attached. */
static void
st2000_create_inferior (char *execfile, char *args, char **env)
{
int entry_pt;
if (args && *args)
error ("Can't pass arguments to remote STDEBUG process");
if (execfile == 0 || exec_bfd == 0)
error ("No executable file specified");
entry_pt = (int) bfd_get_start_address (exec_bfd);
/* The "process" (board) is already stopped awaiting our commands, and
the program is already downloaded. We just set its PC and go. */
clear_proceed_status ();
/* Tell wait_for_inferior that we've started a new process. */
init_wait_for_inferior ();
/* Set up the "saved terminal modes" of the inferior
based on what modes we are starting it with. */
target_terminal_init ();
/* Install inferior's terminal modes. */
target_terminal_inferior ();
/* insert_step_breakpoint (); FIXME, do we need this? */
/* Let 'er rip... */
proceed ((CORE_ADDR) entry_pt, TARGET_SIGNAL_DEFAULT, 0);
}
/* Open a connection to a remote debugger.
NAME is the filename used for communication. */
static int baudrate = 9600;
static char dev_name[100];
static void
st2000_open (char *args, int from_tty)
{
int n;
char junk[100];
target_preopen (from_tty);
n = sscanf (args, " %s %d %s", dev_name, &baudrate, junk);
if (n != 2)
error ("Bad arguments. Usage: target st2000 <device> <speed>\n\
or target st2000 <host> <port>\n");
st2000_close (0);
st2000_desc = serial_open (dev_name);
if (!st2000_desc)
perror_with_name (dev_name);
if (serial_setbaudrate (st2000_desc, baudrate))
{
serial_close (dev_name);
perror_with_name (dev_name);
}
serial_raw (st2000_desc);
push_target (&st2000_ops);
#if defined (LOG_FILE)
log_file = fopen (LOG_FILE, "w");
if (log_file == NULL)
perror_with_name (LOG_FILE);
#endif
/* Hello? Are you there? */
printf_stdebug ("\003"); /* ^C wakes up dbug */
expect_prompt (1);
if (from_tty)
printf ("Remote %s connected to %s\n", target_shortname,
dev_name);
}
/* Close out all files and local state before this target loses control. */
static void
st2000_close (int quitting)
{
serial_close (st2000_desc);
#if defined (LOG_FILE)
if (log_file)
{
if (ferror (log_file))
fprintf (stderr, "Error writing log file.\n");
if (fclose (log_file) != 0)
fprintf (stderr, "Error closing log file.\n");
}
#endif
}
/* Terminate the open connection to the remote debugger.
Use this when you want to detach and do something else
with your gdb. */
static void
st2000_detach (int from_tty)
{
pop_target (); /* calls st2000_close to do the real work */
if (from_tty)
printf ("Ending remote %s debugging\n", target_shortname);
}
/* Tell the remote machine to resume. */
static void
st2000_resume (ptid_t ptid, int step, enum target_signal sig)
{
if (step)
{
printf_stdebug ("ST\r");
/* Wait for the echo. */
expect ("ST\r", 1);
}
else
{
printf_stdebug ("GO\r");
/* Swallow the echo. */
expect ("GO\r", 1);
}
}
/* Wait until the remote machine stops, then return,
storing status in STATUS just as `wait' would. */
static ptid_t
st2000_wait (ptid_t ptid, struct target_waitstatus *status)
{
int old_timeout = timeout;
status->kind = TARGET_WAITKIND_EXITED;
status->value.integer = 0;
timeout = 0; /* Don't time out -- user program is running. */
expect_prompt (0); /* Wait for prompt, outputting extraneous text */
status->kind = TARGET_WAITKIND_STOPPED;
status->value.sig = TARGET_SIGNAL_TRAP;
timeout = old_timeout;
return inferior_ptid;
}
/* Return the name of register number REGNO in the form input and output by
STDEBUG. Currently, REGISTER_NAMES just happens to contain exactly what
STDEBUG wants. Lets take advantage of that just as long as possible! */
static char *
get_reg_name (int regno)
{
static char buf[50];
const char *p;
char *b;
b = buf;
for (p = REGISTER_NAME (regno); *p; p++)
*b++ = toupper (*p);
*b = '\000';
return buf;
}
/* Read the remote registers into the block REGS. */
static void
st2000_fetch_registers (void)
{
int regno;
/* Yeah yeah, I know this is horribly inefficient. But it isn't done
very often... I'll clean it up later. */
for (regno = 0; regno <= PC_REGNUM; regno++)
st2000_fetch_register (regno);
}
/* Fetch register REGNO, or all registers if REGNO is -1.
Returns errno value. */
static void
st2000_fetch_register (int regno)
{
if (regno == -1)
st2000_fetch_registers ();
else
{
char *name = get_reg_name (regno);
printf_stdebug ("DR %s\r", name);
expect (name, 1);
expect (" : ", 1);
get_hex_regs (1, regno);
expect_prompt (1);
}
return;
}
/* Store the remote registers from the contents of the block REGS. */
static void
st2000_store_registers (void)
{
int regno;
for (regno = 0; regno <= PC_REGNUM; regno++)
st2000_store_register (regno);
registers_changed ();
}
/* Store register REGNO, or all if REGNO == 0.
Return errno value. */
static void
st2000_store_register (int regno)
{
if (regno == -1)
st2000_store_registers ();
else
{
printf_stdebug ("PR %s %x\r", get_reg_name (regno),
read_register (regno));
expect_prompt (1);
}
}
/* Get ready to modify the registers array. On machines which store
individual registers, this doesn't need to do anything. On machines
which store all the registers in one fell swoop, this makes sure
that registers contains all the registers from the program being
debugged. */
static void
st2000_prepare_to_store (void)
{
/* Do nothing, since we can store individual regs */
}
static void
st2000_files_info (void)
{
printf ("\tAttached to %s at %d baud.\n",
dev_name, baudrate);
}
/* Copy LEN bytes of data from debugger memory at MYADDR
to inferior's memory at MEMADDR. Returns length moved. */
static int
st2000_write_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
{
int i;
for (i = 0; i < len; i++)
{
printf_stdebug ("PM.B %x %x\r", memaddr + i, myaddr[i]);
expect_prompt (1);
}
return len;
}
/* Read LEN bytes from inferior memory at MEMADDR. Put the result
at debugger address MYADDR. Returns length moved. */
static int
st2000_read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
int i;
/* Number of bytes read so far. */
int count;
/* Starting address of this pass. */
unsigned long startaddr;
/* Number of bytes to read in this pass. */
int len_this_pass;
/* Note that this code works correctly if startaddr is just less
than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
thing). That is, something like
st2000_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
works--it never adds len to memaddr and gets 0. */
/* However, something like
st2000_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
doesn't need to work. Detect it and give up if there's an attempt
to do that. */
if (((memaddr - 1) + len) < memaddr)
{
errno = EIO;
return 0;
}
startaddr = memaddr;
count = 0;
while (count < len)
{
len_this_pass = 16;
if ((startaddr % 16) != 0)
len_this_pass -= startaddr % 16;
if (len_this_pass > (len - count))
len_this_pass = (len - count);
printf_stdebug ("DI.L %x %x\r", startaddr, len_this_pass);
expect (": ", 1);
for (i = 0; i < len_this_pass; i++)
get_hex_byte (&myaddr[count++]);
expect_prompt (1);
startaddr += len_this_pass;
}
return len;
}
/* Transfer LEN bytes between GDB address MYADDR and target address
MEMADDR. If WRITE is non-zero, transfer them to the target,
otherwise transfer them from the target. TARGET is unused.
Returns the number of bytes transferred. */
static int
st2000_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len,
int write, struct mem_attrib *attrib,
struct target_ops *target)
{
if (write)
return st2000_write_inferior_memory (memaddr, myaddr, len);
else
return st2000_read_inferior_memory (memaddr, myaddr, len);
}
static void
st2000_kill (char *args, int from_tty)
{
return; /* Ignore attempts to kill target system */
}
/* Clean up when a program exits.
The program actually lives on in the remote processor's RAM, and may be
run again without a download. Don't leave it full of breakpoint
instructions. */
static void
st2000_mourn_inferior (void)
{
remove_breakpoints ();
unpush_target (&st2000_ops);
generic_mourn_inferior (); /* Do all the proper things now */
}
#define MAX_STDEBUG_BREAKPOINTS 16
static CORE_ADDR breakaddr[MAX_STDEBUG_BREAKPOINTS] =
{0};
static int
st2000_insert_breakpoint (CORE_ADDR addr, char *shadow)
{
int i;
CORE_ADDR bp_addr = addr;
int bp_size = 0;
BREAKPOINT_FROM_PC (&bp_addr, &bp_size);
for (i = 0; i <= MAX_STDEBUG_BREAKPOINTS; i++)
if (breakaddr[i] == 0)
{
breakaddr[i] = addr;
st2000_read_inferior_memory (bp_addr, shadow, bp_size);
printf_stdebug ("BR %x H\r", addr);
expect_prompt (1);
return 0;
}
fprintf (stderr, "Too many breakpoints (> 16) for STDBUG\n");
return 1;
}
static int
st2000_remove_breakpoint (CORE_ADDR addr, char *shadow)
{
int i;
for (i = 0; i < MAX_STDEBUG_BREAKPOINTS; i++)
if (breakaddr[i] == addr)
{
breakaddr[i] = 0;
printf_stdebug ("CB %d\r", i);
expect_prompt (1);
return 0;
}
fprintf (stderr, "Can't find breakpoint associated with 0x%x\n", addr);
return 1;
}
/* Put a command string, in args, out to STDBUG. Output from STDBUG is placed
on the users terminal until the prompt is seen. */
static void
st2000_command (char *args, int fromtty)
{
if (!st2000_desc)
error ("st2000 target not open.");
if (!args)
error ("Missing command.");
printf_stdebug ("%s\r", args);
expect_prompt (0);
}
/* Connect the user directly to STDBUG. This command acts just like the
'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
/*static struct ttystate ttystate; */
static void
cleanup_tty (void)
{
printf ("\r\n[Exiting connect mode]\r\n");
/* serial_restore(0, &ttystate); */
}
#if 0
/* This all should now be in serial.c */
static void
connect_command (char *args, int fromtty)
{
fd_set readfds;
int numfds;
int c;
char cur_esc = 0;
dont_repeat ();
if (st2000_desc < 0)
error ("st2000 target not open.");
if (args)
fprintf ("This command takes no args. They have been ignored.\n");
printf ("[Entering connect mode. Use ~. or ~^D to escape]\n");
serial_raw (0, &ttystate);
make_cleanup (cleanup_tty, 0);
FD_ZERO (&readfds);
while (1)
{
do
{
FD_SET (0, &readfds);
FD_SET (deprecated_serial_fd (st2000_desc), &readfds);
numfds = select (sizeof (readfds) * 8, &readfds, 0, 0, 0);
}
while (numfds == 0);
if (numfds < 0)
perror_with_name ("select");
if (FD_ISSET (0, &readfds))
{ /* tty input, send to stdebug */
c = getchar ();
if (c < 0)
perror_with_name ("connect");
printf_stdebug ("%c", c);
switch (cur_esc)
{
case 0:
if (c == '\r')
cur_esc = c;
break;
case '\r':
if (c == '~')
cur_esc = c;
else
cur_esc = 0;
break;
case '~':
if (c == '.' || c == '\004')
return;
else
cur_esc = 0;
}
}
if (FD_ISSET (deprecated_serial_fd (st2000_desc), &readfds))
{
while (1)
{
c = readchar (0);
if (c < 0)
break;
putchar (c);
}
fflush (stdout);
}
}
}
#endif /* 0 */
/* Define the target subroutine names */
struct target_ops st2000_ops;
static void
init_st2000_ops (void)
{
st2000_ops.to_shortname = "st2000";
st2000_ops.to_longname = "Remote serial Tandem ST2000 target";
st2000_ops.to_doc = "Use a remote computer running STDEBUG connected by a serial line;\n\
or a network connection.\n\
Arguments are the name of the device for the serial line,\n\
the speed to connect at in bits per second.";
st2000_ops.to_open = st2000_open;
st2000_ops.to_close = st2000_close;
st2000_ops.to_attach = 0;
st2000_run_ops.to_post_attach = NULL;
st2000_ops.to_require_attach = NULL;
st2000_ops.to_detach = st2000_detach;
st2000_ops.to_require_detach = NULL;
st2000_ops.to_resume = st2000_resume;
st2000_ops.to_wait = st2000_wait;
st2000_ops.to_post_wait = NULL;
st2000_ops.to_fetch_registers = st2000_fetch_register;
st2000_ops.to_store_registers = st2000_store_register;
st2000_ops.to_prepare_to_store = st2000_prepare_to_store;
st2000_ops.to_xfer_memory = st2000_xfer_inferior_memory;
st2000_ops.to_files_info = st2000_files_info;
st2000_ops.to_insert_breakpoint = st2000_insert_breakpoint;
st2000_ops.to_remove_breakpoint = st2000_remove_breakpoint; /* Breakpoints */
st2000_ops.to_terminal_init = 0;
st2000_ops.to_terminal_inferior = 0;
st2000_ops.to_terminal_ours_for_output = 0;
st2000_ops.to_terminal_ours = 0;
st2000_ops.to_terminal_info = 0; /* Terminal handling */
st2000_ops.to_kill = st2000_kill;
st2000_ops.to_load = 0; /* load */
st2000_ops.to_lookup_symbol = 0; /* lookup_symbol */
st2000_ops.to_create_inferior = st2000_create_inferior;
st2000_ops.to_post_startup_inferior = NULL;
st2000_ops.to_acknowledge_created_inferior = NULL;
st2000_ops.to_clone_and_follow_inferior = NULL;
st2000_ops.to_post_follow_inferior_by_clone = NULL;
st2000_run_ops.to_insert_fork_catchpoint = NULL;
st2000_run_ops.to_remove_fork_catchpoint = NULL;
st2000_run_ops.to_insert_vfork_catchpoint = NULL;
st2000_run_ops.to_remove_vfork_catchpoint = NULL;
st2000_ops.to_has_forked = NULL;
st2000_ops.to_has_vforked = NULL;
st2000_run_ops.to_can_follow_vfork_prior_to_exec = NULL;
st2000_ops.to_post_follow_vfork = NULL;
st2000_run_ops.to_insert_exec_catchpoint = NULL;
st2000_run_ops.to_remove_exec_catchpoint = NULL;
st2000_run_ops.to_has_execd = NULL;
st2000_run_ops.to_reported_exec_events_per_exec_call = NULL;
st2000_run_ops.to_has_exited = NULL;
st2000_ops.to_mourn_inferior = st2000_mourn_inferior;
st2000_ops.to_can_run = 0; /* can_run */
st2000_ops.to_notice_signals = 0; /* notice_signals */
st2000_ops.to_thread_alive = 0; /* thread alive */
st2000_ops.to_stop = 0; /* to_stop */
st2000_ops.to_pid_to_exec_file = NULL;
st2000_ops.to_stratum = process_stratum;
st2000_ops.DONT_USE = 0; /* next */
st2000_ops.to_has_all_memory = 1;
st2000_ops.to_has_memory = 1;
st2000_ops.to_has_stack = 1;
st2000_ops.to_has_registers = 1;
st2000_ops.to_has_execution = 1; /* all mem, mem, stack, regs, exec */
st2000_ops.to_sections = 0;
st2000_ops.to_sections_end = 0; /* Section pointers */
st2000_ops.to_magic = OPS_MAGIC; /* Always the last thing */
};
void
_initialize_remote_st2000 (void)
{
init_st2000_ops ();
add_target (&st2000_ops);
add_com ("st2000 <command>", class_obscure, st2000_command,
"Send a command to the STDBUG monitor.");
add_com ("connect", class_obscure, connect_command,
"Connect the terminal directly up to the STDBUG command monitor.\n\
Use <CR>~. or <CR>~^D to break out.");
}

View File

@ -1,37 +0,0 @@
/* S-record download support for GDB, the GNU debugger.
Copyright 1995, 1996, 2000 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
void load_srec (struct serial *desc, const char *file, bfd_vma load_offset,
int maxrecsize, int flags, int hashmark,
int (*waitack) (void));
/* S-record capability flags */
/* Which record types are supported */
#define SREC_2_BYTE_ADDR 0x00000001
#define SREC_3_BYTE_ADDR 0x00000002
#define SREC_4_BYTE_ADDR 0x00000004
#define SREC_TERM_SHIFT 3
#define SREC_ALL (SREC_2_BYTE_ADDR | SREC_3_BYTE_ADDR | SREC_4_BYTE_ADDR \
| ((SREC_2_BYTE_ADDR | SREC_3_BYTE_ADDR | SREC_4_BYTE_ADDR) \
<< SREC_TERM_SHIFT))
#define SREC_BINARY 0x00000040 /* Supports binary form of S-records */

View File

@ -1,579 +0,0 @@
/* Interface to bare machine for GDB running as kernel debugger.
Copyright 1986, 1989, 1991, 1992, 1993, 1995, 1996, 2000, 2001
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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <stdio.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <sys/types.h>
#include "gdb_stat.h"
#if defined (SIGTSTP) && defined (SIGIO)
#include <sys/time.h>
#include <sys/resource.h>
#endif /* SIGTSTP and SIGIO defined (must be 4.2) */
#include "defs.h"
#include <signal.h>
#include "symtab.h"
#include "frame.h"
#include "inferior.h"
#include "gdb_wait.h"
/* Random system calls, mostly no-ops to prevent link problems */
ioctl (int desc, int code, int arg)
{
}
int (*signal ()) ()
{
}
kill (void)
{
}
getpid (void)
{
return 0;
}
sigsetmask (void)
{
}
chdir (void)
{
}
char *
getcwd (char *buf, unsigned int len)
{
buf[0] = '/';
buf[1] = 0;
return buf;
}
/* Used to check for existence of .gdbinit. Say no. */
access (void)
{
return -1;
}
exit (void)
{
error ("Fatal error; restarting.");
}
/* Reading "files". The contents of some files are written into kdb's
data area before it is run. These files are used to contain the
symbol table for kdb to load, and the source files (in case the
kdb user wants to print them). The symbols are stored in a file
named "kdb-symbols" in a.out format (except that all the text and
data have been stripped to save room).
The files are stored in the following format:
int number of bytes of data for this file, including these four.
char[] name of the file, ending with a null.
padding to multiple of 4 boundary.
char[] file contents. The length can be deduced from what was
specified before. There is no terminating null here.
If the int at the front is zero, it means there are no more files.
Opening a file in kdb returns a nonzero value to indicate success,
but the value does not matter. Only one file can be open, and only
for reading. All the primitives for input from the file know
which file is open and ignore what is specified for the descriptor
or for the stdio stream.
Input with fgetc can be done either on the file that is open
or on stdin (which reads from the terminal through tty_input () */
/* Address of data for the files stored in format described above. */
char *files_start;
/* The file stream currently open: */
char *sourcebeg; /* beginning of contents */
int sourcesize; /* size of contents */
char *sourceptr; /* current read pointer */
int sourceleft; /* number of bytes to eof */
/* "descriptor" for the file now open.
Incremented at each close.
If specified descriptor does not match this,
it means the program is trying to use a closed descriptor.
We report an error for that. */
int sourcedesc;
open (char *filename, int modes)
{
register char *next;
if (modes)
{
errno = EROFS;
return -1;
}
if (sourceptr)
{
errno = EMFILE;
return -1;
}
for (next = files_start; *(int *) next; next += *(int *) next)
{
if (!strcmp (next + 4, filename))
{
sourcebeg = next + 4 + strlen (next + 4) + 1;
sourcebeg = (char *) (((int) sourcebeg + 3) & (-4));
sourceptr = sourcebeg;
sourcesize = next + *(int *) next - sourceptr;
sourceleft = sourcesize;
return sourcedesc;
}
}
return 0;
}
close (int desc)
{
sourceptr = 0;
sourcedesc++;
/* Don't let sourcedesc get big enough to be confused with stdin. */
if (sourcedesc == 100)
sourcedesc = 5;
}
FILE *
fopen (char *filename, char *modes)
{
return (FILE *) open (filename, *modes == 'w');
}
FILE *
fdopen (int desc)
{
return (FILE *) desc;
}
fclose (int desc)
{
close (desc);
}
fstat (int desc, struct stat *statbuf)
{
if (desc != sourcedesc)
{
errno = EBADF;
return -1;
}
statbuf->st_size = sourcesize;
}
myread (int desc, char *destptr, int size, char *filename)
{
int len = min (sourceleft, size);
if (desc != sourcedesc)
{
errno = EBADF;
return -1;
}
memcpy (destptr, sourceptr, len);
sourceleft -= len;
return len;
}
int
fread (int bufp, int numelts, int eltsize, int stream)
{
register int elts = min (numelts, sourceleft / eltsize);
register int len = elts * eltsize;
if (stream != sourcedesc)
{
errno = EBADF;
return -1;
}
memcpy (bufp, sourceptr, len);
sourceleft -= len;
return elts;
}
int
fgetc (int desc)
{
if (desc == (int) stdin)
return tty_input ();
if (desc != sourcedesc)
{
errno = EBADF;
return -1;
}
if (sourceleft-- <= 0)
return EOF;
return *sourceptr++;
}
lseek (int desc, int pos)
{
if (desc != sourcedesc)
{
errno = EBADF;
return -1;
}
if (pos < 0 || pos > sourcesize)
{
errno = EINVAL;
return -1;
}
sourceptr = sourcebeg + pos;
sourceleft = sourcesize - pos;
}
/* Output in kdb can go only to the terminal, so the stream
specified may be ignored. */
printf (int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9)
{
char buffer[1024];
sprintf (buffer, a1, a2, a3, a4, a5, a6, a7, a8, a9);
display_string (buffer);
}
fprintf (int ign, int a1, int a2, int a3, int a4, int a5, int a6, int a7,
int a8, int a9)
{
char buffer[1024];
sprintf (buffer, a1, a2, a3, a4, a5, a6, a7, a8, a9);
display_string (buffer);
}
fwrite (register char *buf, int numelts, int size, int stream)
{
register int i = numelts * size;
while (i-- > 0)
fputc (*buf++, stream);
}
fputc (int c, int ign)
{
char buf[2];
buf[0] = c;
buf[1] = 0;
display_string (buf);
}
/* sprintf refers to this, but loading this from the
library would cause fflush to be loaded from it too.
In fact there should be no need to call this (I hope). */
_flsbuf (void)
{
error ("_flsbuf was actually called.");
}
fflush (int ign)
{
}
/* Entries into core and inflow, needed only to make things link ok. */
exec_file_command (void)
{
}
core_file_command (void)
{
}
char *
get_exec_file (int err)
{
/* Makes one printout look reasonable; value does not matter otherwise. */
return "run";
}
/* Nonzero if there is a core file. */
have_core_file_p (void)
{
return 0;
}
kill_command (void)
{
inferior_ptid = null_ptid;
}
terminal_inferior (void)
{
}
terminal_ours (void)
{
}
terminal_init_inferior (void)
{
}
write_inferior_register (void)
{
}
read_inferior_register (void)
{
}
read_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
memcpy (myaddr, memaddr, len);
}
/* Always return 0 indicating success. */
write_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
memcpy (memaddr, myaddr, len);
return 0;
}
static REGISTER_TYPE saved_regs[NUM_REGS];
REGISTER_TYPE
read_register (int regno)
{
if (regno < 0 || regno >= NUM_REGS)
error ("Register number %d out of range.", regno);
return saved_regs[regno];
}
void
write_register (int regno, REGISTER_TYPE value)
{
if (regno < 0 || regno >= NUM_REGS)
error ("Register number %d out of range.", regno);
saved_regs[regno] = value;
}
/* System calls needed in relation to running the "inferior". */
vfork (void)
{
/* Just appear to "succeed". Say the inferior's pid is 1. */
return 1;
}
/* These are called by code that normally runs in the inferior
that has just been forked. That code never runs, when standalone,
and these definitions are so it will link without errors. */
ptrace (void)
{
}
setpgrp (void)
{
}
execle (void)
{
}
_exit (void)
{
}
/* Malloc calls these. */
malloc_warning (char *str)
{
printf ("\n%s.\n\n", str);
}
char *next_free;
char *memory_limit;
char *
sbrk (int amount)
{
if (next_free + amount > memory_limit)
return (char *) -1;
next_free += amount;
return next_free - amount;
}
/* Various ways malloc might ask where end of memory is. */
char *
ulimit (void)
{
return memory_limit;
}
int
vlimit (void)
{
return memory_limit - next_free;
}
getrlimit (struct rlimit *addr)
{
addr->rlim_cur = memory_limit - next_free;
}
/* Context switching to and from program being debugged. */
/* GDB calls here to run the user program.
The frame pointer for this function is saved in
gdb_stack by save_frame_pointer; then we restore
all of the user program's registers, including PC and PS. */
static int fault_code;
static REGISTER_TYPE gdb_stack;
resume (void)
{
REGISTER_TYPE restore[NUM_REGS];
PUSH_FRAME_PTR;
save_frame_pointer ();
memcpy (restore, saved_regs, sizeof restore);
POP_REGISTERS;
/* Control does not drop through here! */
}
save_frame_pointer (CORE_ADDR val)
{
gdb_stack = val;
}
/* Fault handlers call here, running in the user program stack.
They must first push a fault code,
old PC, old PS, and any other info about the fault.
The exact format is machine-dependent and is known only
in the definition of PUSH_REGISTERS. */
fault (void)
{
/* Transfer all registers and fault code to the stack
in canonical order: registers in order of GDB register number,
followed by fault code. */
PUSH_REGISTERS;
/* Transfer them to saved_regs and fault_code. */
save_registers ();
restore_gdb ();
/* Control does not reach here */
}
restore_gdb (void)
{
CORE_ADDR new_fp = gdb_stack;
/* Switch to GDB's stack */
POP_FRAME_PTR;
/* Return from the function `resume'. */
}
/* Assuming register contents and fault code have been pushed on the stack as
arguments to this function, copy them into the standard place
for the program's registers while GDB is running. */
save_registers (int firstreg)
{
memcpy (saved_regs, &firstreg, sizeof saved_regs);
fault_code = (&firstreg)[NUM_REGS];
}
/* Store into the structure such as `wait' would return
the information on why the program faulted,
converted into a machine-independent signal number. */
static int fault_table[] = FAULT_TABLE;
int
wait (WAITTYPE *w)
{
WSETSTOP (*w, fault_table[fault_code / FAULT_CODE_UNITS]);
return PIDGET (inferior_ptid);
}
/* Allocate a big space in which files for kdb to read will be stored.
Whatever is left is where malloc can allocate storage.
Initialize it, so that there will be space in the executable file
for it. Then the files can be put into kdb by writing them into
kdb's executable file. */
/* The default size is as much space as we expect to be available
for kdb to use! */
#ifndef HEAP_SIZE
#define HEAP_SIZE 400000
#endif
char heap[HEAP_SIZE] =
{0};
#ifndef STACK_SIZE
#define STACK_SIZE 100000
#endif
int kdb_stack_beg[STACK_SIZE / sizeof (int)];
int kdb_stack_end;
_initialize_standalone (void)
{
register char *next;
/* Find start of data on files. */
files_start = heap;
/* Find the end of the data on files. */
for (next = files_start; *(int *) next; next += *(int *) next)
{
}
/* That is where free storage starts for sbrk to give out. */
next_free = next;
memory_limit = heap + sizeof heap;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,196 +0,0 @@
/* Shared library support for RS/6000 (xcoff) object files, for GDB.
Copyright 1991, 1992, 1995, 1996, 1999, 2000, 2001
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 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#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);
xasprintf (&buffer, "%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)
{
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",
paddr (vp->tstart),paddr (vp->tend),
paddr (vp->dstart), paddr (vp->dend),
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 ();
}
}
}
/* LOCAL FUNCTION
no_shared_libraries -- handle command to explicitly discard symbols
from shared libraries.
DESCRIPTION
Implements the command "nosharedlibrary", which discards symbols
that have been auto-loaded from shared libraries. Symbols from
shared libraries that were added by explicit request of the user
are not discarded. Also called from remote.c. */
void
no_shared_libraries (char *ignored, int from_tty)
{
/* FIXME */
}
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_show_from_set
(add_set_cmd ("auto-solib-add", class_support, var_boolean,
(char *) &auto_solib_add,
"Set autoloading of shared library symbols.\n\
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'.",
&setlist),
&showlist);
}