Removed most unused files (about 8M total).

This commit is contained in:
Bruce Evans 1997-06-29 18:12:14 +00:00
parent 574c224708
commit b3174ab1ce
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=27071
120 changed files with 0 additions and 83916 deletions

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,9 +0,0 @@
/* Define if fpregset_t type is available. */
#undef HAVE_FPREGSET_T
/* Define if gregset_t type is available. */
#undef HAVE_GREGSET_T
/* Define if the "%Lg" format works to print long doubles. */
#undef PRINTF_HAS_LONG_DOUBLE

View file

@ -1,243 +0,0 @@
/* Low level Alpha interface, for GDB when running native.
Copyright 1993, 1995, 1996 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 <sys/ptrace.h>
#include <machine/reg.h>
#include <sys/user.h>
/* 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 (pc)
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_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
char *core_reg_sect;
unsigned core_reg_size;
int which;
unsigned 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. */
static int core_reg_mapping[NUM_REGS] =
{
#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
};
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.", reg_names[bad_reg]);
}
}
/* 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. */
unsigned int
register_addr (regno, blockend)
int regno;
int blockend;
{
return REGISTER_PTRACE_ADDR (regno);
}
int
kernel_u_size ()
{
return (sizeof (struct user));
}
#ifdef USE_PROC_FS
#include <sys/procfs.h>
/*
* See the comment in m68k-tdep.c regarding the utility of these functions.
*/
void
supply_gregset (gregsetp)
gregset_t *gregsetp;
{
register int regi;
register long *regp = gregsetp->regs;
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 (gregsetp, regno)
gregset_t *gregsetp;
int regno;
{
int regi;
register long *regp = gregsetp->regs;
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 (fpregsetp)
fpregset_t *fpregsetp;
{
register int regi;
register long *regp = fpregsetp->regs;
for (regi = 0; regi < 32; regi++)
supply_register (regi + FP0_REGNUM, (char *)(regp + regi));
}
void
fill_fpregset (fpregsetp, regno)
fpregset_t *fpregsetp;
int regno;
{
int regi;
register long *regp = fpregsetp->regs;
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_core_fns =
{
bfd_target_aout_flavour,
fetch_core_registers,
NULL
};
void
_initialize_core_alpha ()
{
add_core_fns (&alpha_core_fns);
}

File diff suppressed because it is too large Load diff

View file

@ -1,16 +0,0 @@
.text
.global _convert_from_extended
_convert_from_extended:
ldfe f0,[a1]
stfd f0,[a2]
movs pc,lr
.global _convert_to_extended
_convert_to_extended:
ldfd f0,[a1]
stfe f0,[a2]
movs pc,lr

View file

@ -1,826 +0,0 @@
/* Target-dependent code for the Acorn Risc Machine, for GDB, the GNU Debugger.
Copyright 1988, 1989, 1991, 1992, 1993, 1995 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"
#if 0
#include "gdbcore.h"
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/ptrace.h>
#include <machine/reg.h>
#define N_TXTADDR(hdr) 0x8000
#define N_DATADDR(hdr) (hdr.a_text + 0x8000)
#include <sys/user.h> /* After a.out.h */
#include <sys/file.h>
#include "gdb_stat.h"
#include <errno.h>
#endif
#if 0
/* Work with core dump and executable files, for GDB.
This code would be in corefile.c if it weren't machine-dependent. */
/* Structure to describe the chain of shared libraries used
by the execfile.
e.g. prog shares Xt which shares X11 which shares c. */
struct shared_library {
struct exec_header header;
char name[SHLIBLEN];
CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file */
long data_offset; /* offset of data section in file */
int chan; /* file descriptor for the file */
struct shared_library *shares; /* library this one shares */
};
static struct shared_library *shlib = 0;
/* Hook for `exec_file_command' command to call. */
extern void (*exec_file_display_hook) ();
static CORE_ADDR unshared_text_start;
/* extended header from exec file (for shared library info) */
static struct exec_header exec_header;
void
exec_file_command (filename, from_tty)
char *filename;
int from_tty;
{
int val;
/* Eliminate all traces of old exec file.
Mark text segment as empty. */
if (execfile)
free (execfile);
execfile = 0;
data_start = 0;
data_end -= exec_data_start;
text_start = 0;
unshared_text_start = 0;
text_end = 0;
exec_data_start = 0;
exec_data_end = 0;
if (execchan >= 0)
close (execchan);
execchan = -1;
if (shlib) {
close_shared_library(shlib);
shlib = 0;
}
/* Now open and digest the file the user requested, if any. */
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
&execfile);
if (execchan < 0)
perror_with_name (filename);
{
struct stat st_exec;
#ifdef HEADER_SEEK_FD
HEADER_SEEK_FD (execchan);
#endif
val = myread (execchan, &exec_header, sizeof exec_header);
exec_aouthdr = exec_header.a_exec;
if (val < 0)
perror_with_name (filename);
text_start = 0x8000;
/* Look for shared library if needed */
if (exec_header.a_exec.a_magic & MF_USES_SL)
shlib = open_shared_library(exec_header.a_shlibname, text_start);
text_offset = N_TXTOFF (exec_aouthdr);
exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
if (shlib) {
unshared_text_start = shared_text_end(shlib) & ~0x7fff;
stack_start = shlib->header.a_exec.a_sldatabase;
stack_end = STACK_END_ADDR;
} else
unshared_text_start = 0x8000;
text_end = unshared_text_start + exec_aouthdr.a_text;
exec_data_start = unshared_text_start + exec_aouthdr.a_text;
exec_data_end = exec_data_start + exec_aouthdr.a_data;
data_start = exec_data_start;
data_end += exec_data_start;
fstat (execchan, &st_exec);
exec_mtime = st_exec.st_mtime;
}
validate_files ();
}
else if (from_tty)
printf ("No exec file now.\n");
/* Tell display code (if any) about the changed file name. */
if (exec_file_display_hook)
(*exec_file_display_hook) (filename);
}
#endif
#if 0
/* Read from the program's memory (except for inferior processes).
This function is misnamed, since it only reads, never writes; and
since it will use the core file and/or executable file as necessary.
It should be extended to write as well as read, FIXME, for patching files.
Return 0 if address could be read, EIO if addresss out of bounds. */
int
xfer_core_file (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
register int i;
register int val;
int xferchan;
char **xferfile;
int fileptr;
int returnval = 0;
while (len > 0)
{
xferfile = 0;
xferchan = 0;
/* Determine which file the next bunch of addresses reside in,
and where in the file. Set the file's read/write pointer
to point at the proper place for the desired address
and set xferfile and xferchan for the correct file.
If desired address is nonexistent, leave them zero.
i is set to the number of bytes that can be handled
along with the next address.
We put the most likely tests first for efficiency. */
/* Note that if there is no core file
data_start and data_end are equal. */
if (memaddr >= data_start && memaddr < data_end)
{
i = min (len, data_end - memaddr);
fileptr = memaddr - data_start + data_offset;
xferfile = &corefile;
xferchan = corechan;
}
/* Note that if there is no core file
stack_start and stack_end define the shared library data. */
else if (memaddr >= stack_start && memaddr < stack_end)
{
if (corechan < 0) {
struct shared_library *lib;
for (lib = shlib; lib; lib = lib->shares)
if (memaddr >= lib->header.a_exec.a_sldatabase &&
memaddr < lib->header.a_exec.a_sldatabase +
lib->header.a_exec.a_data)
break;
if (lib) {
i = min (len, lib->header.a_exec.a_sldatabase +
lib->header.a_exec.a_data - memaddr);
fileptr = lib->data_offset + memaddr -
lib->header.a_exec.a_sldatabase;
xferfile = execfile;
xferchan = lib->chan;
}
} else {
i = min (len, stack_end - memaddr);
fileptr = memaddr - stack_start + stack_offset;
xferfile = &corefile;
xferchan = corechan;
}
}
else if (corechan < 0
&& memaddr >= exec_data_start && memaddr < exec_data_end)
{
i = min (len, exec_data_end - memaddr);
fileptr = memaddr - exec_data_start + exec_data_offset;
xferfile = &execfile;
xferchan = execchan;
}
else if (memaddr >= text_start && memaddr < text_end)
{
struct shared_library *lib;
for (lib = shlib; lib; lib = lib->shares)
if (memaddr >= lib->text_start &&
memaddr < lib->text_start + lib->header.a_exec.a_text)
break;
if (lib) {
i = min (len, lib->header.a_exec.a_text +
lib->text_start - memaddr);
fileptr = memaddr - lib->text_start + text_offset;
xferfile = &execfile;
xferchan = lib->chan;
} else {
i = min (len, text_end - memaddr);
fileptr = memaddr - unshared_text_start + text_offset;
xferfile = &execfile;
xferchan = execchan;
}
}
else if (memaddr < text_start)
{
i = min (len, text_start - memaddr);
}
else if (memaddr >= text_end
&& memaddr < (corechan >= 0? data_start : exec_data_start))
{
i = min (len, data_start - memaddr);
}
else if (corechan >= 0
&& memaddr >= data_end && memaddr < stack_start)
{
i = min (len, stack_start - memaddr);
}
else if (corechan < 0 && memaddr >= exec_data_end)
{
i = min (len, - memaddr);
}
else if (memaddr >= stack_end && stack_end != 0)
{
i = min (len, - memaddr);
}
else
{
/* Address did not classify into one of the known ranges.
This shouldn't happen; we catch the endpoints. */
fatal ("Internal: Bad case logic in xfer_core_file.");
}
/* Now we know which file to use.
Set up its pointer and transfer the data. */
if (xferfile)
{
if (*xferfile == 0)
if (xferfile == &execfile)
error ("No program file to examine.");
else
error ("No core dump file or running program to examine.");
val = lseek (xferchan, fileptr, 0);
if (val < 0)
perror_with_name (*xferfile);
val = myread (xferchan, myaddr, i);
if (val < 0)
perror_with_name (*xferfile);
}
/* If this address is for nonexistent memory,
read zeros if reading, or do nothing if writing.
Actually, we never right. */
else
{
memset (myaddr, '\0', i);
returnval = EIO;
}
memaddr += i;
myaddr += i;
len -= i;
}
return returnval;
}
#endif
/* APCS (ARM procedure call standard) defines the following prologue:
mov ip, sp
[stmfd sp!, {a1,a2,a3,a4}]
stmfd sp!, {...,fp,ip,lr,pc}
[stfe f7, [sp, #-12]!]
[stfe f6, [sp, #-12]!]
[stfe f5, [sp, #-12]!]
[stfe f4, [sp, #-12]!]
sub fp, ip, #nn // nn == 20 or 4 depending on second ins
*/
CORE_ADDR
skip_prologue(pc)
CORE_ADDR pc;
{
CORE_ADDR skip_pc = pc;
#if 0
union insn_fmt op;
op.ins = read_memory_integer(skip_pc, 4);
/* look for the "mov ip,sp" */
if (op.generic.type != TYPE_ARITHMETIC ||
op.arith.opcode != OPCODE_MOV ||
op.arith.dest != SPTEMP ||
op.arith.operand2 != SP) return pc;
skip_pc += 4;
/* skip the "stmfd sp!,{a1,a2,a3,a4}" if its there */
op.ins = read_memory_integer(skip_pc, 4);
if (op.generic.type == TYPE_BLOCK_BRANCH &&
op.generic.subtype == SUBTYPE_BLOCK &&
op.block.mask == 0xf &&
op.block.base == SP &&
op.block.is_load == 0 &&
op.block.writeback == 1 &&
op.block.increment == 0 &&
op.block.before == 1) skip_pc += 4;
/* skip the "stmfd sp!,{...,fp,ip,lr,pc} */
op.ins = read_memory_integer(skip_pc, 4);
if (op.generic.type != TYPE_BLOCK_BRANCH ||
op.generic.subtype != SUBTYPE_BLOCK ||
/* the mask should look like 110110xxxxxx0000 */
(op.block.mask & 0xd800) != 0xd800 ||
op.block.base != SP ||
op.block.is_load != 0 ||
op.block.writeback != 1 ||
op.block.increment != 0 ||
op.block.before != 1) return pc;
skip_pc += 4;
/* check for "sub fp,ip,#nn" */
op.ins = read_memory_integer(skip_pc, 4);
if (op.generic.type != TYPE_ARITHMETIC ||
op.arith.opcode != OPCODE_SUB ||
op.arith.dest != FP ||
op.arith.operand1 != SPTEMP) return pc;
#endif
return skip_pc + 4;
}
void
arm_frame_find_saved_regs (frame_info, saved_regs_addr)
struct frame_info *frame_info;
struct frame_saved_regs *saved_regs_addr;
{
register int regnum;
register int frame;
register int next_addr;
register int return_data_save;
register int saved_register_mask;
memset (saved_regs_addr, '\0', sizeof (*saved_regs_addr));
frame = frame_info->frame;
return_data_save = read_memory_integer (frame, 4) & 0x03fffffc - 12;
saved_register_mask = read_memory_integer (return_data_save, 4);
next_addr = frame - 12;
for (regnum = 4; regnum < 10; regnum++)
if (saved_register_mask & (1 << regnum))
{
next_addr -= 4;
saved_regs_addr->regs[regnum] = next_addr;
}
if (read_memory_integer (return_data_save + 4, 4) == 0xed6d7103)
{
next_addr -= 12;
saved_regs_addr->regs[F0_REGNUM + 7] = next_addr;
}
if (read_memory_integer (return_data_save + 8, 4) == 0xed6d6103)
{
next_addr -= 12;
saved_regs_addr->regs[F0_REGNUM + 6] = next_addr;
}
if (read_memory_integer (return_data_save + 12, 4) == 0xed6d5103)
{
next_addr -= 12;
saved_regs_addr->regs[F0_REGNUM + 5] = next_addr;
}
if (read_memory_integer(return_data_save + 16, 4) == 0xed6d4103)
{
next_addr -= 12;
saved_regs_addr->regs[F0_REGNUM + 4] = next_addr;
}
saved_regs_addr->regs[SP_REGNUM] = next_addr;
saved_regs_addr->regs[PC_REGNUM] = frame - 4;
saved_regs_addr->regs[PS_REGNUM] = frame - 4;
saved_regs_addr->regs[FP_REGNUM] = frame - 12;
}
static void
print_fpu_flags(flags)
int flags;
{
if (flags & (1 << 0)) fputs("IVO ", stdout);
if (flags & (1 << 1)) fputs("DVZ ", stdout);
if (flags & (1 << 2)) fputs("OFL ", stdout);
if (flags & (1 << 3)) fputs("UFL ", stdout);
if (flags & (1 << 4)) fputs("INX ", stdout);
putchar('\n');
}
void
arm_float_info()
{
register unsigned long status = read_register(FPS_REGNUM);
int type;
type = (status >> 24) & 127;
printf("%s FPU type %d\n",
(status & (1<<31)) ? "Hardware" : "Software",
type);
fputs("mask: ", stdout);
print_fpu_flags(status >> 16);
fputs("flags: ", stdout);
print_fpu_flags(status);
}
static void arm_othernames()
{
static int toggle;
static char *original[] = ORIGINAL_REGISTER_NAMES;
static char *extra_crispy[] = ADDITIONAL_REGISTER_NAMES;
memcpy (reg_names, toggle ? extra_crispy : original, sizeof(original));
toggle = !toggle;
}
void
_initialize_arm_tdep ()
{
tm_print_insn = print_insn_little_arm;
add_com ("othernames", class_obscure, arm_othernames);
}
/* FIXME: Fill in with the 'right thing', see asm
template in arm-convert.s */
void
convert_from_extended (ptr, dbl)
void *ptr;
double *dbl;
{
*dbl = *(double*)ptr;
}
void
convert_to_extended (dbl, ptr)
void *ptr;
double *dbl;
{
*(double*)ptr = *dbl;
}
int
arm_nullified_insn (inst)
unsigned long inst;
{
unsigned long cond = inst & 0xf0000000;
unsigned long status_reg;
if (cond == INST_AL || cond == INST_NV)
return 0;
status_reg = read_register (PS_REGNUM);
switch (cond)
{
case INST_EQ:
return ((status_reg & FLAG_Z) == 0);
case INST_NE:
return ((status_reg & FLAG_Z) != 0);
case INST_CS:
return ((status_reg & FLAG_C) == 0);
case INST_CC:
return ((status_reg & FLAG_C) != 0);
case INST_MI:
return ((status_reg & FLAG_N) == 0);
case INST_PL:
return ((status_reg & FLAG_N) != 0);
case INST_VS:
return ((status_reg & FLAG_V) == 0);
case INST_VC:
return ((status_reg & FLAG_V) != 0);
case INST_HI:
return ((status_reg & (FLAG_C | FLAG_Z)) != FLAG_C);
case INST_LS:
return (((status_reg & (FLAG_C | FLAG_Z)) ^ FLAG_C) == 0);
case INST_GE:
return (((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0));
case INST_LT:
return (((status_reg & FLAG_N) == 0) == ((status_reg & FLAG_V) == 0));
case INST_GT:
return (((status_reg & FLAG_Z) != 0) ||
(((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0)));
case INST_LE:
return (((status_reg & FLAG_Z) == 0) &&
(((status_reg & FLAG_N) == 0) == ((status_reg & FLAG_V) == 0)));
}
return 0;
}
/* taken from remote-arm.c .. */
#define submask(x) ((1L << ((x) + 1)) - 1)
#define bit(obj,st) (((obj) & (1L << (st))) >> st)
#define bits(obj,st,fn) \
(((obj) & submask (fn) & ~ submask ((st) - 1)) >> (st))
#define sbits(obj,st,fn) \
((long) (bits(obj,st,fn) | ((long) bit(obj,fn) * ~ submask (fn - st))))
#define BranchDest(addr,instr) \
((CORE_ADDR) (((long) (addr)) + 8 + (sbits (instr, 0, 23) << 2)))
#define ARM_PC_32 1
static unsigned long
shifted_reg_val (inst, carry, pc_val)
unsigned long inst;
int carry;
unsigned long pc_val;
{
unsigned long res, shift;
int rm = bits (inst, 0, 3);
unsigned long shifttype = bits (inst, 5, 6);
if (bit(inst, 4))
{
int rs = bits (inst, 8, 11);
shift = (rs == 15 ? pc_val + 8 : read_register (rs)) & 0xFF;
}
else
shift = bits (inst, 7, 11);
res = (rm == 15
? ((pc_val | (ARM_PC_32 ? 0 : read_register (PS_REGNUM)))
+ (bit (inst, 4) ? 12 : 8))
: read_register (rm));
switch (shifttype)
{
case 0: /* LSL */
res = shift >= 32 ? 0 : res << shift;
break;
case 1: /* LSR */
res = shift >= 32 ? 0 : res >> shift;
break;
case 2: /* ASR */
if (shift >= 32) shift = 31;
res = ((res & 0x80000000L)
? ~((~res) >> shift) : res >> shift);
break;
case 3: /* ROR/RRX */
shift &= 31;
if (shift == 0)
res = (res >> 1) | (carry ? 0x80000000L : 0);
else
res = (res >> shift) | (res << (32-shift));
break;
}
return res & 0xffffffff;
}
CORE_ADDR
arm_get_next_pc (pc)
CORE_ADDR pc;
{
unsigned long pc_val = (unsigned long) pc;
unsigned long this_instr = read_memory_integer (pc, 4);
unsigned long status = read_register (PS_REGNUM);
CORE_ADDR nextpc = (CORE_ADDR) (pc_val + 4); /* Default case */
if (! arm_nullified_insn (this_instr))
{
switch (bits(this_instr, 24, 27))
{
case 0x0: case 0x1: /* data processing */
case 0x2: case 0x3:
{
unsigned long operand1, operand2, result = 0;
unsigned long rn;
int c;
if (bits(this_instr, 12, 15) != 15)
break;
if (bits (this_instr, 22, 25) == 0
&& bits (this_instr, 4, 7) == 9) /* multiply */
error ("Illegal update to pc in instruction");
/* Multiply into PC */
c = (status & FLAG_C) ? 1 : 0;
rn = bits (this_instr, 16, 19);
operand1 = (rn == 15) ? pc_val + 8 : read_register (rn);
if (bit (this_instr, 25))
{
unsigned long immval = bits (this_instr, 0, 7);
unsigned long rotate = 2 * bits (this_instr, 8, 11);
operand2 = ((immval >> rotate) | (immval << (32-rotate))
& 0xffffffff);
}
else /* operand 2 is a shifted register */
operand2 = shifted_reg_val (this_instr, c, pc_val);
switch (bits (this_instr, 21, 24))
{
case 0x0: /*and*/
result = operand1 & operand2;
break;
case 0x1: /*eor*/
result = operand1 ^ operand2;
break;
case 0x2: /*sub*/
result = operand1 - operand2;
break;
case 0x3: /*rsb*/
result = operand2 - operand1;
break;
case 0x4: /*add*/
result = operand1 + operand2;
break;
case 0x5: /*adc*/
result = operand1 + operand2 + c;
break;
case 0x6: /*sbc*/
result = operand1 - operand2 + c;
break;
case 0x7: /*rsc*/
result = operand2 - operand1 + c;
break;
case 0x8: case 0x9: case 0xa: case 0xb: /* tst, teq, cmp, cmn */
result = (unsigned long) nextpc;
break;
case 0xc: /*orr*/
result = operand1 | operand2;
break;
case 0xd: /*mov*/
/* Always step into a function. */
result = operand2;
break;
case 0xe: /*bic*/
result = operand1 & ~operand2;
break;
case 0xf: /*mvn*/
result = ~operand2;
break;
}
nextpc = (CORE_ADDR) ADDR_BITS_REMOVE (result);
if (nextpc == pc)
error ("Infinite loop detected");
break;
}
case 0x4: case 0x5: /* data transfer */
case 0x6: case 0x7:
if (bit (this_instr, 20))
{
/* load */
if (bits (this_instr, 12, 15) == 15)
{
/* rd == pc */
unsigned long rn;
unsigned long base;
if (bit (this_instr, 22))
error ("Illegal update to pc in instruction");
/* byte write to PC */
rn = bits (this_instr, 16, 19);
base = (rn == 15) ? pc_val + 8 : read_register (rn);
if (bit (this_instr, 24))
{
/* pre-indexed */
int c = (status & FLAG_C) ? 1 : 0;
unsigned long offset =
(bit (this_instr, 25)
? shifted_reg_val (this_instr, c, pc_val)
: bits (this_instr, 0, 11));
if (bit (this_instr, 23))
base += offset;
else
base -= offset;
}
nextpc = (CORE_ADDR) read_memory_integer ((CORE_ADDR) base,
4);
nextpc = ADDR_BITS_REMOVE (nextpc);
if (nextpc == pc)
error ("Infinite loop detected");
}
}
break;
case 0x8: case 0x9: /* block transfer */
if (bit (this_instr, 20))
{
/* LDM */
if (bit (this_instr, 15))
{
/* loading pc */
int offset = 0;
if (bit (this_instr, 23))
{
/* up */
unsigned long reglist = bits (this_instr, 0, 14);
unsigned long regbit;
for (; reglist != 0; reglist &= ~regbit)
{
regbit = reglist & (-reglist);
offset += 4;
}
if (bit (this_instr, 24)) /* pre */
offset += 4;
}
else if (bit (this_instr, 24))
offset = -4;
{
unsigned long rn_val =
read_register (bits (this_instr, 16, 19));
nextpc =
(CORE_ADDR) read_memory_integer ((CORE_ADDR) (rn_val
+ offset),
4);
}
nextpc = ADDR_BITS_REMOVE (nextpc);
if (nextpc == pc)
error ("Infinite loop detected");
}
}
break;
case 0xb: /* branch & link */
case 0xa: /* branch */
{
nextpc = BranchDest (pc, this_instr);
nextpc = ADDR_BITS_REMOVE (nextpc);
if (nextpc == pc)
error ("Infinite loop detected");
break;
}
case 0xc: case 0xd:
case 0xe: /* coproc ops */
case 0xf: /* SWI */
break;
default:
fprintf (stderr, "Bad bit-field extraction\n");
return (pc);
}
}
return nextpc;
}

View file

@ -1,276 +0,0 @@
/* Acorn Risc Machine host machine support.
Copyright (C) 1988, 1989, 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. */
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include "arm-opcode.h"
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/ptrace.h>
#include <machine/reg.h>
#define N_TXTADDR(hdr) 0x8000
#define N_DATADDR(hdr) (hdr.a_text + 0x8000)
#include "gdbcore.h"
#include <sys/user.h> /* After a.out.h */
#include <sys/file.h>
#include "gdb_stat.h"
#include <errno.h>
void
fetch_inferior_registers (regno)
int regno; /* Original value discarded */
{
register unsigned int regaddr;
char buf[MAX_REGISTER_RAW_SIZE];
register int i;
struct user u;
unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0)
- KERNEL_U_ADDR;
registers_fetched ();
for (regno = 0; regno < 16; regno++)
{
regaddr = offset + regno * 4;
*(int *)&buf[0] = ptrace (PT_READ_U, inferior_pid,
(PTRACE_ARG3_TYPE) regaddr, 0);
if (regno == PC_REGNUM)
*(int *)&buf[0] = GET_PC_PART(*(int *)&buf[0]);
supply_register (regno, buf);
}
*(int *)&buf[0] = ptrace (PT_READ_U, inferior_pid,
(PTRACE_ARG3_TYPE) (offset + PC*4), 0);
supply_register (PS_REGNUM, buf); /* set virtual register ps same as pc */
/* read the floating point registers */
offset = (char *) &u.u_fp_regs - (char *)&u;
*(int *)buf = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0);
supply_register (FPS_REGNUM, buf);
for (regno = 16; regno < 24; regno++) {
regaddr = offset + 4 + 12 * (regno - 16);
for (i = 0; i < 12; i += sizeof(int))
*(int *) &buf[i] = ptrace (PT_READ_U, inferior_pid,
(PTRACE_ARG3_TYPE) (regaddr + i), 0);
supply_register (regno, 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 (regno)
int regno;
{
register unsigned int regaddr;
char buf[80];
struct user u;
unsigned long value;
unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0)
- KERNEL_U_ADDR;
if (regno >= 0) {
if (regno >= 16) return;
regaddr = offset + 4 * regno;
errno = 0;
value = read_register(regno);
if (regno == PC_REGNUM)
value = SET_PC_PART(read_register (PS_REGNUM), value);
ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value);
if (errno != 0)
{
sprintf (buf, "writing register number %d", regno);
perror_with_name (buf);
}
}
else for (regno = 0; regno < 15; regno++)
{
regaddr = offset + regno * 4;
errno = 0;
value = read_register(regno);
if (regno == PC_REGNUM)
value = SET_PC_PART(read_register (PS_REGNUM), value);
ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value);
if (errno != 0)
{
sprintf (buf, "writing all regs, number %d", regno);
perror_with_name (buf);
}
}
}
/* Work with core dump and executable files, for GDB.
This code would be in corefile.c if it weren't machine-dependent. */
/* Structure to describe the chain of shared libraries used
by the execfile.
e.g. prog shares Xt which shares X11 which shares c. */
struct shared_library {
struct exec_header header;
char name[SHLIBLEN];
CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file */
long data_offset; /* offset of data section in file */
int chan; /* file descriptor for the file */
struct shared_library *shares; /* library this one shares */
};
static struct shared_library *shlib = 0;
/* Hook for `exec_file_command' command to call. */
extern void (*exec_file_display_hook) ();
static CORE_ADDR unshared_text_start;
/* extended header from exec file (for shared library info) */
static struct exec_header exec_header;
void
core_file_command (filename, from_tty)
char *filename;
int from_tty;
{
int val;
extern char registers[];
/* Discard all vestiges of any previous core file
and mark data and stack spaces as empty. */
if (corefile)
free (corefile);
corefile = 0;
if (corechan >= 0)
close (corechan);
corechan = -1;
data_start = 0;
data_end = 0;
stack_start = STACK_END_ADDR;
stack_end = STACK_END_ADDR;
/* Now, if a new core file was specified, open it and digest it. */
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
if (have_inferior_p ())
error ("To look at a core file, you must kill the program with \"kill\".");
corechan = open (filename, O_RDONLY, 0);
if (corechan < 0)
perror_with_name (filename);
/* 4.2-style (and perhaps also sysV-style) core dump file. */
{
struct user u;
unsigned int reg_offset, fp_reg_offset;
val = myread (corechan, &u, sizeof u);
if (val < 0)
perror_with_name ("Not a core file: reading upage");
if (val != sizeof u)
error ("Not a core file: could only read %d bytes", val);
/* We are depending on exec_file_command having been called
previously to set exec_data_start. Since the executable
and the core file share the same text segment, the address
of the data segment will be the same in both. */
data_start = exec_data_start;
data_end = data_start + NBPG * u.u_dsize;
stack_start = stack_end - NBPG * u.u_ssize;
data_offset = NBPG * UPAGES;
stack_offset = NBPG * (UPAGES + u.u_dsize);
/* Some machines put an absolute address in here and some put
the offset in the upage of the regs. */
reg_offset = (int) u.u_ar0;
if (reg_offset > NBPG * UPAGES)
reg_offset -= KERNEL_U_ADDR;
fp_reg_offset = (char *) &u.u_fp_regs - (char *)&u;
/* I don't know where to find this info.
So, for now, mark it as not available. */
N_SET_MAGIC (core_aouthdr, 0);
/* Read the register values out of the core file and store
them where `read_register' will find them. */
{
register int regno;
for (regno = 0; regno < NUM_REGS; regno++)
{
char buf[MAX_REGISTER_RAW_SIZE];
if (regno < 16)
val = lseek (corechan, reg_offset + 4 * regno, 0);
else if (regno < 24)
val = lseek (corechan, fp_reg_offset + 4 + 12*(regno - 24), 0);
else if (regno == 24)
val = lseek (corechan, fp_reg_offset, 0);
else if (regno == 25)
val = lseek (corechan, reg_offset + 4 * PC, 0);
if (val < 0
|| (val = myread (corechan, buf, sizeof buf)) < 0)
{
char * buffer = (char *) alloca (strlen (reg_names[regno])
+ 30);
strcpy (buffer, "Reading register ");
strcat (buffer, reg_names[regno]);
perror_with_name (buffer);
}
if (regno == PC_REGNUM)
*(int *)buf = GET_PC_PART(*(int *)buf);
supply_register (regno, buf);
}
}
}
if (filename[0] == '/')
corefile = savestring (filename, strlen (filename));
else
{
corefile = concat (current_directory, "/", filename, NULL);
}
flush_cached_frames ();
select_frame (get_current_frame (), 0);
validate_files ();
}
else if (from_tty)
printf ("No core file now.\n");
}

View file

@ -1,131 +0,0 @@
/* Handle COFF SVR3 shared libraries for GDB, the GNU Debugger.
Copyright 1993 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"
/*
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)
DESCRIPTION
*/
void
coff_solib_add (arg_string, from_tty, target)
char *arg_string;
int from_tty;
struct target_ops *target;
{
asection *libsect;
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,
0, /* addr */
0, /* not mainline */
0, /* not mapped */
0); /* Not readnow */
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()
{
coff_solib_add ((char *) 0, 0, (struct target_ops *) 0);
}

View file

@ -1,60 +0,0 @@
/* COFF (SVR3) Shared library declarations for GDB, the GNU Debugger.
Copyright (C) 1992 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. */
#ifdef __STDC__ /* Forward decl's for prototypes */
struct target_ops;
#endif
/* 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 PARAMS ((void));
#endif
/* Called to add symbols from a shared library to gdb's symbol table. */
#define SOLIB_ADD(filename, from_tty, targ) \
coff_solib_add (filename, from_tty, targ)
extern void
coff_solib_add PARAMS ((char *, int, struct target_ops *));
/* 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 PARAMS((void)); /* solib.c */
/* 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 PARAMS ((CORE_ADDR)); /* solib.c */
#endif

View file

@ -1,2 +0,0 @@
/* This is just a dummy file to symlink to when GDB is configured as a
cross-only debugger. */

View file

@ -1,46 +0,0 @@
/* Common declarations for the GNU Hurd
Copyright (C) 1995 Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.ai.mit.edu>
The GNU Hurd 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, or (at
your option) any later version.
The GNU Hurd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef __NM_GNU_H__
#define __NM_GNU_H__
#include <unistd.h>
#include <mach.h>
#include <mach/exception.h>
#include "solib.h" /* Support for shared libraries. */
#undef target_pid_to_str
#define target_pid_to_str(pid) gnu_target_pid_to_str(pid)
extern char *gnu_target_pid_to_str (int pid);
/* Before storing, we need to read all the registers. */
#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
/* Don't do wait_for_inferior on attach. */
#define ATTACH_NO_WAIT
/* Use SVR4 style shared library support */
#define SVR4_SHARED_LIBS
#define NO_CORE_OPS
#define MAINTENANCE_CMDS 1
#endif /* __NM_GNU_H__ */

View file

@ -1,83 +0,0 @@
/* Native-dependent definitions for LynxOS.
Copyright 1993 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. */
#ifndef NM_LYNX_H
#define NM_LYNX_H
#include <sys/conf.h>
#include <sys/kernel.h>
/* sys/kernel.h should define this, but doesn't always, sigh. */
#ifndef __LYNXOS
#define __LYNXOS
#endif
#include <sys/mem.h>
#include <sys/signal.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/itimer.h>
#include <sys/file.h>
#include <sys/proc.h>
#include "thread.h"
/* This is the amount to subtract from u.u_ar0 to get the offset in
the core file of the register values. */
#define KERNEL_U_ADDR USRSTACK
#undef FLOAT_INFO /* No float info yet */
/* As of LynxOS 2.2.2 (beta 8/15/94), this is int. Previous versions seem to
have had no prototype, so I'm not sure why GDB used to define this to
char *. */
#define PTRACE_ARG3_TYPE int
/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
#define FETCH_INFERIOR_REGISTERS
/* Thread ID of stopped thread. */
#define WIFTID(x) (((union wait *)&x)->w_tid)
/* Override child_wait in inftarg.c */
#define CHILD_WAIT
/* Override child_resume in infptrace.c */
#define CHILD_RESUME
/* Override child_thread_alive in intarg.c */
#define CHILD_THREAD_ALIVE
#include "target.h"
extern int child_wait PARAMS ((int pid, struct target_waitstatus *status));
/* Lynx needs a special definition of this so that we can
print out the pid and thread number seperatly. */
#undef target_pid_to_str
#define target_pid_to_str(PID) lynx_pid_to_str (PID)
extern char *lynx_pid_to_str PARAMS ((int pid));
#endif /* NM_LYNX_H */

View file

@ -1,123 +0,0 @@
/* Mach 3.0 common definitions and global vars.
Copyright (C) 1992 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. */
#ifndef NM_M3_H
#define NM_M3_H
#include <mach.h>
/* Mach3 doesn't declare errno in <errno.h>. */
extern int errno;
/* Task port of our debugged inferior. */
extern task_t inferior_task;
/* Thread port of the current thread in the inferior. */
extern thread_t current_thread;
/* If nonzero, we must suspend/abort && resume threads
* when setting or getting the state.
*/
extern int must_suspend_thread;
#define PREPARE_TO_PROCEED(select_it) mach3_prepare_to_proceed(select_it)
/* Try to get the privileged host port for authentication to machid
*
* If you can get this, you may debug anything on this host.
*
* If you can't, gdb gives it's own task port as the
* authentication port
*/
#define mach_privileged_host_port() task_by_pid(-1)
/*
* This is the MIG ID number of the emulator/server bsd_execve() RPC call.
*
* It SHOULD never change, but if it does, gdb `run'
* command won't work until you fix this define.
*
*/
#define MIG_EXEC_SYSCALL_ID 101000
/* If our_message_port gets a msg with this ID,
* GDB suspends it's inferior and enters command level.
* (Useful at least if ^C does not work)
*/
#define GDB_MESSAGE_ID_STOP 0x41151
/* wait3 WNOHANG is defined in <sys/wait.h> but
* for some reason gdb does not want to include
* that file.
*
* If your system defines WNOHANG differently, this has to be changed.
*/
#define WNOHANG 1
/* Before storing, we need to read all the registers. */
#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
/* Check if the inferior exists */
#define MACH_ERROR_NO_INFERIOR \
do if (!MACH_PORT_VALID (inferior_task)) \
error ("Inferior task does not exist."); while(0)
/* Error handler for mach calls */
#define CHK(str,ret) \
do if (ret != KERN_SUCCESS) \
error ("Gdb %s [%d] %s : %s\n",__FILE__,__LINE__,str, \
mach_error_string(ret)); while(0)
/* This is from POE9 emulator/emul_stack.h
*/
/*
* Top of emulator stack holds link and reply port.
*/
struct emul_stack_top {
struct emul_stack_top *link;
mach_port_t reply_port;
};
#define EMULATOR_STACK_SIZE (4096*4)
#define THREAD_ALLOWED_TO_BREAK(mid) mach_thread_for_breakpoint (mid)
#define THREAD_PARSE_ID(arg) mach_thread_parse_id (arg)
#define THREAD_OUTPUT_ID(mid) mach_thread_output_id (mid)
#define ATTACH_TO_THREAD attach_to_thread
/* Don't do wait_for_inferior on attach. */
#define ATTACH_NO_WAIT
/* Do Mach 3 dependent operations when ^C or a STOP is requested */
#define DO_QUIT() mach3_quit ()
#if 0
/* This is bogus. It is NOT OK to quit out of target_wait. */
/* If in mach_msg() and ^C is typed set immediate_quit */
#define REQUEST_QUIT() mach3_request_quit ()
#endif
#endif /* NM_M3_H */

View file

@ -1,86 +0,0 @@
/* Native-dependent definitions for NetBSD.
Copyright 1994, 1996 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. */
/* This is the amount to subtract from u.u_ar0
to get the offset in the core file of the register values. */
#include <machine/vmparam.h>
#define KERNEL_U_ADDR USRSTACK
#define PTRACE_ARG3_TYPE char*
#define FETCH_INFERIOR_REGISTERS
#define ATTACH_DETACH
#include "solib.h" /* Support for shared libraries. */
/* make structure definitions match up with those expected in solib.c */
#define link_object sod
#define lo_name sod_name
#define lo_library sod_library
#define lo_unused sod_reserved
#define lo_major sod_major
#define lo_minor sod_minor
#define lo_next sod_next
#define link_map so_map
#define lm_addr som_addr
#define lm_name som_path
#define lm_next som_next
#define lm_lop som_sod
#define lm_lob som_sodbase
#define lm_rwt som_write
#define lm_ld som_dynamic
#define lm_lpd som_spd
#define link_dynamic_2 section_dispatch_table
#define ld_loaded sdt_loaded
#define ld_need sdt_sods
#define ld_rules sdt_filler1
#define ld_got sdt_got
#define ld_plt sdt_plt
#define ld_rel sdt_rel
#define ld_hash sdt_hash
#define ld_stab sdt_nzlist
#define ld_stab_hash sdt_filler2
#define ld_buckets sdt_buckets
#define ld_symbols sdt_strings
#define ld_symb_size sdt_str_sz
#define ld_text sdt_text_sz
#define ld_plt_sz sdt_plt_sz
#define rtc_symb rt_symbol
#define rtc_sp rt_sp
#define rtc_next rt_next
#define ld_debug so_debug
#define ldd_version dd_version
#define ldd_in_debugger dd_in_debugger
#define ldd_sym_loaded dd_sym_loaded
#define ldd_bp_addr dd_bpt_addr
#define ldd_bp_inst dd_bpt_shadow
#define ldd_cp dd_cc
#define link_dynamic _dynamic
#define ld_version d_version
#define ldd d_debug
#define ld_un d_un
#define ld_2 d_sdt

View file

@ -1,34 +0,0 @@
/* Definitions for running gdb on a host machine running any flavor of SVR4.
Copyright 1991, 1992 Free Software Foundation, Inc.
Written by Fred Fish at Cygnus Support (fnf@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 "solib.h" /* Support for shared libraries. */
/* Use SVR4 style shared library support */
#define SVR4_SHARED_LIBS
/* SVR4 has /proc support, so use it instead of ptrace. */
#define USE_PROC_FS
/* SVR4 machines can easily do attach and detach via /proc (procfs.c)
support */
#define ATTACH_DETACH

View file

@ -1,34 +0,0 @@
/* Macro definitions for LynxOS targets.
Copyright 1993 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. */
#ifndef TM_LYNX_H
#define TM_LYNX_H
/* Override number of expected traps from sysv. */
#define START_INFERIOR_TRAPS_EXPECTED 2
#include "coff-solib.h" /* COFF shared library support */
/* Lynx's signal.h doesn't seem to have any macros for what signal numbers
the real-time events are. */
#define REALTIME_LO 33
/* One more than the last one. */
#define REALTIME_HI 64
#endif /* TM_LYNX_H */

View file

@ -1,19 +0,0 @@
/* Target machine sub-description for NetBSD.
This is included by other tm-*.h files to specify NetBSD-specific stuff.
Copyright 1993, 1994 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */

View file

@ -1,31 +0,0 @@
/* Target machine sub-description for SunOS version 4.
This is included by other tm-*.h files to specify SunOS-specific stuff.
Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "solib.h" /* Support for shared libraries. */
/* Return non-zero if we are in a shared library trampoline code stub. */
#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) \
lookup_solib_trampoline_symbol_by_pc (pc)
/* If PC is in a shared library trampoline code, return the PC
where the function itself actually starts. If not, return 0. */
#define SKIP_TRAMPOLINE_CODE(pc) find_solib_trampoline_target (pc)

View file

@ -1,45 +0,0 @@
/* Macro definitions for GDB on all SVR4 target systems.
Copyright 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
Written by Fred Fish at Cygnus Support (fnf@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. */
/* For SVR4 shared libraries, each call to a library routine goes through
a small piece of trampoline code in the ".plt" section.
The horribly ugly wait_for_inferior() routine uses this macro to detect
when we have stepped into one of these fragments.
We do not use lookup_solib_trampoline_symbol_by_pc, because
we cannot always find the shared library trampoline symbols
(e.g. on Irix5). */
#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) in_plt_section((pc), (name))
extern int in_plt_section PARAMS ((CORE_ADDR, char *));
/* If PC is in a shared library trampoline code, return the PC
where the function itself actually starts. If not, return 0. */
#define SKIP_TRAMPOLINE_CODE(pc) find_solib_trampoline_target (pc)
/* It is unknown which, if any, SVR4 assemblers do not accept dollar signs
in identifiers. The default in G++ is to use dots instead, for all SVR4
systems, so we make that our default also. FIXME: There should be some
way to get G++ to tell us what CPLUS_MARKER it is using, perhaps by
stashing it in the debugging information as part of the name of an
invented symbol ("gcc_cplus_marker$" for example). */
#undef CPLUS_MARKER
#define CPLUS_MARKER '.'

View file

@ -1,96 +0,0 @@
/* Parameters for hosting on an PowerPC, for GDB, the GNU debugger.
Copyright 1995 Free Software Foundation, Inc.
Contributed by Cygnus 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* The following text is taken from config/rs6000.mh:
* # The IBM version of /usr/include/rpc/rpc.h has a bug -- it says
* # `extern fd_set svc_fdset;' without ever defining the type fd_set.
* # Unfortunately this occurs in the vx-share code, which is not configured
* # like the rest of GDB (e.g. it doesn't include "defs.h").
* # We circumvent this bug by #define-ing fd_set here, but undefining it in
* # the xm-rs6000.h file before ordinary modules try to use it. FIXME, IBM!
* MH_CFLAGS='-Dfd_set=int'
* So, here we do the undefine...which has to occur before we include
* <sys/select.h> below.
*/
#undef fd_set
#include <sys/select.h>
/* Big end is at the low address */
#define HOST_BYTE_ORDER BIG_ENDIAN
/* At least as of AIX 3.2, we have termios. */
#define HAVE_TERMIOS 1
/* #define HAVE_TERMIO 1 */
#define USG 1
#define HAVE_SIGSETMASK 1
#define FIVE_ARG_PTRACE
/* AIX declares the mem functions differently than defs.h does. AIX is
right, but defs.h works on more old systems. For now, override it. */
#define MEM_FNS_DECLARED 1
/* This system requires that we open a terminal with O_NOCTTY for it to
not become our controlling terminal. */
#define USE_O_NOCTTY
/* Brain death inherited from PC's pervades. */
#undef NULL
#define NULL 0
/* The IBM compiler requires this in order to properly compile alloca(). */
#pragma alloca
/* There is no vfork. */
#define vfork fork
/* Signal handler for SIGWINCH `window size changed'. */
#define SIGWINCH_HANDLER aix_resizewindow
extern void aix_resizewindow ();
/* `lines_per_page' and `chars_per_line' are local to utils.c. Rectify this. */
#define SIGWINCH_HANDLER_BODY \
\
/* Respond to SIGWINCH `window size changed' signal, and reset GDB's \
window settings approproatelt. */ \
\
void \
aix_resizewindow () \
{ \
int fd = fileno (stdout); \
if (isatty (fd)) { \
int val; \
\
val = atoi (termdef (fd, 'l')); \
if (val > 0) \
lines_per_page = val; \
val = atoi (termdef (fd, 'c')); \
if (val > 0) \
chars_per_line = val; \
} \
}

View file

@ -1,22 +0,0 @@
/* Host-dependent definitions for any CPU running LynxOS.
Copyright 1993 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. */
/* for INT_MIN, to avoid "INT_MIN redefined" warnings from defs.h */
#include <limits.h>

View file

@ -1,81 +0,0 @@
/* Macro definitions for running GDB on Apple Macintoshes.
Copyright (C) 1994, 1995 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 "mpw.h"
#include "fopen-bin.h"
#include "spin.h"
#define CANT_FORK
/* Map these standard functions to versions that can do I/O in a console
window. */
#define printf hacked_printf
#define fprintf hacked_fprintf
#define vprintf hacked_vfprintf
#define fputs hacked_fputs
#define fputc hacked_fputc
#undef putc
#define putc hacked_putc
#define fflush hacked_fflush
#define fgetc hacked_fgetc
#define POSIX_UTIME
/* No declaration of strdup in MPW's string.h, oddly enough. */
char *strdup (char *s1);
/* '.' indicates drivers on the Mac, so we need a different filename. */
#define GDBINIT_FILENAME "_gdbinit"
/* Commas are more common to separate dirnames in a path on Macs. */
#define DIRNAME_SEPARATOR ','
/* This is a real crufty hack. */
#define HAVE_TERMIO
/* Addons to the basic MPW-supported signal list. */
#ifndef SIGQUIT
#define SIGQUIT (1<<6)
#endif
#ifndef SIGHUP
#define SIGHUP (1<<7)
#endif
/* If __STDC__ is on, then this definition will be missing. */
#ifndef fileno
#define fileno(p) (p)->_file
#endif
#ifndef R_OK
#define R_OK 4
#endif
extern int StandAlone;
extern int mac_app;

View file

@ -1,37 +0,0 @@
/* Host-dependent definitions for any CPU running NetBSD.
Copyright 1993, 1994 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* We have to include these files now, so that GDB will not make
competing definitions in defs.h. */
#include <limits.h>
#include <machine/endian.h>
#if BYTE_ORDER == BIG_ENDIAN
#define HOST_BYTE_ORDER BIG_ENDIAN
#else
#define HOST_BYTE_ORDER LITTLE_ENDIAN
#endif
/* NetBSD has termios facilities. */
#define HAVE_TERMIOS
#if 0
#define CC_HAS_LONG_LONG 1
#define PRINTF_HAS_LONG_LONG 1
#endif

View file

@ -1,36 +0,0 @@
/* Definitions for running gdb on a host machine running any flavor of SVR4.
Copyright 1991, 1992 Free Software Foundation, Inc.
Written by Fred Fish at Cygnus Support (fnf@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. */
/* SVR4 has termios facilities. */
#undef HAVE_TERMIO
#define HAVE_TERMIOS
/* SVR4 is a derivative of System V Release 3 (USG) */
#define USG
/* Use setpgid(0,0) to run inferior in a separate process group */
#define NEED_POSIX_SETPGID
/* We have to include these files now, so that GDB will not make
competing definitions in defs.h. */
#include <limits.h>

View file

@ -1,130 +0,0 @@
/* Machine independent GDB support for core files on systems using "regsets".
Copyright 1993-1996 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. */
/* N O T E S
This file is used by most systems that implement /proc. For these systems,
the general registers are laid out the same way in both the core file and
the gregset_p structure. The current exception to this is Irix-4.*, where
the gregset_p structure is split up into two pieces in the core file.
The general register and floating point register sets are manipulated by
separate ioctl's. This file makes the assumption that if FP0_REGNUM is
defined, then support for the floating point register set is desired,
regardless of whether or not the actual target has floating point hardware.
*/
#include "defs.h"
#include <time.h>
#ifdef HAVE_SYS_PROCFS_H
#include <sys/procfs.h>
#endif
#include <fcntl.h>
#include <errno.h>
#include "gdb_string.h"
#include "inferior.h"
#include "target.h"
#include "command.h"
#include "gdbcore.h"
/*
GLOBAL FUNCTION
fetch_core_registers -- fetch current registers from core file
SYNOPSIS
void fetch_core_registers (char *core_reg_sect,
unsigned core_reg_size,
int which, unsigned in reg_addr)
DESCRIPTION
Read the values of either the general register set (WHICH equals 0)
or the floating point register set (WHICH equals 2) from the core
file data (pointed to by CORE_REG_SECT), and update gdb's idea of
their current values. The CORE_REG_SIZE parameter is ignored.
NOTES
Use the indicated sizes to validate the gregset and fpregset
structures.
*/
static void
fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
char *core_reg_sect;
unsigned core_reg_size;
int which;
unsigned int reg_addr; /* Unused in this version */
{
#if defined (HAVE_GREGSET_T) && defined (HAVE_FPREGSET_T)
gregset_t gregset;
fpregset_t fpregset;
if (which == 0)
{
if (core_reg_size != sizeof (gregset))
{
warning ("wrong size gregset struct in core file");
}
else
{
memcpy ((char *) &gregset, core_reg_sect, sizeof (gregset));
supply_gregset (&gregset);
}
}
else if (which == 2)
{
if (core_reg_size != sizeof (fpregset))
{
warning ("wrong size fpregset struct in core file");
}
else
{
memcpy ((char *) &fpregset, core_reg_sect, sizeof (fpregset));
#if defined (FP0_REGNUM)
supply_fpregset (&fpregset);
#endif
}
}
#endif /* defined(HAVE_GREGSET_T) && defined (HAVE_FPREGSET_T) */
}
/* Register that we are able to handle ELF file formats using standard
procfs "regset" structures. */
static struct core_fns regset_core_fns =
{
bfd_target_elf_flavour,
fetch_core_registers,
NULL
};
void
_initialize_core_regset ()
{
add_core_fns (&regset_core_fns);
}

View file

@ -1,133 +0,0 @@
/* Machine independent support for Solaris 2 core files for GDB.
Copyright 1994 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 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. */
#include "defs.h"
#undef gregset_t
#undef fpregset_t
#include <time.h>
#include <sys/regset.h>
#include <sys/procfs.h>
#include <fcntl.h>
#include <errno.h>
#include "gdb_string.h"
#include "inferior.h"
#include "target.h"
#include "command.h"
#include "gdbcore.h"
static void
fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
char *core_reg_sect;
unsigned core_reg_size;
int which;
unsigned int reg_addr; /* Unused in this version */
{
prgregset_t prgregset;
prfpregset_t prfpregset;
if (which == 0)
{
if (core_reg_size == sizeof (prgregset))
{
memcpy ((char *) &prgregset, core_reg_sect, sizeof (prgregset));
supply_gregset (&prgregset);
}
else if (core_reg_size == sizeof (struct regs))
{
#define 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)
{
if (core_reg_size == sizeof (prfpregset))
{
memcpy ((char *) &prfpregset, core_reg_sect, sizeof (prfpregset));
supply_fpregset (&prfpregset);
}
else if (core_reg_size >= sizeof (struct fpu))
{
#define 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,
fetch_core_registers,
NULL
};
void
_initialize_core_solaris ()
{
add_core_fns (&solaris_core_fns);
}

View file

@ -1,171 +0,0 @@
/* Remote debugging interface for CPU32Bug Rom monitor for GDB, the GNU debugger.
Copyright 1995 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"
static void cpu32bug_open PARAMS ((char *args, int from_tty));
static void
cpu32bug_supply_register (regname, regnamelen, val, vallen)
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 *cpu32bug_regnames[NUM_REGS] =
{
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
"SR", "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 cpu32bug_ops;
static char *cpu32bug_inits[] = {"\r", NULL};
static struct monitor_ops cpu32bug_cmds =
{
MO_CLR_BREAK_USES_ADDR,
cpu32bug_inits, /* Init strings */
"g\r", /* continue command */
"t\r", /* single step */
NULL, /* interrupt command */
"br %x\r", /* set a breakpoint */
"nobr %x\r", /* clear a breakpoint */
"nobr\r", /* clear all breakpoints */
"bf %x:%x %x;b\r", /* fill (start count val) */
{
"ms %x %02x\r", /* setmem.cmdb (addr, value) */
"ms %x %04x\r", /* setmem.cmdw (addr, value) */
"ms %x %08x\r", /* setmem.cmdl (addr, value) */
NULL, /* setmem.cmdll (addr, value) */
NULL, /* setreg.resp_delim */
NULL, /* setreg.term */
NULL, /* setreg.term_cmd */
},
{
"md %x:%x;b\r", /* getmem.cmdb (addr, len) */
"md %x:%x;b\r", /* getmem.cmdw (addr, len) */
"md %x:%x;b\r", /* getmem.cmdl (addr, len) */
NULL, /* getmem.cmdll (addr, len) */
" ", /* getmem.resp_delim */
NULL, /* getmem.term */
NULL, /* getmem.term_cmd */
},
{
"rs %s %x\r", /* setreg.cmd (name, value) */
NULL, /* setreg.resp_delim */
NULL, /* setreg.term */
NULL /* setreg.term_cmd */
},
{
"rs %s\r", /* getreg.cmd (name) */
"=", /* getreg.resp_delim */
NULL, /* getreg.term */
NULL /* getreg.term_cmd */
},
"rd\r", /* dump_registers */
"\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)", /* register_pattern */
cpu32bug_supply_register, /* supply_register */
NULL, /* load_routine (defaults to SRECs) */
"lo\r", /* download command */
"lo\r\n", /* load response */
"CPU32Bug>", /* monitor command prompt */
"\r", /* end-of-line terminator */
NULL, /* optional command terminator */
&cpu32bug_ops, /* target operations */
SERIAL_1_STOPBITS, /* number of stop bits */
cpu32bug_regnames, /* registers names */
MONITOR_OPS_MAGIC /* magic */
};
static void
cpu32bug_open(args, from_tty)
char *args;
int from_tty;
{
monitor_open (args, &cpu32bug_cmds, from_tty);
}
void
_initialize_cpu32bug_rom ()
{
init_monitor_ops (&cpu32bug_ops);
cpu32bug_ops.to_shortname = "cpu32bug";
cpu32bug_ops.to_longname = "CPU32Bug monitor";
cpu32bug_ops.to_doc = "Debug via the CPU32Bug monitor.\n\
Specify the serial device it is connected to (e.g. /dev/ttya).";
cpu32bug_ops.to_open = cpu32bug_open;
add_target (&cpu32bug_ops);
}

View file

@ -1,523 +0,0 @@
/* Native support for Motorola 88k running Harris CX/UX.
Copyright 1988, 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include "gdbcore.h"
#include <sys/user.h>
#include "bfd.h"
#include "symfile.h"
#include "objfiles.h"
#include "symtab.h"
#ifndef USER /* added to support BCS ptrace_user */
#define USER ptrace_user
#endif
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/file.h>
#include "gdb_stat.h"
#include "symtab.h"
#include "setjmp.h"
#include "value.h"
#include <sys/ptrace.h>
/* CX/UX provides them already, but as word offsets instead of char offsets */
#define SXIP_OFFSET (PT_SXIP * 4)
#define SNIP_OFFSET (PT_SNIP * 4)
#define SFIP_OFFSET (PT_SFIP * 4)
#define PSR_OFFSET (PT_PSR * sizeof(int))
#define FPSR_OFFSET (PT_FPSR * sizeof(int))
#define FPCR_OFFSET (PT_FPCR * sizeof(int))
#define XREGADDR(r) (((char *)&u.pt_x0-(char *)&u) + \
((r)-X0_REGNUM)*sizeof(X_REGISTER_RAW_TYPE))
extern int have_symbol_file_p();
extern jmp_buf stack_jmp;
extern int errno;
extern char registers[REGISTER_BYTES];
void
fetch_inferior_registers (regno)
int regno; /* Original value discarded */
{
register unsigned int regaddr;
char buf[MAX_REGISTER_RAW_SIZE];
register int i;
struct USER u;
unsigned int offset;
offset = (char *) &u.pt_r0 - (char *) &u;
regaddr = offset; /* byte offset to r0;*/
/* offset = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0) - KERNEL_U_ADDR; */
for (regno = 0; regno < PC_REGNUM; regno++)
{
/*regaddr = register_addr (regno, offset);*/
/* 88k enhancement */
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
{
*(int *) &buf[i] = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) regaddr, 0);
regaddr += sizeof (int);
}
supply_register (regno, buf);
}
/* now load up registers 32-37; special pc registers */
*(int *) &buf[0] = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) PSR_OFFSET,0);
supply_register (PSR_REGNUM, buf);
*(int *) &buf[0] = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) FPSR_OFFSET,0);
supply_register (FPSR_REGNUM, buf);
*(int *) &buf[0] = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) FPCR_OFFSET,0);
supply_register (FPCR_REGNUM, buf);
*(int *) &buf[0] = ptrace (3,inferior_pid,
(PTRACE_ARG3_TYPE) SXIP_OFFSET ,0);
supply_register (SXIP_REGNUM, buf);
*(int *) &buf[0] = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) SNIP_OFFSET,0);
supply_register (SNIP_REGNUM, buf);
*(int *) &buf[0] = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) SFIP_OFFSET,0);
supply_register (SFIP_REGNUM, buf);
if (target_is_m88110)
{
for (regaddr = XREGADDR(X0_REGNUM), regno = X0_REGNUM;
regno < NUM_REGS;
regno++, regaddr += 16)
{
X_REGISTER_RAW_TYPE xval;
*(int *) &xval.w1 = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) regaddr, 0);
*(int *) &xval.w2 = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) (regaddr+4), 0);
*(int *) &xval.w3 = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) (regaddr+8), 0);
*(int *) &xval.w4 = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) (regaddr+12), 0);
supply_register(regno, (void *)&xval);
}
}
}
/* 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 (regno)
int regno;
{
register unsigned int regaddr;
char buf[80];
struct USER u;
unsigned int offset = (char *) &u.pt_r0 - (char *) &u;
regaddr = offset;
/* Don't try to deal with EXIP_REGNUM or ENIP_REGNUM, because I think either
svr3 doesn't run on an 88110, or the kernel isolates the different (not
completely sure this is true, but seems to be. */
if (regno >= 0)
{
/* regaddr = register_addr (regno, offset); */
if (regno < PC_REGNUM)
{
regaddr = offset + regno * sizeof (int);
errno = 0;
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) regaddr, read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing register number %d", regno);
perror_with_name (buf);
}
}
else if (regno == PSR_REGNUM)
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) PSR_OFFSET, read_register(regno));
else if (regno == FPSR_REGNUM)
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) FPSR_OFFSET, read_register(regno));
else if (regno == FPCR_REGNUM)
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) FPCR_OFFSET, read_register(regno));
else if (regno == SXIP_REGNUM)
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) SXIP_OFFSET, read_register(regno));
else if (regno == SNIP_REGNUM)
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) SNIP_OFFSET, read_register(regno));
else if (regno == SFIP_REGNUM)
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) SFIP_OFFSET, read_register(regno));
else if (target_is_m88110 && regno < NUM_REGS)
{
X_REGISTER_RAW_TYPE xval;
read_register_bytes(REGISTER_BYTE(regno), (char *)&xval,
sizeof(X_REGISTER_RAW_TYPE));
regaddr = XREGADDR(regno);
ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, xval.w1);
ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr+4, xval.w2);
ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr+8, xval.w3);
ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr+12, xval.w4);
}
else
printf_unfiltered ("Bad register number for store_inferior routine\n");
}
else
{
for (regno = 0; regno < PC_REGNUM; regno++)
{
/* regaddr = register_addr (regno, offset); */
errno = 0;
regaddr = offset + regno * sizeof (int);
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) regaddr, read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing register number %d", regno);
perror_with_name (buf);
}
}
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) PSR_OFFSET, read_register(regno));
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) FPSR_OFFSET,read_register(regno));
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) FPCR_OFFSET,read_register(regno));
ptrace (6,inferior_pid,
(PTRACE_ARG3_TYPE) SXIP_OFFSET,read_register(SXIP_REGNUM));
ptrace (6,inferior_pid,
(PTRACE_ARG3_TYPE) SNIP_OFFSET,read_register(SNIP_REGNUM));
ptrace (6,inferior_pid,
(PTRACE_ARG3_TYPE) SFIP_OFFSET,read_register(SFIP_REGNUM));
if (target_is_m88110)
{
for (regno = X0_REGNUM; regno < NUM_REGS; regno++)
{
X_REGISTER_RAW_TYPE xval;
read_register_bytes(REGISTER_BYTE(regno), (char *)&xval,
sizeof(X_REGISTER_RAW_TYPE));
regaddr = XREGADDR(regno);
ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, xval.w1);
ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) (regaddr+4), xval.w2);
ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) (regaddr+8), xval.w3);
ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) (regaddr+12), xval.w4);
}
}
}
}
/* blockend is the address of the end of the user structure */
m88k_register_u_addr (blockend, regnum)
int blockend, regnum;
{
struct USER u;
int ustart = blockend - sizeof (struct USER);
if (regnum < PSR_REGNUM)
return (ustart + ((int) &u.pt_r0 - (int) &u) +
REGISTER_SIZE * regnum);
else if (regnum == PSR_REGNUM)
return (ustart + ((int) &u.pt_psr) - (int) &u);
else if (regnum == FPSR_REGNUM)
return (ustart + ((int) &u.pt_fpsr) - (int) &u);
else if (regnum == FPCR_REGNUM)
return (ustart + ((int) &u.pt_fpcr) - (int) &u);
else if (regnum == SXIP_REGNUM)
return (ustart + SXIP_OFFSET);
else if (regnum == SNIP_REGNUM)
return (ustart + SNIP_OFFSET);
else if (regnum == SFIP_REGNUM)
return (ustart + SFIP_OFFSET);
else if (target_is_m88110)
return (ustart + ((int) &u.pt_x0 - (int) &u) + /* Must be X register */
sizeof(u.pt_x0) * (regnum - X0_REGNUM));
else
return (blockend + REGISTER_SIZE * regnum);
}
#ifdef USE_PROC_FS
#include <sys/procfs.h>
/* 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 (gregsetp)
gregset_t *gregsetp;
{
register int regi;
register greg_t *regp = (greg_t *) gregsetp;
for (regi=0; regi <= SP_REGNUM; regi++)
supply_register (regi, (char *) (regp + regi));
supply_register (SXIP_REGNUM, (char *) (regp + R_XIP));
supply_register (SNIP_REGNUM, (char *) (regp + R_NIP));
supply_register (SFIP_REGNUM, (char *) (regp + R_FIP));
supply_register (PSR_REGNUM, (char *) (regp + R_PSR));
supply_register (FPSR_REGNUM, (char *) (regp + R_FPSR));
supply_register (FPCR_REGNUM, (char *) (regp + R_FPCR));
}
void
fill_gregset (gregsetp, regno)
gregset_t *gregsetp;
int regno;
{
int regi;
register greg_t *regp = (greg_t *) gregsetp;
extern char registers[];
for (regi = 0 ; regi <= R_R31 ; regi++)
if ((regno == -1) || (regno == regi))
*(regp + regi) = *(int *) &registers[REGISTER_BYTE(regi)];
if ((regno == -1) || (regno == SXIP_REGNUM))
*(regp + R_XIP) = *(int *) &registers[REGISTER_BYTE(SXIP_REGNUM)];
if ((regno == -1) || (regno == SNIP_REGNUM))
*(regp + R_NIP) = *(int *) &registers[REGISTER_BYTE(SNIP_REGNUM)];
if ((regno == -1) || (regno == SFIP_REGNUM))
*(regp + R_FIP) = *(int *) &registers[REGISTER_BYTE(SFIP_REGNUM)];
if ((regno == -1) || (regno == PSR_REGNUM))
*(regp + R_PSR) = *(int *) &registers[REGISTER_BYTE(PSR_REGNUM)];
if ((regno == -1) || (regno == FPSR_REGNUM))
*(regp + R_FPSR) = *(int *) &registers[REGISTER_BYTE(FPSR_REGNUM)];
if ((regno == -1) || (regno == FPCR_REGNUM))
*(regp + R_FPCR) = *(int *) &registers[REGISTER_BYTE(FPCR_REGNUM)];
}
#endif /* USE_PROC_FS */
/* This support adds the equivalent of adb's % command. When
the `add-shared-symbol-files' command is given, this routine scans
the dynamic linker's link map and reads the minimal symbols
from each shared object file listed in the map. */
struct link_map {
unsigned long l_addr; /* address at which object is mapped */
char *l_name; /* full name of loaded object */
void *l_ld; /* dynamic structure of object */
struct link_map *l_next; /* next link object */
struct link_map *l_prev; /* previous link object */
};
#define LINKS_MAP_POINTER "_ld_tail"
#define LIBC_FILE "/usr/lib/libc.so.1"
#define SHARED_OFFSET 0xf0001000
#ifndef PATH_MAX
#define PATH_MAX 1023 /* maximum size of path name on OS */
#endif
void
add_shared_symbol_files ()
{
void *desc;
struct link_map *ld_map, *lm, lms;
struct minimal_symbol *minsym;
struct objfile *objfile;
char *path_name;
if (! inferior_pid)
{
warning ("The program has not yet been started.");
return;
}
objfile = symbol_file_add (LIBC_FILE, 0, 0, 0, 0, 1);
minsym = lookup_minimal_symbol (LINKS_MAP_POINTER, objfile);
ld_map = (struct link_map *)
read_memory_integer (((int)SYMBOL_VALUE_ADDRESS(minsym) + SHARED_OFFSET), 4);
lm = ld_map;
while (lm)
{
int local_errno = 0;
read_memory ((CORE_ADDR)lm, (char*)&lms, sizeof (struct link_map));
if (lms.l_name)
{
if (target_read_string ((CORE_ADDR)lms.l_name, &path_name,
PATH_MAX, &local_errno))
{
symbol_file_add (path_name, 1, lms.l_addr, 0, 0, 0);
free(path_name);
}
}
/* traverse links in reverse order so that we get the
the symbols the user actually gets. */
lm = lms.l_prev;
}
/* Getting new symbols may change our opinion about what is
frameless. */
reinit_frame_cache ();
}
#if defined(_ES_MP)
#include <sys/regset.h>
unsigned int
m88k_harris_core_register_addr (regno, reg_ptr)
int regno, reg_ptr;
{
unsigned int word_offset;
switch (regno)
{
case PSR_REGNUM:
word_offset = R_EPSR;
break;
case FPSR_REGNUM:
word_offset = R_FPSR;
break;
case FPCR_REGNUM:
word_offset = R_FPCR;
break;
case SXIP_REGNUM:
word_offset = R_EXIP;
break;
case SNIP_REGNUM:
word_offset = R_ENIP;
break;
case SFIP_REGNUM:
word_offset = R_EFIP;
break;
default:
if (regno <= FP_REGNUM)
word_offset = regno;
else
word_offset = ((regno - X0_REGNUM) * 4);
}
return (word_offset * 4);
}
#endif /* _ES_MP */
void
_initialize_m88k_nat()
{
#ifdef _ES_MP
/* Enable 88110 support, as we don't support the 88100 under ES/MP. */
target_is_m88110 = 1;
#elif defined(_CX_UX)
/* Determine whether we're running on an 88100 or an 88110. */
target_is_m88110 = (sinfo(SYSMACHINE,0) == SYS5800);
#endif /* _CX_UX */
}
#ifdef _ES_MP
/* 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 (gregsetp)
gregset_t *gregsetp;
{
register int regi;
register greg_t *regp = (greg_t *) gregsetp;
for (regi = 0 ; regi < R_R31 ; regi++)
{
supply_register (regi, (char *) (regp + regi));
}
supply_register (PSR_REGNUM, (char *) (regp + R_EPSR));
supply_register (FPSR_REGNUM, (char *) (regp + R_FPSR));
supply_register (FPCR_REGNUM, (char *) (regp + R_FPCR));
supply_register (SXIP_REGNUM, (char *) (regp + R_EXIP));
supply_register (SNIP_REGNUM, (char *) (regp + R_ENIP));
supply_register (SFIP_REGNUM, (char *) (regp + R_EFIP));
}
/* 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. */
void
supply_fpregset (fpregsetp)
fpregset_t *fpregsetp;
{
register int regi;
char *from;
for (regi = FP0_REGNUM ; regi <= FPLAST_REGNUM ; regi++)
{
from = (char *) &((*fpregsetp)[regi-FP0_REGNUM]);
supply_register (regi, from);
}
}
#endif /* _ES_MP */
#ifdef _CX_UX
#include <sys/regset.h>
unsigned int m88k_harris_core_register_addr(int regno, int reg_ptr)
{
unsigned int word_offset;
switch (regno) {
case PSR_REGNUM : word_offset = R_PSR; break;
case FPSR_REGNUM : word_offset = R_FPSR; break;
case FPCR_REGNUM : word_offset = R_FPCR; break;
case SXIP_REGNUM : word_offset = R_XIP; break;
case SNIP_REGNUM : word_offset = R_NIP; break;
case SFIP_REGNUM : word_offset = R_FIP; break;
default :
if (regno <= FP_REGNUM)
word_offset = regno;
else
word_offset = ((regno - X0_REGNUM) * 4) + R_X0;
}
return (word_offset * 4);
}
#endif /* _CX_UX */

File diff suppressed because it is too large Load diff

View file

@ -1,91 +0,0 @@
/* Common things used by the various *gnu-nat.c files
Copyright (C) 1995 Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.ai.mit.edu>
The GNU Hurd 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, or (at
your option) any later version.
The GNU Hurd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef __GNU_NAT_H__
#define __GNU_NAT_H__
#include <unistd.h>
#include <mach.h>
struct inf;
extern struct inf *current_inferior;
/* Converts a GDB pid to a struct proc. */
struct proc *inf_tid_to_thread (struct inf *inf, int tid);
/* A proc is either a thread, or the task (there can only be one task proc
because it always has the same TID, PROC_TID_TASK). */
struct proc
{
thread_t port; /* The task or thread port. */
int tid; /* The GDB pid (actually a thread id). */
int num; /* An id number for threads, to print. */
mach_port_t saved_exc_port; /* The task/thread's real exception port. */
mach_port_t exc_port; /* Our replacement, which for. */
int sc; /* Desired suspend count. */
int cur_sc; /* Implemented suspend count. */
int run_sc; /* Default sc when the program is running. */
int pause_sc; /* Default sc when gdb has control. */
int resume_sc; /* Sc resulting form the last resume. */
thread_state_data_t state; /* Registers, &c. */
int state_valid : 1; /* True if STATE is up to date. */
int state_changed : 1;
int aborted : 1; /* True if thread_abort has been called. */
/* Bit mask of registers fetched by gdb. This is used when we re-fetch
STATE after aborting the thread, to detect that gdb may have out-of-date
information. */
unsigned long fetched_regs;
struct inf *inf; /* Where we come from. */
struct proc *next;
};
/* The task has a thread entry with this TID. */
#define PROC_TID_TASK (-1)
#define proc_is_task(proc) ((proc)->tid == PROC_TID_TASK)
#define proc_is_thread(proc) ((proc)->tid != PROC_TID_TASK)
extern int __proc_pid (struct proc *proc);
extern thread_state_t proc_get_state (struct proc *proc, int will_modify);
#define proc_debug(_proc, msg, args...) \
do { struct proc *__proc = (_proc); \
debug ("{proc %d/%d %p}: " msg, \
__proc_pid (__proc), __proc->tid, __proc , ##args); } while (0)
#if MAINTENANCE_CMDS
extern int gnu_debug_flag;
#define debug(msg, args...) \
do { if (gnu_debug_flag) \
fprintf (stderr, "%s: " msg "\r\n", __FUNCTION__ , ##args); } while (0)
#else
#define debug(msg, args...) (void)0
#endif
#endif /* __GNU_NAT_H__ */

View file

@ -1,35 +0,0 @@
/* Host-dependent code for dos running GO32 for GDB, the GNU debugger.
Copyright 1992 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>
int
sigsetmask (mask)
int mask;
{
return 0;
}
void
strlwr (str)
char *str;
{
for (; *str; str++)
*str = tolower(*str);
}

View file

@ -1,915 +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.
* Also, need to assign exceptionHook and oldExceptionHook.
*
* 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
*/
typedef void (*ExceptionHook)(int); /* pointer to function with int parm */
typedef void (*Function)(); /* pointer to a function */
extern putDebugChar(); /* write a single character */
extern getDebugChar(); /* read and return a single char */
extern Function exceptionHandler(); /* assign an exception handler */
extern ExceptionHook exceptionHook; /* hook variable for errors/exceptions */
/************************************************************************/
/* 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 */
void waitabit();
static const char hexchars[]="0123456789abcdef";
/* Number of bytes of registers. */
#define NUMREGBYTES 64
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[NUMREGBYTES/4];
#define STACKSIZE 10000
int remcomStack[STACKSIZE/sizeof(int)];
static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
/*
* In many cases, the system will want to continue exception processing
* when a continue command is given.
* oldExceptionHook is a function to invoke in this case.
*/
static ExceptionHook oldExceptionHook;
/*************************** 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);
}
/* scan for the sequence $<data>#<checksum> */
void getpacket(buffer)
char * buffer;
{
unsigned char checksum;
unsigned char xmitcsum;
int i;
int count;
char ch;
do {
/* wait around for the start character, ignore all other characters */
while ((ch = (getDebugChar() & 0x7f)) != '$');
checksum = 0;
xmitcsum = -1;
count = 0;
/* now, read until a # or end of buffer is found */
while (count < BUFMAX) {
ch = getDebugChar() & 0x7f;
if (ch == '#') break;
checksum = checksum + ch;
buffer[count] = ch;
count = count + 1;
}
buffer[count] = 0;
if (ch == '#') {
xmitcsum = hex(getDebugChar() & 0x7f) << 4;
xmitcsum += hex(getDebugChar() & 0x7f);
if ((remote_debug ) && (checksum != xmitcsum)) {
fprintf (stderr ,"bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
checksum,xmitcsum,buffer);
}
if (checksum != xmitcsum) 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] );
/* remove sequence chars from buffer */
count = strlen(buffer);
for (i=3; i <= count; i++) buffer[i-3] = buffer[i];
}
}
}
} while (checksum != xmitcsum);
}
/* send the packet in buffer. */
void putpacket(buffer)
char * buffer;
{
unsigned char checksum;
int count;
char ch;
/* $<packet info>#<checksum>. */
do {
putDebugChar('$');
checksum = 0;
count = 0;
while (ch=buffer[count]) {
if (! putDebugChar(ch)) return;
checksum += ch;
count += 1;
}
putDebugChar('#');
putDebugChar(hexchars[checksum >> 4]);
putDebugChar(hexchars[checksum % 16]);
} while ((getDebugChar() & 0x7f) != '+');
}
char remcomInBuffer[BUFMAX];
char remcomOutBuffer[BUFMAX];
static short error;
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 ()
{
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 (addr)
char *addr;
{
return *addr;
}
void
set_char (addr, val)
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( exceptionVector )
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;
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 );
remcomOutBuffer[0] = 'S';
remcomOutBuffer[1] = hexchars[sigval >> 4];
remcomOutBuffer[2] = hexchars[sigval % 16];
remcomOutBuffer[3] = 0;
putpacket(remcomOutBuffer);
while (1==1) {
error = 0;
remcomOutBuffer[0] = 0;
getpacket(remcomInBuffer);
switch (remcomInBuffer[0]) {
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(&remcomInBuffer[1], (char*) registers, NUMREGBYTES, 0);
strcpy(remcomOutBuffer,"OK");
break;
/* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
case 'm' :
/* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
ptr = &remcomInBuffer[1];
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");
debug_error("malformed read memory command: %s",remcomInBuffer);
}
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 */
ptr = &remcomInBuffer[1];
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");
debug_error("malformed write memory command: %s",remcomInBuffer);
}
break;
/* cAA..AA Continue at address AA..AA(optional) */
/* sAA..AA Step one instruction from AA..AA(optional) */
case 'c' :
case 's' :
/* try to read optional parameter, pc unchanged if no parm */
ptr = &remcomInBuffer[1];
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 (remcomInBuffer[0] == 's') registers[ PS ] |= 0x100;
/*
* If we found a match for the PC AND we are not returning
* as a result of a breakpoint (33),
* trace exception (9), nmi (31), jmp to
* the old exception handler as if this code never ran.
*/
#if 0
/* Don't really think we need this, except maybe for protection
exceptions. */
/*
* invoke the previous handler.
*/
if (oldExceptionHook)
(*oldExceptionHook) (frame->exceptionVector);
newPC = registers[ PC ]; /* pc may have changed */
#endif /* 0 */
_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()
{
extern void remcomHandler();
int exception;
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);
if (exceptionHook != remcomHandler)
{
oldExceptionHook = exceptionHook;
exceptionHook = remcomHandler;
}
/* In case GDB is started before us, ack any packets (presumably
"$?#xx") sitting there. */
putDebugChar ('+');
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()
{
if (initialized)
#if 0
handle_exception(3);
#else
BREAKPOINT();
#endif
waitabit();
}
int waitlimit = 1000000;
#if 0
void
bogon()
{
waitabit();
}
#endif
void
waitabit()
{
int i;
for (i = 0; i < waitlimit; i++) ;
}

View file

@ -1,360 +0,0 @@
/* Intel 386 native support.
Copyright (C) 1988, 1989, 1991, 1992 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"
#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;
#ifndef NO_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,
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 (blockend, regnum)
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 (status, ep)
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 ()
{
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 (inferior_pid)
{
char buf[10];
unsigned short status;
ptrace (PT_READ_FPR, inferior_pid, 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 (inferior_pid)
{
int offset;
for (offset = 0; offset < sizeof(fps); offset += 10)
{
char buf[10];
ptrace (PT_READ_FPR, inferior_pid, 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 (regno)
int regno;
{
char buf[MAX_REGISTER_RAW_SIZE];
if (regno < FP0_REGNUM)
*(int *)buf = ptrace (PT_READ_GPR, inferior_pid,
PT_REG(regmap[regno]), 0, 0);
else
ptrace (PT_READ_FPR, inferior_pid, buf,
(regno - FP0_REGNUM)*10 + offsetof(struct env387, regs));
supply_register (regno, buf);
}
void
fetch_inferior_registers (regno)
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 (regno)
int regno;
{
char buf[80];
extern char registers[];
errno = 0;
if (regno < FP0_REGNUM)
ptrace (PT_WRITE_GPR, inferior_pid, PT_REG(regmap[regno]),
*(int *) &registers[REGISTER_BYTE (regno)], 0);
else
ptrace (PT_WRITE_FPR, inferior_pid, &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 (regno)
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,
};
static void
fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
char *core_reg_sect;
unsigned core_reg_size;
int which;
unsigned int reg_addr; /* ignored */
{
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,
fetch_core_registers,
NULL
};
void
_initialize_core_i386aix ()
{
add_core_fns (&i386aix_core_fns);
}

View file

@ -1,348 +0,0 @@
/* Low level interface to I386 running the GNU Hurd
Copyright (C) 1992 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 <stdio.h>
#include <mach.h>
#include <mach/message.h>
#include <mach/exception.h>
#include <mach_error.h>
#include "gnu-nat.h"
/* Hmmm... Should this not be here?
* Now for i386_float_info() target_has_execution
*/
#include <target.h>
/* @@@ Should move print_387_status() to i387-tdep.c */
extern void print_387_control_word (); /* i387-tdep.h */
extern void print_387_status_word ();
/* 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_ADDR(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_ADDR (state, regnum), \
count * REGISTER_RAW_SIZE (regnum))
/* Store COUNT contiguous registers to thread STATE starting from REGNUM */
#define STORE_REGS(state, regnum, count) \
memcpy (REG_ADDR (state, regnum), \
&registers[REGISTER_BYTE (regnum)], \
count * REGISTER_RAW_SIZE (regnum))
/*
* Fetch inferiors registers for gdb.
* REG specifies which (as gdb views it) register, -1 for all.
*/
void
gnu_fetch_registers (int reg)
{
thread_state_t state;
struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid);
if (!thread)
error ("fetch inferior registers: %d: Invalid thread", inferior_pid);
state = proc_get_state (thread, 0);
if (! state)
warning ("Couldn't fetch register %s.", reg_names[reg]);
else if (reg >= 0)
{
proc_debug (thread, "fetching register: %s", reg_names[reg]);
supply_register (reg, REG_ADDR(state, reg));
thread->fetched_regs |= (1 << reg);
}
else
{
proc_debug (thread, "fetching all registers");
for (reg = 0; reg < NUM_REGS; reg++)
supply_register (reg, REG_ADDR(state, reg));
thread->fetched_regs = ~0;
}
}
/* Store our register values back into the inferior.
* If REG is -1, do this for all registers.
* Otherwise, REG specifies which register
*
* On mach3 all registers are always saved in one call.
*/
void
gnu_store_registers (reg)
int reg;
{
int was_aborted, was_valid;
thread_state_t state;
thread_state_data_t old_state;
struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid);
if (! thread)
error ("store inferior registers: %d: Invalid thread", inferior_pid);
proc_debug (thread, "storing register %s.", reg_names[reg]);
was_aborted = thread->aborted;
was_valid = thread->state_valid;
if (! was_aborted && was_valid)
bcopy (&thread->state, &old_state, sizeof (old_state));
state = proc_get_state (thread, 1);
if (! state)
warning ("Couldn't store register %s.", reg_names[reg]);
else
{
if (! was_aborted && was_valid)
/* See which registers have changed after aborting the thread. */
{
int check_reg;
for (check_reg = 0; check_reg < NUM_REGS; check_reg++)
if ((thread->fetched_regs & (1 << check_reg))
&& bcmp (REG_ADDR (&old_state, check_reg),
REG_ADDR (state, check_reg),
REGISTER_RAW_SIZE (check_reg)))
/* Register CHECK_REG has changed! Ack! */
{
warning ("Register %s changed after thread was aborted.",
reg_names [check_reg]);
if (reg >= 0 && reg != check_reg)
/* Update gdb's copy of the register. */
supply_register (check_reg, REG_ADDR (state, check_reg));
else
warning ("... also writing this register! Suspicious...");
}
}
if (reg >= 0)
{
proc_debug (thread, "storing register: %s", reg_names[reg]);
STORE_REGS (state, reg, 1);
}
else
{
proc_debug (thread, "storing all registers");
for (reg = 0; reg < NUM_REGS; reg++)
STORE_REGS (state, reg, 1);
}
}
}
/* 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
*/
static
print_387_status (status, ep)
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.
*/
static int
get_i387_state (fstate)
struct fpstate *fstate;
{
error_t err;
thread_state_data_t state;
unsigned int fsCnt = i386_FLOAT_STATE_COUNT;
struct i386_float_state *fsp;
struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid);
if (!thread)
error ("get_i387_state: Invalid thread");
proc_abort (thread, 0); /* Make sure THREAD's in a reasonable state. */
err = thread_get_state (thread->port, i386_FLOAT_STATE, state, &fsCnt);
if (err)
{
warning ("Can not get live floating point state: %s",
mach_error_string (err));
return 0;
}
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 0;
/* 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 1;
}
/*
* This is called by "info float" command
*/
void
i386_mach3_float_info()
{
char buf [sizeof (struct fpstate) + 2 * sizeof (int)];
int valid = 0;
fpstate_t fps;
if (target_has_execution)
valid = get_i387_state (buf);
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,42 +0,0 @@
/* Target-dependent code for Intel 386 running LynxOS.
Copyright 1993 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"
/* 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 (frame)
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,421 +0,0 @@
/* Low level interface to I386 running mach 3.0.
Copyright (C) 1992 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 <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 (regno)
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 (regno)
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)
*/
unsigned int
register_addr (regno, blockend)
int regno;
int blockend;
{
unsigned int 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 (status, ep)
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 (fstate)
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 (fstate)
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()
{
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,163 +0,0 @@
/* Native dependent code for Mach 386's for GDB, the GNU debugger.
Copyright (C) 1986, 1987, 1989, 1991, 1992 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 <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>
void
fetch_inferior_registers (regno)
int regno; /* Original value discarded */
{
struct regs inferior_registers;
struct fp_state inferior_fp_registers;
extern char registers[];
registers_fetched ();
ptrace (PTRACE_GETREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_registers);
ptrace (PTRACE_GETFPREGS, inferior_pid,
(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 (regno)
int regno;
{
struct regs inferior_registers;
struct fp_state inferior_fp_registers;
extern char 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, inferior_pid,
(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, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_registers);
ptrace (PTRACE_POKEDATA, inferior_pid, (PTRACE_ARG3_TYPE) stack, 0xc589);
ptrace (PTRACE_SINGLESTEP, inferior_pid, (PTRACE_ARG3_TYPE) stack, 0);
wait (0);
ptrace (PTRACE_POKEDATA, inferior_pid, (PTRACE_ARG3_TYPE) stack, stuff);
inferior_registers.r_reg[EAX] = reg;
}
#endif
ptrace (PTRACE_SETREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_registers);
ptrace (PTRACE_SETFPREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_fp_registers);
}
/* Work with core files, for GDB. */
static void
fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
char *core_reg_sect;
unsigned core_reg_size;
int which;
unsigned int reg_addr; /* Unused in this version */
{
int val;
extern char registers[];
switch (which) {
case 0:
case 1:
memcpy (registers, core_reg_sect, core_reg_size);
break;
case 2:
#ifdef FP0_REGNUM
memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)],
core_reg_sect,
core_reg_size); /* FIXME, probably bogus */
#endif
#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,
fetch_core_registers,
NULL
};
void
_initialize_core_i386mach ()
{
add_core_fns (&i386mach_core_fns);
}

View file

@ -1,371 +0,0 @@
/* Intel 386 native support for SYSV systems (pre-SVR4).
Copyright (C) 1988, 1989, 1991, 1992, 1994, 1996 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"
#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>
#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
#include <sys/debugreg.h>
#endif
#include <sys/file.h>
#include "gdb_stat.h"
#ifndef NO_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 (blockend, regnum)
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 ()
{
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 PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
int));
static int
i386_insert_nonaligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
int));
/* Insert a watchpoint. */
int
i386_insert_watchpoint (pid, addr, len, rw)
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 (pid, waddr, addr, len, rw)
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 : 0) | ((rw & 2) ? DR_RW_WRITE : 0);
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 (pid, waddr, addr, len, rw)
int pid;
CORE_ADDR waddr;
CORE_ADDR addr;
int len;
int rw;
{
int align;
int size;
int rv;
static int size_try_array[16] = {
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 = (len > 4) ? 3 : len - 1;
size = size_try_array[size * 4 + 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 (pid, addr, len)
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 (pid)
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 */
#if 0
/* using FLOAT_INFO as is would be a problem. FLOAT_INFO is called
via a command xxx and eventually calls ptrace without ever having
traversed the target vector. This would be terribly impolite
behaviour for a sun4 hosted remote gdb.
A fix might be to move this code into the "info registers" command.
rich@cygnus.com 15 Sept 92. */
i386_float_info ()
{
struct user u; /* just for address computations */
int i;
/* fpstate defined in <sys/user.h> */
struct fpstate *fpstatep;
char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
unsigned int uaddr;
char fpvalid = 0;
unsigned int rounded_addr;
unsigned int rounded_size;
extern int corechan;
int skip;
uaddr = (char *)&u.u_fpvalid - (char *)&u;
if (target_has_execution)
{
unsigned int data;
unsigned int mask;
rounded_addr = uaddr & -sizeof (int);
data = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) rounded_addr, 0);
mask = 0xff << ((uaddr - rounded_addr) * 8);
fpvalid = ((data & mask) != 0);
}
#if 0
else
{
if (lseek (corechan, uaddr, 0) < 0)
perror ("seek on core file");
if (myread (corechan, &fpvalid, 1) < 0)
perror ("read on core file");
}
#endif /* no core support yet */
if (fpvalid == 0)
{
printf_unfiltered ("no floating point status saved\n");
return;
}
uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
if (target_has_execution)
{
int *ip;
rounded_addr = uaddr & -sizeof (int);
rounded_size = (((uaddr + sizeof (struct fpstate)) - uaddr) +
sizeof (int) - 1) / sizeof (int);
skip = uaddr - rounded_addr;
ip = (int *)buf;
for (i = 0; i < rounded_size; i++)
{
*ip++ = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) rounded_addr, 0);
rounded_addr += sizeof (int);
}
}
#if 0
else
{
if (lseek (corechan, uaddr, 0) < 0)
perror_with_name ("seek on core file");
if (myread (corechan, buf, sizeof (struct fpstate)) < 0)
perror_with_name ("read from core file");
skip = 0;
}
#endif /* 0 */
fpstatep = (struct fpstate *)(buf + skip);
print_387_status (fpstatep->status, (struct env387 *)fpstatep->state);
}
#endif /* never */

View file

@ -1,163 +0,0 @@
/* Native-dependent code for SVR4 Unix running on i386's, for GDB.
Copyright 1988, 1989, 1991, 1992, 1996 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_SYS_PROCFS_H
#include <sys/procfs.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,
};
/* 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 (gregsetp)
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 (gregsetp, regno)
gregset_t *gregsetp;
int regno;
{
int regi;
register greg_t *regp = (greg_t *) gregsetp;
extern char registers[];
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 (FP0_REGNUM) && 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. */
void
supply_fpregset (fpregsetp)
fpregset_t *fpregsetp;
{
register int regi;
/* FIXME: see m68k-tdep.c for an example, for the m68k. */
}
/* 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 (fpregsetp, regno)
fpregset_t *fpregsetp;
int regno;
{
int regi;
char *to;
char *from;
extern char registers[];
/* FIXME: see m68k-tdep.c for an example, for the m68k. */
}
#endif /* defined (FP0_REGNUM) && defined (HAVE_FPREGSET_T) */
#endif /* HAVE_SYS_PROCFS_H */

View file

@ -1,192 +0,0 @@
/* Native support for the SGI Iris running IRIX version 4, for GDB.
Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1995
Free Software Foundation, Inc.
Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
Implemented for Irix 4.x by Garrett A. Wollman.
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 <sys/time.h>
#include <sys/procfs.h>
#include <setjmp.h> /* For JB_XXX. */
/* Size of elements in jmpbuf */
#define JB_ELEMENT_SIZE 4
typedef unsigned int greg_t; /* why isn't this defined? */
/*
* See the comment in m68k-tdep.c regarding the utility of these functions.
*/
void
supply_gregset (gregsetp)
gregset_t *gregsetp;
{
register int regi;
register greg_t *regp = (greg_t *)(gregsetp->gp_regs);
static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
/* FIXME: somewhere, there should be a #define for the meaning
of this magic number 32; we should use that. */
for(regi = 0; regi < 32; regi++)
supply_register (regi, (char *)(regp + regi));
supply_register (PC_REGNUM, (char *)&(gregsetp->gp_pc));
supply_register (HI_REGNUM, (char *)&(gregsetp->gp_mdhi));
supply_register (LO_REGNUM, (char *)&(gregsetp->gp_mdlo));
supply_register (CAUSE_REGNUM, (char *)&(gregsetp->gp_cause));
/* Fill inaccessible registers with zero. */
supply_register (BADVADDR_REGNUM, zerobuf);
}
void
fill_gregset (gregsetp, regno)
gregset_t *gregsetp;
int regno;
{
int regi;
register greg_t *regp = (greg_t *)(gregsetp->gp_regs);
/* same FIXME as above wrt 32*/
for (regi = 0; regi < 32; regi++)
if ((regno == -1) || (regno == regi))
*(regp + regi) = *(greg_t *) &registers[REGISTER_BYTE (regi)];
if ((regno == -1) || (regno == PC_REGNUM))
gregsetp->gp_pc = *(greg_t *) &registers[REGISTER_BYTE (PC_REGNUM)];
if ((regno == -1) || (regno == CAUSE_REGNUM))
gregsetp->gp_cause = *(greg_t *) &registers[REGISTER_BYTE (CAUSE_REGNUM)];
if ((regno == -1) || (regno == HI_REGNUM))
gregsetp->gp_mdhi = *(greg_t *) &registers[REGISTER_BYTE (HI_REGNUM)];
if ((regno == -1) || (regno == LO_REGNUM))
gregsetp->gp_mdlo = *(greg_t *) &registers[REGISTER_BYTE (LO_REGNUM)];
}
/*
* Now we do the same thing for floating-point registers.
* We don't bother to condition on FP0_REGNUM since any
* reasonable MIPS configuration has an R3010 in it.
*
* Again, see the comments in m68k-tdep.c.
*/
void
supply_fpregset (fpregsetp)
fpregset_t *fpregsetp;
{
register int regi;
static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
for (regi = 0; regi < 32; regi++)
supply_register (FP0_REGNUM + regi,
(char *)&fpregsetp->fp_r.fp_regs[regi]);
supply_register (FCRCS_REGNUM, (char *)&fpregsetp->fp_csr);
/* FIXME: how can we supply FCRIR_REGNUM? SGI doesn't tell us. */
supply_register (FCRIR_REGNUM, zerobuf);
}
void
fill_fpregset (fpregsetp, regno)
fpregset_t *fpregsetp;
int regno;
{
int regi;
char *from, *to;
for (regi = FP0_REGNUM; regi < FP0_REGNUM + 32; regi++)
{
if ((regno == -1) || (regno == regi))
{
from = (char *) &registers[REGISTER_BYTE (regi)];
to = (char *) &(fpregsetp->fp_r.fp_regs[regi - FP0_REGNUM]);
memcpy(to, from, REGISTER_RAW_SIZE (regi));
}
}
if ((regno == -1) || (regno == FCRCS_REGNUM))
fpregsetp->fp_csr = *(unsigned *) &registers[REGISTER_BYTE(FCRCS_REGNUM)];
}
/* Figure out where the longjmp will land.
We expect the first arg to be a pointer to the jmp_buf structure from which
we extract the pc (JB_PC) that we will land at. The pc is copied into PC.
This routine returns true on success. */
int
get_longjmp_target (pc)
CORE_ADDR *pc;
{
char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
CORE_ADDR jb_addr;
jb_addr = read_register (A0_REGNUM);
if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
TARGET_PTR_BIT / TARGET_CHAR_BIT))
return 0;
*pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
return 1;
}
static void
fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
char *core_reg_sect;
unsigned core_reg_size;
int which; /* Unused */
unsigned int reg_addr; /* Unused */
{
if (core_reg_size != REGISTER_BYTES)
{
warning ("wrong size gregset struct in core file");
return;
}
memcpy ((char *)registers, core_reg_sect, core_reg_size);
}
/* Register that we are able to handle irix4 core file formats.
FIXME: is this really bfd_target_unknown_flavour? */
static struct core_fns irix4_core_fns =
{
bfd_target_unknown_flavour,
fetch_core_registers,
NULL
};
void
_initialize_core_irix4 ()
{
add_core_fns (&irix4_core_fns);
}

File diff suppressed because it is too large Load diff

View file

@ -1,20 +0,0 @@
/* Copyright (C) 1993 Free Software Foundation, Inc.
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 <machine/reg.h>
int rloc[] = {
R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, FP, SP, PS, PC
};

View file

@ -1,35 +0,0 @@
/* Main loop for the standalone kernel debugger, for GDB, the GNU Debugger.
Copyright 1989, 1991, 1992 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"
static char *args[] = {"kdb", "kdb-symbols", 0};
static char *environment[] = {0};
char **environ;
start ()
{
INIT_STACK (kdb_stack_beg, kdb_stack_end);
environ = environment;
main (2, args, environment);
}

View file

@ -1,838 +0,0 @@
/* Native-dependent code for LynxOS.
Copyright 1993, 1994 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include "target.h"
#include "gdbcore.h"
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/fpp.h>
static unsigned long registers_addr PARAMS ((int pid));
#define X(ENTRY)(offsetof(struct econtext, ENTRY))
#ifdef I386
/* Mappings from tm-i386v.h */
static int regmap[] =
{
X(eax),
X(ecx),
X(edx),
X(ebx),
X(esp), /* sp */
X(ebp), /* fp */
X(esi),
X(edi),
X(eip), /* pc */
X(flags), /* ps */
X(cs),
X(ss),
X(ds),
X(es),
X(ecode), /* Lynx doesn't give us either fs or gs, so */
X(fault), /* we just substitute these two in the hopes
that they are useful. */
};
#endif /* I386 */
#ifdef M68K
/* Mappings from tm-m68k.h */
static int regmap[] =
{
X(regs[0]), /* d0 */
X(regs[1]), /* d1 */
X(regs[2]), /* d2 */
X(regs[3]), /* d3 */
X(regs[4]), /* d4 */
X(regs[5]), /* d5 */
X(regs[6]), /* d6 */
X(regs[7]), /* d7 */
X(regs[8]), /* a0 */
X(regs[9]), /* a1 */
X(regs[10]), /* a2 */
X(regs[11]), /* a3 */
X(regs[12]), /* a4 */
X(regs[13]), /* a5 */
X(regs[14]), /* fp */
offsetof (st_t, usp) - offsetof (st_t, ec), /* sp */
X(status), /* ps */
X(pc),
X(fregs[0*3]), /* fp0 */
X(fregs[1*3]), /* fp1 */
X(fregs[2*3]), /* fp2 */
X(fregs[3*3]), /* fp3 */
X(fregs[4*3]), /* fp4 */
X(fregs[5*3]), /* fp5 */
X(fregs[6*3]), /* fp6 */
X(fregs[7*3]), /* fp7 */
X(fcregs[0]), /* fpcontrol */
X(fcregs[1]), /* fpstatus */
X(fcregs[2]), /* fpiaddr */
X(ssw), /* fpcode */
X(fault), /* fpflags */
};
#endif /* M68K */
#ifdef SPARC
/* Mappings from tm-sparc.h */
#define FX(ENTRY)(offsetof(struct fcontext, ENTRY))
static int regmap[] =
{
-1, /* g0 */
X(g1),
X(g2),
X(g3),
X(g4),
-1, /* g5->g7 aren't saved by Lynx */
-1,
-1,
X(o[0]),
X(o[1]),
X(o[2]),
X(o[3]),
X(o[4]),
X(o[5]),
X(o[6]), /* sp */
X(o[7]), /* ra */
-1,-1,-1,-1,-1,-1,-1,-1, /* l0 -> l7 */
-1,-1,-1,-1,-1,-1,-1,-1, /* i0 -> i7 */
FX(f.fregs[0]), /* f0 */
FX(f.fregs[1]),
FX(f.fregs[2]),
FX(f.fregs[3]),
FX(f.fregs[4]),
FX(f.fregs[5]),
FX(f.fregs[6]),
FX(f.fregs[7]),
FX(f.fregs[8]),
FX(f.fregs[9]),
FX(f.fregs[10]),
FX(f.fregs[11]),
FX(f.fregs[12]),
FX(f.fregs[13]),
FX(f.fregs[14]),
FX(f.fregs[15]),
FX(f.fregs[16]),
FX(f.fregs[17]),
FX(f.fregs[18]),
FX(f.fregs[19]),
FX(f.fregs[20]),
FX(f.fregs[21]),
FX(f.fregs[22]),
FX(f.fregs[23]),
FX(f.fregs[24]),
FX(f.fregs[25]),
FX(f.fregs[26]),
FX(f.fregs[27]),
FX(f.fregs[28]),
FX(f.fregs[29]),
FX(f.fregs[30]),
FX(f.fregs[31]),
X(y),
X(psr),
X(wim),
X(tbr),
X(pc),
X(npc),
FX(fsr), /* fpsr */
-1, /* cpsr */
};
#endif /* SPARC */
#ifdef rs6000
static int regmap[] =
{
X(iregs[0]), /* r0 */
X(iregs[1]),
X(iregs[2]),
X(iregs[3]),
X(iregs[4]),
X(iregs[5]),
X(iregs[6]),
X(iregs[7]),
X(iregs[8]),
X(iregs[9]),
X(iregs[10]),
X(iregs[11]),
X(iregs[12]),
X(iregs[13]),
X(iregs[14]),
X(iregs[15]),
X(iregs[16]),
X(iregs[17]),
X(iregs[18]),
X(iregs[19]),
X(iregs[20]),
X(iregs[21]),
X(iregs[22]),
X(iregs[23]),
X(iregs[24]),
X(iregs[25]),
X(iregs[26]),
X(iregs[27]),
X(iregs[28]),
X(iregs[29]),
X(iregs[30]),
X(iregs[31]),
X(fregs[0]), /* f0 */
X(fregs[1]),
X(fregs[2]),
X(fregs[3]),
X(fregs[4]),
X(fregs[5]),
X(fregs[6]),
X(fregs[7]),
X(fregs[8]),
X(fregs[9]),
X(fregs[10]),
X(fregs[11]),
X(fregs[12]),
X(fregs[13]),
X(fregs[14]),
X(fregs[15]),
X(fregs[16]),
X(fregs[17]),
X(fregs[18]),
X(fregs[19]),
X(fregs[20]),
X(fregs[21]),
X(fregs[22]),
X(fregs[23]),
X(fregs[24]),
X(fregs[25]),
X(fregs[26]),
X(fregs[27]),
X(fregs[28]),
X(fregs[29]),
X(fregs[30]),
X(fregs[31]),
X(srr0), /* IAR (PC) */
X(srr1), /* MSR (PS) */
X(cr), /* CR */
X(lr), /* LR */
X(ctr), /* CTR */
X(xer), /* XER */
X(mq) /* MQ */
};
#endif /* rs6000 */
#ifdef SPARC
/* This routine handles some oddball cases for Sparc registers and LynxOS.
In partucular, it causes refs to G0, g5->7, and all fp regs to return zero.
It also handles knows where to find the I & L regs on the stack. */
void
fetch_inferior_registers (regno)
int regno;
{
int whatregs = 0;
#define WHATREGS_FLOAT 1
#define WHATREGS_GEN 2
#define WHATREGS_STACK 4
if (regno == -1)
whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
whatregs = WHATREGS_STACK;
else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
whatregs = WHATREGS_FLOAT;
else
whatregs = WHATREGS_GEN;
if (whatregs & WHATREGS_GEN)
{
struct econtext ec; /* general regs */
char buf[MAX_REGISTER_RAW_SIZE];
int retval;
int i;
errno = 0;
retval = ptrace (PTRACE_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &ec,
0);
if (errno)
perror_with_name ("ptrace(PTRACE_GETREGS)");
memset (buf, 0, REGISTER_RAW_SIZE (G0_REGNUM));
supply_register (G0_REGNUM, buf);
supply_register (TBR_REGNUM, (char *)&ec.tbr);
memcpy (&registers[REGISTER_BYTE (G1_REGNUM)], &ec.g1,
4 * REGISTER_RAW_SIZE (G1_REGNUM));
for (i = G1_REGNUM; i <= G1_REGNUM + 3; i++)
register_valid[i] = 1;
supply_register (PS_REGNUM, (char *)&ec.psr);
supply_register (Y_REGNUM, (char *)&ec.y);
supply_register (PC_REGNUM, (char *)&ec.pc);
supply_register (NPC_REGNUM, (char *)&ec.npc);
supply_register (WIM_REGNUM, (char *)&ec.wim);
memcpy (&registers[REGISTER_BYTE (O0_REGNUM)], ec.o,
8 * REGISTER_RAW_SIZE (O0_REGNUM));
for (i = O0_REGNUM; i <= O0_REGNUM + 7; i++)
register_valid[i] = 1;
}
if (whatregs & WHATREGS_STACK)
{
CORE_ADDR sp;
int i;
sp = read_register (SP_REGNUM);
target_xfer_memory (sp + FRAME_SAVED_I0,
&registers[REGISTER_BYTE(I0_REGNUM)],
8 * REGISTER_RAW_SIZE (I0_REGNUM), 0);
for (i = I0_REGNUM; i <= I7_REGNUM; i++)
register_valid[i] = 1;
target_xfer_memory (sp + FRAME_SAVED_L0,
&registers[REGISTER_BYTE(L0_REGNUM)],
8 * REGISTER_RAW_SIZE (L0_REGNUM), 0);
for (i = L0_REGNUM; i <= L0_REGNUM + 7; i++)
register_valid[i] = 1;
}
if (whatregs & WHATREGS_FLOAT)
{
struct fcontext fc; /* fp regs */
int retval;
int i;
errno = 0;
retval = ptrace (PTRACE_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc,
0);
if (errno)
perror_with_name ("ptrace(PTRACE_GETFPREGS)");
memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], fc.f.fregs,
32 * REGISTER_RAW_SIZE (FP0_REGNUM));
for (i = FP0_REGNUM; i <= FP0_REGNUM + 31; i++)
register_valid[i] = 1;
supply_register (FPS_REGNUM, (char *)&fc.fsr);
}
}
/* This routine handles storing of the I & L regs for the Sparc. The trick
here is that they actually live on the stack. The really tricky part is
that when changing the stack pointer, the I & L regs must be written to
where the new SP points, otherwise the regs will be incorrect when the
process is started up again. We assume that the I & L regs are valid at
this point. */
void
store_inferior_registers (regno)
int regno;
{
int whatregs = 0;
if (regno == -1)
whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
whatregs = WHATREGS_STACK;
else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
whatregs = WHATREGS_FLOAT;
else if (regno == SP_REGNUM)
whatregs = WHATREGS_STACK | WHATREGS_GEN;
else
whatregs = WHATREGS_GEN;
if (whatregs & WHATREGS_GEN)
{
struct econtext ec; /* general regs */
int retval;
ec.tbr = read_register (TBR_REGNUM);
memcpy (&ec.g1, &registers[REGISTER_BYTE (G1_REGNUM)],
4 * REGISTER_RAW_SIZE (G1_REGNUM));
ec.psr = read_register (PS_REGNUM);
ec.y = read_register (Y_REGNUM);
ec.pc = read_register (PC_REGNUM);
ec.npc = read_register (NPC_REGNUM);
ec.wim = read_register (WIM_REGNUM);
memcpy (ec.o, &registers[REGISTER_BYTE (O0_REGNUM)],
8 * REGISTER_RAW_SIZE (O0_REGNUM));
errno = 0;
retval = ptrace (PTRACE_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &ec,
0);
if (errno)
perror_with_name ("ptrace(PTRACE_SETREGS)");
}
if (whatregs & WHATREGS_STACK)
{
int regoffset;
CORE_ADDR sp;
sp = read_register (SP_REGNUM);
if (regno == -1 || regno == SP_REGNUM)
{
if (!register_valid[L0_REGNUM+5])
abort();
target_xfer_memory (sp + FRAME_SAVED_I0,
&registers[REGISTER_BYTE (I0_REGNUM)],
8 * REGISTER_RAW_SIZE (I0_REGNUM), 1);
target_xfer_memory (sp + FRAME_SAVED_L0,
&registers[REGISTER_BYTE (L0_REGNUM)],
8 * REGISTER_RAW_SIZE (L0_REGNUM), 1);
}
else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
{
if (!register_valid[regno])
abort();
if (regno >= L0_REGNUM && regno <= L0_REGNUM + 7)
regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM)
+ FRAME_SAVED_L0;
else
regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (I0_REGNUM)
+ FRAME_SAVED_I0;
target_xfer_memory (sp + regoffset, &registers[REGISTER_BYTE (regno)],
REGISTER_RAW_SIZE (regno), 1);
}
}
if (whatregs & WHATREGS_FLOAT)
{
struct fcontext fc; /* fp regs */
int retval;
/* We read fcontext first so that we can get good values for fq_t... */
errno = 0;
retval = ptrace (PTRACE_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc,
0);
if (errno)
perror_with_name ("ptrace(PTRACE_GETFPREGS)");
memcpy (fc.f.fregs, &registers[REGISTER_BYTE (FP0_REGNUM)],
32 * REGISTER_RAW_SIZE (FP0_REGNUM));
fc.fsr = read_register (FPS_REGNUM);
errno = 0;
retval = ptrace (PTRACE_SETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc,
0);
if (errno)
perror_with_name ("ptrace(PTRACE_SETFPREGS)");
}
}
#endif /* SPARC */
#if defined (I386) || defined (M68K) || defined (rs6000)
/* Return the offset relative to the start of the per-thread data to the
saved context block. */
static unsigned long
registers_addr(pid)
int pid;
{
CORE_ADDR stblock;
int ecpoff = offsetof(st_t, ecp);
CORE_ADDR ecp;
errno = 0;
stblock = (CORE_ADDR) ptrace (PTRACE_THREADUSER, pid, (PTRACE_ARG3_TYPE)0,
0);
if (errno)
perror_with_name ("ptrace(PTRACE_THREADUSER)");
ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, pid, (PTRACE_ARG3_TYPE)ecpoff,
0);
if (errno)
perror_with_name ("ptrace(PTRACE_PEEKTHREAD)");
return ecp - stblock;
}
/* Fetch one or more registers from the inferior. REGNO == -1 to get
them all. We actually fetch more than requested, when convenient,
marking them as valid so we won't fetch them again. */
void
fetch_inferior_registers (regno)
int regno;
{
int reglo, reghi;
int i;
unsigned long ecp;
if (regno == -1)
{
reglo = 0;
reghi = NUM_REGS - 1;
}
else
reglo = reghi = regno;
ecp = registers_addr (inferior_pid);
for (regno = reglo; regno <= reghi; regno++)
{
char buf[MAX_REGISTER_RAW_SIZE];
int ptrace_fun = PTRACE_PEEKTHREAD;
#ifdef M68K
ptrace_fun = regno == SP_REGNUM ? PTRACE_PEEKUSP : PTRACE_PEEKTHREAD;
#endif
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
{
unsigned int reg;
errno = 0;
reg = ptrace (ptrace_fun, inferior_pid,
(PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), 0);
if (errno)
perror_with_name ("ptrace(PTRACE_PEEKUSP)");
*(int *)&buf[i] = reg;
}
supply_register (regno, 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). */
/* Registers we shouldn't try to store. */
#if !defined (CANNOT_STORE_REGISTER)
#define CANNOT_STORE_REGISTER(regno) 0
#endif
void
store_inferior_registers (regno)
int regno;
{
int reglo, reghi;
int i;
unsigned long ecp;
if (regno == -1)
{
reglo = 0;
reghi = NUM_REGS - 1;
}
else
reglo = reghi = regno;
ecp = registers_addr (inferior_pid);
for (regno = reglo; regno <= reghi; regno++)
{
int ptrace_fun = PTRACE_POKEUSER;
if (CANNOT_STORE_REGISTER (regno))
continue;
#ifdef M68K
ptrace_fun = regno == SP_REGNUM ? PTRACE_POKEUSP : PTRACE_POKEUSER;
#endif
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
{
unsigned int reg;
reg = *(unsigned int *)&registers[REGISTER_BYTE (regno) + i];
errno = 0;
ptrace (ptrace_fun, inferior_pid,
(PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), reg);
if (errno)
perror_with_name ("ptrace(PTRACE_POKEUSP)");
}
}
}
#endif /* defined (I386) || defined (M68K) || defined (rs6000) */
/* Wait for child to do something. Return pid of child, or -1 in case
of error; store status through argument pointer OURSTATUS. */
int
child_wait (pid, ourstatus)
int pid;
struct target_waitstatus *ourstatus;
{
int save_errno;
int thread;
union wait status;
while (1)
{
int sig;
set_sigint_trap(); /* Causes SIGINT to be passed on to the
attached process. */
pid = wait (&status);
save_errno = errno;
clear_sigint_trap();
if (pid == -1)
{
if (save_errno == EINTR)
continue;
fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
safe_strerror (save_errno));
/* Claim it exited with unknown signal. */
ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
return -1;
}
if (pid != PIDGET (inferior_pid)) /* Some other process?!? */
continue;
thread = status.w_tid; /* Get thread id from status */
/* Initial thread value can only be acquired via wait, so we have to
resort to this hack. */
if (TIDGET (inferior_pid) == 0 && thread != 0)
{
inferior_pid = BUILDPID (inferior_pid, thread);
add_thread (inferior_pid);
}
pid = BUILDPID (pid, thread);
/* We've become a single threaded process again. */
if (thread == 0)
inferior_pid = pid;
/* Check for thread creation. */
if (WIFSTOPPED(status)
&& WSTOPSIG(status) == SIGTRAP
&& !in_thread_list (pid))
{
int realsig;
realsig = ptrace (PTRACE_GETTRACESIG, pid, (PTRACE_ARG3_TYPE)0, 0);
if (realsig == SIGNEWTHREAD)
{
/* It's a new thread notification. Nothing to do here since
the machine independent code in wait_for_inferior will
add the thread to the thread list and restart the thread
when pid != inferior_pid and pid is not in the thread
list. We don't even want to much with realsig -- the
code in wait_for_inferior expects SIGTRAP. */
;
}
else
error ("Signal for unknown thread was not SIGNEWTHREAD");
}
/* Check for thread termination. */
else if (WIFSTOPPED(status)
&& WSTOPSIG(status) == SIGTRAP
&& in_thread_list (pid))
{
int realsig;
realsig = ptrace (PTRACE_GETTRACESIG, pid, (PTRACE_ARG3_TYPE)0, 0);
if (realsig == SIGTHREADEXIT)
{
ptrace (PTRACE_CONT, PIDGET (pid), (PTRACE_ARG3_TYPE)0, 0);
continue;
}
}
#ifdef SPARC
/* SPARC Lynx uses an byte reversed wait status; we must use the
host macros to access it. These lines just a copy of
store_waitstatus. We can't use CHILD_SPECIAL_WAITSTATUS
because target.c can't include the Lynx <sys/wait.h>. */
if (WIFEXITED (status))
{
ourstatus->kind = TARGET_WAITKIND_EXITED;
ourstatus->value.integer = WEXITSTATUS (status);
}
else if (!WIFSTOPPED (status))
{
ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
ourstatus->value.sig =
target_signal_from_host (WTERMSIG (status));
}
else
{
ourstatus->kind = TARGET_WAITKIND_STOPPED;
ourstatus->value.sig =
target_signal_from_host (WSTOPSIG (status));
}
#else
store_waitstatus (ourstatus, status.w_status);
#endif
return pid;
}
}
/* Return nonzero if the given thread is still alive. */
int
child_thread_alive (pid)
int pid;
{
/* Arggh. Apparently pthread_kill only works for threads within
the process that calls pthread_kill.
We want to avoid the lynx signal extensions as they simply don't
map well to the generic gdb interface we want to keep.
All we want to do is determine if a particular thread is alive;
it appears as if we can just make a harmless thread specific
ptrace call to do that. */
return (ptrace (PTRACE_THREADUSER, pid, 0, 0) != -1);
}
/* Resume execution of the inferior process.
If STEP is nonzero, single-step it.
If SIGNAL is nonzero, give it that signal. */
void
child_resume (pid, step, signal)
int pid;
int step;
enum target_signal signal;
{
int func;
errno = 0;
/* If pid == -1, then we want to step/continue all threads, else
we only want to step/continue a single thread. */
if (pid == -1)
{
pid = inferior_pid;
func = step ? PTRACE_SINGLESTEP : PTRACE_CONT;
}
else
func = step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT_ONE;
/* An address of (PTRACE_ARG3_TYPE)1 tells ptrace to continue from where
it was. (If GDB wanted it to start some other way, we have already
written a new PC value to the child.)
If this system does not support PT_STEP, a higher level function will
have called single_step() to transmute the step request into a
continue request (by setting breakpoints on all possible successor
instructions), so we don't have to worry about that here. */
ptrace (func, pid, (PTRACE_ARG3_TYPE) 1, target_signal_to_host (signal));
if (errno)
perror_with_name ("ptrace");
}
/* Convert a Lynx process ID to a string. Returns the string in a static
buffer. */
char *
lynx_pid_to_str (pid)
int pid;
{
static char buf[40];
sprintf (buf, "process %d thread %d", PIDGET (pid), TIDGET (pid));
return buf;
}
/* 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_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
char *core_reg_sect;
unsigned core_reg_size;
int which;
unsigned reg_addr;
{
struct st_entry s;
unsigned int regno;
for (regno = 0; regno < NUM_REGS; regno++)
if (regmap[regno] != -1)
supply_register (regno, core_reg_sect + offsetof (st_t, ec)
+ regmap[regno]);
#ifdef SPARC
/* Fetching this register causes all of the I & L regs to be read from the
stack and validated. */
fetch_inferior_registers (I0_REGNUM);
#endif
}
/* Register that we are able to handle lynx core file formats.
FIXME: is this really bfd_target_unknown_flavour? */
static struct core_fns lynx_core_fns =
{
bfd_target_unknown_flavour,
fetch_core_registers,
NULL
};
void
_initialize_core_lynx ()
{
add_core_fns (&lynx_core_fns);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,514 +0,0 @@
/* Target dependent code for the Motorola 68000 series.
Copyright (C) 1990, 1992 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 "symtab.h"
/* Push an empty stack frame, to record the current PC, etc. */
void
m68k_push_dummy_frame ()
{
register CORE_ADDR sp = read_register (SP_REGNUM);
register int regnum;
char raw_buffer[12];
sp = push_word (sp, read_register (PC_REGNUM));
sp = push_word (sp, read_register (FP_REGNUM));
write_register (FP_REGNUM, sp);
/* Always save the floating-point registers, whether they exist on
this target or not. */
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)
{
read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);
sp = push_bytes (sp, raw_buffer, 12);
}
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)
{
sp = push_word (sp, read_register (regnum));
}
sp = push_word (sp, read_register (PS_REGNUM));
write_register (SP_REGNUM, sp);
}
/* Discard from the stack the innermost frame,
restoring all saved registers. */
void
m68k_pop_frame ()
{
register struct frame_info *frame = get_current_frame ();
register CORE_ADDR fp;
register int regnum;
struct frame_saved_regs fsr;
struct frame_info *fi;
char raw_buffer[12];
fp = FRAME_FP (frame);
get_frame_saved_regs (frame, &fsr);
for (regnum = FP0_REGNUM + 7 ; regnum >= FP0_REGNUM ; regnum--)
{
if (fsr.regs[regnum])
{
read_memory (fsr.regs[regnum], raw_buffer, 12);
write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);
}
}
for (regnum = FP_REGNUM - 1 ; regnum >= 0 ; regnum--)
{
if (fsr.regs[regnum])
{
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
}
}
if (fsr.regs[PS_REGNUM])
{
write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4));
}
write_register (FP_REGNUM, read_memory_integer (fp, 4));
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
write_register (SP_REGNUM, fp + 8);
flush_cached_frames ();
}
/* Given an ip value corresponding to the start of a function,
return the ip of the first instruction after the function
prologue. This is the generic m68k support. Machines which
require something different can override the SKIP_PROLOGUE
macro to point elsewhere.
Some instructions which typically may appear in a function
prologue include:
A link instruction, word form:
link.w %a6,&0 4e56 XXXX
A link instruction, long form:
link.l %fp,&F%1 480e XXXX XXXX
A movm instruction to preserve integer regs:
movm.l &M%1,(4,%sp) 48ef XXXX XXXX
A fmovm instruction to preserve float regs:
fmovm &FPM%1,(FPO%1,%sp) f237 XXXX XXXX XXXX XXXX
Some profiling setup code (FIXME, not recognized yet):
lea.l (.L3,%pc),%a1 43fb XXXX XXXX XXXX
bsr _mcount 61ff XXXX XXXX
*/
#define P_LINK_L 0x480e
#define P_LINK_W 0x4e56
#define P_MOV_L 0x207c
#define P_JSR 0x4eb9
#define P_BSR 0x61ff
#define P_LEA_L 0x43fb
#define P_MOVM_L 0x48ef
#define P_FMOVM 0xf237
#define P_TRAP 0x4e40
CORE_ADDR
m68k_skip_prologue (ip)
CORE_ADDR ip;
{
register CORE_ADDR limit;
struct symtab_and_line sal;
register int op;
/* Find out if there is a known limit for the extent of the prologue.
If so, ensure we don't go past it. If not, assume "infinity". */
sal = find_pc_line (ip, 0);
limit = (sal.end) ? sal.end : (CORE_ADDR) ~0;
while (ip < limit)
{
op = read_memory_integer (ip, 2);
op &= 0xFFFF;
if (op == P_LINK_W)
{
ip += 4; /* Skip link.w */
}
else if (op == 0x4856)
ip += 2; /* Skip pea %fp */
else if (op == 0x2c4f)
ip += 2; /* Skip move.l %sp, %fp */
else if (op == P_LINK_L)
{
ip += 6; /* Skip link.l */
}
else if (op == P_MOVM_L)
{
ip += 6; /* Skip movm.l */
}
else if (op == P_FMOVM)
{
ip += 10; /* Skip fmovm */
}
else
{
break; /* Found unknown code, bail out. */
}
}
return (ip);
}
void
m68k_find_saved_regs (frame_info, saved_regs)
struct frame_info *frame_info;
struct frame_saved_regs *saved_regs;
{
register int regnum;
register int regmask;
register CORE_ADDR next_addr;
register CORE_ADDR pc;
/* First possible address for a pc in a call dummy for this frame. */
CORE_ADDR possible_call_dummy_start =
(frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 4 - 8*12;
int nextinsn;
memset (saved_regs, 0, sizeof (*saved_regs));
if ((frame_info)->pc >= possible_call_dummy_start
&& (frame_info)->pc <= (frame_info)->frame)
{
/* It is a call dummy. We could just stop now, since we know
what the call dummy saves and where. But this code proceeds
to parse the "prologue" which is part of the call dummy.
This is needlessly complex and confusing. FIXME. */
next_addr = (frame_info)->frame;
pc = possible_call_dummy_start;
}
else
{
pc = get_pc_function_start ((frame_info)->pc);
if (0x4856 == read_memory_integer (pc, 2)
&& 0x2c4f == read_memory_integer (pc + 2, 2))
{
/*
pea %fp
move.l %sp, %fp */
pc += 4;
next_addr = frame_info->frame;
}
else if (044016 == read_memory_integer (pc, 2))
/* link.l %fp */
/* Find the address above the saved
regs using the amount of storage from the link instruction. */
next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 4), pc+=4;
else if (047126 == read_memory_integer (pc, 2))
/* link.w %fp */
/* Find the address above the saved
regs using the amount of storage from the link instruction. */
next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 2), pc+=2;
else goto lose;
/* If have an addal #-n, sp next, adjust next_addr. */
if ((0177777 & read_memory_integer (pc, 2)) == 0157774)
next_addr += read_memory_integer (pc += 2, 4), pc += 4;
}
regmask = read_memory_integer (pc + 2, 2);
/* Here can come an fmovem. Check for it. */
nextinsn = 0xffff & read_memory_integer (pc, 2);
if (0xf227 == nextinsn
&& (regmask & 0xff00) == 0xe000)
{ pc += 4; /* Regmask's low bit is for register fp7, the first pushed */
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1)
if (regmask & 1)
saved_regs->regs[regnum] = (next_addr -= 12);
regmask = read_memory_integer (pc + 2, 2); }
/* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */
if (0044327 == read_memory_integer (pc, 2))
{ pc += 4; /* Regmask's low bit is for register 0, the first written */
for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)
if (regmask & 1)
saved_regs->regs[regnum] = (next_addr += 4) - 4; }
else if (0044347 == read_memory_integer (pc, 2))
{
pc += 4; /* Regmask's low bit is for register 15, the first pushed */
for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1)
if (regmask & 1)
saved_regs->regs[regnum] = (next_addr -= 4);
}
else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2)))
{
regnum = 0xf & read_memory_integer (pc, 2); pc += 2;
saved_regs->regs[regnum] = (next_addr -= 4);
/* gcc, at least, may use a pair of movel instructions when saving
exactly 2 registers. */
if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2)))
{
regnum = 0xf & read_memory_integer (pc, 2);
pc += 2;
saved_regs->regs[regnum] = (next_addr -= 4);
}
}
/* fmovemx to index of sp may follow. */
regmask = read_memory_integer (pc + 2, 2);
nextinsn = 0xffff & read_memory_integer (pc, 2);
if (0xf236 == nextinsn
&& (regmask & 0xff00) == 0xf000)
{ pc += 10; /* Regmask's low bit is for register fp0, the first written */
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1)
if (regmask & 1)
saved_regs->regs[regnum] = (next_addr += 12) - 12;
regmask = read_memory_integer (pc + 2, 2); }
/* clrw -(sp); movw ccr,-(sp) may follow. */
if (0x426742e7 == read_memory_integer (pc, 4))
saved_regs->regs[PS_REGNUM] = (next_addr -= 4);
lose: ;
saved_regs->regs[SP_REGNUM] = (frame_info)->frame + 8;
saved_regs->regs[FP_REGNUM] = (frame_info)->frame;
saved_regs->regs[PC_REGNUM] = (frame_info)->frame + 4;
#ifdef SIG_SP_FP_OFFSET
/* Adjust saved SP_REGNUM for fake _sigtramp frames. */
if (frame_info->signal_handler_caller && frame_info->next)
saved_regs->regs[SP_REGNUM] = frame_info->next->frame + SIG_SP_FP_OFFSET;
#endif
}
#ifdef USE_PROC_FS /* Target dependent support for /proc */
#include <sys/procfs.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 m68k for example, the general register set is typically defined
by:
typedef int gregset_t[18];
#define R_D0 0
...
#define R_PS 17
and the floating point set by:
typedef struct fpregset {
int f_pcr;
int f_psr;
int f_fpiaddr;
int f_fpregs[8][3]; (8 regs, 96 bits each)
} fpregset_t;
These routines provide the packing and unpacking of gregset_t and
fpregset_t formatted data.
*/
/* Atari SVR4 has R_SR but not R_PS */
#if !defined (R_PS) && defined (R_SR)
#define R_PS R_SR
#endif
/* 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 (gregsetp)
gregset_t *gregsetp;
{
register int regi;
register greg_t *regp = (greg_t *) gregsetp;
for (regi = 0 ; regi < R_PC ; regi++)
{
supply_register (regi, (char *) (regp + regi));
}
supply_register (PS_REGNUM, (char *) (regp + R_PS));
supply_register (PC_REGNUM, (char *) (regp + R_PC));
}
void
fill_gregset (gregsetp, regno)
gregset_t *gregsetp;
int regno;
{
register int regi;
register greg_t *regp = (greg_t *) gregsetp;
extern char registers[];
for (regi = 0 ; regi < R_PC ; regi++)
{
if ((regno == -1) || (regno == regi))
{
*(regp + regi) = *(int *) &registers[REGISTER_BYTE (regi)];
}
}
if ((regno == -1) || (regno == PS_REGNUM))
{
*(regp + R_PS) = *(int *) &registers[REGISTER_BYTE (PS_REGNUM)];
}
if ((regno == -1) || (regno == PC_REGNUM))
{
*(regp + R_PC) = *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
}
}
#if defined (FP0_REGNUM)
/* 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. */
void
supply_fpregset (fpregsetp)
fpregset_t *fpregsetp;
{
register int regi;
char *from;
for (regi = FP0_REGNUM ; regi < FPC_REGNUM ; regi++)
{
from = (char *) &(fpregsetp -> f_fpregs[regi-FP0_REGNUM][0]);
supply_register (regi, from);
}
supply_register (FPC_REGNUM, (char *) &(fpregsetp -> f_pcr));
supply_register (FPS_REGNUM, (char *) &(fpregsetp -> f_psr));
supply_register (FPI_REGNUM, (char *) &(fpregsetp -> f_fpiaddr));
}
/* 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 (fpregsetp, regno)
fpregset_t *fpregsetp;
int regno;
{
int regi;
char *to;
char *from;
extern char registers[];
for (regi = FP0_REGNUM ; regi < FPC_REGNUM ; regi++)
{
if ((regno == -1) || (regno == regi))
{
from = (char *) &registers[REGISTER_BYTE (regi)];
to = (char *) &(fpregsetp -> f_fpregs[regi-FP0_REGNUM][0]);
memcpy (to, from, REGISTER_RAW_SIZE (regi));
}
}
if ((regno == -1) || (regno == FPC_REGNUM))
{
fpregsetp -> f_pcr = *(int *) &registers[REGISTER_BYTE (FPC_REGNUM)];
}
if ((regno == -1) || (regno == FPS_REGNUM))
{
fpregsetp -> f_psr = *(int *) &registers[REGISTER_BYTE (FPS_REGNUM)];
}
if ((regno == -1) || (regno == FPI_REGNUM))
{
fpregsetp -> f_fpiaddr = *(int *) &registers[REGISTER_BYTE (FPI_REGNUM)];
}
}
#endif /* defined (FP0_REGNUM) */
#endif /* USE_PROC_FS */
#ifdef GET_LONGJMP_TARGET
/* Figure out where the longjmp will land. Slurp the args out of the stack.
We expect the first arg to be a pointer to the jmp_buf structure from which
we extract the pc (JB_PC) that we will land at. The pc is copied into PC.
This routine returns true on success. */
int
get_longjmp_target(pc)
CORE_ADDR *pc;
{
char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
CORE_ADDR sp, jb_addr;
sp = read_register(SP_REGNUM);
if (target_read_memory (sp + SP_ARG0, /* Offset of first arg on stack */
buf,
TARGET_PTR_BIT / TARGET_CHAR_BIT))
return 0;
jb_addr = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
TARGET_PTR_BIT / TARGET_CHAR_BIT))
return 0;
*pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
return 1;
}
#endif /* GET_LONGJMP_TARGET */
/* Immediately after a function call, return the saved pc before the frame
is setup. For sun3's, we check for the common case of being inside of a
system call, and if so, we know that Sun pushes the call # on the stack
prior to doing the trap. */
CORE_ADDR
m68k_saved_pc_after_call(frame)
struct frame_info *frame;
{
#ifdef SYSCALL_TRAP
int op;
op = read_memory_integer (frame->pc - SYSCALL_TRAP_OFFSET, 2);
if (op == SYSCALL_TRAP)
return read_memory_integer (read_register (SP_REGNUM) + 4, 4);
else
#endif /* SYSCALL_TRAP */
return read_memory_integer (read_register (SP_REGNUM), 4);
}
void
_initialize_m68k_tdep ()
{
tm_print_insn = print_insn_m68k;
}

View file

@ -1,86 +0,0 @@
/* Native-dependent code for Motorola m68k's running NetBSD, for GDB.
Copyright 1988, 1989, 1991, 1992, 1994, 1996 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 <sys/types.h>
#include <sys/ptrace.h>
#include <machine/reg.h>
#include <machine/frame.h>
#include "defs.h"
#include "inferior.h"
void
fetch_inferior_registers(regno)
int regno;
{
struct reg inferior_registers;
struct fpreg inferior_fp_registers;
ptrace (PT_GETREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_registers, 0);
memcpy (&registers[REGISTER_BYTE (0)], &inferior_registers,
sizeof(inferior_registers));
ptrace (PT_GETFPREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
sizeof(inferior_fp_registers));
registers_fetched ();
}
void
store_inferior_registers(regno)
int regno;
{
struct reg inferior_registers;
struct fpreg inferior_fp_registers;
memcpy (&inferior_registers, &registers[REGISTER_BYTE (0)],
sizeof(inferior_registers));
ptrace (PT_SETREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_registers, 0);
memcpy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
sizeof(inferior_fp_registers));
ptrace (PT_SETFPREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
}
struct md_core {
struct reg intreg;
struct fpreg freg;
};
void
fetch_core_registers (core_reg_sect, core_reg_size, which, ignore)
char *core_reg_sect;
unsigned core_reg_size;
int which;
unsigned int ignore;
{
struct md_core *core_reg = (struct md_core *)core_reg_sect;
/* Integer registers */
memcpy(&registers[REGISTER_BYTE (0)],
&core_reg->intreg, sizeof(struct reg));
/* Floating point registers */
memcpy(&registers[REGISTER_BYTE (FP0_REGNUM)],
&core_reg->freg, sizeof(struct fpreg));
}

View file

@ -1,285 +0,0 @@
/* Native-dependent Motorola 88xxx support for GDB, the GNU Debugger.
Copyright 1988, 1990, 1991, 1992 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 <sys/types.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include "gdbcore.h"
#include <sys/user.h>
#ifndef USER /* added to support BCS ptrace_user */
#define USER ptrace_user
#endif
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/file.h>
#include "gdb_stat.h"
#include "symtab.h"
#include "setjmp.h"
#include "value.h"
#ifdef DELTA88
#include <sys/ptrace.h>
/* define offsets to the pc instruction offsets in ptrace_user struct */
#define SXIP_OFFSET ((char *)&u.pt_sigframe.sig_sxip - (char *)&u)
#define SNIP_OFFSET ((char *)&u.pt_sigframe.sig_snip - (char *)&u)
#define SFIP_OFFSET ((char *)&u.pt_sigframe.sig_sfip - (char *)&u)
#else
/* define offsets to the pc instruction offsets in ptrace_user struct */
#define SXIP_OFFSET ((char *)&u.pt_sigframe.dg_sigframe.sc_sxip - (char *)&u)
#define SNIP_OFFSET ((char *)&u.pt_sigframe.dg_sigframe.sc_snip - (char *)&u)
#define SFIP_OFFSET ((char *)&u.pt_sigframe.dg_sigframe.sc_sfip - (char *)&u)
#endif
extern int have_symbol_file_p();
extern jmp_buf stack_jmp;
extern int errno;
extern char registers[REGISTER_BYTES];
void
fetch_inferior_registers (regno)
int regno; /* Original value discarded */
{
register unsigned int regaddr;
char buf[MAX_REGISTER_RAW_SIZE];
register int i;
struct USER u;
unsigned int offset;
offset = (char *) &u.pt_r0 - (char *) &u;
regaddr = offset; /* byte offset to r0;*/
/* offset = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0) - KERNEL_U_ADDR; */
for (regno = 0; regno < NUM_REGS; regno++)
{
/*regaddr = register_addr (regno, offset);*/
/* 88k enhancement */
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
{
*(int *) &buf[i] = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) regaddr, 0);
regaddr += sizeof (int);
}
supply_register (regno, buf);
}
/* now load up registers 36 - 38; special pc registers */
*(int *) &buf[0] = ptrace (3,inferior_pid,
(PTRACE_ARG3_TYPE) SXIP_OFFSET ,0);
supply_register (SXIP_REGNUM, buf);
*(int *) &buf[0] = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) SNIP_OFFSET,0);
supply_register (SNIP_REGNUM, buf);
*(int *) &buf[0] = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) SFIP_OFFSET,0);
supply_register (SFIP_REGNUM, 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 (regno)
int regno;
{
register unsigned int regaddr;
char buf[80];
struct USER u;
unsigned int offset = (char *) &u.pt_r0 - (char *) &u;
regaddr = offset;
/* Don't try to deal with EXIP_REGNUM or ENIP_REGNUM, because I think either
svr3 doesn't run on an 88110, or the kernel isolates the different (not
completely sure this is true, but seems to be. */
if (regno >= 0)
{
/* regaddr = register_addr (regno, offset); */
if (regno < PC_REGNUM)
{
regaddr = offset + regno * sizeof (int);
errno = 0;
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) regaddr, read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing register number %d", regno);
perror_with_name (buf);
}
}
else if (regno == SXIP_REGNUM)
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) SXIP_OFFSET, read_register(regno));
else if (regno == SNIP_REGNUM)
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) SNIP_OFFSET, read_register(regno));
else if (regno == SFIP_REGNUM)
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) SFIP_OFFSET, read_register(regno));
else
printf_unfiltered ("Bad register number for store_inferior routine\n");
}
else
{
for (regno = 0; regno < PC_REGNUM; regno++)
{
/* regaddr = register_addr (regno, offset); */
errno = 0;
regaddr = offset + regno * sizeof (int);
ptrace (6, inferior_pid,
(PTRACE_ARG3_TYPE) regaddr, read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing register number %d", regno);
perror_with_name (buf);
}
}
ptrace (6,inferior_pid,
(PTRACE_ARG3_TYPE) SXIP_OFFSET,read_register(SXIP_REGNUM));
ptrace (6,inferior_pid,
(PTRACE_ARG3_TYPE) SNIP_OFFSET,read_register(SNIP_REGNUM));
ptrace (6,inferior_pid,
(PTRACE_ARG3_TYPE) SFIP_OFFSET,read_register(SFIP_REGNUM));
}
}
/* blockend is the address of the end of the user structure */
m88k_register_u_addr (blockend, regnum)
{
struct USER u;
int ustart = blockend - sizeof (struct USER);
switch (regnum)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29:
case 30:
case 31:
return (ustart + ((int) &u.pt_r0 - (int) &u) + REGISTER_SIZE * regnum);
case PSR_REGNUM: return (ustart + ((int) &u.pt_psr - (int) &u));
case FPSR_REGNUM: return (ustart + ((int) &u.pt_fpsr - (int) &u));
case FPCR_REGNUM: return (ustart + ((int) &u.pt_fpcr - (int) &u));
case SXIP_REGNUM: return (ustart + SXIP_OFFSET);
case SNIP_REGNUM: return (ustart + SNIP_OFFSET);
case SFIP_REGNUM: return (ustart + SFIP_OFFSET);
default:
if (regnum < NUM_REGS)
/* The register is one of those which is not defined...
give it zero */
return (ustart + ((int) &u.pt_r0 - (int) &u));
else
return (blockend + REGISTER_SIZE * regnum);
}
}
#ifdef USE_PROC_FS
#include <sys/procfs.h>
/* 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 (gregsetp)
gregset_t *gregsetp;
{
register int regi;
register greg_t *regp = (greg_t *) gregsetp;
for (regi=0; regi <= SP_REGNUM; regi++)
supply_register (regi, (char *) (regp + regi));
supply_register (SXIP_REGNUM, (char *) (regp + R_XIP));
supply_register (SNIP_REGNUM, (char *) (regp + R_NIP));
supply_register (SFIP_REGNUM, (char *) (regp + R_FIP));
supply_register (PSR_REGNUM, (char *) (regp + R_PSR));
supply_register (FPSR_REGNUM, (char *) (regp + R_FPSR));
supply_register (FPCR_REGNUM, (char *) (regp + R_FPCR));
}
void
fill_gregset (gregsetp, regno)
gregset_t *gregsetp;
int regno;
{
int regi;
register greg_t *regp = (greg_t *) gregsetp;
extern char registers[];
for (regi = 0 ; regi <= R_R31 ; regi++)
if ((regno == -1) || (regno == regi))
*(regp + regi) = *(int *) &registers[REGISTER_BYTE(regi)];
if ((regno == -1) || (regno == SXIP_REGNUM))
*(regp + R_XIP) = *(int *) &registers[REGISTER_BYTE(SXIP_REGNUM)];
if ((regno == -1) || (regno == SNIP_REGNUM))
*(regp + R_NIP) = *(int *) &registers[REGISTER_BYTE(SNIP_REGNUM)];
if ((regno == -1) || (regno == SFIP_REGNUM))
*(regp + R_FIP) = *(int *) &registers[REGISTER_BYTE(SFIP_REGNUM)];
if ((regno == -1) || (regno == PSR_REGNUM))
*(regp + R_PSR) = *(int *) &registers[REGISTER_BYTE(PSR_REGNUM)];
if ((regno == -1) || (regno == FPSR_REGNUM))
*(regp + R_FPSR) = *(int *) &registers[REGISTER_BYTE(FPSR_REGNUM)];
if ((regno == -1) || (regno == FPCR_REGNUM))
*(regp + R_FPCR) = *(int *) &registers[REGISTER_BYTE(FPCR_REGNUM)];
}
#endif /* USE_PROC_FS */

View file

@ -1,616 +0,0 @@
/* Target-machine dependent code for Motorola 88000 series, for GDB.
Copyright 1988, 1990, 1991, 1994, 1995 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 "value.h"
#include "gdbcore.h"
#include "symtab.h"
#include "setjmp.h"
#include "value.h"
/* Size of an instruction */
#define BYTES_PER_88K_INSN 4
void frame_find_saved_regs ();
/* Is this target an m88110? Otherwise assume m88100. This has
relevance for the ways in which we screw with instruction pointers. */
int target_is_m88110 = 0;
/* Given a GDB frame, determine the address of the calling function's frame.
This will be used to create a new GDB frame struct, and then
INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
For us, the frame address is its stack pointer value, so we look up
the function prologue to determine the caller's sp value, and return it. */
CORE_ADDR
frame_chain (thisframe)
struct frame_info *thisframe;
{
frame_find_saved_regs (thisframe, (struct frame_saved_regs *) 0);
/* NOTE: this depends on frame_find_saved_regs returning the VALUE, not
the ADDRESS, of SP_REGNUM. It also depends on the cache of
frame_find_saved_regs results. */
if (thisframe->fsr->regs[SP_REGNUM])
return thisframe->fsr->regs[SP_REGNUM];
else
return thisframe->frame; /* Leaf fn -- next frame up has same SP. */
}
int
frameless_function_invocation (frame)
struct frame_info *frame;
{
frame_find_saved_regs (frame, (struct frame_saved_regs *) 0);
/* NOTE: this depends on frame_find_saved_regs returning the VALUE, not
the ADDRESS, of SP_REGNUM. It also depends on the cache of
frame_find_saved_regs results. */
if (frame->fsr->regs[SP_REGNUM])
return 0; /* Frameful -- return addr saved somewhere */
else
return 1; /* Frameless -- no saved return address */
}
void
init_extra_frame_info (fromleaf, frame)
int fromleaf;
struct frame_info *frame;
{
frame->fsr = 0; /* Not yet allocated */
frame->args_pointer = 0; /* Unknown */
frame->locals_pointer = 0; /* Unknown */
}
/* Examine an m88k function prologue, recording the addresses at which
registers are saved explicitly by the prologue code, and returning
the address of the first instruction after the prologue (but not
after the instruction at address LIMIT, as explained below).
LIMIT places an upper bound on addresses of the instructions to be
examined. If the prologue code scan reaches LIMIT, the scan is
aborted and LIMIT is returned. This is used, when examining the
prologue for the current frame, to keep examine_prologue () from
claiming that a given register has been saved when in fact the
instruction that saves it has not yet been executed. LIMIT is used
at other times to stop the scan when we hit code after the true
function prologue (e.g. for the first source line) which might
otherwise be mistaken for function prologue.
The format of the function prologue matched by this routine is
derived from examination of the source to gcc 1.95, particularly
the routine output_prologue () in config/out-m88k.c.
subu r31,r31,n # stack pointer update
(st rn,r31,offset)? # save incoming regs
(st.d rn,r31,offset)?
(addu r30,r31,n)? # frame pointer update
(pic sequence)? # PIC code prologue
(or rn,rm,0)? # Move parameters to other regs
*/
/* Macros for extracting fields from instructions. */
#define BITMASK(pos, width) (((0x1 << (width)) - 1) << (pos))
#define EXTRACT_FIELD(val, pos, width) ((val) >> (pos) & BITMASK (0, width))
#define SUBU_OFFSET(x) ((unsigned)(x & 0xFFFF))
#define ST_OFFSET(x) ((unsigned)((x) & 0xFFFF))
#define ST_SRC(x) EXTRACT_FIELD ((x), 21, 5)
#define ADDU_OFFSET(x) ((unsigned)(x & 0xFFFF))
/*
* prologue_insn_tbl is a table of instructions which may comprise a
* function prologue. Associated with each table entry (corresponding
* to a single instruction or group of instructions), is an action.
* This action is used by examine_prologue (below) to determine
* the state of certain machine registers and where the stack frame lives.
*/
enum prologue_insn_action {
PIA_SKIP, /* don't care what the instruction does */
PIA_NOTE_ST, /* note register stored and where */
PIA_NOTE_STD, /* note pair of registers stored and where */
PIA_NOTE_SP_ADJUSTMENT, /* note stack pointer adjustment */
PIA_NOTE_FP_ASSIGNMENT, /* note frame pointer assignment */
PIA_NOTE_PROLOGUE_END, /* no more prologue */
};
struct prologue_insns {
unsigned long insn;
unsigned long mask;
enum prologue_insn_action action;
};
struct prologue_insns prologue_insn_tbl[] = {
/* Various register move instructions */
{ 0x58000000, 0xf800ffff, PIA_SKIP }, /* or/or.u with immed of 0 */
{ 0xf4005800, 0xfc1fffe0, PIA_SKIP }, /* or rd, r0, rs */
{ 0xf4005800, 0xfc00ffff, PIA_SKIP }, /* or rd, rs, r0 */
/* Stack pointer setup: "subu sp, sp, n" where n is a multiple of 8 */
{ 0x67ff0000, 0xffff0007, PIA_NOTE_SP_ADJUSTMENT },
/* Frame pointer assignment: "addu r30, r31, n" */
{ 0x63df0000, 0xffff0000, PIA_NOTE_FP_ASSIGNMENT },
/* Store to stack instructions; either "st rx, sp, n" or "st.d rx, sp, n" */
{ 0x241f0000, 0xfc1f0000, PIA_NOTE_ST }, /* st rx, sp, n */
{ 0x201f0000, 0xfc1f0000, PIA_NOTE_STD }, /* st.d rs, sp, n */
/* Instructions needed for setting up r25 for pic code. */
{ 0x5f200000, 0xffff0000, PIA_SKIP }, /* or.u r25, r0, offset_high */
{ 0xcc000002, 0xffffffff, PIA_SKIP }, /* bsr.n Lab */
{ 0x5b390000, 0xffff0000, PIA_SKIP }, /* or r25, r25, offset_low */
{ 0xf7396001, 0xffffffff, PIA_SKIP }, /* Lab: addu r25, r25, r1 */
/* Various branch or jump instructions which have a delay slot -- these
do not form part of the prologue, but the instruction in the delay
slot might be a store instruction which should be noted. */
{ 0xc4000000, 0xe4000000, PIA_NOTE_PROLOGUE_END },
/* br.n, bsr.n, bb0.n, or bb1.n */
{ 0xec000000, 0xfc000000, PIA_NOTE_PROLOGUE_END }, /* bcnd.n */
{ 0xf400c400, 0xfffff7e0, PIA_NOTE_PROLOGUE_END } /* jmp.n or jsr.n */
};
/* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or
is not the address of a valid instruction, the address of the next
instruction beyond ADDR otherwise. *PWORD1 receives the first word
of the instruction. */
#define NEXT_PROLOGUE_INSN(addr, lim, pword1) \
(((addr) < (lim)) ? next_insn (addr, pword1) : 0)
/* Read the m88k instruction at 'memaddr' and return the address of
the next instruction after that, or 0 if 'memaddr' is not the
address of a valid instruction. The instruction
is stored at 'pword1'. */
CORE_ADDR
next_insn (memaddr, pword1)
unsigned long *pword1;
CORE_ADDR memaddr;
{
*pword1 = read_memory_integer (memaddr, BYTES_PER_88K_INSN);
return memaddr + BYTES_PER_88K_INSN;
}
/* Read a register from frames called by us (or from the hardware regs). */
static int
read_next_frame_reg(frame, regno)
struct frame_info *frame;
int regno;
{
for (; frame; frame = frame->next) {
if (regno == SP_REGNUM)
return FRAME_FP (frame);
else if (frame->fsr->regs[regno])
return read_memory_integer(frame->fsr->regs[regno], 4);
}
return read_register(regno);
}
/* Examine the prologue of a function. `ip' points to the first instruction.
`limit' is the limit of the prologue (e.g. the addr of the first
linenumber, or perhaps the program counter if we're stepping through).
`frame_sp' is the stack pointer value in use in this frame.
`fsr' is a pointer to a frame_saved_regs structure into which we put
info about the registers saved by this frame.
`fi' is a struct frame_info pointer; we fill in various fields in it
to reflect the offsets of the arg pointer and the locals pointer. */
static CORE_ADDR
examine_prologue (ip, limit, frame_sp, fsr, fi)
register CORE_ADDR ip;
register CORE_ADDR limit;
CORE_ADDR frame_sp;
struct frame_saved_regs *fsr;
struct frame_info *fi;
{
register CORE_ADDR next_ip;
register int src;
unsigned int insn;
int size, offset;
char must_adjust[32]; /* If set, must adjust offsets in fsr */
int sp_offset = -1; /* -1 means not set (valid must be mult of 8) */
int fp_offset = -1; /* -1 means not set */
CORE_ADDR frame_fp;
CORE_ADDR prologue_end = 0;
memset (must_adjust, '\0', sizeof (must_adjust));
next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn);
while (next_ip)
{
struct prologue_insns *pip;
for (pip=prologue_insn_tbl; (insn & pip->mask) != pip->insn; )
if (++pip >= prologue_insn_tbl + sizeof prologue_insn_tbl)
goto end_of_prologue_found; /* not a prologue insn */
switch (pip->action)
{
case PIA_NOTE_ST:
case PIA_NOTE_STD:
if (sp_offset != -1) {
src = ST_SRC (insn);
offset = ST_OFFSET (insn);
must_adjust[src] = 1;
fsr->regs[src++] = offset; /* Will be adjusted later */
if (pip->action == PIA_NOTE_STD && src < 32)
{
offset += 4;
must_adjust[src] = 1;
fsr->regs[src++] = offset;
}
}
else
goto end_of_prologue_found;
break;
case PIA_NOTE_SP_ADJUSTMENT:
if (sp_offset == -1)
sp_offset = -SUBU_OFFSET (insn);
else
goto end_of_prologue_found;
break;
case PIA_NOTE_FP_ASSIGNMENT:
if (fp_offset == -1)
fp_offset = ADDU_OFFSET (insn);
else
goto end_of_prologue_found;
break;
case PIA_NOTE_PROLOGUE_END:
if (!prologue_end)
prologue_end = ip;
break;
case PIA_SKIP:
default :
/* Do nothing */
break;
}
ip = next_ip;
next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn);
}
end_of_prologue_found:
if (prologue_end)
ip = prologue_end;
/* We're done with the prologue. If we don't care about the stack
frame itself, just return. (Note that fsr->regs has been trashed,
but the one caller who calls with fi==0 passes a dummy there.) */
if (fi == 0)
return ip;
/*
OK, now we have:
sp_offset original (before any alloca calls) displacement of SP
(will be negative).
fp_offset displacement from original SP to the FP for this frame
or -1.
fsr->regs[0..31] displacement from original SP to the stack
location where reg[0..31] is stored.
must_adjust[0..31] set if corresponding offset was set.
If alloca has been called between the function prologue and the current
IP, then the current SP (frame_sp) will not be the original SP as set by
the function prologue. If the current SP is not the original SP, then the
compiler will have allocated an FP for this frame, fp_offset will be set,
and we can use it to calculate the original SP.
Then, we figure out where the arguments and locals are, and relocate the
offsets in fsr->regs to absolute addresses. */
if (fp_offset != -1) {
/* We have a frame pointer, so get it, and base our calc's on it. */
frame_fp = (CORE_ADDR) read_next_frame_reg (fi->next, ACTUAL_FP_REGNUM);
frame_sp = frame_fp - fp_offset;
} else {
/* We have no frame pointer, therefore frame_sp is still the same value
as set by prologue. But where is the frame itself? */
if (must_adjust[SRP_REGNUM]) {
/* Function header saved SRP (r1), the return address. Frame starts
4 bytes down from where it was saved. */
frame_fp = frame_sp + fsr->regs[SRP_REGNUM] - 4;
fi->locals_pointer = frame_fp;
} else {
/* Function header didn't save SRP (r1), so we are in a leaf fn or
are otherwise confused. */
frame_fp = -1;
}
}
/* The locals are relative to the FP (whether it exists as an allocated
register, or just as an assumed offset from the SP) */
fi->locals_pointer = frame_fp;
/* The arguments are just above the SP as it was before we adjusted it
on entry. */
fi->args_pointer = frame_sp - sp_offset;
/* Now that we know the SP value used by the prologue, we know where
it saved all the registers. */
for (src = 0; src < 32; src++)
if (must_adjust[src])
fsr->regs[src] += frame_sp;
/* The saved value of the SP is always known. */
/* (we hope...) */
if (fsr->regs[SP_REGNUM] != 0
&& fsr->regs[SP_REGNUM] != frame_sp - sp_offset)
fprintf_unfiltered(gdb_stderr, "Bad saved SP value %x != %x, offset %x!\n",
fsr->regs[SP_REGNUM],
frame_sp - sp_offset, sp_offset);
fsr->regs[SP_REGNUM] = frame_sp - sp_offset;
return (ip);
}
/* Given an ip value corresponding to the start of a function,
return the ip of the first instruction after the function
prologue. */
CORE_ADDR
skip_prologue (ip)
CORE_ADDR (ip);
{
struct frame_saved_regs saved_regs_dummy;
struct symtab_and_line sal;
CORE_ADDR limit;
sal = find_pc_line (ip, 0);
limit = (sal.end) ? sal.end : 0xffffffff;
return (examine_prologue (ip, limit, (CORE_ADDR) 0, &saved_regs_dummy,
(struct frame_info *)0 ));
}
/* Put here the code to store, into a struct frame_saved_regs,
the addresses of the saved registers of frame described by FRAME_INFO.
This includes special registers such as pc and fp saved in special
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame.
We cache the result of doing this in the frame_cache_obstack, since
it is fairly expensive. */
void
frame_find_saved_regs (fi, fsr)
struct frame_info *fi;
struct frame_saved_regs *fsr;
{
register struct frame_saved_regs *cache_fsr;
extern struct obstack frame_cache_obstack;
CORE_ADDR ip;
struct symtab_and_line sal;
CORE_ADDR limit;
if (!fi->fsr)
{
cache_fsr = (struct frame_saved_regs *)
obstack_alloc (&frame_cache_obstack,
sizeof (struct frame_saved_regs));
memset (cache_fsr, '\0', sizeof (struct frame_saved_regs));
fi->fsr = cache_fsr;
/* Find the start and end of the function prologue. If the PC
is in the function prologue, we only consider the part that
has executed already. In the case where the PC is not in
the function prologue, we set limit to two instructions beyond
where the prologue ends in case if any of the prologue instructions
were moved into a delay slot of a branch instruction. */
ip = get_pc_function_start (fi->pc);
sal = find_pc_line (ip, 0);
limit = (sal.end && sal.end < fi->pc) ? sal.end + 2 * BYTES_PER_88K_INSN
: fi->pc;
/* This will fill in fields in *fi as well as in cache_fsr. */
#ifdef SIGTRAMP_FRAME_FIXUP
if (fi->signal_handler_caller)
SIGTRAMP_FRAME_FIXUP(fi->frame);
#endif
examine_prologue (ip, limit, fi->frame, cache_fsr, fi);
#ifdef SIGTRAMP_SP_FIXUP
if (fi->signal_handler_caller && fi->fsr->regs[SP_REGNUM])
SIGTRAMP_SP_FIXUP(fi->fsr->regs[SP_REGNUM]);
#endif
}
if (fsr)
*fsr = *fi->fsr;
}
/* Return the address of the locals block for the frame
described by FI. Returns 0 if the address is unknown.
NOTE! Frame locals are referred to by negative offsets from the
argument pointer, so this is the same as frame_args_address(). */
CORE_ADDR
frame_locals_address (fi)
struct frame_info *fi;
{
struct frame_saved_regs fsr;
if (fi->args_pointer) /* Cached value is likely there. */
return fi->args_pointer;
/* Nope, generate it. */
get_frame_saved_regs (fi, &fsr);
return fi->args_pointer;
}
/* Return the address of the argument block for the frame
described by FI. Returns 0 if the address is unknown. */
CORE_ADDR
frame_args_address (fi)
struct frame_info *fi;
{
struct frame_saved_regs fsr;
if (fi->args_pointer) /* Cached value is likely there. */
return fi->args_pointer;
/* Nope, generate it. */
get_frame_saved_regs (fi, &fsr);
return fi->args_pointer;
}
/* Return the saved PC from this frame.
If the frame has a memory copy of SRP_REGNUM, use that. If not,
just use the register SRP_REGNUM itself. */
CORE_ADDR
frame_saved_pc (frame)
struct frame_info *frame;
{
return read_next_frame_reg(frame, SRP_REGNUM);
}
#define DUMMY_FRAME_SIZE 192
static void
write_word (sp, word)
CORE_ADDR sp;
unsigned LONGEST word;
{
register int len = REGISTER_SIZE;
char buffer[MAX_REGISTER_RAW_SIZE];
store_unsigned_integer (buffer, len, word);
write_memory (sp, buffer, len);
}
void
m88k_push_dummy_frame()
{
register CORE_ADDR sp = read_register (SP_REGNUM);
register int rn;
int offset;
sp -= DUMMY_FRAME_SIZE; /* allocate a bunch of space */
for (rn = 0, offset = 0; rn <= SP_REGNUM; rn++, offset+=4)
write_word (sp+offset, read_register(rn));
write_word (sp+offset, read_register (SXIP_REGNUM));
offset += 4;
write_word (sp+offset, read_register (SNIP_REGNUM));
offset += 4;
write_word (sp+offset, read_register (SFIP_REGNUM));
offset += 4;
write_word (sp+offset, read_register (PSR_REGNUM));
offset += 4;
write_word (sp+offset, read_register (FPSR_REGNUM));
offset += 4;
write_word (sp+offset, read_register (FPCR_REGNUM));
offset += 4;
write_register (SP_REGNUM, sp);
write_register (ACTUAL_FP_REGNUM, sp);
}
void
pop_frame ()
{
register struct frame_info *frame = get_current_frame ();
register CORE_ADDR fp;
register int regnum;
struct frame_saved_regs fsr;
fp = FRAME_FP (frame);
get_frame_saved_regs (frame, &fsr);
if (PC_IN_CALL_DUMMY (read_pc (), read_register (SP_REGNUM), FRAME_FP (fi)))
{
/* FIXME: I think get_frame_saved_regs should be handling this so
that we can deal with the saved registers properly (e.g. frame
1 is a call dummy, the user types "frame 2" and then "print $ps"). */
register CORE_ADDR sp = read_register (ACTUAL_FP_REGNUM);
int offset;
for (regnum = 0, offset = 0; regnum <= SP_REGNUM; regnum++, offset+=4)
(void) write_register (regnum, read_memory_integer (sp+offset, 4));
write_register (SXIP_REGNUM, read_memory_integer (sp+offset, 4));
offset += 4;
write_register (SNIP_REGNUM, read_memory_integer (sp+offset, 4));
offset += 4;
write_register (SFIP_REGNUM, read_memory_integer (sp+offset, 4));
offset += 4;
write_register (PSR_REGNUM, read_memory_integer (sp+offset, 4));
offset += 4;
write_register (FPSR_REGNUM, read_memory_integer (sp+offset, 4));
offset += 4;
write_register (FPCR_REGNUM, read_memory_integer (sp+offset, 4));
offset += 4;
}
else
{
for (regnum = FP_REGNUM ; regnum > 0 ; regnum--)
if (fsr.regs[regnum])
write_register (regnum,
read_memory_integer (fsr.regs[regnum], 4));
write_pc (frame_saved_pc (frame));
}
reinit_frame_cache ();
}
void
_initialize_m88k_tdep ()
{
tm_print_insn = print_insn_m88k;
}

View file

@ -1,562 +0,0 @@
/* Definitions and macros for support of AMD's remote debugger, MiniMON.
Copyright (C) 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;
};

View file

@ -1,270 +0,0 @@
/* Remote target glue for the Intel 960 ROM monitor.
Copyright 1995, 1996 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 "gdbcore.h"
#include "target.h"
#include "monitor.h"
#include "serial.h"
#include "srec.h"
#include "xmodem.h"
#if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY)
#define HAVE_SGTTY
#endif
#ifdef HAVE_SGTTY
#include <sys/ioctl.h>
#endif
#include <sys/types.h> /* Needed by file.h on Sys V */
#include <sys/file.h>
#include <signal.h>
#include <sys/stat.h>
#define USE_GENERIC_LOAD
int quiet = 0; /* 1 => stifle unnecessary messages */
serial_t mon960_serial;
char *mon960_ttyname; /* name of tty to talk to mon960 on, or null */
static struct monitor_ops mon960_cmds;
#ifdef USE_GENERIC_LOAD
extern void generic_load PARAMS ((char* filename, int from_tty));
#endif
static void mon960_open PARAMS ((char *args, int from_tty));
#ifdef USE_GENERIC_LOAD
static void
mon960_load_gen (filename, from_tty)
char *filename;
int from_tty;
{
extern int inferior_pid;
generic_load (filename, from_tty);
/* Finally, make the PC point at the start address */
if (exec_bfd)
write_pc (bfd_get_start_address (exec_bfd));
inferior_pid = 0; /* No process now */
}
#else
static void
mon960_load (desc, file, hashmark)
serial_t desc;
char *file;
int hashmark;
{
bfd *abfd;
asection *s;
char *buffer;
int i;
buffer = alloca (XMODEM_PACKETSIZE);
abfd = bfd_openr (file, 0);
if (!abfd)
{
printf_filtered ("Unable to open file %s\n", file);
return;
}
if (bfd_check_format (abfd, bfd_object) == 0)
{
printf_filtered ("File is not an object file\n");
return;
}
for (s = abfd->sections; s; s = s->next)
if (s->flags & SEC_LOAD)
{
bfd_size_type section_size;
printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, s->vma,
s->vma + s->_raw_size);
gdb_flush (gdb_stdout);
monitor_printf (mon960_cmds.load, s->vma);
if (mon960_cmds.loadresp)
monitor_expect (mon960_cmds.loadresp, NULL, 0);
xmodem_init_xfer (desc);
section_size = bfd_section_size (abfd, s);
for (i = 0; i < section_size; i += XMODEM_DATASIZE)
{
int numbytes;
numbytes = min (XMODEM_DATASIZE, section_size - i);
bfd_get_section_contents (abfd, s, buffer + XMODEM_DATAOFFSET, i,
numbytes);
xmodem_send_packet (desc, buffer, numbytes, hashmark);
if (hashmark)
{
putchar_unfiltered ('#');
gdb_flush (gdb_stdout);
}
} /* Per-packet (or S-record) loop */
xmodem_finish_xfer (desc);
monitor_expect_prompt (NULL, 0);
putchar_unfiltered ('\n');
} /* Loadable sections */
if (hashmark)
putchar_unfiltered ('\n');
}
#endif
/* This array of registers need to match the indexes used by GDB.
This exists because the various ROM monitors use different strings
than does GDB, and don't necessarily support all the registers
either. So, typing "info reg sp" becomes a "r30". */
/* these correspond to the offsets from tm-* files from config directories */
/* g0-g14, fp, pfp, sp, rip,r3-15, pc, ac, tc, fp0-3 */
/* NOTE: "ip" is documented as "ir" in the Mon960 UG. */
/* NOTE: "ir" can't be accessed... but there's an ip and rip. */
static char *mon960_regnames[NUM_REGS] = {
/* 0 */ "pfp", "sp", "rip", "r3", "r4", "r5", "r6", "r7", \
/* 8 */ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",\
/* 16 */ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", \
/* 24 */ "g8", "g9", "g10", "g11", "g12", "g13", "g14", "fp", \
/* 32 */ "pc", "ac", "tc", "ip", "fp0", "fp1", "fp2", "fp3",\
};
/* Define the monitor command strings. Since these are passed directly
through to a printf style function, we may include formatting
strings. We also need a CR or LF on the end. */
static struct target_ops mon960_ops;
/* need to pause the monitor for timing reasons, so slow it down */
static char *mon960_inits[] = {"\n\r\r\r\r\r\r\r\r\r\r\r\r\r\r\n\r\n\r\n", NULL}; /* Exits sub-command mode & download cmds */
static struct monitor_ops mon960_cmds =
{
MO_CLR_BREAK_USES_ADDR
| MO_NO_ECHO_ON_OPEN
| MO_SEND_BREAK_ON_STOP
| MO_GETMEM_READ_SINGLE, /* flags */
mon960_inits, /* Init strings */
"go\n\r", /* continue command */
"st\n\r", /* single step */
"\n\r", /* break interrupts the program */
NULL, /* set a breakpoint */
/* can't use "br" because only 2 hw bps are supported */
NULL, /* clear a breakpoint - "de" is for hw bps */
NULL, /* clear all breakpoints */
NULL, /* fill (start end val) */
/* can't use "fi" because it takes words, not bytes */
{
/* can't use "mb", "md" or "mo" because they require interaction */
NULL, /* setmem.cmdb (addr, value) */
"md %x %x\n\r", /* setmem.cmdw (addr, value) */
NULL, /* setmem.cmdl (addr, value) */
NULL, /* setmem.cmdll (addr, value) */
NULL, /* setmem.resp_delim */
NULL, /* setmem.term */
NULL, /* setmem.term_cmd */
},
{
/* since the parsing of multiple bytes is difficult due to
interspersed addresses, we'll only read 1 value at a time,
even tho these can handle a count */
"db %x\n\r", /* getmem.cmdb (addr, #bytes) */
"ds %x\n\r", /* getmem.cmdw (addr, #swords) */
"di %x\n\r", /* getmem.cmdl (addr, #words) */
"dd %x\n\r", /* getmem.cmdll (addr, #dwords) */
" : ", /* getmem.resp_delim */
NULL, /* getmem.term */
NULL, /* getmem.term_cmd */
},
{
"md %s %x\n\r", /* setreg.cmd (name, value) */
NULL, /* setreg.resp_delim */
NULL, /* setreg.term */
NULL /* setreg.term_cmd */
},
{
"di %s\n\r", /* getreg.cmd (name) */
" : ", /* getreg.resp_delim */
NULL, /* getreg.term */
NULL, /* getreg.term_cmd */
},
"re\n\r", /* dump_registers */
"\\(\\w+\\)=\\([0-9a-fA-F]+\\)", /* register_pattern */
NULL, /* supply_register */
#ifdef USE_GENERIC_LOAD
NULL, /* load_routine (defaults to SRECs) */
NULL, /* download command */
NULL, /* load response */
#else
mon960_load, /* load_routine (defaults to SRECs) */
"do\n\r", /* download command */
"Downloading\n\r", /* load response */
#endif
"=>", /* monitor command prompt */
"\n\r", /* end-of-command delimitor */
NULL, /* optional command terminator */
&mon960_ops, /* target operations */
SERIAL_1_STOPBITS, /* number of stop bits */
mon960_regnames, /* registers names */
MONITOR_OPS_MAGIC /* magic */
};
/* invoked from monitor.c - opens the serial port */
static void
mon960_open (args, from_tty)
char *args;
int from_tty;
{
char *serial_port_name = args;
if (args)
{
char *cursor = serial_port_name = strsave (args);
while (*cursor && *cursor != ' ')
cursor++;
if (*cursor)
*cursor++ = 0;
while (*cursor == ' ')
cursor++;
}
monitor_open (serial_port_name, &mon960_cmds, from_tty);
}
void
_initialize_mon960 ()
{
init_monitor_ops (&mon960_ops);
mon960_ops.to_shortname = "mon960"; /* for the target command */
mon960_ops.to_longname = "Intel 960 rom monitor";
#ifdef USE_GENERIC_LOAD
mon960_ops.to_load = mon960_load_gen; /* FIXME - should go back and try "do" */
#endif
/* use SW breaks; target only supports 2 HW breakpoints */
mon960_ops.to_insert_breakpoint = memory_insert_breakpoint;
mon960_ops.to_remove_breakpoint = memory_remove_breakpoint;
mon960_ops.to_doc =
"Debug on an Intel 960 eval board running the Mon960 rom monitor.\n"
"Specify the serial device it is connected to (e.g. /dev/ttya).";
mon960_ops.to_open = mon960_open;
add_target (&mon960_ops);
}

File diff suppressed because it is too large Load diff

View file

@ -1,177 +0,0 @@
/* Remote debugging interface ROM monitors.
* Copyright 1990, 1991, 1992, 1996 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.
*/
#include "serial.h"
/* 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 */
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) PARAMS ((char *name, int namelen, char *val, int vallen));
void (*load_routine) PARAMS ((serial_t desc, char *file, int hashmark)); /* Download routine */
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 magic; /* Check value */
};
#define MONITOR_OPS_MAGIC 600925
/* Flag defintions */
#define MO_CLR_BREAK_USES_ADDR 0x1 /* If set, then clear breakpoint command
uses address, otherwise it uses an index
returned by the monitor. */
#define MO_FILL_USES_ADDR 0x2 /* If set, then memory fill command uses
STARTADDR, ENDADDR+1, VALUE as args, else it
uses STARTADDR, LENGTH, VALUE as args. */
#define MO_NEED_REGDUMP_AFTER_CONT 0x4 /* If set, then monitor doesn't auto-
matically supply register dump when
coming back after a continue. */
#define MO_GETMEM_NEEDS_RANGE 0x8 /* getmem needs start addr and end addr */
#define MO_GETMEM_READ_SINGLE 0x10 /* getmem can only read one loc at a time */
#define MO_HANDLE_NL 0x20 /* handle \r\n combinations */
#define MO_NO_ECHO_ON_OPEN 0x40 /* don't expect echos in monitor_open */
#define MO_SEND_BREAK_ON_STOP 0x80 /* If set, send break to stop monitor */
extern struct monitor_ops *current_monitor;
#define LOADTYPES (current_monitor->loadtypes)
#define LOADPROTOS (current_monitor->loadprotos)
#define INIT_CMD (current_monitor->init)
#define CONT_CMD (current_monitor->cont)
#define STEP_CMD (current_monitor->step)
#define SET_BREAK_CMD (current_monitor->set_break)
#define CLR_BREAK_CMD (current_monitor->clr_break)
#define SET_MEM (current_monitor->setmem)
#define GET_MEM (current_monitor->getmem)
#define LOAD_CMD (current_monitor->load)
#define GET_REG (current_monitor->regget)
#define SET_REG (current_monitor->regset)
#define CMD_END (current_monitor->cmd_end)
#define CMD_DELIM (current_monitor->cmd_delim)
#define PROMPT (current_monitor->prompt)
#define TARGET_OPS (current_monitor->target)
#define TARGET_NAME (current_monitor->target->to_shortname)
#define BAUDRATES (current_monitor->baudrates)
#define STOPBITS (current_monitor->stopbits)
#define REGNAMES(x) (current_monitor->regnames[x])
#define ROMCMD(x) (x.cmd)
#define ROMDELIM(x) (x.delim)
#define ROMRES(x) (x.result)
#define push_monitor(x) current_monitor = x;
#define SREC_SIZE 160
/*
* FIXME: These are to temporarily maintain compatability with the
* old monitor structure till remote-mon.c is fixed to work
* like the *-rom.c files.
*/
#define MEM_PROMPT (current_monitor->loadtypes)
#define MEM_SET_CMD (current_monitor->setmem)
#define MEM_DIS_CMD (current_monitor->getmem)
#define REG_DELIM (current_monitor->regset.delim)
extern void monitor_open PARAMS ((char *args, struct monitor_ops *ops, int from_tty));
extern void monitor_close PARAMS ((int quitting));
extern char *monitor_supply_register PARAMS ((int regno, char *valstr));
extern int monitor_expect PARAMS ((char *prompt, char *buf, int buflen));
extern int monitor_expect_prompt PARAMS ((char *buf, int buflen));
extern void monitor_printf PARAMS ((char *, ...))
ATTR_FORMAT(printf, 1, 2);
extern void monitor_printf_noecho PARAMS ((char *, ...))
ATTR_FORMAT(printf, 1, 2);
extern void init_monitor_ops PARAMS ((struct target_ops *));

View file

@ -1,82 +0,0 @@
# Configuration fragment for GDB.
If "{host_canonical}" =~ /m68k-apple-mpw/
forward-include "{srcdir}"config:m68k:xm-mpw.h xm.h
Set siow_lib '"{Libraries}"SIOW.o'
Else If "{host_canonical}" =~ /powerpc-apple-mpw/
forward-include "{srcdir}"config:powerpc:xm-mpw.h xm.h
Set siow_lib '"{PPCLibraries}"PPCSIOW.o'
End If
Set xdepfiles '"{o}"mac-xdep.c.o'
Set enable_cflags ""
# Make a copy of this file and give it a different name, so it
# won't be confused with GDB's serial.h.
Duplicate -y "{CIncludes}"Serial.h MacSerial.h
Echo "/* dummy */" >termio.h
If "{target_canonical}" =~ /m68k-apple-macos/
forward-include "{srcdir}"config:m68k:tm-mac.h tm.h
forward-include "{srcdir}"config:m68k:tm-m68k.h 'm68k/tm-m68k.h'
Set tdepfiles '"{o}"m68k-tdep.c.o'
Else If "{target_canonical}" =~ /powerpc-apple-macos/
forward-include "{srcdir}"config:powerpc:tm-macos.h tm.h
forward-include "{srcdir}"config:rs6000:tm-rs6000.h 'rs6000/tm-rs6000.h'
Set tdepfiles '"{o}"rs6000-tdep.c.o "{o}"xcoffread.c.o'
Else If "{target_canonical}" =~ /i386-unknown-go32/
forward-include "{srcdir}"config:i386:tm-i386v.h tm.h
Set tdepfiles '"{o}"i386-tdep.c.o'
Else If "{target_canonical}" =~ /mips-idt-ecoff/
forward-include "{srcdir}"config:mips:tm-embed.h tm.h
forward-include "{srcdir}"config:mips:tm-bigmips.h 'mips/tm-bigmips.h'
forward-include "{srcdir}"config:mips:tm-mips.h 'mips/tm-mips.h'
Set tdepfiles '"{o}"mips-tdep.c.o "{o}"remote-mips.c.o'
Else If "{target_canonical}" =~ /sh-hitachi-hms/
forward-include "{srcdir}"config:sh:tm-sh.h tm.h
Set tdepfiles '"{o}"sh-tdep.c.o'
End If
If "{target_canonical}" =~ /m68k-apple-macos/
forward-include "{srcdir}"config:m68k:nm-macos.h nm.h
Set natdepfiles '"{o}"mac-nat.c.o'
Else If "{target_canonical}" =~ /powerpc-apple-macos/
forward-include "{srcdir}"config:powerpc:nm-macos.h nm.h
Set natdepfiles '"{o}"mac-nat.c.o'
Else
forward-include "{srcdir}"config:nm-empty.h nm.h
Set natdepfiles ' '
End If
Echo '# From mpw-config.in' > "{o}"mk.tmp
Echo "TDEPFILES = " {tdepfiles} >> "{o}"mk.tmp
Echo "XDEPFILES = " {xdepfiles} >> "{o}"mk.tmp
Echo "NATDEPFILES = " {natdepfiles} >> "{o}"mk.tmp
Echo "XM_ADD_FILES = " >> "{o}"mk.tmp
Echo "TM_ADD_FILES = " >> "{o}"mk.tmp
Echo "NAT_ADD_FILES = " >> "{o}"mk.tmp
Echo "XM_CDEPS = " >> "{o}"mk.tmp
Echo "TM_CDEPS = " >> "{o}"mk.tmp
Echo "NAT_CDEPS = " >> "{o}"mk.tmp
Echo "SIOW_LIB = " {siow_lib} >> "{o}"mk.tmp
Echo "ENABLE_CFLAGS = " {enable_cflags} >> "{o}"mk.tmp
Echo '# End from mpw-config.in' >> "{o}"mk.tmp
Echo '/* config.h. Generated by mpw-configure. */' > "{o}"config.new
Echo '#include "mpw.h"' >> "{o}"config.new
MoveIfChange "{o}"config.new "{o}"config.h

View file

@ -1,167 +0,0 @@
# Sed commands that finish translating the GDB Unix Makefile to MPW syntax.
/^host_alias =/s/^/#/
/^target_alias =/s/^/#/
/^host_makefile_frag@$/d
/^target_makefile_frag@$/d
/@ENABLE_CFLAGS@/s/@ENABLE_CFLAGS@/{ENABLE_CFLAGS}/g
/^ENABLE_CFLAGS=/s/^/#/
# Edit all the symbolic definitions pointing to various libraries and such.
/^INCLUDE_DIR = /s/"{srcdir}":include/"{topsrcdir}"include:/
/^MMALLOC_DIR = /s/::mmalloc/mmalloc:/
/^MMALLOC_SRC = /s/"{srcdir}"/"{topsrcdir}"/
/^MMALLOC =/s/=.*$/=/
/#MMALLOC_DISABLE/s/^#//
/^BFD_DIR = /s/::bfd/bfd:/
/^BFD = /s/{BFD_DIR}:libbfd/{BFD_DIR}libbfd/
/^BFD_SRC = /s/"{srcdir}"/"{topsrcdir}"/
/^READLINE_DIR = /s/::readline/readline:/
/^READLINE =/s/=.*$/=/
/^READLINE_SRC = /s/"{srcdir}"/"{topsrcdir}"/
/^INCLUDE_CFLAGS = /s/$/ -i "{topsrcdir}"include:mpw: -i ::extra-include:/
/^SER_HARDWIRE =/s/ser-unix/ser-mac/
/^TERMCAP =/s/ =.*$/ =/
/@DEFS@/s/@DEFS@//g
/@YACC@/s/@YACC@/byacc/g
/@ENABLE_OBS@/s/@ENABLE_OBS@//g
/@ENABLE_CLIBS@/s/@ENABLE_CLIBS@//g
/@LIBS@/s/@LIBS@//g
/INCLUDE_DIR/s/"{s}"{INCLUDE_DIR}/{INCLUDE_DIR}/g
/INCLUDE_DIR/s/{INCLUDE_DIR}:/{INCLUDE_DIR}/g
/INCLUDE_DIR/s/"{INCLUDE_DIR}":/"{INCLUDE_DIR}"/g
/{BFD_DIR}/s/"{BFD_DIR}":/"{BFD_DIR}"/g
/{BFD_DIR}/s/\([ ]\){BFD_DIR}/\1::{BFD_DIR}/g
/{BFD_DIR}/s/\([ ]\)"{BFD_DIR}"/\1::"{BFD_DIR}"/g
/{BFD_SRC}/s/"{s}"{BFD_SRC}/{BFD_SRC}/g
/{BFD_SRC}/s/{BFD_SRC}:/{BFD_SRC}/g
/{READLINE_SRC}/s/"{s}"{READLINE_SRC}/{READLINE_SRC}/g
/^readline_headers =/,/^$/c\
readline_headers =\
/{MMALLOC_CHECK}/s/{MMALLOC_CHECK}//g
# This isn't really useful, and seems to cause nonsensical complaints.
/{ALLDEPFILES}/s/{ALLDEPFILES}//g
/^copying.c \\Option-f /,/^$/d
# Fix the syntax of bits of C code that go into version.c.
/char /s/'char .Option-x/'char */
/version/s/"{s}"version\.c/"{o}"version.c/g
/version/s/^version\.c/"{o}"version.c/
/config/s/"{s}"config\.h/"{o}"config.h/g
/config/s/^config\.h/"{o}"config.h/
/xm/s/"{s}"xm\.h/"{o}"xm.h/g
/xm/s/^xm\.h/"{o}"xm.h/
/tm/s/"{s}"tm\.h/"{o}"tm.h/g
/tm/s/^tm\.h/"{o}"tm.h/
/nm/s/"{s}"nm\.h/"{o}"nm.h/g
/nm/s/^nm\.h/"{o}"nm.h/
/exp.tab.c/s/"{s}"\([a-z0-9]*\)-exp\.tab\.c/"{o}"\1-exp.tab.c/g
/exp.tab.c/s/^\([a-z0-9]*\)-exp\.tab\.c/"{o}"\1-exp.tab.c/
/y.tab/s/"{s}"y.tab\.c/"{o}"y.tab.c/g
/y.tab/s/^y.tab\.c/"{o}"y.tab.c/
/init/s/"{s}"init\.c-tmp/"{o}"init.c-tmp/g
/init/s/^init\.c-tmp/"{o}"init.c-tmp/
/init/s/"{s}"init\.c/"{o}"init.c/g
/init/s/^init\.c/"{o}"init.c/
/"{o}"version.c \\Option-f Makefile/,/^$/c\
"{o}"version.c \\Option-f Makefile\
echo -n 'char *version = "' >"{o}"version.c\
echo -n "{VERSION}" >>"{o}"version.c\
echo '";' >>"{o}"version.c\
echo -n 'char *host_name = "' >>"{o}"version.c\
echo -n "{host_alias}" >>"{o}"version.c\
echo '";' >>"{o}"version.c\
echo -n 'char *target_name = "' >>"{o}"version.c\
echo -n "{target_alias}" >>"{o}"version.c\
echo '";' >>"{o}"version.c\
# Open-brace in a command causes much confusion; replace with the
# result from a script.
/initialize_all_files ()/c\
Echo -n 'void initialize_all_files () ' >> "{o}"init.c-tmp\
open-brace >> "{o}"init.c-tmp
# Replace the whole sed bit for init.c; it's simpler that way...
/filename=`echo $i | sed/,/esac/c\
set filename "`Echo {i} | sed \\Option-d\
-e '/^Onindy.c.o/d' \\Option-d\
-e '/^nindy.c.o/d' \\Option-d\
-e '/ttyflush.c.o/d' \\Option-d\
-e '/xdr_ld.c.o/d' \\Option-d\
-e '/xdr_ptrace.c.o/d' \\Option-d\
-e '/xdr_rdb.c.o/d' \\Option-d\
-e '/udr.c.o/d' \\Option-d\
-e '/udip2soc.c.o/d' \\Option-d\
-e '/udi2go32.c.o/d' \\Option-d\
-e '/version.c.o/d' \\Option-d\
-e '/[a-z0-9A-Z_]*-exp.tab.c.o/d' \\Option-d\
-e 's/\\.c\\.o/.c/' \\Option-d\
-e 's/^://'`"\
If "{filename}" != ""\
sed <"{s}""{filename}" >>"{o}"init.c-tmp -n \\Option-d\
-e '/^_initialize_[a-z_0-9A-Z]* *(/s/^\\([a-z_0-9A-Z]*\\).*/ {extern void \\1 (); \\1 ();}/p'\
End If
# Fix the main compile/link command.
/{CC_LD} {INTERNAL_LDFLAGS} -o gdb/,/"{o}"init.c.o {OBS} {TSOBS} {ADD_FILES} {CLIBS} {LOADLIBES}/c\
{CC_LD} {INTERNAL_LDFLAGS} -o gdb{PROG_EXT} "{o}"init.c.o {OBS} {TSOBS} {ADD_FILES} {CLIBS} {LOADLIBES} {EXTRALIBS}\
{MAKEPEF} gdb{PROG_EXT} -o gdb {MAKEPEF_TOOL_FLAGS} {MAKEPEF_FLAGS}\
{REZ} "{s}"mac-gdb.r -o gdb -append -d PROG_NAME='"'gdb'"' -d VERSION_STRING='"'{version}'"'\
/^install \\Option-f /,/^$/c\
install \\Option-f all install-only\
\
install-only \\Option-f \
Duplicate -y gdb "{bindir}"gdb\
If "`Exists SiowGDB`" != ""\
Duplicate -y SiowGDB "{bindir}"SiowGDB\
End If\
# Don't do any recursive subdir stuff.
/ subdir_do/s/{MAKE}/null-command/
# Edit out actions that only confuse MPW Make.
/^config.status \\Option-f/,/^$/d
/^Makefile \\Option-f/,/^$/d
/^"{o}"config.h \\Option-f/s/^/#/
# Add an action to build SIOWgdb.
$a\
SIOWgdb \\Option-f {OBS} {TSOBS} {ADD_DEPS} {CDEPS} "{o}"init.c.o\
Delete -i -y SIOWgdb\
{CC_LD} {INTERNAL_LDFLAGS} -t 'APPL' -c 'gdb ' -o SIOWgdb{PROG_EXT} "{o}"init.c.o {OBS} {TSOBS} {ADD_FILES} {CLIBS} {SIOW_LIB} {LOADLIBES} {EXTRALIBS}\
{MAKEPEF} SIOWgdb{PROG_EXT} -o SIOWgdb -ft 'APPL' -fc 'gdb ' {MAKEPEF_FLAGS} \
{REZ} -o SIOWgdb "{RIncludes}"siow.r -append -d __kPrefSize=5000 -d __kMinSize=2000 -d APPNAME='"'SIOWgdb'"' \
{REZ} "{s}"mac-gdb.r -o SIOWgdb -append -d VERSION_STRING='"'{version}'"'\

View file

@ -1,65 +0,0 @@
/* Low level interface to ptrace, for GDB when running under Unix.
Copyright (C) 1986, 1987, 1989 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. */
#ifdef __GNUC__
/* Bad implement execle(3). It's depend for "/bin/cc".
main()
{
printf("execle:\n");
execle(FILE, ARGS, envp);
exit(1);
}
GCC:
link a6,#0
pea LC5 ; call printf
jbsr _printf
; ; (not popd stack)
pea _envp ; call execle
clrl sp@-
pea LC4
pea LC4
pea LC4
pea LC3
pea LC6
jbsr _execle
addw #32,sp ; delayed pop !!
/bin/cc:
link.l fp,#L23
movem.l #L24,(sp)
pea L26 ; call printf
jbsr _printf
addq.l #4,sp ; <--- popd stack !!
pea _envp ; call execle
clr.l -(sp)
pea L32
*/
execle(name, args)
char *name, *args;
{
register char **env = &args;
while (*env++)
;
execve(name, (char **)&args, (char **)*env);
}
#endif

View file

@ -1,73 +0,0 @@
/* Target-machine dependent code for the NINDY monitor running on the Intel 960
Copyright (C) 1991 Free Software Foundation, Inc.
Contributed by Intel 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. */
/* Miscellaneous NINDY-dependent routines.
Some replace macros normally defined in "tm.h". */
#include "defs.h"
#include "symtab.h"
#include "frame.h"
/* 'start_frame' is a variable in the NINDY runtime startup routine
that contains the frame pointer of the 'start' routine (the routine
that calls 'main'). By reading its contents out of remote memory,
we can tell where the frame chain ends: backtraces should halt before
they display this frame. */
int
nindy_frame_chain_valid (chain, curframe)
unsigned int chain;
struct frame_info *curframe;
{
struct symbol *sym;
struct minimal_symbol *msymbol;
/* crtnindy.o is an assembler module that is assumed to be linked
* first in an i80960 executable. It contains the true entry point;
* it performs startup up initialization and then calls 'main'.
*
* 'sf' is the name of a variable in crtnindy.o that is set
* during startup to the address of the first frame.
*
* 'a' is the address of that variable in 80960 memory.
*/
static char sf[] = "start_frame";
CORE_ADDR a;
chain &= ~0x3f; /* Zero low 6 bits because previous frame pointers
contain return status info in them. */
if ( chain == 0 ){
return 0;
}
sym = lookup_symbol(sf, 0, VAR_NAMESPACE, (int *)NULL,
(struct symtab **)NULL);
if ( sym != 0 ){
a = SYMBOL_VALUE (sym);
} else {
msymbol = lookup_minimal_symbol (sf, NULL, NULL);
if (msymbol == NULL)
return 0;
a = SYMBOL_VALUE_ADDRESS (msymbol);
}
return ( chain != read_memory_integer(a,4) );
}

View file

@ -1,27 +0,0 @@
/* Print NS 32000 instructions for GDB, the GNU debugger.
Copyright 1986, 1988, 1991, 1992, 1994, 1995
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"
void
_initialize_ns32k_tdep ()
{
tm_print_insn = print_insn_ns32k;
}

View file

@ -1,181 +0,0 @@
/* Low level interface to ns532 running mach 3.0.
Copyright (C) 1992 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 <stdio.h>
#include <mach.h>
#include <mach/message.h>
#include <mach/exception.h>
#include <mach_error.h>
#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_N_OFFSET(reg) (int)(&((struct ns532_combined_state *)0)->ts.reg)
#define REG_F_OFFSET(reg) (int)(&((struct ns532_combined_state *)0)->fs.reg)
/* at reg_offset[i] is the offset to the ns532_combined_state
* location where the gdb registers[i] is stored.
*/
static int reg_offset[] =
{
REG_N_OFFSET(r0), REG_N_OFFSET(r1), REG_N_OFFSET(r2), REG_N_OFFSET(r3),
REG_N_OFFSET(r4), REG_N_OFFSET(r5), REG_N_OFFSET(r6), REG_N_OFFSET(r7),
REG_F_OFFSET(l0a), REG_F_OFFSET(l1a),REG_F_OFFSET(l2a),REG_F_OFFSET(l3a),
REG_F_OFFSET(l4a), REG_F_OFFSET(l5a),REG_F_OFFSET(l6a),REG_F_OFFSET(l7a),
REG_N_OFFSET(sp), REG_N_OFFSET(fp), REG_N_OFFSET(pc), REG_N_OFFSET(psr),
REG_F_OFFSET(fsr),
REG_F_OFFSET(l0a), REG_F_OFFSET(l2a),REG_F_OFFSET(l4a),REG_F_OFFSET(l6a)
/* @@@ 532 has more double length floating point regs, not accessed currently */
};
/* 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)], \
(char *)state+reg_offset[ regnum ], \
count*REGISTER_SIZE)
/* Store COUNT contiguous registers to thread STATE starting from REGNUM */
#define STORE_REGS(state, regnum, count) \
memcpy ((char *)state+reg_offset[ 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 (regno)
int regno;
{
kern_return_t ret;
thread_state_data_t state;
unsigned int stateCnt = NS532_COMBINED_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,
NS532_COMBINED_STATE,
state,
&stateCnt);
if (ret != KERN_SUCCESS)
message ("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 (regno)
int regno;
{
kern_return_t ret;
thread_state_data_t state;
unsigned int stateCnt = NS532_COMBINED_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,
NS532_COMBINED_STATE,
state,
&stateCnt);
if (ret != KERN_SUCCESS)
{
message ("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,
NS532_COMBINED_STATE,
state,
NS532_COMBINED_STATE_COUNT);
if (ret != KERN_SUCCESS)
message ("store_inferior_registers (set): %s",
mach_error_string (ret));
if (must_suspend_thread)
setup_thread (current_thread, 0);
}

View file

@ -1,146 +0,0 @@
/* Remote target glue for the Oki op50n based eval board.
Copyright 1995 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 "gdbcore.h"
#include "target.h"
#include "monitor.h"
#include "serial.h"
static void op50n_open PARAMS ((char *args, int from_tty));
/*
* this array of registers need to match the indexes used by GDB. The
* whole reason this exists is cause the various ROM monitors use
* different strings than GDB does, and doesn't support all the
* registers either. So, typing "info reg sp" becomes a "r30".
*/
static char *op50n_regnames[NUM_REGS] =
{
"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",
"cr11", "p", NULL, NULL, NULL, "cr15", "cr19", "cr20",
"cr21", "cr22", NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, "cr0", "cr8", "cr9", "cr10","cr12",
"cr13", "cr24", "cr25", "cr26",
};
/*
* 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 op50n_ops;
static char *op50n_inits[] = {".\r", NULL};
static struct monitor_ops op50n_cmds =
{
MO_CLR_BREAK_USES_ADDR /*| MO_GETMEM_READ_SINGLE*/, /* flags */
op50n_inits, /* Init strings */
"g\r", /* continue command */
"t\r", /* single step */
"\003.\r", /* Interrupt char */
"b %x\r", /* set a breakpoint */
"b %x,0\r", /* clear breakpoint at addr */
"bx\r", /* clear all breakpoints */
"fx %x s%x %x\r", /* memory fill cmd (addr, len, val) */
{
"sx %x %x\r", /* setmem.cmdb (addr, value) */
"sh %x %x\r", /* setmem.cmdw (addr, value) */
"s %x %x\r", /* setmem.cmdl (addr, value) */
NULL, /* setmem.cmdll (addr, value) */
NULL, /* setmem.resp_delim */
NULL, /* setmem.term */
NULL, /* setmem.term_cmd */
},
#if 0
{
"sx %x\r", /* getmem.cmdb (addr, len) */
"sh %x\r", /* getmem.cmdw (addr, len) */
"s %x\r", /* getmem.cmdl (addr, len) */
NULL, /* getmem.cmdll (addr, len) */
" : ", /* getmem.resp_delim */
" ", /* getmem.term */
".\r", /* getmem.term_cmd */
},
#else
{
"dx %x s%x\r", /* getmem.cmdb (addr, len) */
NULL, /* getmem.cmdw (addr, len) */
NULL, /* getmem.cmdl (addr, len) */
NULL, /* getmem.cmdll (addr, len) */
" : ", /* getmem.resp_delim */
NULL, /* getmem.term */
NULL, /* getmem.term_cmd */
},
#endif
{
"x %s %x\r", /* setreg.cmd (name, value) */
NULL, /* setreg.resp_delim */
NULL, /* setreg.term */
NULL, /* setreg.term_cmd */
},
{
"x %s\r", /* getreg.cmd (name) */
"=", /* getreg.resp_delim */
" ", /* getreg.term */
".\r", /* getreg.term_cmd */
},
NULL, /* dump_registers */
NULL, /* register_pattern */
NULL, /* supply_register */
NULL, /* load routine */
"r 0\r", /* download command */
NULL, /* load response */
"\n#", /* monitor command prompt */
"\r", /* end-of-command delimitor */
NULL, /* optional command terminator */
&op50n_ops, /* target operations */
SERIAL_1_STOPBITS, /* number of stop bits */
op50n_regnames, /* register names */
MONITOR_OPS_MAGIC /* magic */
};
static void
op50n_open (args, from_tty)
char *args;
int from_tty;
{
monitor_open (args, &op50n_cmds, from_tty);
}
void
_initialize_op50n ()
{
init_monitor_ops (&op50n_ops);
op50n_ops.to_shortname = "op50n";
op50n_ops.to_longname = "Oki's debug monitor for the Op50n Eval board";
op50n_ops.to_doc = "Debug on a Oki OP50N eval board.\n\
Specify the serial device it is connected to (e.g. /dev/ttya).";
op50n_ops.to_open = op50n_open;
add_target (&op50n_ops);
}

View file

@ -1,955 +0,0 @@
/* Handle OSF/1 shared libraries for GDB, the GNU Debugger.
Copyright 1993, 1994, 1995, 1996 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 "gnu-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 PARAMS ((CORE_ADDR, char *, int, int));
static int
ldr_read_memory (memaddr, myaddr, len, readstring)
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);
free (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 PARAMS ((int, int)); /* In libiberty */
/* Local function prototypes */
static void
sharedlibrary_command PARAMS ((char *, int));
static void
info_sharedlibrary_command PARAMS ((char *, int));
static int
symbol_add_stub PARAMS ((char *));
static struct so_list *
find_solib PARAMS ((struct so_list *));
static struct link_map *
first_link_map_member PARAMS ((void));
static struct link_map *
next_link_map_member PARAMS ((struct so_list *));
static void
xfer_link_map_member PARAMS ((struct so_list *, struct link_map *));
static void
solib_map_sections PARAMS ((struct so_list *));
/*
LOCAL FUNCTION
solib_map_sections -- open bfd and build sections for shared lib
SYNOPSIS
static void 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 void
solib_map_sections (so)
struct so_list *so;
{
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 (free, 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 = true;
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);
}
/*
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 ()
{
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 (so_list_ptr)
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 (so_list_ptr, lm)
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);
free (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);
free (buffer);
}
}
#endif
solib_map_sections (so_list_ptr);
}
}
/*
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 (so_list_ptr)
struct so_list *so_list_ptr; /* Last lm or NULL for first one */
{
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 (arg)
char *arg;
{
register struct so_list *so = (struct so_list *) arg; /* catch_errs bogon */
so -> objfile = symbol_file_add (so -> so_name, so -> from_tty,
so -> textsection -> addr,
0, 0, 0);
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)
DESCRIPTION
*/
void
solib_add (arg_string, from_tty, target)
char *arg_string;
int from_tty;
struct target_ops *target;
{
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 ((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)
{
int update_coreops;
/* We must update the to_sections field in the core_ops structure
here, otherwise we dereference a potential dangling pointer
for each call to target_read/write_memory within this routine. */
update_coreops = core_ops.to_sections == target->to_sections;
/* Reallocate the target's section table including the new size. */
if (target -> to_sections)
{
old = target -> to_sections_end - target -> to_sections;
target -> to_sections = (struct section_table *)
xrealloc ((char *)target -> to_sections,
(sizeof (struct section_table)) * (count + old));
}
else
{
old = 0;
target -> to_sections = (struct section_table *)
xmalloc ((sizeof (struct section_table)) * count);
}
target -> to_sections_end = target -> to_sections + (count + old);
/* Update the to_sections field in the core_ops structure
if needed. */
if (update_coreops)
{
core_ops.to_sections = target->to_sections;
core_ops.to_sections_end = target->to_sections_end;
}
/* Add these section table entries to the target's table. */
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 (ignore, from_tty)
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 exec 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 (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()
{
struct so_list *next;
char *bfd_filename;
while (so_list_head)
{
if (so_list_head -> sections)
{
free ((PTR)so_list_head -> sections);
}
if (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)
free ((PTR)bfd_filename);
free ((PTR)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()
{
/* 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 (-1, 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. */
if (auto_solib_add)
solib_add ((char *) 0, 0, (struct target_ops *) 0);
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 (args, from_tty)
char *args;
int from_tty;
{
dont_repeat ();
solib_add (args, from_tty, (struct target_ops *) 0);
}
void
_initialize_solib()
{
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_zinteger,
(char *) &auto_solib_add,
"Set autoloading of shared library symbols.\n\
If nonzero, symbols from all shared object libraries will be loaded\n\
automatically when the inferior begins execution or when the dynamic linker\n\
informs gdb that a new library has been loaded. Otherwise, symbols\n\
must be loaded manually, using `sharedlibrary'.",
&setlist),
&showlist);
}

View file

@ -1,233 +0,0 @@
/* Remote debugging interface for PPCbug (PowerPC) Rom monitor
for GDB, the GNU debugger.
Copyright 1995 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"
static void ppcbug_open PARAMS ((char *args, int from_tty));
static void
ppcbug_supply_register (regname, regnamelen, val, vallen)
char *regname;
int regnamelen;
char *val;
int vallen;
{
int regno = 0, base = 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[NUM_REGS] =
{
"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};
#define PPC_CMDS(LOAD_CMD, OPS) \
{ \
MO_CLR_BREAK_USES_ADDR | MO_HANDLE_NL, \
ppcbug_inits, /* Init strings */ \
"g\r", /* continue command */ \
"t\r", /* single step */ \
NULL, /* interrupt command */ \
"br %x\r", /* set a breakpoint */ \
"nobr %x\r", /* clear a breakpoint */ \
"nobr\r", /* clear all breakpoints */ \
"bf %x:%x %x;b\r", /* fill (start count val) */ \
{ \
"ms %x %02x\r", /* setmem.cmdb (addr, value) */ \
"ms %x %04x\r", /* setmem.cmdw (addr, value) */ \
"ms %x %08x\r", /* setmem.cmdl (addr, value) */ \
NULL, /* setmem.cmdll (addr, value) */ \
NULL, /* setreg.resp_delim */ \
NULL, /* setreg.term */ \
NULL, /* setreg.term_cmd */ \
}, \
{ \
"md %x:%x;b\r", /* getmem.cmdb (addr, len) */ \
"md %x:%x;b\r", /* getmem.cmdw (addr, len) */ \
"md %x:%x;b\r", /* getmem.cmdl (addr, len) */ \
NULL, /* getmem.cmdll (addr, len) */ \
" ", /* getmem.resp_delim */ \
NULL, /* getmem.term */ \
NULL, /* getmem.term_cmd */ \
}, \
{ \
"rs %s %x\r", /* setreg.cmd (name, value) */ \
NULL, /* setreg.resp_delim */ \
NULL, /* setreg.term */ \
NULL /* setreg.term_cmd */ \
}, \
{ \
"rs %s\r", /* getreg.cmd (name) */ \
"=", /* getreg.resp_delim */ \
NULL, /* getreg.term */ \
NULL /* getreg.term_cmd */ \
}, \
"rd\r", /* dump_registers */ \
"\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)", /* register_pattern */ \
ppcbug_supply_register, /* supply_register */ \
NULL, /* load_routine (defaults to SRECs) */ \
LOAD_CMD, /* download command */ \
NULL, /* load response */ \
"PPC1-Bug>", /* monitor command prompt */ \
"\r", /* end-of-line terminator */ \
NULL, /* optional command terminator */ \
&OPS, /* target operations */ \
SERIAL_1_STOPBITS, /* number of stop bits */ \
ppcbug_regnames, /* registers names */ \
MONITOR_OPS_MAGIC /* magic */ \
}
static struct monitor_ops ppcbug_cmds0 = PPC_CMDS("lo 0\r", ppcbug_ops0);
static struct monitor_ops ppcbug_cmds1 = PPC_CMDS("lo 1\r", ppcbug_ops1);
static void
ppcbug_open0(args, from_tty)
char *args;
int from_tty;
{
monitor_open (args, &ppcbug_cmds0, from_tty);
}
static void
ppcbug_open1(args, from_tty)
char *args;
int from_tty;
{
monitor_open (args, &ppcbug_cmds1, from_tty);
}
void
_initialize_ppcbug_rom ()
{
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

View file

@ -1,209 +0,0 @@
/* Native-dependent code for ptx 4.0
Copyright 1988, 1989, 1991, 1992 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 <sys/procfs.h>
#include <sys/ptrace.h>
#include <sys/param.h>
#include <fcntl.h>
/* 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 (gregsetp)
gregset_t *gregsetp;
{
supply_register(EAX_REGNUM, (char *)&(*gregsetp)[EAX]);
supply_register(EDX_REGNUM, (char *)&(*gregsetp)[EDX]);
supply_register(ECX_REGNUM, (char *)&(*gregsetp)[ECX]);
supply_register(EBX_REGNUM, (char *)&(*gregsetp)[EBX]);
supply_register(ESI_REGNUM, (char *)&(*gregsetp)[ESI]);
supply_register(EDI_REGNUM, (char *)&(*gregsetp)[EDI]);
supply_register(ESP_REGNUM, (char *)&(*gregsetp)[UESP]);
supply_register(EBP_REGNUM, (char *)&(*gregsetp)[EBP]);
supply_register(EIP_REGNUM, (char *)&(*gregsetp)[EIP]);
supply_register(EFLAGS_REGNUM, (char *)&(*gregsetp)[EFL]);
}
void
fill_gregset (gregsetp, regno)
gregset_t *gregsetp;
int regno;
{
int regi;
extern char registers[];
for (regi = 0 ; regi < NUM_REGS ; regi++)
{
if ((regno == -1) || (regno == regi))
{
(*gregsetp)[regi] = *(greg_t *)&registers[REGISTER_BYTE (regi)];
}
}
}
#if defined (FP0_REGNUM)
/* 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. */
void
supply_fpregset (fpregsetp)
fpregset_t *fpregsetp;
{
supply_fpu_registers((struct fpusave *)&fpregsetp->fp_reg_set);
supply_fpa_registers((struct fpasave *)&fpregsetp->f_wregs);
}
/* 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 (fpregsetp, regno)
fpregset_t *fpregsetp;
int regno;
{
int regi;
char *to;
char *from;
extern char registers[];
/* FIXME: see m68k-tdep.c for an example, for the m68k. */
}
#endif /* defined (FP0_REGNUM) */
/*
* This doesn't quite do the same thing as the procfs.c version, but give
* it the same name so we don't have to put an ifdef in solib.c.
*/
/* this could use elf_interpreter() from elfread.c */
int
proc_iterate_over_mappings(func)
int (*func) PARAMS ((int, CORE_ADDR));
{
vaddr_t curseg, memptr;
pt_vseg_t pv;
int rv, cmperr;
sec_ptr interp_sec;
char *interp_content;
int interp_fd, funcstat;
unsigned int size;
char buf1[NBPG], buf2[NBPG];
/*
* The following is really vile. We can get the name of the
* shared library from the exec_bfd, and we can get a list of
* each virtual memory segment, but there is no simple way to
* find the mapped segment from the shared library (ala
* procfs's PIOCOPENMEM). As a pretty nasty kludge, we
* compare the virtual memory segment to the contents of the
* .interp file. If they match, we assume that we've got the
* right one.
*/
/*
* TODO: for attach, use XPT_OPENT to get the executable, in
* case we're attached without knowning the executable's
* filename.
*/
#ifdef VERBOSE_DEBUG
printf("proc_iter\n");
#endif
interp_sec = bfd_get_section_by_name(exec_bfd, ".interp");
if (!interp_sec) {
return 0;
}
size = bfd_section_size(exec_bfd, interp_sec);
interp_content = alloca(size);
if (0 == bfd_get_section_contents(exec_bfd, interp_sec,
interp_content, (file_ptr)0, size)) {
return 0;
}
#ifdef VERBOSE_DEBUG
printf("proc_iter: \"%s\"\n", interp_content);
#endif
interp_fd = open(interp_content, O_RDONLY, 0);
if (-1 == interp_fd) {
return 0;
}
curseg = 0;
while (1) {
rv = ptrace(PT_NEXT_VSEG, inferior_pid, &pv, curseg);
#ifdef VERBOSE_DEBUG
printf("PT_NEXT_VSEG: rv %d errno %d\n", rv, errno);
#endif
if (-1 == rv)
break;
if (0 == rv)
break;
#ifdef VERBOSE_DEBUG
printf("pv.pv_start 0x%x pv_size 0x%x pv_prot 0x%x\n",
pv.pv_start, pv.pv_size, pv.pv_prot);
#endif
curseg = pv.pv_start + pv.pv_size;
rv = lseek(interp_fd, 0, SEEK_SET);
if (-1 == rv) {
perror("lseek");
close(interp_fd);
return 0;
}
for (memptr = pv.pv_start; memptr < pv.pv_start + pv.pv_size;
memptr += NBPG) {
#ifdef VERBOSE_DEBUG
printf("memptr 0x%x\n", memptr);
#endif
rv = read(interp_fd, buf1, NBPG);
if (-1 == rv) {
perror("read");
close(interp_fd);
return 0;
}
rv = ptrace(PT_RDATA_PAGE, inferior_pid, buf2,
memptr);
if (-1 == rv) {
perror("ptrace");
close(interp_fd);
return 0;
}
cmperr = memcmp(buf1, buf2, NBPG);
if (cmperr)
break;
}
if (0 == cmperr) {
/* this is it */
funcstat = (*func)(interp_fd, pv.pv_start);
break;
}
}
close(interp_fd);
return 0;
}

View file

@ -1,452 +0,0 @@
/* Pyramid target-dependent code for GDB.
Copyright (C) 1988, 1989, 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. */
#include "defs.h"
/*** Prettier register printing. ***/
/* Print registers in the same format as pyramid's dbx, adb, sdb. */
pyr_print_registers(reg_buf, regnum)
long *reg_buf[];
{
register int regno;
int usp, ksp;
struct user u;
for (regno = 0; regno < 16; regno++) {
printf_unfiltered/*_filtered*/ ("%6.6s: %8x %6.6s: %8x %6s: %8x %6s: %8x\n",
reg_names[regno], reg_buf[regno],
reg_names[regno+16], reg_buf[regno+16],
reg_names[regno+32], reg_buf[regno+32],
reg_names[regno+48], reg_buf[regno+48]);
}
usp = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) ((char *)&u.u_pcb.pcb_usp) -
((char *)&u), 0);
ksp = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) ((char *)&u.u_pcb.pcb_ksp) -
((char *)&u), 0);
printf_unfiltered/*_filtered*/ ("\n%6.6s: %8x %6.6s: %8x (%08x) %6.6s %8x\n",
reg_names[CSP_REGNUM],reg_buf[CSP_REGNUM],
reg_names[KSP_REGNUM], reg_buf[KSP_REGNUM], ksp,
"usp", usp);
}
/* Print the register regnum, or all registers if regnum is -1.
fpregs is currently ignored. */
pyr_do_registers_info (regnum, fpregs)
int regnum;
int fpregs;
{
/* On a pyr, we know a virtual register can always fit in an long.
Here (and elsewhere) we take advantage of that. Yuk. */
long raw_regs[MAX_REGISTER_RAW_SIZE*NUM_REGS];
register int i;
for (i = 0 ; i < 64 ; i++) {
read_relative_register_raw_bytes(i, raw_regs+i);
}
if (regnum == -1)
pyr_print_registers (raw_regs, regnum);
else
for (i = 0; i < NUM_REGS; i++)
if (i == regnum) {
long val = raw_regs[i];
fputs_filtered (reg_names[i], stdout);
printf_filtered(":");
print_spaces_filtered (6 - strlen (reg_names[i]), stdout);
if (val == 0)
printf_filtered ("0");
else
printf_filtered ("%s %d", local_hex_string_custom(val,"08"), val);
printf_filtered("\n");
}
}
/*** Debugging editions of various macros from m-pyr.h ****/
CORE_ADDR frame_locals_address (frame)
struct frame_info *frame;
{
register int addr = find_saved_register (frame,CFP_REGNUM);
register int result = read_memory_integer (addr, 4);
#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
fprintf_unfiltered (stderr,
"\t[[..frame_locals:%8x, %s= %x @%x fcfp= %x foo= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n",
frame->frame,
reg_names[CFP_REGNUM],
result, addr,
frame->frame_cfp, (CFP_REGNUM),
read_register(13), read_register(29), read_register(61),
find_saved_register(frame, 61));
#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
/* FIXME: I thought read_register (CFP_REGNUM) should be the right answer;
or at least CFP_REGNUM relative to FRAME (ie, result).
There seems to be a bug in the way the innermost frame is set up. */
return ((frame->next) ? result: frame->frame_cfp);
}
CORE_ADDR frame_args_addr (frame)
struct frame_info *frame;
{
register int addr = find_saved_register (frame,CFP_REGNUM);
register int result = read_memory_integer (addr, 4);
#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
fprintf_unfiltered (stderr,
"\t[[..frame_args:%8x, %s= %x @%x fcfp= %x r_r= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n",
frame->frame,
reg_names[CFP_REGNUM],
result, addr,
frame->frame_cfp, read_register(CFP_REGNUM),
read_register(13), read_register(29), read_register(61),
find_saved_register(frame, 61));
#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
/* FIXME: I thought read_register (CFP_REGNUM) should be the right answer;
or at least CFP_REGNUM relative to FRAME (ie, result).
There seems to be a bug in the way the innermost frame is set up. */
return ((frame->next) ? result: frame->frame_cfp);
}
#include "symtab.h"
#include "opcode/pyr.h"
#include "gdbcore.h"
/* A couple of functions used for debugging frame-handling on
Pyramids. (The Pyramid-dependent handling of register values for
windowed registers is known to be buggy.)
When debugging, these functions can supplant the normal definitions of some
of the macros in tm-pyramid.h The quantity of information produced
when these functions are used makes the gdb unusable as a
debugger for user programs. */
extern unsigned pyr_saved_pc(), pyr_frame_chain();
CORE_ADDR pyr_frame_chain(frame)
CORE_ADDR frame;
{
int foo=frame - CONTROL_STACK_FRAME_SIZE;
/* printf_unfiltered ("...following chain from %x: got %x\n", frame, foo);*/
return foo;
}
CORE_ADDR pyr_saved_pc(frame)
CORE_ADDR frame;
{
int foo=0;
foo = read_memory_integer (((CORE_ADDR)(frame))+60, 4);
printf_unfiltered ("..reading pc from frame 0x%0x+%d regs: got %0x\n",
frame, 60/4, foo);
return foo;
}
/* Pyramid instructions are never longer than this many bytes. */
#define MAXLEN 24
/* Number of elements in the opcode table. */
/*const*/ static int nopcodes = (sizeof (pyr_opcodes) / sizeof( pyr_opcodes[0]));
#define NOPCODES (nopcodes)
/* Let's be byte-independent so we can use this as a cross-assembler. */
#define NEXTLONG(p) \
(p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
/* Print one instruction at address MEMADDR in debugged memory,
on STREAM. Returns length of the instruction, in bytes. */
int
pyr_print_insn (memaddr, stream)
CORE_ADDR memaddr;
FILE *stream;
{
unsigned char buffer[MAXLEN];
register int i, nargs, insn_size =4;
register unsigned char *p;
register char *d;
register int insn_opcode, operand_mode;
register int index_multiplier, index_reg_regno, op_1_regno, op_2_regno ;
long insn; /* first word of the insn, not broken down. */
pyr_insn_format insn_decode; /* the same, broken out into op{code,erands} */
long extra_1, extra_2;
read_memory (memaddr, buffer, MAXLEN);
insn_decode = *((pyr_insn_format *) buffer);
insn = * ((int *) buffer);
insn_opcode = insn_decode.operator;
operand_mode = insn_decode.mode;
index_multiplier = insn_decode.index_scale;
index_reg_regno = insn_decode.index_reg;
op_1_regno = insn_decode.operand_1;
op_2_regno = insn_decode.operand_2;
if (*((int *)buffer) == 0x0) {
/* "halt" looks just like an invalid "jump" to the insn decoder,
so is dealt with as a special case */
fprintf_unfiltered (stream, "halt");
return (4);
}
for (i = 0; i < NOPCODES; i++)
if (pyr_opcodes[i].datum.code == insn_opcode)
break;
if (i == NOPCODES)
/* FIXME: Handle unrecognised instructions better. */
fprintf_unfiltered (stream, "???\t#%08x\t(op=%x mode =%x)",
insn, insn_decode.operator, insn_decode.mode);
else
{
/* Print the mnemonic for the instruction. Pyramid insn operands
are so regular that we can deal with almost all of them
separately.
Unconditional branches are an exception: they are encoded as
conditional branches (branch if false condition, I think)
with no condition specified. The average user will not be
aware of this. To maintain their illusion that an
unconditional branch insn exists, we will have to FIXME to
treat the insn mnemnonic of all branch instructions here as a
special case: check the operands of branch insn and print an
appropriate mnemonic. */
fprintf_unfiltered (stream, "%s\t", pyr_opcodes[i].name);
/* Print the operands of the insn (as specified in
insn.operand_mode).
Branch operands of branches are a special case: they are a word
offset, not a byte offset. */
if (insn_decode.operator == 0x01 || insn_decode.operator == 0x02) {
register int bit_codes=(insn >> 16)&0xf;
register int i;
register int displacement = (insn & 0x0000ffff) << 2;
static char cc_bit_names[] = "cvzn"; /* z,n,c,v: strange order? */
/* Is bfc and no bits specified an unconditional branch?*/
for (i=0;i<4;i++) {
if ((bit_codes) & 0x1)
fputc_unfiltered (cc_bit_names[i], stream);
bit_codes >>= 1;
}
fprintf_unfiltered (stream, ",%0x",
displacement + memaddr);
return (insn_size);
}
switch (operand_mode) {
case 0:
fprintf_unfiltered (stream, "%s,%s",
reg_names [op_1_regno],
reg_names [op_2_regno]);
break;
case 1:
fprintf_unfiltered (stream, " 0x%0x,%s",
op_1_regno,
reg_names [op_2_regno]);
break;
case 2:
read_memory (memaddr+4, buffer, MAXLEN);
insn_size += 4;
extra_1 = * ((int *) buffer);
fprintf_unfiltered (stream, " $0x%0x,%s",
extra_1,
reg_names [op_2_regno]);
break;
case 3:
fprintf_unfiltered (stream, " (%s),%s",
reg_names [op_1_regno],
reg_names [op_2_regno]);
break;
case 4:
read_memory (memaddr+4, buffer, MAXLEN);
insn_size += 4;
extra_1 = * ((int *) buffer);
fprintf_unfiltered (stream, " 0x%0x(%s),%s",
extra_1,
reg_names [op_1_regno],
reg_names [op_2_regno]);
break;
/* S1 destination mode */
case 5:
fprintf_unfiltered (stream,
((index_reg_regno) ? "%s,(%s)[%s*%1d]" : "%s,(%s)"),
reg_names [op_1_regno],
reg_names [op_2_regno],
reg_names [index_reg_regno],
index_multiplier);
break;
case 6:
fprintf_unfiltered (stream,
((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]"
: " $%#0x,(%s)"),
op_1_regno,
reg_names [op_2_regno],
reg_names [index_reg_regno],
index_multiplier);
break;
case 7:
read_memory (memaddr+4, buffer, MAXLEN);
insn_size += 4;
extra_1 = * ((int *) buffer);
fprintf_unfiltered (stream,
((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]"
: " $%#0x,(%s)"),
extra_1,
reg_names [op_2_regno],
reg_names [index_reg_regno],
index_multiplier);
break;
case 8:
fprintf_unfiltered (stream,
((index_reg_regno) ? " (%s),(%s)[%s*%1d]" : " (%s),(%s)"),
reg_names [op_1_regno],
reg_names [op_2_regno],
reg_names [index_reg_regno],
index_multiplier);
break;
case 9:
read_memory (memaddr+4, buffer, MAXLEN);
insn_size += 4;
extra_1 = * ((int *) buffer);
fprintf_unfiltered (stream,
((index_reg_regno)
? "%#0x(%s),(%s)[%s*%1d]"
: "%#0x(%s),(%s)"),
extra_1,
reg_names [op_1_regno],
reg_names [op_2_regno],
reg_names [index_reg_regno],
index_multiplier);
break;
/* S2 destination mode */
case 10:
read_memory (memaddr+4, buffer, MAXLEN);
insn_size += 4;
extra_1 = * ((int *) buffer);
fprintf_unfiltered (stream,
((index_reg_regno) ? "%s,%#0x(%s)[%s*%1d]" : "%s,%#0x(%s)"),
reg_names [op_1_regno],
extra_1,
reg_names [op_2_regno],
reg_names [index_reg_regno],
index_multiplier);
break;
case 11:
read_memory (memaddr+4, buffer, MAXLEN);
insn_size += 4;
extra_1 = * ((int *) buffer);
fprintf_unfiltered (stream,
((index_reg_regno) ?
" $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"),
op_1_regno,
extra_1,
reg_names [op_2_regno],
reg_names [index_reg_regno],
index_multiplier);
break;
case 12:
read_memory (memaddr+4, buffer, MAXLEN);
insn_size += 4;
extra_1 = * ((int *) buffer);
read_memory (memaddr+8, buffer, MAXLEN);
insn_size += 4;
extra_2 = * ((int *) buffer);
fprintf_unfiltered (stream,
((index_reg_regno) ?
" $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"),
extra_1,
extra_2,
reg_names [op_2_regno],
reg_names [index_reg_regno],
index_multiplier);
break;
case 13:
read_memory (memaddr+4, buffer, MAXLEN);
insn_size += 4;
extra_1 = * ((int *) buffer);
fprintf_unfiltered (stream,
((index_reg_regno)
? " (%s),%#0x(%s)[%s*%1d]"
: " (%s),%#0x(%s)"),
reg_names [op_1_regno],
extra_1,
reg_names [op_2_regno],
reg_names [index_reg_regno],
index_multiplier);
break;
case 14:
read_memory (memaddr+4, buffer, MAXLEN);
insn_size += 4;
extra_1 = * ((int *) buffer);
read_memory (memaddr+8, buffer, MAXLEN);
insn_size += 4;
extra_2 = * ((int *) buffer);
fprintf_unfiltered (stream,
((index_reg_regno) ? "%#0x(%s),%#0x(%s)[%s*%1d]"
: "%#0x(%s),%#0x(%s) "),
extra_1,
reg_names [op_1_regno],
extra_2,
reg_names [op_2_regno],
reg_names [index_reg_regno],
index_multiplier);
break;
default:
fprintf_unfiltered (stream,
((index_reg_regno) ? "%s,%s [%s*%1d]" : "%s,%s"),
reg_names [op_1_regno],
reg_names [op_2_regno],
reg_names [index_reg_regno],
index_multiplier);
fprintf_unfiltered (stream,
"\t\t# unknown mode in %08x",
insn);
break;
} /* switch */
}
{
return insn_size;
}
abort ();
}

View file

@ -1,370 +0,0 @@
/* Low level Pyramid interface to ptrace, for GDB when running under Unix.
Copyright (C) 1988, 1989, 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. */
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/ioctl.h>
/* #include <fcntl.h> Can we live without this? */
#include "gdbcore.h"
#include <sys/user.h> /* After a.out.h */
#include <sys/file.h>
#include "gdb_stat.h"
void
fetch_inferior_registers (regno)
int regno;
{
register int datum;
register unsigned int regaddr;
int reg_buf[NUM_REGS+1];
struct user u;
register int skipped_frames = 0;
registers_fetched ();
for (regno = 0; regno < 64; regno++) {
reg_buf[regno] = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) regno, 0);
#if defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
printf_unfiltered ("Fetching register %s, got %0x\n",
reg_names[regno],
reg_buf[regno]);
#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
if (reg_buf[regno] == -1 && errno == EIO) {
printf_unfiltered("fetch_interior_registers: fetching register %s\n",
reg_names[regno]);
errno = 0;
}
supply_register (regno, reg_buf+regno);
}
/* that leaves regs 64, 65, and 66 */
datum = ptrace (3, inferior_pid,
(PTRACE_ARG3_TYPE) (((char *)&u.u_pcb.pcb_csp) -
((char *)&u)), 0);
/* FIXME: Find the Current Frame Pointer (CFP). CFP is a global
register (ie, NOT windowed), that gets saved in a frame iff
the code for that frame has a prologue (ie, "adsf N"). If
there is a prologue, the adsf insn saves the old cfp in
pr13, cfp is set to sp, and N bytes of locals are allocated
(sp is decremented by n).
This makes finding CFP hard. I guess the right way to do it
is:
- If this is the innermost frame, believe ptrace() or
the core area.
- Otherwise:
Find the first insn of the current frame.
- find the saved pc;
- find the call insn that saved it;
- figure out where the call is to;
- if the first insn is an adsf, we got a frame
pointer. */
/* Normal processors have separate stack pointers for user and
kernel mode. Getting the last user mode frame on such
machines is easy: the kernel context of the ptrace()'d
process is on the kernel stack, and the USP points to what
we want. But Pyramids only have a single cfp for both user and
kernel mode. And processes being ptrace()'d have some
kernel-context control frames on their stack.
To avoid tracing back into the kernel context of an inferior,
we skip 0 or more contiguous control frames where the pc is
in the kernel. */
while (1) {
register int inferior_saved_pc;
inferior_saved_pc = ptrace (1, inferior_pid,
(PTRACE_ARG3_TYPE) (datum+((32+15)*4)), 0);
if (inferior_saved_pc > 0) break;
#if defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
printf_unfiltered("skipping kernel frame %08x, pc=%08x\n", datum,
inferior_saved_pc);
#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
skipped_frames++;
datum -= CONTROL_STACK_FRAME_SIZE;
}
reg_buf[CSP_REGNUM] = datum;
supply_register(CSP_REGNUM, reg_buf+CSP_REGNUM);
#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
if (skipped_frames) {
fprintf_unfiltered (stderr,
"skipped %d frames from %x to %x; cfp was %x, now %x\n",
skipped_frames, reg_buf[CSP_REGNUM]);
}
#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
}
/* 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 (regno)
int regno;
{
register unsigned int regaddr;
char buf[80];
if (regno >= 0)
{
if ((0 <= regno) && (regno < 64)) {
/*regaddr = register_addr (regno, offset);*/
regaddr = regno;
errno = 0;
ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing register number %d", regno);
perror_with_name (buf);
}
}
}
else
{
for (regno = 0; regno < NUM_REGS; regno++)
{
/*regaddr = register_addr (regno, offset);*/
regaddr = regno;
errno = 0;
ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing all regs, number %d", regno);
perror_with_name (buf);
}
}
}
/*** Extensions to core and dump files, for GDB. */
extern unsigned int last_frame_offset;
#ifdef PYRAMID_CORE
/* Can't make definitions here static, since corefile.c needs them
to do bounds checking on the core-file areas. O well. */
/* have two stacks: one for data, one for register windows. */
extern CORE_ADDR reg_stack_start;
extern CORE_ADDR reg_stack_end;
/* need this so we can find the global registers: they never get saved. */
CORE_ADDR global_reg_offset;
static CORE_ADDR last_frame_address;
CORE_ADDR last_frame_offset;
/* Address in core file of start of register window stack area.
Don't know if is this any of meaningful, useful or necessary. */
extern int reg_stack_offset;
#endif /* PYRAMID_CORE */
/* Work with core dump and executable files, for GDB.
This code would be in corefile.c if it weren't machine-dependent. */
void
core_file_command (filename, from_tty)
char *filename;
int from_tty;
{
int val;
extern char registers[];
/* Discard all vestiges of any previous core file
and mark data and stack spaces as empty. */
if (corefile)
free (corefile);
corefile = 0;
if (corechan >= 0)
close (corechan);
corechan = -1;
data_start = 0;
data_end = 0;
stack_start = STACK_END_ADDR;
stack_end = STACK_END_ADDR;
#ifdef PYRAMID_CORE
reg_stack_start = CONTROL_STACK_ADDR;
reg_stack_end = CONTROL_STACK_ADDR; /* this isn't strictly true...*/
#endif /* PYRAMID_CORE */
/* Now, if a new core file was specified, open it and digest it. */
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
if (have_inferior_p ())
error ("To look at a core file, you must kill the program with \"kill\".");
corechan = open (filename, O_RDONLY, 0);
if (corechan < 0)
perror_with_name (filename);
/* 4.2-style (and perhaps also sysV-style) core dump file. */
{
struct user u;
unsigned int reg_offset;
val = myread (corechan, &u, sizeof u);
if (val < 0)
perror_with_name ("Not a core file: reading upage");
if (val != sizeof u)
error ("Not a core file: could only read %d bytes", val);
data_start = exec_data_start;
data_end = data_start + NBPG * u.u_dsize;
data_offset = NBPG * UPAGES;
stack_offset = NBPG * (UPAGES + u.u_dsize);
/* find registers in core file */
#ifdef PYRAMID_PTRACE
stack_start = stack_end - NBPG * u.u_ussize;
reg_stack_offset = stack_offset + (NBPG *u.u_ussize);
reg_stack_end = reg_stack_start + NBPG * u.u_cssize;
last_frame_address = ((int) u.u_pcb.pcb_csp);
last_frame_offset = reg_stack_offset + last_frame_address
- CONTROL_STACK_ADDR ;
global_reg_offset = (char *)&u - (char *)&u.u_pcb.pcb_gr0 ;
/* skip any control-stack frames that were executed in the
kernel. */
while (1) {
char buf[4];
val = lseek (corechan, last_frame_offset+(47*4), 0);
if (val < 0)
perror_with_name (filename);
val = myread (corechan, buf, sizeof buf);
if (val < 0)
perror_with_name (filename);
if (*(int *)buf >= 0)
break;
printf_unfiltered ("skipping frame %s\n", local_hex_string (last_frame_address));
last_frame_offset -= CONTROL_STACK_FRAME_SIZE;
last_frame_address -= CONTROL_STACK_FRAME_SIZE;
}
reg_offset = last_frame_offset;
#if 1 || defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
printf_unfiltered ("Control stack pointer = %s\n",
local_hex_string (u.u_pcb.pcb_csp));
printf_unfiltered ("offset to control stack %d outermost frame %d (%s)\n",
reg_stack_offset, reg_offset, local_hex_string (last_frame_address));
#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
#else /* not PYRAMID_CORE */
stack_start = stack_end - NBPG * u.u_ssize;
reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
#endif /* not PYRAMID_CORE */
#ifdef __not_on_pyr_yet
/* Some machines put an absolute address in here and some put
the offset in the upage of the regs. */
reg_offset = (int) u.u_ar0;
if (reg_offset > NBPG * UPAGES)
reg_offset -= KERNEL_U_ADDR;
#endif
/* I don't know where to find this info.
So, for now, mark it as not available. */
N_SET_MAGIC (core_aouthdr, 0);
/* Read the register values out of the core file and store
them where `read_register' will find them. */
{
register int regno;
for (regno = 0; regno < 64; regno++)
{
char buf[MAX_REGISTER_RAW_SIZE];
val = lseek (corechan, register_addr (regno, reg_offset), 0);
if (val < 0
|| (val = myread (corechan, buf, sizeof buf)) < 0)
{
char * buffer = (char *) alloca (strlen (reg_names[regno])
+ 30);
strcpy (buffer, "Reading register ");
strcat (buffer, reg_names[regno]);
perror_with_name (buffer);
}
if (val < 0)
perror_with_name (filename);
#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
printf_unfiltered ("[reg %s(%d), offset in file %s=0x%0x, addr =0x%0x, =%0x]\n",
reg_names[regno], regno, filename,
register_addr(regno, reg_offset),
regno * 4 + last_frame_address,
*((int *)buf));
#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
supply_register (regno, buf);
}
}
}
if (filename[0] == '/')
corefile = savestring (filename, strlen (filename));
else
{
corefile = concat (current_directory, "/", filename, NULL);
}
#if 1 || defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
printf_unfiltered ("Providing CSP (%s) as nominal address of current frame.\n",
local_hex_string(last_frame_address));
#endif PYRAMID_CONTROL_FRAME_DEBUGGING
/* FIXME: Which of the following is correct? */
#if 0
set_current_frame ( create_new_frame (read_register (FP_REGNUM),
read_pc ()));
#else
set_current_frame ( create_new_frame (last_frame_address,
read_pc ()));
#endif
select_frame (get_current_frame (), 0);
validate_files ();
}
else if (from_tty)
printf_unfiltered ("No core file now.\n");
}

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

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,174 +0,0 @@
/* Remote debugging interface for EST-300 ICE, for GDB
Copyright 1995 Free Software Foundation, Inc.
Contributed by Cygnus Support.
Written by Steve Chamberlain for Cygnus Support.
Re-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"
static void est_open PARAMS ((char *args, int from_tty));
static void
est_supply_register (regname, regnamelen, val, vallen)
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 a "r30".
*/
static char *est_regnames[NUM_REGS] =
{
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
"SR", "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 est_ops;
static char *est_inits[] = {"he\r", /* Resets the prompt, and clears repeated cmds */
NULL};
static struct monitor_ops est_cmds =
{
MO_CLR_BREAK_USES_ADDR | MO_FILL_USES_ADDR | MO_NEED_REGDUMP_AFTER_CONT,
est_inits, /* Init strings */
"go\r", /* continue command */
"sidr\r", /* single step */
"\003", /* ^C interrupts the program */
"sb %x\r", /* set a breakpoint */
"rb %x\r", /* clear a breakpoint */
"rb\r", /* clear all breakpoints */
"bfb %x %x %x\r", /* fill (start end val) */
{
"smb %x %x\r", /* setmem.cmdb (addr, value) */
"smw %x %x\r", /* setmem.cmdw (addr, value) */
"sml %x %x\r", /* setmem.cmdl (addr, value) */
NULL, /* setmem.cmdll (addr, value) */
NULL, /* setreg.resp_delim */
NULL, /* setreg.term */
NULL, /* setreg.term_cmd */
},
{
"dmb %x %x\r", /* getmem.cmdb (addr, len) */
"dmw %x %x\r", /* getmem.cmdw (addr, len) */
"dml %x %x\r", /* getmem.cmdl (addr, len) */
NULL, /* getmem.cmdll (addr, len) */
": ", /* getmem.resp_delim */
NULL, /* getmem.term */
NULL, /* getmem.term_cmd */
},
{
"sr %s %x\r", /* setreg.cmd (name, value) */
NULL, /* setreg.resp_delim */
NULL, /* setreg.term */
NULL /* setreg.term_cmd */
},
{
"dr %s\r", /* getreg.cmd (name) */
" = ", /* getreg.resp_delim */
NULL, /* getreg.term */
NULL /* getreg.term_cmd */
},
"dr\r", /* dump_registers */
"\\(\\w+\\) = \\([0-9a-fA-F]+\\)", /* register_pattern */
est_supply_register, /* supply_register */
NULL, /* load_routine (defaults to SRECs) */
"dl\r", /* download command */
"+", /* load response */
">BKM>", /* monitor command prompt */
"\r", /* end-of-line terminator */
NULL, /* optional command terminator */
&est_ops, /* target operations */
SERIAL_1_STOPBITS, /* number of stop bits */
est_regnames, /* registers names */
MONITOR_OPS_MAGIC /* magic */
};
static void
est_open(args, from_tty)
char *args;
int from_tty;
{
monitor_open (args, &est_cmds, from_tty);
}
void
_initialize_est ()
{
init_monitor_ops (&est_ops);
est_ops.to_shortname = "est";
est_ops.to_longname = "EST background debug monitor";
est_ops.to_doc = "Debug via the EST BDM.\n\
Specify the serial device it is connected to (e.g. /dev/ttya).";
est_ops.to_open = est_open;
add_target (&est_ops);
}

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,820 +0,0 @@
/* Memory-access and commands for remote NINDY process, for GDB.
Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
Contributed by Intel Corporation. Modified from remote.c by Chris Benenati.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
/*
Except for the data cache routines, this file bears little resemblence
to remote.c. A new (although similar) protocol has been specified, and
portions of the code are entirely dependent on having an i80960 with a
NINDY ROM monitor at the other end of the line.
*/
/*****************************************************************************
*
* REMOTE COMMUNICATION PROTOCOL BETWEEN GDB960 AND THE NINDY ROM MONITOR.
*
*
* MODES OF OPERATION
* ----- -- ---------
*
* As far as NINDY is concerned, GDB is always in one of two modes: command
* mode or passthrough mode.
*
* In command mode (the default) pre-defined packets containing requests
* are sent by GDB to NINDY. NINDY never talks except in reponse to a request.
*
* Once the the user program is started, GDB enters passthrough mode, to give
* the user program access to the terminal. GDB remains in this mode until
* NINDY indicates that the program has stopped.
*
*
* PASSTHROUGH MODE
* ----------- ----
*
* GDB writes all input received from the keyboard directly to NINDY, and writes
* all characters received from NINDY directly to the monitor.
*
* Keyboard input is neither buffered nor echoed to the monitor.
*
* GDB remains in passthrough mode until NINDY sends a single ^P character,
* to indicate that the user process has stopped.
*
* Note:
* GDB assumes NINDY performs a 'flushreg' when the user program stops.
*
*
* COMMAND MODE
* ------- ----
*
* All info (except for message ack and nak) is transferred between gdb
* and the remote processor in messages of the following format:
*
* <info>#<checksum>
*
* where
* # is a literal character
*
* <info> ASCII information; all numeric information is in the
* form of hex digits ('0'-'9' and lowercase 'a'-'f').
*
* <checksum>
* is a pair of ASCII hex digits representing an 8-bit
* checksum formed by adding together each of the
* characters in <info>.
*
* The receiver of a message always sends a single character to the sender
* to indicate that the checksum was good ('+') or bad ('-'); the sender
* re-transmits the entire message over until a '+' is received.
*
* In response to a command NINDY always sends back either data or
* a result code of the form "Xnn", where "nn" are hex digits and "X00"
* means no errors. (Exceptions: the "s" and "c" commands don't respond.)
*
* SEE THE HEADER OF THE FILE "gdb.c" IN THE NINDY MONITOR SOURCE CODE FOR A
* FULL DESCRIPTION OF LEGAL COMMANDS.
*
* SEE THE FILE "stop.h" IN THE NINDY MONITOR SOURCE CODE FOR A LIST
* OF STOP CODES.
*
***************************************************************************/
#include "defs.h"
#include <signal.h>
#include <sys/types.h>
#include <setjmp.h>
#include "frame.h"
#include "inferior.h"
#include "bfd.h"
#include "symfile.h"
#include "target.h"
#include "gdbcore.h"
#include "command.h"
#include "floatformat.h"
#include "wait.h"
#include <sys/file.h>
#include <ctype.h>
#include "serial.h"
#include "nindy-share/env.h"
#include "nindy-share/stop.h"
#include "dcache.h"
#include "remote-utils.h"
static DCACHE *nindy_dcache;
extern int unlink();
extern char *getenv();
extern char *mktemp();
extern void generic_mourn_inferior ();
extern struct target_ops nindy_ops;
extern GDB_FILE *instream;
extern char ninStopWhy ();
extern int ninMemGet ();
extern int ninMemPut ();
int nindy_initial_brk; /* nonzero if want to send an initial BREAK to nindy */
int nindy_old_protocol; /* nonzero if want to use old protocol */
char *nindy_ttyname; /* name of tty to talk to nindy on, or null */
#define DLE '\020' /* Character NINDY sends to indicate user program has
* halted. */
#define TRUE 1
#define FALSE 0
/* From nindy-share/nindy.c. */
extern serial_t nindy_serial;
static int have_regs = 0; /* 1 iff regs read since i960 last halted */
static int regs_changed = 0; /* 1 iff regs were modified since last read */
extern char *exists();
static void
nindy_fetch_registers PARAMS ((int));
static void
nindy_store_registers PARAMS ((int));
static char *savename;
static void
nindy_close (quitting)
int quitting;
{
if (nindy_serial != NULL)
SERIAL_CLOSE (nindy_serial);
nindy_serial = NULL;
if (savename)
free (savename);
savename = 0;
}
/* Open a connection to a remote debugger.
FIXME, there should be "set" commands for the options that are
now specified with gdb command-line options (old_protocol,
and initial_brk). */
void
nindy_open (name, from_tty)
char *name; /* "/dev/ttyXX", "ttyXX", or "XX": tty to be opened */
int from_tty;
{
char baudrate[1024];
if (!name)
error_no_arg ("serial port device name");
target_preopen (from_tty);
nindy_close (0);
have_regs = regs_changed = 0;
nindy_dcache = dcache_init(ninMemGet, ninMemPut);
/* Allow user to interrupt the following -- we could hang if there's
no NINDY at the other end of the remote tty. */
immediate_quit++;
/* If baud_rate is -1, then ninConnect will not recognize the baud rate
and will deal with the situation in a (more or less) reasonable
fashion. */
sprintf(baudrate, "%d", baud_rate);
ninConnect(name, baudrate,
nindy_initial_brk, !from_tty, nindy_old_protocol);
immediate_quit--;
if (nindy_serial == NULL)
{
perror_with_name (name);
}
savename = savestring (name, strlen (name));
push_target (&nindy_ops);
target_fetch_registers(-1);
}
/* User-initiated quit of nindy operations. */
static void
nindy_detach (name, from_tty)
char *name;
int from_tty;
{
if (name)
error ("Too many arguments");
pop_target ();
}
static void
nindy_files_info ()
{
/* FIXME: this lies about the baud rate if we autobauded. */
printf_unfiltered("\tAttached to %s at %d bits per second%s%s.\n", savename,
baud_rate,
nindy_old_protocol? " in old protocol": "",
nindy_initial_brk? " with initial break": "");
}
/* Return the number of characters in the buffer before
the first DLE character. */
static
int
non_dle( buf, n )
char *buf; /* Character buffer; NOT '\0'-terminated */
int n; /* Number of characters in buffer */
{
int i;
for ( i = 0; i < n; i++ ){
if ( buf[i] == DLE ){
break;
}
}
return i;
}
/* Tell the remote machine to resume. */
void
nindy_resume (pid, step, siggnal)
int pid, step;
enum target_signal siggnal;
{
if (siggnal != TARGET_SIGNAL_0 && siggnal != stop_signal)
warning ("Can't send signals to remote NINDY targets.");
dcache_flush(nindy_dcache);
if ( regs_changed )
{
nindy_store_registers (-1);
regs_changed = 0;
}
have_regs = 0;
ninGo( step );
}
/* FIXME, we can probably use the normal terminal_inferior stuff here.
We have to do terminal_inferior and then set up the passthrough
settings initially. Thereafter, terminal_ours and terminal_inferior
will automatically swap the settings around for us. */
struct clean_up_tty_args {
serial_ttystate state;
serial_t serial;
};
static struct clean_up_tty_args tty_args;
static void
clean_up_tty (ptrarg)
PTR ptrarg;
{
struct clean_up_tty_args *args = (struct clean_up_tty_args *) ptrarg;
SERIAL_SET_TTY_STATE (args->serial, args->state);
free (args->state);
warning ("\n\nYou may need to reset the 80960 and/or reload your program.\n");
}
/* Recover from ^Z or ^C while remote process is running */
static void (*old_ctrlc)();
#ifdef SIGTSTP
static void (*old_ctrlz)();
#endif
static void
clean_up_int()
{
SERIAL_SET_TTY_STATE (tty_args.serial, tty_args.state);
free (tty_args.state);
signal(SIGINT, old_ctrlc);
#ifdef SIGTSTP
signal(SIGTSTP, old_ctrlz);
#endif
error("\n\nYou may need to reset the 80960 and/or reload your program.\n");
}
/* Wait until the remote machine stops. While waiting, operate in passthrough
* mode; i.e., pass everything NINDY sends to gdb_stdout, and everything from
* stdin to NINDY.
*
* Return to caller, storing status in 'status' just as `wait' would.
*/
static int
nindy_wait( pid, status )
int pid;
struct target_waitstatus *status;
{
fd_set fds;
int c;
char buf[2];
int i, n;
unsigned char stop_exit;
unsigned char stop_code;
struct cleanup *old_cleanups;
long ip_value, fp_value, sp_value; /* Reg values from stop */
status->kind = TARGET_WAITKIND_EXITED;
status->value.integer = 0;
/* OPERATE IN PASSTHROUGH MODE UNTIL NINDY SENDS A DLE CHARACTER */
/* Save current tty attributes, and restore them when done. */
tty_args.serial = SERIAL_FDOPEN (0);
tty_args.state = SERIAL_GET_TTY_STATE (tty_args.serial);
old_ctrlc = signal( SIGINT, clean_up_int );
#ifdef SIGTSTP
old_ctrlz = signal( SIGTSTP, clean_up_int );
#endif
old_cleanups = make_cleanup (clean_up_tty, &tty_args);
/* Pass input from keyboard to NINDY as it arrives. NINDY will interpret
<CR> and perform echo. */
/* This used to set CBREAK and clear ECHO and CRMOD. I hope this is close
enough. */
SERIAL_RAW (tty_args.serial);
while (1)
{
/* Input on remote */
c = SERIAL_READCHAR (nindy_serial, -1);
if (c == SERIAL_ERROR)
{
error ("Cannot read from serial line");
}
else if (c == 0x1b) /* ESC */
{
c = SERIAL_READCHAR (nindy_serial, -1);
c &= ~0x40;
}
else if (c != 0x10) /* DLE */
/* Write out any characters preceding DLE */
{
buf[0] = (char)c;
write (1, buf, 1);
}
else
{
stop_exit = ninStopWhy(&stop_code,
&ip_value, &fp_value, &sp_value);
if (!stop_exit && (stop_code == STOP_SRQ))
{
immediate_quit++;
ninSrq();
immediate_quit--;
}
else
{
/* Get out of loop */
supply_register (IP_REGNUM,
(char *)&ip_value);
supply_register (FP_REGNUM,
(char *)&fp_value);
supply_register (SP_REGNUM,
(char *)&sp_value);
break;
}
}
}
SERIAL_SET_TTY_STATE (tty_args.serial, tty_args.state);
free (tty_args.state);
discard_cleanups (old_cleanups);
if (stop_exit)
{
status->kind = TARGET_WAITKIND_EXITED;
status->value.integer = stop_code;
}
else
{
/* nindy has some special stop code need to be handled */
if (stop_code == STOP_GDB_BPT)
stop_code = TRACE_STEP;
status->kind = TARGET_WAITKIND_STOPPED;
status->value.sig = i960_fault_to_signal (stop_code);
}
return inferior_pid;
}
/* Read the remote registers into the block REGS. */
/* This is the block that ninRegsGet and ninRegsPut handles. */
struct nindy_regs {
char local_regs[16 * 4];
char global_regs[16 * 4];
char pcw_acw[2 * 4];
char ip[4];
char tcw[4];
char fp_as_double[4 * 8];
};
static void
nindy_fetch_registers(regno)
int regno;
{
struct nindy_regs nindy_regs;
int regnum, inv;
double dub;
immediate_quit++;
ninRegsGet( (char *) &nindy_regs );
immediate_quit--;
memcpy (&registers[REGISTER_BYTE (R0_REGNUM)], nindy_regs.local_regs, 16*4);
memcpy (&registers[REGISTER_BYTE (G0_REGNUM)], nindy_regs.global_regs, 16*4);
memcpy (&registers[REGISTER_BYTE (PCW_REGNUM)], nindy_regs.pcw_acw, 2*4);
memcpy (&registers[REGISTER_BYTE (IP_REGNUM)], nindy_regs.ip, 1*4);
memcpy (&registers[REGISTER_BYTE (TCW_REGNUM)], nindy_regs.tcw, 1*4);
for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) {
dub = unpack_double (builtin_type_double,
&nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
&inv);
/* dub now in host byte order */
floatformat_from_double (&floatformat_i960_ext, &dub,
&registers[REGISTER_BYTE (regnum)]);
}
registers_fetched ();
}
static void
nindy_prepare_to_store()
{
/* Fetch all regs if they aren't already here. */
read_register_bytes (0, NULL, REGISTER_BYTES);
}
static void
nindy_store_registers(regno)
int regno;
{
struct nindy_regs nindy_regs;
int regnum;
double dub;
memcpy (nindy_regs.local_regs, &registers[REGISTER_BYTE (R0_REGNUM)], 16*4);
memcpy (nindy_regs.global_regs, &registers[REGISTER_BYTE (G0_REGNUM)], 16*4);
memcpy (nindy_regs.pcw_acw, &registers[REGISTER_BYTE (PCW_REGNUM)], 2*4);
memcpy (nindy_regs.ip, &registers[REGISTER_BYTE (IP_REGNUM)], 1*4);
memcpy (nindy_regs.tcw, &registers[REGISTER_BYTE (TCW_REGNUM)], 1*4);
for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++)
{
floatformat_to_double (&floatformat_i960_ext,
&registers[REGISTER_BYTE (regnum)], &dub);
store_floating (&nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
REGISTER_VIRTUAL_SIZE (regnum),
dub);
}
immediate_quit++;
ninRegsPut( (char *) &nindy_regs );
immediate_quit--;
}
/* Read a word from remote address ADDR and return it.
* This goes through the data cache.
*/
int
nindy_fetch_word (addr)
CORE_ADDR addr;
{
return dcache_fetch (nindy_dcache, addr);
}
/* Write a word WORD into remote address ADDR.
This goes through the data cache. */
void
nindy_store_word (addr, word)
CORE_ADDR addr;
int word;
{
dcache_poke (nindy_dcache, addr, word);
}
/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
to debugger memory starting at MYADDR. Copy to inferior if
WRITE is nonzero. Returns the length copied.
This is stolen almost directly from infptrace.c's child_xfer_memory,
which also deals with a word-oriented memory interface. Sometime,
FIXME, rewrite this to not use the word-oriented routines. */
int
nindy_xfer_inferior_memory(memaddr, myaddr, len, write, target)
CORE_ADDR memaddr;
char *myaddr;
int len;
int write;
struct target_ops *target; /* ignored */
{
register int i;
/* Round starting address down to longword boundary. */
register CORE_ADDR addr = memaddr & - sizeof (int);
/* Round ending address up; get number of longwords that makes. */
register int count
= (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
/* Allocate buffer of that many longwords. */
register int *buffer = (int *) alloca (count * sizeof (int));
if (write)
{
/* Fill start and end extra bytes of buffer with existing memory data. */
if (addr != memaddr || len < (int)sizeof (int)) {
/* Need part of initial word -- fetch it. */
buffer[0] = nindy_fetch_word (addr);
}
if (count > 1) /* FIXME, avoid if even boundary */
{
buffer[count - 1]
= nindy_fetch_word (addr + (count - 1) * sizeof (int));
}
/* Copy data to be written over corresponding part of buffer */
memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
/* Write the entire buffer. */
for (i = 0; i < count; i++, addr += sizeof (int))
{
errno = 0;
nindy_store_word (addr, buffer[i]);
if (errno)
return 0;
}
}
else
{
/* Read all the longwords */
for (i = 0; i < count; i++, addr += sizeof (int))
{
errno = 0;
buffer[i] = nindy_fetch_word (addr);
if (errno)
return 0;
QUIT;
}
/* Copy appropriate bytes out of the buffer. */
memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
}
return len;
}
static void
nindy_create_inferior (execfile, args, env)
char *execfile;
char *args;
char **env;
{
int entry_pt;
int pid;
if (args && *args)
error ("Can't pass arguments to remote NINDY process");
if (execfile == 0 || exec_bfd == 0)
error ("No exec file specified");
entry_pt = (int) bfd_get_start_address (exec_bfd);
pid = 42;
/* The "process" (board) is already stopped awaiting our commands, and
the program is already downloaded. We just set its PC and go. */
inferior_pid = pid; /* Needed for wait_for_inferior below */
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);
}
static void
reset_command(args, from_tty)
char *args;
int from_tty;
{
if (nindy_serial == NULL)
{
error( "No target system to reset -- use 'target nindy' command.");
}
if ( query("Really reset the target system?",0,0) )
{
SERIAL_SEND_BREAK (nindy_serial);
tty_flush (nindy_serial);
}
}
void
nindy_kill (args, from_tty)
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. */
void
nindy_mourn_inferior ()
{
remove_breakpoints ();
unpush_target (&nindy_ops);
generic_mourn_inferior (); /* Do all the proper things now */
}
/* Pass the args the way catch_errors wants them. */
static int
nindy_open_stub (arg)
char *arg;
{
nindy_open (arg, 1);
return 1;
}
static void
nindy_load( filename, from_tty )
char *filename;
int from_tty;
{
asection *s;
/* Can't do unix style forking on a VMS system, so we'll use bfd to do
all the work for us
*/
bfd *file = bfd_openr(filename,0);
if (!file)
{
perror_with_name(filename);
return;
}
if (!bfd_check_format(file, bfd_object))
{
error("can't prove it's an object file\n");
return;
}
for ( s = file->sections; s; s=s->next)
{
if (s->flags & SEC_LOAD)
{
char *buffer = xmalloc(s->_raw_size);
bfd_get_section_contents(file, s, buffer, 0, s->_raw_size);
printf("Loading section %s, size %x vma %x\n",
s->name,
s->_raw_size,
s->vma);
ninMemPut(s->vma, buffer, s->_raw_size);
free(buffer);
}
}
bfd_close(file);
}
static int
load_stub (arg)
char *arg;
{
target_load (arg, 1);
return 1;
}
/* This routine is run as a hook, just before the main command loop is
entered. If gdb is configured for the i960, but has not had its
nindy target specified yet, this will loop prompting the user to do so.
Unlike the loop provided by Intel, we actually let the user get out
of this with a RETURN. This is useful when e.g. simply examining
an i960 object file on the host system. */
void
nindy_before_main_loop ()
{
char ttyname[100];
char *p, *p2;
while (target_stack->target_ops != &nindy_ops) /* What is this crap??? */
{ /* remote tty not specified yet */
if ( instream == stdin ){
printf_unfiltered("\nAttach /dev/ttyNN -- specify NN, or \"quit\" to quit: ");
gdb_flush( gdb_stdout );
}
fgets( ttyname, sizeof(ttyname)-1, stdin );
/* Strip leading and trailing whitespace */
for ( p = ttyname; isspace(*p); p++ ){
;
}
if ( *p == '\0' ){
return; /* User just hit spaces or return, wants out */
}
for ( p2= p; !isspace(*p2) && (*p2 != '\0'); p2++ ){
;
}
*p2= '\0';
if ( STREQ("quit",p) ){
exit(1);
}
if (catch_errors (nindy_open_stub, p, "", RETURN_MASK_ALL))
{
/* Now that we have a tty open for talking to the remote machine,
download the executable file if one was specified. */
if (exec_bfd)
{
catch_errors (load_stub, bfd_get_filename (exec_bfd), "",
RETURN_MASK_ALL);
}
}
}
}
/* Define the target subroutine names */
struct target_ops nindy_ops = {
"nindy", "Remote serial target in i960 NINDY-specific protocol",
"Use a remote i960 system running NINDY connected by a serial line.\n\
Specify the name of the device the serial line is connected to.\n\
The speed (baud rate), whether to use the old NINDY protocol,\n\
and whether to send a break on startup, are controlled by options\n\
specified when you started GDB.",
nindy_open, nindy_close,
0,
nindy_detach,
nindy_resume,
nindy_wait,
nindy_fetch_registers, nindy_store_registers,
nindy_prepare_to_store,
nindy_xfer_inferior_memory, nindy_files_info,
memory_insert_breakpoint,
memory_remove_breakpoint,
0, 0, 0, 0, 0, /* Terminal crud */
nindy_kill,
nindy_load,
0, /* lookup_symbol */
nindy_create_inferior,
nindy_mourn_inferior,
0, /* can_run */
0, /* notice_signals */
0, /* to_thread_alive */
0, /* to_stop */
process_stratum, 0, /* next */
1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
0, 0, /* Section pointers */
OPS_MAGIC, /* Always the last thing */
};
void
_initialize_nindy ()
{
add_target (&nindy_ops);
add_com ("reset", class_obscure, reset_command,
"Send a 'break' to the remote target system.\n\
Only useful if the target has been equipped with a circuit\n\
to perform a hard reset when a break is detected.");
}

View file

@ -1,332 +0,0 @@
/* Remote debugging with the XLNT Designs, Inc (XDI) NetROM.
Copyright 1990, 1991, 1992, 1995 Free Software Foundation, Inc.
Contributed by:
Roger Moyers
XLNT Designs, Inc.
15050 Avenue of Science, Suite 106
San Diego, CA 92128
(619)487-9320
roger@xlnt.com
Adapted from work done at Cygnus Support in remote-nindy.c,
later merged in by Stan Shebs at 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. */
#include "defs.h"
#include "gdbcmd.h"
#include "serial.h"
#include "target.h"
/* Default ports used to talk with the NetROM. */
#define DEFAULT_NETROM_LOAD_PORT 1236
#define DEFAULT_NETROM_CONTROL_PORT 1237
static void nrom_close PARAMS ((int quitting));
/* New commands. */
static void nrom_passthru PARAMS ((char *, int));
/* We talk to the NetROM over these sockets. */
static serial_t load_desc = NULL;
static serial_t ctrl_desc = NULL;
static int load_port = DEFAULT_NETROM_LOAD_PORT;
static int control_port = DEFAULT_NETROM_CONTROL_PORT;
static char nrom_hostname[100];
/* Forward data declaration. */
extern struct target_ops nrom_ops;
/* Scan input from the remote system, until STRING is found. Print chars that
don't match. */
static int
expect (string)
char *string;
{
char *p = string;
int c;
immediate_quit = 1;
while (1)
{
c = SERIAL_READCHAR (ctrl_desc, 5);
if (c == *p++)
{
if (*p == '\0')
{
immediate_quit = 0;
return 0;
}
}
else
{
fputc_unfiltered (c, gdb_stdout);
p = string;
if (c == *p)
p++;
}
}
}
static void
nrom_kill ()
{
nrom_close (0);
}
static serial_t
open_socket (name, port)
char *name;
int port;
{
char sockname[100];
serial_t desc;
sprintf (sockname, "%s:%d", name, port);
desc = SERIAL_OPEN (sockname);
if (!desc)
perror_with_name (sockname);
return desc;
}
static void
load_cleanup ()
{
SERIAL_CLOSE (load_desc);
load_desc = NULL;
}
/* Download a file specified in ARGS to the netROM. */
static void
nrom_load (args, fromtty)
char *args;
int fromtty;
{
int fd, rd_amt, fsize;
bfd *pbfd;
asection *section;
char *downloadstring = "download 0\n";
struct cleanup *old_chain;
/* Tell the netrom to get ready to download. */
if (SERIAL_WRITE (ctrl_desc, downloadstring, strlen (downloadstring)))
error ("nrom_load: control_send() of `%s' failed", downloadstring);
expect ("Waiting for a connection...\n");
load_desc = open_socket (nrom_hostname, load_port);
old_chain = make_cleanup (load_cleanup, 0);
pbfd = bfd_openr (args, 0);
if (pbfd)
{
make_cleanup (bfd_close, pbfd);
if (!bfd_check_format (pbfd, bfd_object))
error ("\"%s\": not in executable format: %s",
args, bfd_errmsg (bfd_get_error ()));
for (section = pbfd->sections; section; section = section->next)
{
if (bfd_get_section_flags (pbfd, section) & SEC_ALLOC)
{
bfd_vma section_address;
unsigned long section_size;
const char *section_name;
section_name = bfd_get_section_name (pbfd, section);
section_address = bfd_get_section_vma (pbfd, section);
section_size = bfd_section_size (pbfd, section);
if (bfd_get_section_flags (pbfd, section) & SEC_LOAD)
{
file_ptr fptr;
printf_filtered ("[Loading section %s at %x (%d bytes)]\n",
section_name, section_address,
section_size);
fptr = 0;
while (section_size > 0)
{
char buffer[1024];
int count;
count = min (section_size, 1024);
bfd_get_section_contents (pbfd, section, buffer, fptr,
count);
SERIAL_WRITE (load_desc, buffer, count);
section_address += count;
fptr += count;
section_size -= count;
}
}
else /* BSS and such */
{
printf_filtered ("[section %s: not loading]\n",
section_name);
}
}
}
}
else
error ("\"%s\": Could not open", args);
do_cleanups (old_chain);
}
/* Open a connection to the remote NetROM devices. */
static void
nrom_open (name, from_tty)
char *name;
int from_tty;
{
int errn;
if (!name || strchr (name, '/') || strchr (name, ':'))
error (
"To open a NetROM connection, you must specify the hostname\n\
or IP address of the NetROM device you wish to use.");
strcpy (nrom_hostname, name);
target_preopen (from_tty);
unpush_target (&nrom_ops);
ctrl_desc = open_socket (nrom_hostname, control_port);
push_target (&nrom_ops);
if (from_tty)
printf_filtered ("Connected to NetROM device \"%s\"\n", nrom_hostname);
}
/* Close out all files and local state before this target loses control. */
static void
nrom_close (quitting)
int quitting;
{
if (load_desc)
SERIAL_CLOSE (load_desc);
if (ctrl_desc)
SERIAL_CLOSE (ctrl_desc);
}
/* Pass arguments directly to the NetROM. */
static void
nrom_passthru (args, fromtty)
char *args;
int fromtty;
{
char buf[1024];
sprintf (buf, "%s\n", args);
if (SERIAL_WRITE (ctrl_desc, buf, strlen (buf)))
error ("nrom_reset: control_send() of `%s'failed", args);
}
static void
nrom_mourn()
{
unpush_target (&nrom_ops);
generic_mourn_inferior ();
}
/* Define the target vector. */
struct target_ops nrom_ops = {
"nrom", /* to_shortname */
"Remote XDI `NetROM' target", /* to_longname */
"Remote debug using a NetROM over Ethernet", /* to_doc */
nrom_open, /* to_open */
nrom_close, /* to_close */
NULL, /* to_attach */
NULL, /* to_detach */
NULL, /* to_resume */
NULL, /* to_wait */
NULL, /* to_fetch_registers */
NULL, /* to_store_registers */
NULL, /* to_prepare_to_store */
NULL, /* to_xfer_memory */
NULL, /* to_files_info */
NULL, /* to_insert_breakpoint */
NULL, /* to_remove_breakpoint */
NULL, /* to_terminal_init */
NULL, /* to_terminal_inferior */
NULL, /* to_terminal_ours_for_output */
NULL, /* to_terminal_ours */
NULL, /* to_terminal_info */
nrom_kill, /* to_kill */
nrom_load, /* to_load */
NULL, /* to_lookup_symbol */
NULL, /* to_create_inferior */
nrom_mourn, /* to_mourn_inferior */
NULL, /* to_can_run */
0, /* to_notice_signals */
0, /* to_thread_alive */
0, /* to_stop */
download_stratum, /* to_stratum */
NULL, /* to_next */
1, /* to_has_all_memory */
1, /* to_has_memory */
1, /* to_has_stack */
1, /* to_has_registers */
0, /* to_has_execution */
NULL, /* sections */
NULL, /* sections_end */
OPS_MAGIC /* to_magic */
};
void
_initialize_remote_nrom ()
{
add_target (&nrom_ops);
add_show_from_set (
add_set_cmd ("nrom_load_port", no_class, var_zinteger, (char *)&load_port,
"Set the port to use for NetROM downloads\n", &setlist),
&showlist);
add_show_from_set (
add_set_cmd ("nrom_control_port", no_class, var_zinteger, (char *)&control_port,
"Set the port to use for NetROM debugger services\n", &setlist),
&showlist);
add_cmd ("nrom", no_class, nrom_passthru,
"Pass arguments as command to NetROM",
&cmdlist);
}

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,468 +0,0 @@
/* Generic remote debugging interface for simulators.
Copyright 1993, 1994 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 "wait.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 "remote-sim.h"
#include "remote-utils.h"
#include "callback.h"
/* Naming convention:
sim_* are the interface to the simulator (see remote-sim.h).
sim_callback_* are the stuff which the simulator can see inside GDB.
gdbsim_* are stuff which is internal to gdb. */
/* Forward data declarations */
extern struct target_ops gdbsim_ops;
static int program_loaded = 0;
static void
dump_mem (buf, len)
char *buf;
int len;
{
if (len <= 8)
{
if (len == 8 || len == 4)
{
long l[2];
memcpy (l, buf, len);
printf_filtered ("\t0x%x", l[0]);
printf_filtered (len == 8 ? " 0x%x\n" : "\n", l[1]);
}
else
{
int i;
printf_filtered ("\t");
for (i = 0; i < len; i++)
printf_filtered ("0x%x ", buf[i]);
printf_filtered ("\n");
}
}
}
static void
gdbsim_fetch_register (regno)
int regno;
{
if (regno == -1)
{
for (regno = 0; regno < NUM_REGS; regno++)
gdbsim_fetch_register (regno);
}
else
{
char buf[MAX_REGISTER_RAW_SIZE];
sim_fetch_register (regno, buf);
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 (regno)
int regno;
{
if (regno == -1)
{
for (regno = 0; regno < NUM_REGS; regno++)
gdbsim_store_register (regno);
}
else
{
/* FIXME: Until read_register() returns LONGEST, we have this. */
char tmp[MAX_REGISTER_RAW_SIZE];
read_register_gen (regno, tmp);
sim_store_register (regno, tmp);
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 ()
{
if (sr_get_debug ())
printf_filtered ("gdbsim_kill\n");
sim_kill (); /* close fd's, remove mappings */
inferior_pid = 0;
}
/* 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 (prog, fromtty)
char *prog;
int fromtty;
{
if (sr_get_debug ())
printf_filtered ("gdbsim_load: prog \"%s\"\n", prog);
inferior_pid = 0;
/* This must be done before calling gr_load_image. */
program_loaded = 1;
if (sim_load (prog, fromtty) != 0)
generic_load (prog, fromtty);
}
/* Start an inferior process and set inferior_pid to its pid.
EXEC_FILE is the file to run.
ALLARGS 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 (exec_file, args, env)
char *exec_file;
char *args;
char **env;
{
int len;
char *arg_buf,**argv;
CORE_ADDR entry_pt;
if (! program_loaded)
error ("No program loaded.");
if (sr_get_debug ())
printf_filtered ("gdbsim_create_inferior: exec_file \"%s\", args \"%s\"\n",
exec_file, args);
if (exec_file == 0 || exec_bfd == 0)
error ("No exec file specified.");
entry_pt = (CORE_ADDR) bfd_get_start_address (exec_bfd);
gdbsim_kill (NULL, NULL);
remove_breakpoints ();
init_wait_for_inferior ();
len = 5 + 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, (char *) argv);
sim_create_inferior (entry_pt, argv, env);
inferior_pid = 42;
insert_breakpoints (); /* Needed to get correct instruction in cache */
proceed (entry_pt, 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 (args, from_tty)
char *args;
int from_tty;
{
if (sr_get_debug ())
printf_filtered ("gdbsim_open: args \"%s\"\n", args ? args : "(null)");
sim_set_callbacks (&default_callback);
default_callback.init (&default_callback);
sim_open (args);
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 (quitting)
int quitting;
{
if (sr_get_debug ())
printf_filtered ("gdbsim_close: quitting %d\n", quitting);
program_loaded = 0;
sim_close (quitting);
}
/* 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 (args,from_tty)
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 void
gdbsim_resume (pid, step, siggnal)
int pid, step;
enum target_signal siggnal;
{
if (sr_get_debug ())
printf_filtered ("gdbsim_resume: step %d, signal %d\n", step, siggnal);
sim_resume (step, target_signal_to_host (siggnal));
}
/* 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 int
gdbsim_wait (pid, status)
int pid;
struct target_waitstatus *status;
{
int sigrc;
enum sim_stop reason;
if (sr_get_debug ())
printf_filtered ("gdbsim_wait\n");
sim_stop_reason (&reason, &sigrc);
switch (reason)
{
case sim_exited:
status->kind = TARGET_WAITKIND_EXITED;
status->value.integer = sigrc;
break;
case sim_stopped:
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;
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;
}
return inferior_pid;
}
/* 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 ()
{
/* Do nothing, since we can store individual regs */
}
static int
gdbsim_xfer_inferior_memory (memaddr, myaddr, len, write, target)
CORE_ADDR memaddr;
char *myaddr;
int len;
int write;
struct target_ops *target; /* ignored */
{
if (! program_loaded)
error ("No program loaded.");
if (sr_get_debug ())
{
printf_filtered ("gdbsim_xfer_inferior_memory: myaddr 0x%x, memaddr 0x%x, len %d, write %d\n",
myaddr, memaddr, len, write);
if (sr_get_debug () && write)
dump_mem(myaddr, len);
}
if (write)
{
len = sim_write (memaddr, myaddr, len);
}
else
{
len = sim_read (memaddr, myaddr, len);
if (sr_get_debug () && len > 0)
dump_mem(myaddr, len);
}
return len;
}
static void
gdbsim_files_info (target)
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 (0);
}
}
/* Clear the simulator's notion of what the break points are. */
static void
gdbsim_mourn_inferior ()
{
if (sr_get_debug ())
printf_filtered ("gdbsim_mourn_inferior:\n");
remove_breakpoints ();
generic_mourn_inferior ();
}
/* Put a command string, in args, out to MONITOR. Output from MONITOR
is placed on the users terminal until the prompt is seen. FIXME: We
read the characters ourseleves here cause of a nasty echo. */
static void
simulator_command (args, from_tty)
char *args;
int from_tty;
{
sim_do_command (args);
}
/* Define the target subroutine names */
struct target_ops gdbsim_ops = {
"sim", /* to_shortname */
"simulator", /* to_longname */
"Use the compiled-in simulator.", /* to_doc */
gdbsim_open, /* to_open */
gdbsim_close, /* to_close */
NULL, /* to_attach */
gdbsim_detach, /* to_detach */
gdbsim_resume, /* to_resume */
gdbsim_wait, /* to_wait */
gdbsim_fetch_register, /* to_fetch_registers */
gdbsim_store_register, /* to_store_registers */
gdbsim_prepare_to_store, /* to_prepare_to_store */
gdbsim_xfer_inferior_memory, /* to_xfer_memory */
gdbsim_files_info, /* to_files_info */
memory_insert_breakpoint, /* to_insert_breakpoint */
memory_remove_breakpoint, /* to_remove_breakpoint */
NULL, /* to_terminal_init */
NULL, /* to_terminal_inferior */
NULL, /* to_terminal_ours_for_output */
NULL, /* to_terminal_ours */
NULL, /* to_terminal_info */
gdbsim_kill, /* to_kill */
gdbsim_load, /* to_load */
NULL, /* to_lookup_symbol */
gdbsim_create_inferior, /* to_create_inferior */
gdbsim_mourn_inferior, /* to_mourn_inferior */
0, /* to_can_run */
0, /* to_notice_signals */
0, /* to_thread_alive */
0, /* to_stop */
process_stratum, /* to_stratum */
NULL, /* to_next */
1, /* to_has_all_memory */
1, /* to_has_memory */
1, /* to_has_stack */
1, /* to_has_registers */
1, /* to_has_execution */
NULL, /* sections */
NULL, /* sections_end */
OPS_MAGIC, /* to_magic */
};
void
_initialize_remote_sim ()
{
add_target (&gdbsim_ops);
add_com ("sim <command>", class_obscure, simulator_command,
"Send a command to the simulator.");
}

View file

@ -1,847 +0,0 @@
/* Remote debugging interface for Tandem ST2000 phone switch, for GDB.
Copyright 1990, 1991, 1992 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 "wait.h"
#ifdef ANSI_PROTOTYPES
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <signal.h>
#include "gdb_string.h"
#include <sys/types.h>
#include "serial.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 serial_t st2000_desc;
/* Send data to stdebug. Works just like printf. */
static void
#ifdef ANSI_PROTOTYPES
printf_stdebug(char *pattern, ...)
#else
printf_stdebug(va_alist)
va_dcl
#endif
{
va_list args;
char buf[200];
#ifdef ANSI_PROTOTYPES
va_start(args, pattern);
#else
char *pattern;
va_start(args);
pattern = va_arg(args, char *);
#endif
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(timeout)
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(string, discard)
char *string;
int discard;
{
char *p = string;
int c;
immediate_quit = 1;
while (1)
{
c = readchar(timeout);
if (c == *p++)
{
if (*p == '\0')
{
immediate_quit = 0;
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(discard)
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(ignore_space)
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 (byt)
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 (n, regno)
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 (execfile, args, env)
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 exec 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(args, from_tty)
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);
SERIAL_SETBAUDRATE(st2000_desc, baudrate);
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 (quitting)
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 (from_tty)
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 (pid, step, sig)
int pid, 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 int
st2000_wait (status)
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 0;
}
/* 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 (regno)
int regno;
{
static char buf[50];
const char *p;
char *b;
b = buf;
for (p = reg_names[regno]; *p; p++)
*b++ = toupper(*p);
*b = '\000';
return buf;
}
/* Read the remote registers into the block REGS. */
static void
st2000_fetch_registers ()
{
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 (regno)
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 ()
{
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 (regno)
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 ()
{
/* Do nothing, since we can store individual regs */
}
static void
st2000_files_info ()
{
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 (memaddr, myaddr, len)
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(memaddr, myaddr, len)
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;
}
/* FIXME-someday! Merge these two. */
static int
st2000_xfer_inferior_memory (memaddr, myaddr, len, write, target)
CORE_ADDR memaddr;
char *myaddr;
int len;
int write;
struct target_ops *target; /* ignored */
{
if (write)
return st2000_write_inferior_memory (memaddr, myaddr, len);
else
return st2000_read_inferior_memory (memaddr, myaddr, len);
}
static void
st2000_kill (args, from_tty)
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 ()
{
remove_breakpoints ();
unpush_target (&st2000_ops);
generic_mourn_inferior (); /* Do all the proper things now */
}
#define MAX_STDEBUG_BREAKPOINTS 16
extern int memory_breakpoint_size;
static CORE_ADDR breakaddr[MAX_STDEBUG_BREAKPOINTS] = {0};
static int
st2000_insert_breakpoint (addr, shadow)
CORE_ADDR addr;
char *shadow;
{
int i;
for (i = 0; i <= MAX_STDEBUG_BREAKPOINTS; i++)
if (breakaddr[i] == 0)
{
breakaddr[i] = addr;
st2000_read_inferior_memory(addr, shadow, memory_breakpoint_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 (addr, shadow)
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 (args, fromtty)
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()
{
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 (args, fromtty)
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(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(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 = {
"st2000",
"Remote serial Tandem ST2000 target",
"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_open,
st2000_close,
0,
st2000_detach,
st2000_resume,
st2000_wait,
st2000_fetch_register,
st2000_store_register,
st2000_prepare_to_store,
st2000_xfer_inferior_memory,
st2000_files_info,
st2000_insert_breakpoint,
st2000_remove_breakpoint, /* Breakpoints */
0,
0,
0,
0,
0, /* Terminal handling */
st2000_kill,
0, /* load */
0, /* lookup_symbol */
st2000_create_inferior,
st2000_mourn_inferior,
0, /* can_run */
0, /* notice_signals */
0, /* to_stop */
process_stratum,
0, /* next */
1,
1,
1,
1,
1, /* all mem, mem, stack, regs, exec */
0,
0, /* Section pointers */
OPS_MAGIC, /* Always the last thing */
};
void
_initialize_remote_st2000 ()
{
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.");
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,188 +0,0 @@
/* Am29k-dependent portions of the RPC protocol
used with a VxWorks target
Contributed by Wind River Systems.
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 "defs.h"
#include "vx-share/regPacket.h"
#include "frame.h"
#include "inferior.h"
#include "wait.h"
#include "target.h"
#include "gdbcore.h"
#include "command.h"
#include "symtab.h"
#include "symfile.h" /* for struct complaint */
#include "gdb_string.h"
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#ifdef _AIX /* IBM claims "void *malloc()" not char * */
#define malloc bogon_malloc
#endif
#include <rpc/rpc.h>
#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
#include <netdb.h>
#include "vx-share/ptrace.h"
#include "vx-share/xdr_ptrace.h"
#include "vx-share/xdr_ld.h"
#include "vx-share/xdr_rdb.h"
#include "vx-share/dbgRpcLib.h"
/* get rid of value.h if possible */
#include <value.h>
#include <symtab.h>
/* Flag set if target has fpu */
extern int target_has_fp;
/* Generic register read/write routines in remote-vx.c. */
extern void net_read_registers ();
extern void net_write_registers ();
/* Read a register or registers from the VxWorks target.
REGNO is the register to read, or -1 for all; currently,
it is ignored. FIXME look at regno to improve efficiency. */
void
vx_read_register (regno)
int regno;
{
char am29k_greg_packet[AM29K_GREG_PLEN];
char am29k_fpreg_packet[AM29K_FPREG_PLEN];
/* Get general-purpose registers. When copying values into
registers [], don't assume that a location in registers []
is properly aligned for the target data type. */
net_read_registers (am29k_greg_packet, AM29K_GREG_PLEN, PTRACE_GETREGS);
/* Now copy the register values into registers[].
Note that this code depends on the ordering of the REGNUMs
as defined in "tm-29k.h". */
bcopy (&am29k_greg_packet[AM29K_R_GR96],
&registers[REGISTER_BYTE (GR96_REGNUM)], 160 * AM29K_GREG_SIZE);
bcopy (&am29k_greg_packet[AM29K_R_VAB],
&registers[REGISTER_BYTE (VAB_REGNUM)], 15 * AM29K_GREG_SIZE);
registers[REGISTER_BYTE (INTE_REGNUM)] = am29k_greg_packet[AM29K_R_INTE];
bcopy (&am29k_greg_packet[AM29K_R_RSP],
&registers[REGISTER_BYTE (GR1_REGNUM)], 5 * AM29K_GREG_SIZE);
/* PAD For now, don't care about exop register */
memset (&registers[REGISTER_BYTE (EXO_REGNUM)], '\0', AM29K_GREG_SIZE);
/* If the target has floating point registers, fetch them.
Otherwise, zero the floating point register values in
registers[] for good measure, even though we might not
need to. */
if (target_has_fp)
{
net_read_registers (am29k_fpreg_packet, AM29K_FPREG_PLEN,
PTRACE_GETFPREGS);
registers[REGISTER_BYTE (FPE_REGNUM)] = am29k_fpreg_packet[AM29K_R_FPE];
registers[REGISTER_BYTE (FPS_REGNUM)] = am29k_fpreg_packet[AM29K_R_FPS];
/* PAD For now, don't care about registers (?) AI0 to q */
memset (&registers[REGISTER_BYTE (161)], '\0', 21 * AM29K_FPREG_SIZE);
}
else
{
memset (&registers[REGISTER_BYTE (FPE_REGNUM)], '\0', AM29K_FPREG_SIZE);
memset (&registers[REGISTER_BYTE (FPS_REGNUM)], '\0', AM29K_FPREG_SIZE);
/* PAD For now, don't care about registers (?) AI0 to q */
memset (&registers[REGISTER_BYTE (161)], '\0', 21 * AM29K_FPREG_SIZE);
}
/* Mark the register cache valid. */
registers_fetched ();
}
/* Store a register or registers into the VxWorks target.
REGNO is the register to store, or -1 for all; currently,
it is ignored. FIXME look at regno to improve efficiency. */
void
vx_write_register (regno)
int regno;
{
char am29k_greg_packet[AM29K_GREG_PLEN];
char am29k_fpreg_packet[AM29K_FPREG_PLEN];
/* Store general purpose registers. When copying values from
registers [], don't assume that a location in registers []
is properly aligned for the target data type. */
bcopy (&registers[REGISTER_BYTE (GR96_REGNUM)],
&am29k_greg_packet[AM29K_R_GR96], 160 * AM29K_GREG_SIZE);
bcopy (&registers[REGISTER_BYTE (VAB_REGNUM)],
&am29k_greg_packet[AM29K_R_VAB], 15 * AM29K_GREG_SIZE);
am29k_greg_packet[AM29K_R_INTE] = registers[REGISTER_BYTE (INTE_REGNUM)];
bcopy (&registers[REGISTER_BYTE (GR1_REGNUM)],
&am29k_greg_packet[AM29K_R_RSP], 5 * AM29K_GREG_SIZE);
net_write_registers (am29k_greg_packet, AM29K_GREG_PLEN, PTRACE_SETREGS);
/* Store floating point registers if the target has them. */
if (target_has_fp)
{
am29k_fpreg_packet[AM29K_R_FPE] = registers[REGISTER_BYTE (FPE_REGNUM)];
am29k_fpreg_packet[AM29K_R_FPS] = registers[REGISTER_BYTE (FPS_REGNUM)];
net_write_registers (am29k_fpreg_packet, AM29K_FPREG_PLEN,
PTRACE_SETFPREGS);
}
}
/* VxWorks zeroes fp when the task is initialized; we use this
to terminate the frame chain. Chain means here the nominal address of
a frame, that is, the return address (lr0) address in the stack. To
obtain the frame pointer (lr1) contents, we must add 4 bytes.
Note : may be we should modify init_frame_info() to get the frame pointer
and store it into the frame_info struct rather than reading its
contents when FRAME_CHAIN_VALID is invoked. */
int
get_fp_contents (chain, thisframe)
CORE_ADDR chain;
struct frame_info *thisframe; /* not used here */
{
int fp_contents;
read_memory ((CORE_ADDR)(chain + 4), (char *) &fp_contents, 4);
return (fp_contents != 0);
}

View file

@ -1,158 +0,0 @@
/* 68k-dependent portions of the RPC protocol
used with a VxWorks target
Contributed by Wind River Systems.
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 "defs.h"
#include "vx-share/regPacket.h"
#include "frame.h"
#include "inferior.h"
#include "wait.h"
#include "target.h"
#include "gdbcore.h"
#include "command.h"
#include "symtab.h"
#include "symfile.h" /* for struct complaint */
#include "gdb_string.h"
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#ifdef _AIX /* IBM claims "void *malloc()" not char * */
#define malloc bogon_malloc
#endif
#include <rpc/rpc.h>
#ifdef _AIX
#undef malloc
#endif
#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
#include <netdb.h>
#include "vx-share/ptrace.h"
#include "vx-share/xdr_ptrace.h"
#include "vx-share/xdr_ld.h"
#include "vx-share/xdr_rdb.h"
#include "vx-share/dbgRpcLib.h"
/* get rid of value.h if possible */
#include <value.h>
#include <symtab.h>
/* Flag set if target has fpu */
extern int target_has_fp;
/* Generic register read/write routines in remote-vx.c. */
extern void net_read_registers ();
extern void net_write_registers ();
/* Read a register or registers from the VxWorks target.
REGNO is the register to read, or -1 for all; currently,
it is ignored. FIXME look at regno to improve efficiency. */
void
vx_read_register (regno)
int regno;
{
char mc68k_greg_packet[MC68K_GREG_PLEN];
char mc68k_fpreg_packet[MC68K_FPREG_PLEN];
/* Get general-purpose registers. */
net_read_registers (mc68k_greg_packet, MC68K_GREG_PLEN, PTRACE_GETREGS);
bcopy (&mc68k_greg_packet[MC68K_R_D0], registers, 16 * MC68K_GREG_SIZE);
bcopy (&mc68k_greg_packet[MC68K_R_SR], &registers[REGISTER_BYTE (PS_REGNUM)],
MC68K_GREG_SIZE);
bcopy (&mc68k_greg_packet[MC68K_R_PC], &registers[REGISTER_BYTE (PC_REGNUM)],
MC68K_GREG_SIZE);
/* Get floating-point registers, if the target system has them.
Otherwise, zero them. */
if (target_has_fp)
{
net_read_registers (mc68k_fpreg_packet, MC68K_FPREG_PLEN,
PTRACE_GETFPREGS);
bcopy (&mc68k_fpreg_packet[MC68K_R_FP0],
&registers[REGISTER_BYTE (FP0_REGNUM)],
MC68K_FPREG_SIZE * 8);
bcopy (&mc68k_fpreg_packet[MC68K_R_FPCR],
&registers[REGISTER_BYTE (FPC_REGNUM)],
MC68K_FPREG_PLEN - (MC68K_FPREG_SIZE * 8));
}
else
{
bzero (&registers[REGISTER_BYTE (FP0_REGNUM)],
MC68K_FPREG_SIZE * 8);
bzero (&registers[REGISTER_BYTE (FPC_REGNUM)],
MC68K_FPREG_PLEN - (MC68K_FPREG_SIZE * 8));
}
/* Mark the register cache valid. */
registers_fetched ();
}
/* Store a register or registers into the VxWorks target.
REGNO is the register to store, or -1 for all; currently,
it is ignored. FIXME look at regno to improve efficiency. */
void
vx_write_register (regno)
int regno;
{
char mc68k_greg_packet[MC68K_GREG_PLEN];
char mc68k_fpreg_packet[MC68K_FPREG_PLEN];
/* Store general-purpose registers. */
bcopy (registers, &mc68k_greg_packet[MC68K_R_D0], 16 * MC68K_GREG_SIZE);
bcopy (&registers[REGISTER_BYTE (PS_REGNUM)],
&mc68k_greg_packet[MC68K_R_SR], MC68K_GREG_SIZE);
bcopy (&registers[REGISTER_BYTE (PC_REGNUM)],
&mc68k_greg_packet[MC68K_R_PC], MC68K_GREG_SIZE);
net_write_registers (mc68k_greg_packet, MC68K_GREG_PLEN, PTRACE_SETREGS);
/* Store floating point registers if the target has them. */
if (target_has_fp)
{
bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)],
&mc68k_fpreg_packet[MC68K_R_FP0],
MC68K_FPREG_SIZE * 8);
bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
&mc68k_fpreg_packet[MC68K_R_FPCR],
MC68K_FPREG_PLEN - (MC68K_FPREG_SIZE * 8));
net_write_registers (mc68k_fpreg_packet, MC68K_FPREG_PLEN,
PTRACE_SETFPREGS);
}
}

View file

@ -1,163 +0,0 @@
/* i80960-dependent portions of the RPC protocol
used with a VxWorks target
Contributed by Wind River Systems.
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 "defs.h"
#include "vx-share/regPacket.h"
#include "frame.h"
#include "inferior.h"
#include "wait.h"
#include "target.h"
#include "gdbcore.h"
#include "command.h"
#include "symtab.h"
#include "symfile.h" /* for struct complaint */
#include "gdb_string.h"
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#ifdef _AIX /* IBM claims "void *malloc()" not char * */
#define malloc bogon_malloc
#endif
#include <rpc/rpc.h>
#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
#include <netdb.h>
#include "vx-share/ptrace.h"
#include "vx-share/xdr_ptrace.h"
#include "vx-share/xdr_ld.h"
#include "vx-share/xdr_rdb.h"
#include "vx-share/dbgRpcLib.h"
/* get rid of value.h if possible */
#include <value.h>
#include <symtab.h>
/* Flag set if target has fpu */
extern int target_has_fp;
/* 960 floating point format descriptor, from "i960-tdep.c." */
extern struct ext_format ext_format_i960;
/* Generic register read/write routines in remote-vx.c. */
extern void net_read_registers ();
extern void net_write_registers ();
/* Read a register or registers from the VxWorks target.
REGNO is the register to read, or -1 for all; currently,
it is ignored. FIXME look at regno to improve efficiency. */
void
vx_read_register (regno)
int regno;
{
char i960_greg_packet[I960_GREG_PLEN];
char i960_fpreg_packet[I960_FPREG_PLEN];
/* Get general-purpose registers. When copying values into
registers [], don't assume that a location in registers []
is properly aligned for the target data type. */
net_read_registers (i960_greg_packet, I960_GREG_PLEN, PTRACE_GETREGS);
bcopy (&i960_greg_packet[I960_R_R0],
&registers[REGISTER_BYTE (R0_REGNUM)], 16 * I960_GREG_SIZE);
bcopy (&i960_greg_packet[I960_R_G0],
&registers[REGISTER_BYTE (G0_REGNUM)], 16 * I960_GREG_SIZE);
bcopy (&i960_greg_packet[I960_R_PCW],
&registers[REGISTER_BYTE (PCW_REGNUM)], sizeof (int));
bcopy (&i960_greg_packet[I960_R_ACW],
&registers[REGISTER_BYTE (ACW_REGNUM)], sizeof (int));
bcopy (&i960_greg_packet[I960_R_TCW],
&registers[REGISTER_BYTE (TCW_REGNUM)], sizeof (int));
/* If the target has floating point registers, fetch them.
Otherwise, zero the floating point register values in
registers[] for good measure, even though we might not
need to. */
if (target_has_fp)
{
net_read_registers (i960_fpreg_packet, I960_FPREG_PLEN,
PTRACE_GETFPREGS);
bcopy (&i960_fpreg_packet[I960_R_FP0],
&registers[REGISTER_BYTE (FP0_REGNUM)],
REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
}
else
bzero (&registers[REGISTER_BYTE (FP0_REGNUM)],
REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
/* Mark the register cache valid. */
registers_fetched ();
}
/* Store a register or registers into the VxWorks target.
REGNO is the register to store, or -1 for all; currently,
it is ignored. FIXME look at regno to improve efficiency. */
void
vx_write_register (regno)
int regno;
{
char i960_greg_packet[I960_GREG_PLEN];
char i960_fpreg_packet[I960_FPREG_PLEN];
/* Store floating-point registers. When copying values from
registers [], don't assume that a location in registers []
is properly aligned for the target data type. */
bcopy (&registers[REGISTER_BYTE (R0_REGNUM)],
&i960_greg_packet[I960_R_R0], 16 * I960_GREG_SIZE);
bcopy (&registers[REGISTER_BYTE (G0_REGNUM)],
&i960_greg_packet[I960_R_G0], 16 * I960_GREG_SIZE);
bcopy (&registers[REGISTER_BYTE (PCW_REGNUM)],
&i960_greg_packet[I960_R_PCW], sizeof (int));
bcopy (&registers[REGISTER_BYTE (ACW_REGNUM)],
&i960_greg_packet[I960_R_ACW], sizeof (int));
bcopy (&registers[REGISTER_BYTE (TCW_REGNUM)],
&i960_greg_packet[I960_R_TCW], sizeof (int));
net_write_registers (i960_greg_packet, I960_GREG_PLEN, PTRACE_SETREGS);
/* Store floating point registers if the target has them. */
if (target_has_fp)
{
bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)],
&i960_fpreg_packet[I960_R_FP0],
REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
net_write_registers (i960_fpreg_packet, I960_FPREG_PLEN,
PTRACE_SETFPREGS);
}
}

View file

@ -1,201 +0,0 @@
/* MIPS-dependent portions of the RPC protocol
used with a VxWorks target
Contributed by Wind River Systems.
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 "defs.h"
#include "vx-share/regPacket.h"
#include "frame.h"
#include "inferior.h"
#include "wait.h"
#include "target.h"
#include "gdbcore.h"
#include "command.h"
#include "symtab.h"
#include "symfile.h" /* for struct complaint */
#include "gdb_string.h"
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <rpc/rpc.h>
#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
#include <netdb.h>
#include "vx-share/ptrace.h"
#include "vx-share/xdr_ptrace.h"
#include "vx-share/xdr_ld.h"
#include "vx-share/xdr_rdb.h"
#include "vx-share/dbgRpcLib.h"
/* get rid of value.h if possible */
#include <value.h>
#include <symtab.h>
/* Flag set if target has fpu */
extern int target_has_fp;
/* Generic register read/write routines in remote-vx.c. */
extern void net_read_registers ();
extern void net_write_registers ();
/* Read a register or registers from the VxWorks target.
REGNO is the register to read, or -1 for all; currently,
it is ignored. FIXME look at regno to improve efficiency. */
void
vx_read_register (regno)
int regno;
{
char mips_greg_packet[MIPS_GREG_PLEN];
char mips_fpreg_packet[MIPS_FPREG_PLEN];
/* Get general-purpose registers. */
net_read_registers (mips_greg_packet, MIPS_GREG_PLEN, PTRACE_GETREGS);
/* this code copies the registers obtained by RPC
stored in a structure(s) like this :
Register(s) Offset(s)
gp 0-31 0x00
hi 0x80
lo 0x84
sr 0x88
pc 0x8c
into a stucture like this:
0x00 GP 0-31
0x80 SR
0x84 LO
0x88 HI
0x8C BAD --- Not available currently
0x90 CAUSE --- Not available currently
0x94 PC
0x98 FP 0-31
0x118 FCSR
0x11C FIR --- Not available currently
0x120 FP --- Not available currently
structure is 0x124 (292) bytes in length */
/* Copy the general registers. */
bcopy (&mips_greg_packet[MIPS_R_GP0], &registers[0], 32 * MIPS_GREG_SIZE);
/* Copy SR, LO, HI, and PC. */
bcopy (&mips_greg_packet[MIPS_R_SR],
&registers[REGISTER_BYTE (PS_REGNUM)], MIPS_GREG_SIZE);
bcopy (&mips_greg_packet[MIPS_R_LO],
&registers[REGISTER_BYTE (LO_REGNUM)], MIPS_GREG_SIZE);
bcopy (&mips_greg_packet[MIPS_R_HI],
&registers[REGISTER_BYTE (HI_REGNUM)], MIPS_GREG_SIZE);
bcopy (&mips_greg_packet[MIPS_R_PC],
&registers[REGISTER_BYTE (PC_REGNUM)], MIPS_GREG_SIZE);
/* If the target has floating point registers, fetch them.
Otherwise, zero the floating point register values in
registers[] for good measure, even though we might not
need to. */
if (target_has_fp)
{
net_read_registers (mips_fpreg_packet, MIPS_FPREG_PLEN,
PTRACE_GETFPREGS);
/* Copy the floating point registers. */
bcopy (&mips_fpreg_packet[MIPS_R_FP0],
&registers[REGISTER_BYTE (FP0_REGNUM)],
REGISTER_RAW_SIZE (FP0_REGNUM) * 32);
/* Copy the floating point control/status register (fpcsr). */
bcopy (&mips_fpreg_packet[MIPS_R_FPCSR],
&registers[REGISTER_BYTE (FCRCS_REGNUM)],
REGISTER_RAW_SIZE (FCRCS_REGNUM));
}
else
{
bzero ((char *) &registers[REGISTER_BYTE (FP0_REGNUM)],
REGISTER_RAW_SIZE (FP0_REGNUM) * 32);
bzero ((char *) &registers[REGISTER_BYTE (FCRCS_REGNUM)],
REGISTER_RAW_SIZE (FCRCS_REGNUM));
}
/* Mark the register cache valid. */
registers_fetched ();
}
/* Store a register or registers into the VxWorks target.
REGNO is the register to store, or -1 for all; currently,
it is ignored. FIXME look at regno to improve efficiency. */
vx_write_register (regno)
int regno;
{
char mips_greg_packet[MIPS_GREG_PLEN];
char mips_fpreg_packet[MIPS_FPREG_PLEN];
/* Store general registers. */
bcopy (&registers[0], &mips_greg_packet[MIPS_R_GP0], 32 * MIPS_GREG_SIZE);
/* Copy SR, LO, HI, and PC. */
bcopy (&registers[REGISTER_BYTE (PS_REGNUM)],
&mips_greg_packet[MIPS_R_SR], MIPS_GREG_SIZE);
bcopy (&registers[REGISTER_BYTE (LO_REGNUM)],
&mips_greg_packet[MIPS_R_LO], MIPS_GREG_SIZE);
bcopy (&registers[REGISTER_BYTE (HI_REGNUM)],
&mips_greg_packet[MIPS_R_HI], MIPS_GREG_SIZE);
bcopy (&registers[REGISTER_BYTE (PC_REGNUM)],
&mips_greg_packet[MIPS_R_PC], MIPS_GREG_SIZE);
net_write_registers (mips_greg_packet, MIPS_GREG_PLEN, PTRACE_SETREGS);
/* Store floating point registers if the target has them. */
if (target_has_fp)
{
/* Copy the floating point data registers. */
bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)],
&mips_fpreg_packet[MIPS_R_FP0],
REGISTER_RAW_SIZE (FP0_REGNUM) * 32);
/* Copy the floating point control/status register (fpcsr). */
bcopy (&registers[REGISTER_BYTE (FCRCS_REGNUM)],
&mips_fpreg_packet[MIPS_R_FPCSR],
REGISTER_RAW_SIZE (FCRCS_REGNUM));
net_write_registers (mips_fpreg_packet, MIPS_FPREG_PLEN,
PTRACE_SETFPREGS);
}
}

View file

@ -1,196 +0,0 @@
/* sparc-dependent portions of the RPC protocol
used with a VxWorks target
Contributed by Wind River Systems.
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 "defs.h"
#include "vx-share/regPacket.h"
#include "frame.h"
#include "inferior.h"
#include "wait.h"
#include "target.h"
#include "gdbcore.h"
#include "command.h"
#include "symtab.h"
#include "symfile.h" /* for struct complaint */
#include "gdb_string.h"
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#ifdef _AIX /* IBM claims "void *malloc()" not char * */
#define malloc bogon_malloc
#endif
#include <rpc/rpc.h>
#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
#include <netdb.h>
#include "vx-share/ptrace.h"
#include "vx-share/xdr_ptrace.h"
#include "vx-share/xdr_ld.h"
#include "vx-share/xdr_rdb.h"
#include "vx-share/dbgRpcLib.h"
/* get rid of value.h if possible */
#include <value.h>
#include <symtab.h>
/* Flag set if target has fpu */
extern int target_has_fp;
/* sparc floating point format descriptor, from "sparc-tdep.c." */
extern struct ext_format ext_format_sparc;
/* Generic register read/write routines in remote-vx.c. */
extern void net_read_registers ();
extern void net_write_registers ();
/* Read a register or registers from the VxWorks target.
REGNO is the register to read, or -1 for all; currently,
it is ignored. FIXME look at regno to improve efficiency. */
void
vx_read_register (regno)
int regno;
{
char sparc_greg_packet[SPARC_GREG_PLEN];
char sparc_fpreg_packet[SPARC_FPREG_PLEN];
CORE_ADDR sp;
/* Get general-purpose registers. When copying values into
registers [], don't assume that a location in registers []
is properly aligned for the target data type. */
net_read_registers (sparc_greg_packet, SPARC_GREG_PLEN, PTRACE_GETREGS);
/* Now copy the register values into registers[].
Note that this code depends on the ordering of the REGNUMs
as defined in "tm-sparc.h". */
bcopy (&sparc_greg_packet[SPARC_R_G0],
&registers[REGISTER_BYTE (G0_REGNUM)], 32 * SPARC_GREG_SIZE);
bcopy (&sparc_greg_packet[SPARC_R_Y],
&registers[REGISTER_BYTE (Y_REGNUM)], 6 * SPARC_GREG_SIZE);
/* Now write the local and in registers to the register window
spill area in the frame. VxWorks does not do this for the
active frame automatically; it greatly simplifies debugging
(FRAME_FIND_SAVED_REGS, in particular, depends on this). */
sp = extract_address (&registers[REGISTER_BYTE (SP_REGNUM)],
REGISTER_RAW_SIZE (CORE_ADDR));
write_memory (sp, &registers[REGISTER_BYTE (L0_REGNUM)],
16 * REGISTER_RAW_SIZE (L0_REGNUM));
/* If the target has floating point registers, fetch them.
Otherwise, zero the floating point register values in
registers[] for good measure, even though we might not
need to. */
if (target_has_fp)
{
net_read_registers (sparc_fpreg_packet, SPARC_FPREG_PLEN,
PTRACE_GETFPREGS);
bcopy (&sparc_fpreg_packet[SPARC_R_FP0],
&registers[REGISTER_BYTE (FP0_REGNUM)], 32 * SPARC_FPREG_SIZE);
bcopy (&sparc_fpreg_packet[SPARC_R_FSR],
&registers[REGISTER_BYTE (FPS_REGNUM)], 1 * SPARC_FPREG_SIZE);
}
else
{
bzero (&registers[REGISTER_BYTE (FP0_REGNUM)], 32 * SPARC_FPREG_SIZE);
bzero (&registers[REGISTER_BYTE (FPS_REGNUM)], 1 * SPARC_FPREG_SIZE);
}
/* Mark the register cache valid. */
registers_fetched ();
}
/* Store a register or registers into the VxWorks target.
REGNO is the register to store, or -1 for all; currently,
it is ignored. FIXME look at regno to improve efficiency. */
void
vx_write_register (regno)
int regno;
{
char sparc_greg_packet[SPARC_GREG_PLEN];
char sparc_fpreg_packet[SPARC_FPREG_PLEN];
int in_gp_regs;
int in_fp_regs;
CORE_ADDR sp;
/* Store general purpose registers. When copying values from
registers [], don't assume that a location in registers []
is properly aligned for the target data type. */
in_gp_regs = 1;
in_fp_regs = 1;
if (regno >= 0)
{
if ((G0_REGNUM <= regno && regno <= I7_REGNUM)
|| (Y_REGNUM <= regno && regno <= NPC_REGNUM))
in_fp_regs = 0;
else
in_gp_regs = 0;
}
if (in_gp_regs)
{
bcopy (&registers[REGISTER_BYTE (G0_REGNUM)],
&sparc_greg_packet[SPARC_R_G0], 32 * SPARC_GREG_SIZE);
bcopy (&registers[REGISTER_BYTE (Y_REGNUM)],
&sparc_greg_packet[SPARC_R_Y], 6 * SPARC_GREG_SIZE);
net_write_registers (sparc_greg_packet, SPARC_GREG_PLEN, PTRACE_SETREGS);
/* If this is a local or in register, or we're storing all
registers, update the register window spill area. */
if (regno < 0 || (L0_REGNUM <= regno && regno <= I7_REGNUM))
{
sp = extract_address (&registers[REGISTER_BYTE (SP_REGNUM)],
REGISTER_RAW_SIZE (CORE_ADDR));
write_memory (sp, &registers[REGISTER_BYTE (L0_REGNUM)],
16 * REGISTER_RAW_SIZE (L0_REGNUM));
}
}
/* Store floating point registers if the target has them. */
if (in_fp_regs && target_has_fp)
{
bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)],
&sparc_fpreg_packet[SPARC_R_FP0], 32 * SPARC_FPREG_SIZE);
bcopy (&registers[REGISTER_BYTE (FPS_REGNUM)],
&sparc_fpreg_packet[SPARC_R_FSR], 1 * SPARC_FPREG_SIZE);
net_write_registers (sparc_fpreg_packet, SPARC_FPREG_PLEN,
PTRACE_SETFPREGS);
}
}

View file

@ -1,420 +0,0 @@
/* Remote serial interface using Hitachi E7000 PC ISA card in a PC
Copyright 1994 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifdef __GO32__
#include "defs.h"
#include "serial.h"
#include <sys/dos.h>
static int e7000pc_open PARAMS ((serial_t scb, const char *name));
static void e7000pc_raw PARAMS ((serial_t scb));
static int e7000pc_readchar PARAMS ((serial_t scb, int timeout));
static int e7000pc_setbaudrate PARAMS ((serial_t scb, int rate));
static int e7000pc_write PARAMS ((serial_t scb, const char *str, int len));
static void e7000pc_close PARAMS ((serial_t scb));
static serial_ttystate e7000pc_get_tty_state PARAMS ((serial_t scb));
static int e7000pc_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
static char *aptr PARAMS ((short p));
static int dos_async_init PARAMS ((int port));
static void dos_async_tx PARAMS ((const char c));
static int dos_async_rx PARAMS (());
#define OFF_DPD 0x0000
#define OFF_DDP 0x1000
#define OFF_CPD 0x2000
#define OFF_CDP 0x2400
#define OFF_FA 0x3000
#define OFF_FB 0x3002
#define OFF_FC 0x3004
#define OFF_IRQTOD 0x3008
#define OFF_IRQTOP 0x300a
#define OFF_READY 0x300c
#define OFF_PON 0x300e
#define IDLE 0x0000
#define CMD_CI 0x4349
#define CMD_CO 0x434f
#define CMD_LO 0x4c4f
#define CMD_LS 0x4c53
#define CMD_SV 0x5356
#define CMD_SS 0x5353
#define CMD_OK 0x4f4b
#define CMD_ER 0x4552
#define CMD_NF 0x4e46
#define CMD_AB 0x4142
#define CMD_ED 0x4544
#define CMD_CE 0x4345
static unsigned long fa;
static unsigned long irqtod;
static unsigned long ready;
static unsigned long fb;
static unsigned long cpd ;
static unsigned long cdp ;
static unsigned long ready;
static unsigned long pon;
static unsigned long irqtop;
static unsigned long board_at;
#define SET_BYTE(x,y) { char _buf = y;dosmemput(&_buf,1, x);}
#define SET_WORD(x,y) { short _buf = y;dosmemput(&_buf,2, x);}
#define GET_BYTE(x) ( dosmemget(x,1,&bb), bb)
#define GET_WORD(x) ( dosmemget(x,2,&sb), sb)
static unsigned char bb;
static unsigned short sb;
static struct sw
{
int sw;
int addr;
} sigs[] = {
{0x14, 0xd0000},
{0x15, 0xd4000},
{0x16, 0xd8000},
{0x17, 0xdc000},
0};
static int
e7000pc_init ()
{
/* Look around in memory for the board's signature */
int try;
for (try = 0; sigs[try].sw; try++)
{
int val;
board_at = sigs[try].addr;
fa = board_at + OFF_FA;
fb = board_at + OFF_FB;
cpd = board_at + OFF_CPD;
cdp = board_at + OFF_CDP;
ready =board_at + OFF_READY;
pon = board_at + OFF_PON;
irqtop = board_at + OFF_IRQTOP;
irqtod = board_at + OFF_IRQTOD;
val = GET_WORD (ready);
if (val == (0xaaa0 | sigs[try].sw))
{
if (GET_BYTE (pon) & 0xf)
{
SET_BYTE(fa, 0);
SET_BYTE (fb, 0);
SET_BYTE (irqtop, 1); /* Disable interrupts from e7000 */
SET_WORD (ready, 1);
printf_filtered ("\nConnected to the E7000PC at address 0x%x\n",
sigs[try].addr);
return 1;
}
error ("The E7000 PC board is working, but the E7000 is turned off.\n");
return 0;
}
}
error ("GDB cannot connect to the E7000 PC board, check that it is installed\n\
and that the switch settings are correct. Some other DOS programs can \n\
stop the board from working. Try starting from a very minimal boot, \n\
perhaps you need to disable EMM386 over the region where the board has\n\
its I/O space, remove other unneeded cards, etc etc\n");
return 0;
}
static int pbuf_size;
static int pbuf_index;
static
int
e7000_get ()
{
static char pbuf[1000];
char tmp[1000];
int x;
if (pbuf_index < pbuf_size)
{
x = pbuf[pbuf_index++];
}
else if ((GET_BYTE (fb) & 1))
{
int i;
pbuf_size = GET_WORD(cdp + 2);
dosmemget (cdp + 8, pbuf_size + 1, tmp);
/* Tell the E7000 we've eaten */
SET_BYTE(fb,0);
/* Swap it around */
for (i = 0; i < pbuf_size; i++)
{
pbuf[i] = tmp[i^1];
}
pbuf_index = 0;
x = pbuf[pbuf_index++];
}
else
{
x = -1;
}
return x;
}
static int
dosasync_read (fd, buf, len, timeout)
int fd;
char *buf;
int len;
int timeout;
{
long now;
long then;
int i = 0;
int p;
/* Then look for some more if we're still hungry */
time (&now);
then = now + timeout;
while (i < len)
{
int ch = e7000_get();
/* While there's room in the buffer, and we've already
read the stuff in, suck it over */
if (ch != -1)
{
buf[i++] = ch;
while (i < len && pbuf_index < pbuf_size )
{
ch = e7000_get();
if (ch == -1)
break;
buf[i++] = ch;
}
}
time (&now);
if (timeout == 0)
return i;
if (now >= then && timeout > 0)
{
return i;
}
}
return len;
}
static int
dosasync_write (fd, buf, len)
int fd;
const char *buf;
int len;
{
int i;
char dummy[1000];
/* Construct copy locally */
((short *)dummy)[0] = CMD_CI;
((short *)dummy)[1] = len;
((short *)dummy)[2] = 0;
((short *)dummy)[3] = 0;
for (i = 0; i < len ; i++)
{
dummy[8 + i ^ 1] = buf[i];
}
/* Wait for the card to get ready */
while ((GET_BYTE(fa) & 1) != 0)
;
/* Blast onto the ISA card */
dosmemput (dummy, 8 + len + 1, cpd);
SET_BYTE(fa, 1);
SET_BYTE(irqtod, 1); /* Interrupt the E7000 */
return len;
}
static int
e7000pc_open (scb, name)
serial_t scb;
const char *name;
{
if (strncasecmp (name, "pc", 2) != 0)
{
errno = ENOENT;
return -1;
}
scb->fd = e7000pc_init ();
if (!scb->fd)
return -1;
return 0;
}
static int
e7000pc_noop (scb)
serial_t scb;
{
return 0;
}
static void
e7000pc_raw (scb)
serial_t scb;
{
/* Always in raw mode */
}
static int
e7000pc_readchar (scb, timeout)
serial_t scb;
int timeout;
{
char buf;
top:
if (dosasync_read (scb->fd, &buf, 1, timeout))
{
if (buf == 0) goto top;
return buf;
}
else
return SERIAL_TIMEOUT;
}
struct e7000pc_ttystate {
int dummy;
};
/* e7000pc_{get set}_tty_state() are both dummys to fill out the function
vector. Someday, they may do something real... */
static serial_ttystate
e7000pc_get_tty_state (scb)
serial_t scb;
{
struct e7000pc_ttystate *state;
state = (struct e7000pc_ttystate *) xmalloc (sizeof *state);
return (serial_ttystate) state;
}
static int
e7000pc_set_tty_state (scb, ttystate)
serial_t scb;
serial_ttystate ttystate;
{
return 0;
}
static int
e7000pc_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
serial_t scb;
serial_ttystate new_ttystate;
serial_ttystate old_ttystate;
{
return 0;
}
static void
e7000pc_print_tty_state (scb, ttystate)
serial_t scb;
serial_ttystate ttystate;
{
/* Nothing to print. */
return;
}
static int
e7000pc_setbaudrate (scb, rate)
serial_t scb;
int rate;
{
return 0;
}
static int
e7000pc_write (scb, str, len)
serial_t scb;
const char *str;
int len;
{
dosasync_write (scb->fd, str, len);
return 0;
}
static void
e7000pc_close (scb)
serial_t scb;
{
}
static struct serial_ops e7000pc_ops =
{
"pc",
0,
e7000pc_open,
e7000pc_close,
e7000pc_readchar,
e7000pc_write,
e7000pc_noop, /* flush output */
e7000pc_noop, /* flush input */
e7000pc_noop, /* send break -- currently used only for nindy */
e7000pc_raw,
e7000pc_get_tty_state,
e7000pc_set_tty_state,
e7000pc_print_tty_state,
e7000pc_noflush_set_tty_state,
e7000pc_setbaudrate,
};
void
_initialize_ser_e7000pc ()
{
serial_add_interface (&e7000pc_ops);
}
#else
void
_initialize_ser_e7000pc ()
{
}
#endif

View file

@ -1,957 +0,0 @@
/* Remote serial interface for local (hardwired) serial ports for
GO32. Copyright 1992, 1993 Free Software Foundation, Inc.
Contributed by Nigel Stephens, Algorithmics Ltd. (nigel@algor.co.uk).
This version uses DPMI interrupts to handle buffered i/o
without the separate "asynctsr" program.
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 "gdbcmd.h"
#include "serial.h"
/*
* NS16550 UART registers
*/
#define COM1ADDR 0x3f8
#define COM2ADDR 0x2f8
#define COM3ADDR 0x3e8
#define COM4ADDR 0x3e0
#define com_data 0 /* data register (R/W) */
#define com_dlbl 0 /* divisor latch low (W) */
#define com_ier 1 /* interrupt enable (W) */
#define com_dlbh 1 /* divisor latch high (W) */
#define com_iir 2 /* interrupt identification (R) */
#define com_fifo 2 /* FIFO control (W) */
#define com_lctl 3 /* line control register (R/W) */
#define com_cfcr 3 /* line control register (R/W) */
#define com_mcr 4 /* modem control register (R/W) */
#define com_lsr 5 /* line status register (R/W) */
#define com_msr 6 /* modem status register (R/W) */
/*
* Constants for computing 16 bit baud rate divisor (lower byte
* in com_dlbl, upper in com_dlbh) from 1.8432MHz crystal. Divisor is
* 1.8432 MHz / (16 * X) for X bps. If the baud rate can't be set
* to within +- (desired_rate*SPEED_TOLERANCE/1000) bps, we fail.
*/
#define COMTICK (1843200/16)
#define SPEED_TOLERANCE 30 /* thousandths; real == desired +- 3.0% */
/* interrupt enable register */
#define IER_ERXRDY 0x1 /* int on rx ready */
#define IER_ETXRDY 0x2 /* int on tx ready */
#define IER_ERLS 0x4 /* int on line status change */
#define IER_EMSC 0x8 /* int on modem status change */
/* interrupt identification register */
#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */
#define IIR_IMASK 0xf /* interrupt cause mask */
#define IIR_NOPEND 0x1 /* nothing pending */
#define IIR_RLS 0x6 /* receive line status */
#define IIR_RXRDY 0x4 /* receive ready */
#define IIR_RXTOUT 0xc /* receive timeout */
#define IIR_TXRDY 0x2 /* transmit ready */
#define IIR_MLSC 0x0 /* modem status */
/* fifo control register */
#define FIFO_ENABLE 0x01 /* enable fifo */
#define FIFO_RCV_RST 0x02 /* reset receive fifo */
#define FIFO_XMT_RST 0x04 /* reset transmit fifo */
#define FIFO_DMA_MODE 0x08 /* enable dma mode */
#define FIFO_TRIGGER_1 0x00 /* trigger at 1 char */
#define FIFO_TRIGGER_4 0x40 /* trigger at 4 chars */
#define FIFO_TRIGGER_8 0x80 /* trigger at 8 chars */
#define FIFO_TRIGGER_14 0xc0 /* trigger at 14 chars */
/* character format control register */
#define CFCR_DLAB 0x80 /* divisor latch */
#define CFCR_SBREAK 0x40 /* send break */
#define CFCR_PZERO 0x30 /* zero parity */
#define CFCR_PONE 0x20 /* one parity */
#define CFCR_PEVEN 0x10 /* even parity */
#define CFCR_PODD 0x00 /* odd parity */
#define CFCR_PENAB 0x08 /* parity enable */
#define CFCR_STOPB 0x04 /* 2 stop bits */
#define CFCR_8BITS 0x03 /* 8 data bits */
#define CFCR_7BITS 0x02 /* 7 data bits */
#define CFCR_6BITS 0x01 /* 6 data bits */
#define CFCR_5BITS 0x00 /* 5 data bits */
/* modem control register */
#define MCR_LOOPBACK 0x10 /* loopback */
#define MCR_IENABLE 0x08 /* output 2 = int enable */
#define MCR_DRS 0x04 /* output 1 = xxx */
#define MCR_RTS 0x02 /* enable RTS */
#define MCR_DTR 0x01 /* enable DTR */
/* line status register */
#define LSR_RCV_FIFO 0x80 /* error in receive fifo */
#define LSR_TSRE 0x40 /* transmitter empty */
#define LSR_TXRDY 0x20 /* transmitter ready */
#define LSR_BI 0x10 /* break detected */
#define LSR_FE 0x08 /* framing error */
#define LSR_PE 0x04 /* parity error */
#define LSR_OE 0x02 /* overrun error */
#define LSR_RXRDY 0x01 /* receiver ready */
#define LSR_RCV_MASK 0x1f
/* modem status register */
#define MSR_DCD 0x80
#define MSR_RI 0x40
#define MSR_DSR 0x20
#define MSR_CTS 0x10
#define MSR_DDCD 0x08
#define MSR_TERI 0x04
#define MSR_DDSR 0x02
#define MSR_DCTS 0x01
#include <sys/dos.h>
#include <sys/go32.h>
#include <sys/dpmi.h>
/* DPMI Communication */
static union REGS dpmi_regs;
static struct SREGS dpmi_sregs;
/* 16550 rx fifo trigger point */
#define FIFO_TRIGGER FIFO_TRIGGER_4
/* input buffer size */
#define CBSIZE 4096
/* return raw 18Hz clock count */
extern long rawclock (void);
#define RAWHZ 18
#ifdef DOS_STATS
#define CNT_RX 16
#define CNT_TX 17
#define CNT_STRAY 18
#define CNT_ORUN 19
#define NCNT 20
static int intrcnt;
static int cnts[NCNT];
static char *cntnames[NCNT] = {
/* h/w interrupt counts. */
"mlsc", "nopend", "txrdy", "?3",
"rxrdy", "?5", "rls", "?7",
"?8", "?9", "?a", "?b",
"rxtout", "?d", "?e", "?f",
/* s/w counts. */
"rxcnt", "txcnt", "stray", "swoflo"
};
#define COUNT(x) cnts[x]++
#else
#define COUNT(x)
#endif
/* Main interrupt controller port addresses. */
#define ICU_BASE 0x20
#define ICU_OCW2 (ICU_BASE + 0)
#define ICU_MASK (ICU_BASE + 1)
/* Original interrupt controller mask register. */
unsigned char icu_oldmask;
/* Maximum of 8 interrupts (we don't handle the slave icu yet). */
#define NINTR 8
static struct intrupt
{
char inuse;
struct dos_ttystate *port;
_go32_dpmi_seginfo old_rmhandler;
_go32_dpmi_seginfo old_pmhandler;
_go32_dpmi_seginfo new_rmhandler;
_go32_dpmi_seginfo new_pmhandler;
_go32_dpmi_registers regs;
} intrupts[NINTR];
static struct dos_ttystate
{
int base;
int irq;
int refcnt;
struct intrupt *intrupt;
int fifo;
int baudrate;
unsigned char cbuf[CBSIZE];
unsigned int first;
unsigned int count;
int txbusy;
unsigned char old_mcr;
int ferr;
int perr;
int oflo;
int msr;
} ports[4] = {
{COM1ADDR, 4},
{COM2ADDR, 3},
{COM3ADDR, 4},
{COM4ADDR, 3}
};
static int dos_open PARAMS ((serial_t scb, const char *name));
static void dos_raw PARAMS ((serial_t scb));
static int dos_readchar PARAMS ((serial_t scb, int timeout));
static int dos_setbaudrate PARAMS ((serial_t scb, int rate));
static int dos_write PARAMS ((serial_t scb, const char *str, int len));
static void dos_close PARAMS ((serial_t scb));
static serial_ttystate dos_get_tty_state PARAMS ((serial_t scb));
static int dos_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
static int dos_baudconv PARAMS ((int rate));
#define inb(p,a) inportb((p)->base + (a))
#define outb(p,a,v) outportb((p)->base + (a), (v))
#define disable() asm volatile ("cli");
#define enable() asm volatile ("sti");
static int
dos_getc (port)
volatile struct dos_ttystate *port;
{
int c;
if (port->count == 0)
return -1;
c = port->cbuf[port->first];
disable ();
port->first = (port->first + 1) & (CBSIZE - 1);
port->count--;
enable ();
return c;
}
static int
dos_putc (c, port)
int c;
struct dos_ttystate *port;
{
if (port->count >= CBSIZE - 1)
return -1;
port->cbuf[(port->first + port->count) & (CBSIZE - 1)] = c;
port->count++;
return 0;
}
static void
dos_comisr (irq)
int irq;
{
struct dos_ttystate *port;
unsigned char iir, lsr, c;
disable (); /* Paranoia */
outportb (ICU_OCW2, 0x20); /* End-Of-Interrupt */
#ifdef DOS_STATS
++intrcnt;
#endif
port = intrupts[irq].port;
if (!port)
{
COUNT (CNT_STRAY);
return; /* not open */
}
while (1)
{
iir = inb (port, com_iir) & IIR_IMASK;
switch (iir)
{
case IIR_RLS:
lsr = inb (port, com_lsr);
goto rx;
case IIR_RXTOUT:
case IIR_RXRDY:
lsr = 0;
rx:
do
{
c = inb (port, com_data);
if (lsr & (LSR_BI | LSR_FE | LSR_PE | LSR_OE))
{
if (lsr & (LSR_BI | LSR_FE))
port->ferr++;
else if (lsr & LSR_PE)
port->perr++;
if (lsr & LSR_OE)
port->oflo++;
}
if (dos_putc (c, port) < 0)
{
COUNT (CNT_ORUN);
}
else
{
COUNT (CNT_RX);
}
}
while ((lsr = inb (port, com_lsr)) & LSR_RXRDY);
break;
case IIR_MLSC:
/* could be used to flowcontrol Tx */
port->msr = inb (port, com_msr);
break;
case IIR_TXRDY:
port->txbusy = 0;
break;
case IIR_NOPEND:
/* no more pending interrupts, all done */
return;
default:
/* unexpected interrupt, ignore */
break;
}
COUNT (iir);
}
}
#ifdef __STDC__
#define ISRNAME(x) dos_comisr##x
#else
#define ISRNAME(x) dos_comisr/**/x
#endif
#define ISR(x) static void ISRNAME(x)() {dos_comisr(x);}
ISR(0) ISR(1) ISR(2) ISR(3)
ISR(4) ISR(5) ISR(6) ISR(7)
typedef void (*isr_t)();
static isr_t isrs[NINTR] = {
ISRNAME(0), ISRNAME(1), ISRNAME(2), ISRNAME(3),
ISRNAME(4), ISRNAME(5), ISRNAME(6), ISRNAME(7)
};
static struct intrupt *
dos_hookirq (irq)
unsigned int irq;
{
struct intrupt *intr;
unsigned int vec;
isr_t isr;
if (irq >= NINTR)
return 0;
intr = &intrupts[irq];
if (intr->inuse)
return 0;
vec = 0x08 + irq;
isr = isrs[irq];
/* setup real mode handler */
_go32_dpmi_get_real_mode_interrupt_vector (vec, &intr->old_rmhandler);
intr->new_rmhandler.pm_selector = _go32_my_cs();
intr->new_rmhandler.pm_offset = (u_long)isr;
if (_go32_dpmi_allocate_real_mode_callback_iret (&intr->new_rmhandler,
&intr->regs))
{
return 0;
}
if (_go32_dpmi_set_real_mode_interrupt_vector (vec, &intr->new_rmhandler))
{
return 0;
}
/* setup protected mode handler */
_go32_dpmi_get_protected_mode_interrupt_vector(vec, &intr->old_pmhandler);
intr->new_pmhandler.pm_selector = _go32_my_cs();
intr->new_pmhandler.pm_offset = (u_long)isr;
_go32_dpmi_allocate_iret_wrapper (&intr->new_pmhandler);
if (_go32_dpmi_set_protected_mode_interrupt_vector(vec, &intr->new_pmhandler))
{
return 0;
}
/* setup interrupt controller mask */
disable ();
outportb (ICU_MASK, inportb (ICU_MASK) & ~(1 << irq));
enable ();
intr->inuse = 1;
return intr;
}
static void
dos_unhookirq (intr)
struct intrupt *intr;
{
unsigned int irq, vec;
unsigned char mask;
irq = intr - intrupts;
vec = 0x08 + irq;
/* restore old interrupt mask bit */
mask = 1 << irq;
disable ();
outportb (ICU_MASK, inportb (ICU_MASK) | (mask & icu_oldmask));
enable ();
/* remove real mode handler */
_go32_dpmi_set_real_mode_interrupt_vector (vec, &intr->old_rmhandler);
_go32_dpmi_free_real_mode_callback (&intr->new_rmhandler);
/* remove protected mode handler */
_go32_dpmi_set_protected_mode_interrupt_vector (vec, &intr->old_pmhandler);
_go32_dpmi_free_iret_wrapper (&intr->new_pmhandler);
intr->inuse = 0;
}
static int
dos_open (scb, name)
serial_t scb;
const char *name;
{
struct dos_ttystate *port;
int fd, i;
if (strncasecmp (name, "/dev/", 5) == 0)
name += 5;
else if (strncasecmp (name, "\\dev\\", 5) == 0)
name += 5;
if (strlen (name) != 4 || strncasecmp (name, "com", 3) != 0)
{
errno = ENOENT;
return -1;
}
if (name[3] < '1' || name[3] > '4')
{
errno = ENOENT;
return -1;
}
fd = name[3] - '1';
port = &ports[fd];
if (port->refcnt++ > 0)
{
/* Device already opened another user. Just point at it. */
scb->fd = fd;
return 0;
}
/* force access to ID reg */
outb(port, com_cfcr, 0);
outb(port, com_iir, 0);
for (i = 0; i < 17; i++) {
if ((inb(port, com_iir) & 0x38) == 0)
goto ok;
(void) inb(port, com_data); /* clear recv */
}
errno = ENODEV;
return -1;
ok:
/* disable all interrupts in chip */
outb(port, com_ier, 0);
/* tentatively enable 16550 fifo, and see if it responds */
outb(port, com_fifo, FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER);
sleep(1);
port->fifo = ((inb(port, com_iir) & IIR_FIFO_MASK) == IIR_FIFO_MASK);
/* clear pending status reports. */
(void) inb(port, com_lsr);
(void) inb(port, com_msr);
/* enable external interrupt gate (to avoid floating IRQ) */
outb(port, com_mcr, MCR_IENABLE);
/* hook up interrupt handler and initialise icu */
port->intrupt = dos_hookirq (port->irq);
if (!port->intrupt)
{
outb(port, com_mcr, 0);
outb(port, com_fifo, 0);
errno = ENODEV;
return -1;
}
disable ();
/* record port */
port->intrupt->port = port;
scb->fd = fd;
/* clear rx buffer, tx busy flag and overflow count */
port->first = port->count = 0;
port->txbusy = 0;
port->oflo = 0;
/* set default baud rate and mode: 9600,8,n,1 */
i = dos_baudconv (port->baudrate = 9600);
outb(port, com_cfcr, CFCR_DLAB);
outb(port, com_dlbl, i & 0xff);
outb(port, com_dlbh, i >> 8);
outb(port, com_cfcr, CFCR_8BITS);
/* enable all interrupts */
outb(port, com_ier, IER_ETXRDY | IER_ERXRDY | IER_ERLS | IER_EMSC);
/* enable DTR & RTS */
outb(port, com_mcr, MCR_DTR | MCR_RTS | MCR_IENABLE);
enable ();
return 0;
}
static void
dos_close (scb)
serial_t scb;
{
struct dos_ttystate *port;
struct intrupt *intrupt;
if (!scb)
return;
port = &ports[scb->fd];
if (port->refcnt-- > 1)
return;
if (!(intrupt = port->intrupt))
return;
/* disable interrupts, fifo, flow control */
disable ();
port->intrupt = 0;
intrupt->port = 0;
outb(port, com_fifo, 0);
outb(port, com_ier, 0);
enable ();
/* unhook handler, and disable interrupt gate */
dos_unhookirq (intrupt);
outb(port, com_mcr, 0);
/* Check for overflow errors */
if (port->oflo)
{
fprintf_unfiltered (gdb_stderr,
"Serial input overruns occurred.\n");
fprintf_unfiltered (gdb_stderr, "This system %s handle %d baud.\n",
port->fifo ? "cannot" : "needs a 16550 to",
port->baudrate);
}
}
static int
dos_noop (scb)
serial_t scb;
{
return 0;
}
static void
dos_raw (scb)
serial_t scb;
{
/* Always in raw mode */
}
static int
dos_readchar (scb, timeout)
serial_t scb;
int timeout;
{
struct dos_ttystate *port = &ports[scb->fd];
long then;
int c;
then = rawclock() + (timeout * RAWHZ);
while ((c = dos_getc (port)) < 0)
{
if (timeout >= 0 && (rawclock () - then) >= 0)
return SERIAL_TIMEOUT;
notice_quit ();
}
return c;
}
static serial_ttystate
dos_get_tty_state (scb)
serial_t scb;
{
struct dos_ttystate *port = &ports[scb->fd];
struct dos_ttystate *state;
state = (struct dos_ttystate *) xmalloc (sizeof *state);
*state = *port;
return (serial_ttystate) state;
}
static int
dos_set_tty_state (scb, ttystate)
serial_t scb;
serial_ttystate ttystate;
{
struct dos_ttystate *state;
state = (struct dos_ttystate *) ttystate;
dos_setbaudrate (scb, state->baudrate);
return 0;
}
static int
dos_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
serial_t scb;
serial_ttystate new_ttystate;
serial_ttystate old_ttystate;
{
struct dos_ttystate *state;
state = (struct dos_ttystate *) new_ttystate;
dos_setbaudrate (scb, state->baudrate);
return 0;
}
static int
dos_flush_input (scb)
serial_t scb;
{
struct dos_ttystate *port = &ports[scb->fd];
disable();
port->first = port->count = 0;
if (port->fifo)
outb(port, com_fifo, FIFO_ENABLE|FIFO_RCV_RST|FIFO_TRIGGER);
enable();
}
static void
dos_print_tty_state (scb, ttystate)
serial_t scb;
serial_ttystate ttystate;
{
/* Nothing to print */
return;
}
static int
dos_baudconv (rate)
int rate;
{
long x, err;
if (rate <= 0)
return -1;
#define divrnd(n, q) (((n) * 2 / (q) + 1) / 2) /* divide and round off */
x = divrnd(COMTICK, rate);
if (x <= 0)
return -1;
err = divrnd(1000 * COMTICK, x * rate) - 1000;
if (err < 0)
err = -err;
if (err > SPEED_TOLERANCE)
return -1;
#undef divrnd
return x;
}
static int
dos_setbaudrate (scb, rate)
serial_t scb;
int rate;
{
struct dos_ttystate *port = &ports[scb->fd];
if (port->baudrate != rate)
{
int x;
unsigned char cfcr;
x = dos_baudconv (rate);
if (x <= 0)
{
fprintf_unfiltered (gdb_stderr, "%d: impossible baudrate\n", rate);
errno = EINVAL;
return -1;
}
disable ();
cfcr = inb (port, com_cfcr);
outb(port, com_cfcr, CFCR_DLAB);
outb(port, com_dlbl, x & 0xff);
outb(port, com_dlbh, x >> 8);
outb(port, com_cfcr, cfcr);
port->baudrate = rate;
enable ();
}
return 0;
}
static int
dos_setstopbits (scb, num)
serial_t scb;
int num;
{
struct dos_ttystate *port = &ports[scb->fd];
unsigned char cfcr;
disable ();
cfcr = inb (port, com_cfcr);
switch (num)
{
case SERIAL_1_STOPBITS:
outb (port, com_cfcr, cfcr & ~CFCR_STOPB);
break;
case SERIAL_1_AND_A_HALF_STOPBITS:
case SERIAL_2_STOPBITS:
outb (port, com_cfcr, cfcr | CFCR_STOPB);
break;
default:
enable ();
return 1;
}
enable ();
return 0;
}
static int
dos_write (scb, str, len)
serial_t scb;
const char *str;
int len;
{
volatile struct dos_ttystate *port = &ports[scb->fd];
int fifosize = port->fifo ? 16 : 1;
long then;
int cnt;
while (len > 0)
{
/* send the data, fifosize bytes at a time */
cnt = fifosize > len ? len : fifosize;
port->txbusy = 1;
outportsb (port->base + com_data, str, cnt);
str += cnt;
len -= cnt;
#ifdef DOS_STATS
cnts[CNT_TX] += cnt;
#endif
/* wait for transmission to complete (max 1 sec) */
then = rawclock() + RAWHZ;
while (port->txbusy)
{
if ((rawclock () - then) >= 0)
{
errno = EIO;
return SERIAL_ERROR;
}
}
}
return 0;
}
static int
dos_sendbreak (scb)
serial_t scb;
{
volatile struct dos_ttystate *port = &ports[scb->fd];
unsigned char cfcr;
long then;
cfcr = inb(port, com_cfcr);
outb(port, com_cfcr, cfcr | CFCR_SBREAK);
/* 0.25 sec delay */
then = rawclock () + RAWHZ / 4;
while ((rawclock () - then) < 0)
continue;
outb(port, com_cfcr, cfcr);
return 0;
}
static struct serial_ops dos_ops =
{
"hardwire",
0,
dos_open,
dos_close,
dos_readchar,
dos_write,
dos_noop, /* flush output */
dos_flush_input,
dos_sendbreak,
dos_raw,
dos_get_tty_state,
dos_set_tty_state,
dos_print_tty_state,
dos_noflush_set_tty_state,
dos_setbaudrate,
dos_setstopbits,
};
static void
dos_info (arg, from_tty)
char *arg;
int from_tty;
{
struct dos_ttystate *port;
int i;
for (port = ports; port < &ports[4]; port++)
{
if (port->baudrate == 0)
continue;
printf_filtered ("Port:\tCOM%d (%sactive)\n", port - ports + 1,
port->intrupt ? "" : "not ");
printf_filtered ("Addr:\t0x%03x (irq %d)\n", port->base, port->irq);
printf_filtered ("16550:\t%s\n", port->fifo ? "yes" : "no");
printf_filtered ("Speed:\t%d baud\n", port->baudrate);
printf_filtered ("Errs:\tframing %d parity %d overflow %d\n\n",
port->ferr, port->perr, port->oflo);
}
#ifdef DOS_STATS
printf_filtered ("\nTotal interrupts: %d\n", intrcnt);
for (i = 0; i < NCNT; i++)
if (cnts[i])
printf_filtered ("%s:\t%d\n", cntnames[i], cnts[i]);
#endif
}
void
_initialize_ser_dos ()
{
struct cmd_list_element *c;
serial_add_interface (&dos_ops);
/* Save original interrupt mask register. */
icu_oldmask = inportb (ICU_MASK);
/* Mark fixed motherboard irqs as inuse. */
intrupts[0].inuse = /* timer tick */
intrupts[1].inuse = /* keyboard */
intrupts[2].inuse = 1; /* slave icu */
add_show_from_set (
add_set_cmd ("com1base", class_obscure, var_zinteger,
(char *) &ports[0].base,
"Set COM1 base i/o port address.",
&setlist),
&showlist);
add_show_from_set (
add_set_cmd ("com1irq", class_obscure, var_zinteger,
(char *) &ports[0].irq,
"Set COM1 interrupt request.",
&setlist),
&showlist);
add_show_from_set (
add_set_cmd ("com2base", class_obscure, var_zinteger,
(char *) &ports[1].base,
"Set COM2 base i/o port address.",
&setlist),
&showlist);
add_show_from_set (
add_set_cmd ("com2irq", class_obscure, var_zinteger,
(char *) &ports[1].irq,
"Set COM2 interrupt request.",
&setlist),
&showlist);
add_show_from_set (
add_set_cmd ("com3base", class_obscure, var_zinteger,
(char *) &ports[2].base,
"Set COM3 base i/o port address.",
&setlist),
&showlist);
add_show_from_set (
add_set_cmd ("com3irq", class_obscure, var_zinteger,
(char *) &ports[2].irq,
"Set COM3 interrupt request.",
&setlist),
&showlist);
add_show_from_set (
add_set_cmd ("com4base", class_obscure, var_zinteger,
(char *) &ports[3].base,
"Set COM4 base i/o port address.",
&setlist),
&showlist);
add_show_from_set (
add_set_cmd ("com4irq", class_obscure, var_zinteger,
(char *) &ports[3].irq,
"Set COM4 interrupt request.",
&setlist),
&showlist);
add_info ("serial", dos_info,
"Print DOS serial port status.");
}

View file

@ -1,361 +0,0 @@
/* Remote serial interface for local (hardwired) serial ports for Macintosh.
Copyright 1994 Free Software Foundation, Inc.
Contributed by Cygnus Support. Written by Stan Shebs.
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 "serial.h"
#include <Types.h>
#include <Devices.h>
/* This is the regular Mac Serial.h, but copied to a different name
so as not to get confused with the GDB serial.h above. */
#include "MacSerial.h"
/* This is unused for now. We just return a placeholder. */
struct mac_ttystate
{
int bogus;
};
static int mac_open PARAMS ((serial_t scb, const char *name));
static void mac_raw PARAMS ((serial_t scb));
static int mac_readchar PARAMS ((serial_t scb, int timeout));
static int mac_setbaudrate PARAMS ((serial_t scb, int rate));
static int mac_write PARAMS ((serial_t scb, const char *str, int len));
static void mac_close PARAMS ((serial_t scb));
static serial_ttystate mac_get_tty_state PARAMS ((serial_t scb));
static int mac_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
static char *aptr PARAMS ((short p));
short input_refnum;
short output_refnum;
char *mac_input_buffer;
char *mac_output_buffer;
static int
mac_open (scb, name)
serial_t scb;
const char *name;
{
OSErr err;
/* Alloc buffer space first - that way any allocation failures are
intercepted before the serial driver gets involved. */
if (mac_input_buffer == NULL)
mac_input_buffer = (char *) xmalloc (4096);
/* Match on a name and open a port. */
if (strcmp (name, "modem") == 0)
{
err = OpenDriver ("\p.AIn", &input_refnum);
if (err != 0)
{
return (-1);
}
err = OpenDriver ("\p.AOut", &output_refnum);
if (err != 0)
{
CloseDriver (input_refnum);
return (-1);
}
}
else if (strcmp (name, "printer") == 0)
{
err = OpenDriver ("\p.BIn", &input_refnum);
if (err != 0)
{
return (-1);
}
err = OpenDriver ("\p.BOut", &output_refnum);
if (err != 0)
{
CloseDriver (input_refnum);
return (-1);
}
/* fake */
scb->fd = 1;
return 0;
}
else
{
error ("You must specify a valid serial port name; your choices are `modem' or `printer'.");
errno = ENOENT;
return (-1);
}
/* We got something open. */
if (1 /* using custom buffer */)
SerSetBuf (input_refnum, mac_input_buffer, 4096);
/* Set to a GDB-preferred state. */
SerReset (input_refnum, stop10|noParity|data8|baud9600);
SerReset (output_refnum, stop10|noParity|data8|baud9600);
{
CntrlParam cb;
struct SerShk *handshake;
cb.ioCRefNum = output_refnum;
cb.csCode = 14;
handshake = (struct SerShk *) &cb.csParam[0];
handshake->fXOn = 0;
handshake->fCTS = 0;
handshake->xOn = 0;
handshake->xOff = 0;
handshake->errs = 0;
handshake->evts = 0;
handshake->fInX = 0;
handshake->fDTR = 0;
err = PBControl ((ParmBlkPtr) &cb, 0);
if (err < 0)
return (-1);
}
/* fake */
scb->fd = 1;
return 0;
}
static int
mac_noop (scb)
serial_t scb;
{
return 0;
}
static void
mac_raw (scb)
serial_t scb;
{
/* Always effectively in raw mode. */
}
/* Read a character with user-specified timeout. TIMEOUT is number of seconds
to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns
char if successful. Returns -2 if timeout expired, EOF if line dropped
dead, or -3 for any other error (see errno in that case). */
static int
mac_readchar (scb, timeout)
serial_t scb;
int timeout;
{
int status, n;
/* time_t */ unsigned long start_time, now;
OSErr err;
CntrlParam cb;
IOParam pb;
if (scb->bufcnt-- > 0)
return *scb->bufp++;
time (&start_time);
while (1)
{
cb.ioCRefNum = input_refnum;
cb.csCode = 2;
err = PBStatus ((ParmBlkPtr) &cb, 0);
if (err < 0)
return SERIAL_ERROR;
n = *((long *) &cb.csParam[0]);
if (n > 0)
{
pb.ioRefNum = input_refnum;
pb.ioBuffer = (Ptr) (scb->buf);
pb.ioReqCount = (n > 64 ? 64 : n);
err = PBRead ((ParmBlkPtr) &pb, 0);
if (err < 0)
return SERIAL_ERROR;
scb->bufcnt = pb.ioReqCount;
scb->bufcnt--;
scb->bufp = scb->buf;
return *scb->bufp++;
}
else if (timeout == 0)
return SERIAL_TIMEOUT;
else if (timeout == -1)
;
else
{
time (&now);
if (now > start_time + timeout)
return SERIAL_TIMEOUT;
}
PROGRESS (1);
}
}
/* mac_{get set}_tty_state() are both dummys to fill out the function
vector. Someday, they may do something real... */
static serial_ttystate
mac_get_tty_state (scb)
serial_t scb;
{
struct mac_ttystate *state;
state = (struct mac_ttystate *) xmalloc (sizeof *state);
return (serial_ttystate) state;
}
static int
mac_set_tty_state (scb, ttystate)
serial_t scb;
serial_ttystate ttystate;
{
return 0;
}
static int
mac_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
serial_t scb;
serial_ttystate new_ttystate;
serial_ttystate old_ttystate;
{
return 0;
}
static void
mac_print_tty_state (scb, ttystate)
serial_t scb;
serial_ttystate ttystate;
{
/* Nothing to print. */
return;
}
/* If there is a tricky formula to relate real baud rates
to what the serial driver wants, we should use it. Until
we get one, this table will have to do. */
static struct {
int real_rate;
int bits;
} mac_baud_rate_table[] = {
{ 57600, baud57600 },
{ 38400, 1 },
{ 19200, baud19200 },
{ 9600, baud9600 },
{ 7200, baud7200 },
{ 4800, baud4800 },
{ 3600, baud3600 },
{ 2400, baud2400 },
{ 1800, baud1800 },
{ 1200, baud1200 },
{ 600, baud600 },
{ 300, baud300 },
{ 0, 0 }
};
static int
mac_set_baud_rate (scb, rate)
serial_t scb;
int rate;
{
int i, bits;
for (i = 0; mac_baud_rate_table[i].real_rate != 0; ++i)
{
if (mac_baud_rate_table[i].real_rate == rate)
{
bits = mac_baud_rate_table[i].bits;
break;
}
}
SerReset (input_refnum, stop10|noParity|data8|bits);
SerReset (output_refnum, stop10|noParity|data8|bits);
}
static int
mac_set_stop_bits (scb, num)
serial_t scb;
int num;
{
return 0;
}
int first_mac_write = 0;
static int
mac_write (scb, str, len)
serial_t scb;
const char *str;
int len;
{
OSErr err;
IOParam pb;
if (first_mac_write++ < 4)
{
sleep (1);
}
pb.ioRefNum = output_refnum;
pb.ioBuffer = (Ptr) str;
pb.ioReqCount = len;
err = PBWrite ((ParmBlkPtr) &pb, 0);
if (err < 0)
{
return 1;
}
return 0;
}
static void
mac_close (serial_t scb)
{
if (input_refnum)
{
if (1 /* custom buffer */)
SerSetBuf (input_refnum, mac_input_buffer, 0);
CloseDriver (input_refnum);
input_refnum = 0;
}
if (output_refnum)
{
if (0 /* custom buffer */)
SetSetBuf (input_refnum, mac_output_buffer, 0);
CloseDriver (output_refnum);
output_refnum = 0;
}
}
static struct serial_ops mac_ops =
{
"hardwire",
0,
mac_open,
mac_close,
mac_readchar,
mac_write,
mac_noop, /* flush output */
mac_noop, /* flush input */
mac_noop, /* send break -- currently only for nindy */
mac_raw,
mac_get_tty_state,
mac_set_tty_state,
mac_print_tty_state,
mac_noflush_set_tty_state,
mac_set_baud_rate,
mac_set_stop_bits,
};
void
_initialize_ser_mac ()
{
serial_add_interface (&mac_ops);
}

View file

@ -1,470 +0,0 @@
/* Read HP PA/Risc object files for GDB.
Copyright 1991, 1992, 1996 Free Software Foundation, Inc.
Written by Fred Fish at 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 "bfd.h"
#include "som.h"
#include "libhppa.h"
#include <syms.h>
#include "symtab.h"
#include "symfile.h"
#include "objfiles.h"
#include "buildsym.h"
#include "stabsread.h"
#include "gdb-stabs.h"
#include "complaints.h"
#include "gdb_string.h"
#include "demangle.h"
#include <sys/file.h>
/* Various things we might complain about... */
static void
som_symfile_init PARAMS ((struct objfile *));
static void
som_new_init PARAMS ((struct objfile *));
static void
som_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
static void
som_symfile_finish PARAMS ((struct objfile *));
static void
som_symtab_read PARAMS ((bfd *, struct objfile *,
struct section_offsets *));
static struct section_offsets *
som_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR));
static void
record_minimal_symbol PARAMS ((char *, CORE_ADDR,
enum minimal_symbol_type,
struct objfile *));
static void
record_minimal_symbol (name, address, ms_type, objfile)
char *name;
CORE_ADDR address;
enum minimal_symbol_type ms_type;
struct objfile *objfile;
{
name = obsavestring (name, strlen (name), &objfile -> symbol_obstack);
prim_record_minimal_symbol (name, address, ms_type, objfile);
}
/*
LOCAL FUNCTION
som_symtab_read -- read the symbol table of a SOM file
SYNOPSIS
void som_symtab_read (bfd *abfd, struct objfile *objfile,
struct section_offsets *section_offsets)
DESCRIPTION
Given an open bfd, a base address to relocate symbols to, and a
flag that specifies whether or not this bfd is for an executable
or not (may be shared library for example), add all the global
function and data symbols to the minimal symbol table.
*/
static void
som_symtab_read (abfd, objfile, section_offsets)
bfd *abfd;
struct objfile *objfile;
struct section_offsets *section_offsets;
{
unsigned int number_of_symbols;
int val, dynamic;
char *stringtab;
asection *shlib_info;
struct symbol_dictionary_record *buf, *bufp, *endbufp;
char *symname;
CONST int symsize = sizeof (struct symbol_dictionary_record);
CORE_ADDR text_offset, data_offset;
text_offset = ANOFFSET (section_offsets, 0);
data_offset = ANOFFSET (section_offsets, 1);
number_of_symbols = bfd_get_symcount (abfd);
buf = alloca (symsize * number_of_symbols);
bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET);
val = bfd_read (buf, symsize * number_of_symbols, 1, abfd);
if (val != symsize * number_of_symbols)
error ("Couldn't read symbol dictionary!");
stringtab = alloca (obj_som_stringtab_size (abfd));
bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET);
val = bfd_read (stringtab, obj_som_stringtab_size (abfd), 1, abfd);
if (val != obj_som_stringtab_size (abfd))
error ("Can't read in HP string table.");
/* We need to determine if objfile is a dynamic executable (so we
can do the right thing for ST_ENTRY vs ST_CODE symbols).
There's nothing in the header which easily allows us to do
this. The only reliable way I know of is to check for the
existance of a $SHLIB_INFO$ section with a non-zero size. */
shlib_info = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
if (shlib_info)
dynamic = (bfd_section_size (objfile->obfd, shlib_info) != 0);
else
dynamic = 0;
endbufp = buf + number_of_symbols;
for (bufp = buf; bufp < endbufp; ++bufp)
{
enum minimal_symbol_type ms_type;
QUIT;
switch (bufp->symbol_scope)
{
case SS_UNIVERSAL:
case SS_EXTERNAL:
switch (bufp->symbol_type)
{
case ST_SYM_EXT:
case ST_ARG_EXT:
continue;
case ST_CODE:
case ST_PRI_PROG:
case ST_SEC_PROG:
case ST_MILLICODE:
symname = bufp->name.n_strx + stringtab;
ms_type = mst_text;
bufp->symbol_value += text_offset;
#ifdef SMASH_TEXT_ADDRESS
SMASH_TEXT_ADDRESS (bufp->symbol_value);
#endif
break;
case ST_ENTRY:
symname = bufp->name.n_strx + stringtab;
/* For a dynamic executable, ST_ENTRY symbols are
the stubs, while the ST_CODE symbol is the real
function. */
if (dynamic)
ms_type = mst_solib_trampoline;
else
ms_type = mst_text;
bufp->symbol_value += text_offset;
#ifdef SMASH_TEXT_ADDRESS
SMASH_TEXT_ADDRESS (bufp->symbol_value);
#endif
break;
case ST_STUB:
symname = bufp->name.n_strx + stringtab;
ms_type = mst_solib_trampoline;
bufp->symbol_value += text_offset;
#ifdef SMASH_TEXT_ADDRESS
SMASH_TEXT_ADDRESS (bufp->symbol_value);
#endif
break;
case ST_DATA:
symname = bufp->name.n_strx + stringtab;
bufp->symbol_value += data_offset;
ms_type = mst_data;
break;
default:
continue;
}
break;
#if 0
/* SS_GLOBAL and SS_LOCAL are two names for the same thing (!). */
case SS_GLOBAL:
#endif
case SS_LOCAL:
switch (bufp->symbol_type)
{
case ST_SYM_EXT:
case ST_ARG_EXT:
continue;
case ST_CODE:
symname = bufp->name.n_strx + stringtab;
ms_type = mst_file_text;
bufp->symbol_value += text_offset;
#ifdef SMASH_TEXT_ADDRESS
SMASH_TEXT_ADDRESS (bufp->symbol_value);
#endif
check_strange_names:
/* Utah GCC 2.5, FSF GCC 2.6 and later generate correct local
label prefixes for stabs, constant data, etc. So we need
only filter out L$ symbols which are left in due to
limitations in how GAS generates SOM relocations.
When linking in the HPUX C-library the HP linker has
the nasty habit of placing section symbols from the literal
subspaces in the middle of the program's text. Filter
those out as best we can. Check for first and last character
being '$'.
And finally, the newer HP compilers emit crud like $PIC_foo$N
in some circumstance (PIC code I guess). It's also claimed
that they emit D$ symbols too. What stupidity. */
if ((symname[0] == 'L' && symname[1] == '$')
|| (symname[0] == '$' && symname[strlen(symname) - 1] == '$')
|| (symname[0] == 'D' && symname[1] == '$')
|| (strncmp (symname, "$PIC", 4) == 0))
continue;
break;
case ST_PRI_PROG:
case ST_SEC_PROG:
case ST_MILLICODE:
symname = bufp->name.n_strx + stringtab;
ms_type = mst_file_text;
bufp->symbol_value += text_offset;
#ifdef SMASH_TEXT_ADDRESS
SMASH_TEXT_ADDRESS (bufp->symbol_value);
#endif
break;
case ST_ENTRY:
symname = bufp->name.n_strx + stringtab;
/* For a dynamic executable, ST_ENTRY symbols are
the stubs, while the ST_CODE symbol is the real
function. */
if (dynamic)
ms_type = mst_solib_trampoline;
else
ms_type = mst_file_text;
bufp->symbol_value += text_offset;
#ifdef SMASH_TEXT_ADDRESS
SMASH_TEXT_ADDRESS (bufp->symbol_value);
#endif
break;
case ST_STUB:
symname = bufp->name.n_strx + stringtab;
ms_type = mst_solib_trampoline;
bufp->symbol_value += text_offset;
#ifdef SMASH_TEXT_ADDRESS
SMASH_TEXT_ADDRESS (bufp->symbol_value);
#endif
break;
case ST_DATA:
symname = bufp->name.n_strx + stringtab;
bufp->symbol_value += data_offset;
ms_type = mst_file_data;
goto check_strange_names;
default:
continue;
}
break;
/* This can happen for common symbols when -E is passed to the
final link. No idea _why_ that would make the linker force
common symbols to have an SS_UNSAT scope, but it does. */
case SS_UNSAT:
switch (bufp->symbol_type)
{
case ST_STORAGE:
symname = bufp->name.n_strx + stringtab;
bufp->symbol_value += data_offset;
ms_type = mst_data;
break;
default:
continue;
}
break;
default:
continue;
}
if (bufp->name.n_strx > obj_som_stringtab_size (abfd))
error ("Invalid symbol data; bad HP string table offset: %d",
bufp->name.n_strx);
record_minimal_symbol (symname,
bufp->symbol_value, ms_type,
objfile);
}
}
/* Scan and build partial symbols for a symbol file.
We have been initialized by a call to som_symfile_init, which
currently does nothing.
SECTION_OFFSETS is a set of offsets to apply to relocate the symbols
in each section. This is ignored, as it isn't needed for SOM.
MAINLINE is true if we are reading the main symbol
table (as opposed to a shared lib or dynamically loaded file).
This function only does the minimum work necessary for letting the
user "name" things symbolically; it does not read the entire symtab.
Instead, it reads the external and static symbols and puts them in partial
symbol tables. When more extensive information is requested of a
file, the corresponding partial symbol table is mutated into a full
fledged symbol table by going back and reading the symbols
for real.
We look for sections with specific names, to tell us what debug
format to look for: FIXME!!!
somstab_build_psymtabs() handles STABS symbols.
Note that SOM files have a "minimal" symbol table, which is vaguely
reminiscent of a COFF symbol table, but has only the minimal information
necessary for linking. We process this also, and use the information to
build gdb's minimal symbol table. This gives us some minimal debugging
capability even for files compiled without -g. */
static void
som_symfile_read (objfile, section_offsets, mainline)
struct objfile *objfile;
struct section_offsets *section_offsets;
int mainline;
{
bfd *abfd = objfile->obfd;
struct cleanup *back_to;
init_minimal_symbol_collection ();
back_to = make_cleanup (discard_minimal_symbols, 0);
/* Process the normal SOM symbol table first. */
som_symtab_read (abfd, objfile, section_offsets);
/* Now read information from the stabs debug sections. */
stabsect_build_psymtabs (objfile, section_offsets, mainline,
"$GDB_SYMBOLS$", "$GDB_STRINGS$", "$TEXT$");
/* Now read the native debug information. */
hpread_build_psymtabs (objfile, section_offsets, mainline);
/* Install any minimal symbols that have been collected as the current
minimal symbols for this objfile. */
install_minimal_symbols (objfile);
/* Force hppa-tdep.c to re-read the unwind descriptors. */
objfile->obj_private = NULL;
do_cleanups (back_to);
}
/* Initialize anything that needs initializing when a completely new symbol
file is specified (not just adding some symbols from another file, e.g. a
shared library).
We reinitialize buildsym, since we may be reading stabs from a SOM file. */
static void
som_new_init (ignore)
struct objfile *ignore;
{
stabsread_new_init ();
buildsym_new_init ();
}
/* Perform any local cleanups required when we are done with a particular
objfile. I.E, we are in the process of discarding all symbol information
for an objfile, freeing up all memory held for it, and unlinking the
objfile struct from the global list of known objfiles. */
static void
som_symfile_finish (objfile)
struct objfile *objfile;
{
if (objfile -> sym_stab_info != NULL)
{
mfree (objfile -> md, objfile -> sym_stab_info);
}
hpread_symfile_finish (objfile);
}
/* SOM specific initialization routine for reading symbols. */
static void
som_symfile_init (objfile)
struct objfile *objfile;
{
/* SOM objects may be reordered, so set OBJF_REORDERED. If we
find this causes a significant slowdown in gdb then we could
set it in the debug symbol readers only when necessary. */
objfile->flags |= OBJF_REORDERED;
hpread_symfile_init (objfile);
}
/* SOM specific parsing routine for section offsets.
Plain and simple for now. */
static struct section_offsets *
som_symfile_offsets (objfile, addr)
struct objfile *objfile;
CORE_ADDR addr;
{
struct section_offsets *section_offsets;
int i;
objfile->num_sections = SECT_OFF_MAX;
section_offsets = (struct section_offsets *)
obstack_alloc (&objfile -> psymbol_obstack,
sizeof (struct section_offsets)
+ sizeof (section_offsets->offsets) * (SECT_OFF_MAX-1));
/* First see if we're a shared library. If so, get the section
offsets from the library, else get them from addr. */
if (!som_solib_section_offsets (objfile, section_offsets))
{
for (i = 0; i < SECT_OFF_MAX; i++)
ANOFFSET (section_offsets, i) = addr;
}
return section_offsets;
}
/* Register that we are able to handle SOM object file formats. */
static struct sym_fns som_sym_fns =
{
bfd_target_som_flavour,
som_new_init, /* sym_new_init: init anything gbl to entire symtab */
som_symfile_init, /* sym_init: read initial info, setup for sym_read() */
som_symfile_read, /* sym_read: read a symbol file into symtab */
som_symfile_finish, /* sym_finish: finished with file, cleanup */
som_symfile_offsets, /* sym_offsets: Translate ext. to int. relocation */
NULL /* next: pointer to next struct sym_fns */
};
void
_initialize_somread ()
{
add_symtab_fns (&som_sym_fns);
}

View file

@ -1,820 +0,0 @@
/* Handle HP SOM shared libraries for GDB, the GNU Debugger.
Copyright 1993, 1996 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.
Written by the Center for Software Science at the Univerity of Utah
and by Cygnus Support. */
#include "defs.h"
#include "frame.h"
#include "bfd.h"
#include "som.h"
#include "libhppa.h"
#include "gdbcore.h"
#include "symtab.h"
#include "breakpoint.h"
#include "symfile.h"
#include "objfiles.h"
#include "inferior.h"
#include "gdb-stabs.h"
#include "gdbcmd.h"
/* TODO:
* Most of this code should work for hp300 shared libraries. Does
anyone care enough to weed out any SOM-isms.
* Support for hpux8 dynamic linker. */
/* The basic structure which describes a dynamically loaded object. This
data structure is private to the dynamic linker and isn't found in
any HPUX include file. */
struct som_solib_mapped_entry
{
/* The name of the library. */
char *name;
/* Version of this structure (it is expected to change again in hpux10). */
unsigned char struct_version;
/* Binding mode for this library. */
unsigned char bind_mode;
/* Version of this library. */
short library_version;
/* Start of text address, link-time text location, end of text address. */
CORE_ADDR text_addr;
CORE_ADDR text_link_addr;
CORE_ADDR text_end;
/* Start of data, start of bss and end of data. */
CORE_ADDR data_start;
CORE_ADDR bss_start;
CORE_ADDR data_end;
/* Value of linkage pointer (%r19). */
CORE_ADDR got_value;
/* Next entry. */
struct som_solib_mapped_entry *next;
/* There are other fields, but I don't have information as to what is
contained in them. */
};
/* A structure to keep track of all the known shared objects. */
struct so_list
{
struct som_solib_mapped_entry som_solib;
struct objfile *objfile;
bfd *abfd;
struct section_table *sections;
struct section_table *sections_end;
struct so_list *next;
};
static struct so_list *so_list_head;
static void som_sharedlibrary_info_command PARAMS ((char *, int));
/* Add symbols from shared libraries into the symtab list. */
void
som_solib_add (arg_string, from_tty, target)
char *arg_string;
int from_tty;
struct target_ops *target;
{
struct minimal_symbol *msymbol;
struct so_list *so_list_tail;
CORE_ADDR addr;
asection *shlib_info;
int status;
unsigned int dld_flags;
char buf[4], *re_err;
/* First validate our arguments. */
if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL)
{
error ("Invalid regexp: %s", re_err);
}
/* If we're debugging a core file, or have attached to a running
process, then som_solib_create_inferior_hook will not have been
called.
We need to first determine if we're dealing with a dynamically
linked executable. If not, then return without an error or warning.
We also need to examine __dld_flags to determine if the shared library
list is valid and to determine if the libraries have been privately
mapped. */
if (symfile_objfile == NULL)
return;
/* First see if the objfile was dynamically linked. */
shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
if (!shlib_info)
return;
/* It's got a $SHLIB_INFO$ section, make sure it's not empty. */
if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
return;
msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
if (msymbol == NULL)
{
error ("Unable to find __dld_flags symbol in object file.\n");
return;
}
addr = SYMBOL_VALUE_ADDRESS (msymbol);
/* Read the current contents. */
status = target_read_memory (addr, buf, 4);
if (status != 0)
{
error ("Unable to read __dld_flags\n");
return;
}
dld_flags = extract_unsigned_integer (buf, 4);
/* __dld_list may not be valid. If it's not valid tell the user. */
if ((dld_flags & 4) == 0)
{
error ("__dld_list is not valid according to __dld_flags.\n");
return;
}
/* If the libraries were not mapped private, warn the user. */
if ((dld_flags & 1) == 0)
warning ("The shared libraries were not privately mapped; setting a\nbreakpoint in a shared library will not work until you rerun the program.\n");
msymbol = lookup_minimal_symbol ("__dld_list", NULL, NULL);
if (!msymbol)
{
/* Older crt0.o files (hpux8) don't have __dld_list as a symbol,
but the data is still available if you know where to look. */
msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
if (!msymbol)
{
error ("Unable to find dynamic library list.\n");
return;
}
addr = SYMBOL_VALUE_ADDRESS (msymbol) - 8;
}
else
addr = SYMBOL_VALUE_ADDRESS (msymbol);
status = target_read_memory (addr, buf, 4);
if (status != 0)
{
error ("Unable to find dynamic library list.\n");
return;
}
addr = extract_unsigned_integer (buf, 4);
/* If addr is zero, then we're using an old dynamic loader which
doesn't maintain __dld_list. We'll have to use a completely
different approach to get shared library information. */
if (addr == 0)
goto old_dld;
/* Using the information in __dld_list is the preferred method
to get at shared library information. It doesn't depend on
any functions in /usr/lib/end.o and has a chance of working
with hpux10 when it is released. */
status = target_read_memory (addr, buf, 4);
if (status != 0)
{
error ("Unable to find dynamic library list.\n");
return;
}
/* addr now holds the address of the first entry in the dynamic
library list. */
addr = extract_unsigned_integer (buf, 4);
/* Now that we have a pointer to the dynamic library list, walk
through it and add the symbols for each library. */
so_list_tail = so_list_head;
/* Find the end of the list of shared objects. */
while (so_list_tail && so_list_tail->next)
so_list_tail = so_list_tail->next;
while (1)
{
CORE_ADDR name_addr, text_addr;
unsigned int name_len;
char *name;
struct so_list *new_so;
struct so_list *so_list = so_list_head;
struct section_table *p;
struct stat statbuf;
if (addr == 0)
break;
/* Get a pointer to the name of this library. */
status = target_read_memory (addr, buf, 4);
if (status != 0)
goto err;
name_addr = extract_unsigned_integer (buf, 4);
name_len = 0;
while (1)
{
target_read_memory (name_addr + name_len, buf, 1);
if (status != 0)
goto err;
name_len++;
if (*buf == '\0')
break;
}
name = alloca (name_len);
status = target_read_memory (name_addr, name, name_len);
if (status != 0)
goto err;
/* See if we've already loaded something with this name. */
while (so_list)
{
if (!strcmp (so_list->som_solib.name, name))
break;
so_list = so_list->next;
}
/* See if the file exists. If not, give a warning, but don't
die. */
status = stat (name, &statbuf);
if (status == -1)
{
warning ("Can't find file %s referenced in dld_list.", name);
status = target_read_memory (addr + 36, buf, 4);
if (status != 0)
goto err;
addr = (CORE_ADDR) extract_unsigned_integer (buf, 4);
continue;
}
/* If we've already loaded this one or it's the main program, skip it. */
if (so_list || !strcmp (name, symfile_objfile->name))
{
status = target_read_memory (addr + 36, buf, 4);
if (status != 0)
goto err;
addr = (CORE_ADDR) extract_unsigned_integer (buf, 4);
continue;
}
name = obsavestring (name, name_len - 1,
&symfile_objfile->symbol_obstack);
status = target_read_memory (addr + 8, buf, 4);
if (status != 0)
goto err;
text_addr = extract_unsigned_integer (buf, 4);
new_so = (struct so_list *) xmalloc (sizeof (struct so_list));
memset ((char *)new_so, 0, sizeof (struct so_list));
if (so_list_head == NULL)
{
so_list_head = new_so;
so_list_tail = new_so;
}
else
{
so_list_tail->next = new_so;
so_list_tail = new_so;
}
/* Fill in all the entries in GDB's shared library list. */
new_so->som_solib.name = name;
status = target_read_memory (addr + 4, buf, 4);
if (status != 0)
goto err;
new_so->som_solib.struct_version = extract_unsigned_integer (buf + 3, 1);
new_so->som_solib.bind_mode = extract_unsigned_integer (buf + 2, 1);
new_so->som_solib.library_version = extract_unsigned_integer (buf, 2);
new_so->som_solib.text_addr = text_addr;
status = target_read_memory (addr + 12, buf, 4);
if (status != 0)
goto err;
new_so->som_solib.text_link_addr = extract_unsigned_integer (buf, 4);
status = target_read_memory (addr + 16, buf, 4);
if (status != 0)
goto err;
new_so->som_solib.text_end = extract_unsigned_integer (buf, 4);
status = target_read_memory (addr + 20, buf, 4);
if (status != 0)
goto err;
new_so->som_solib.data_start = extract_unsigned_integer (buf, 4);
status = target_read_memory (addr + 24, buf, 4);
if (status != 0)
goto err;
new_so->som_solib.bss_start = extract_unsigned_integer (buf, 4);
status = target_read_memory (addr + 28, buf, 4);
if (status != 0)
goto err;
new_so->som_solib.data_end = extract_unsigned_integer (buf, 4);
status = target_read_memory (addr + 32, buf, 4);
if (status != 0)
goto err;
new_so->som_solib.got_value = extract_unsigned_integer (buf, 4);
status = target_read_memory (addr + 36, buf, 4);
if (status != 0)
goto err;
new_so->som_solib.next = (void *)extract_unsigned_integer (buf, 4);
addr = (CORE_ADDR)new_so->som_solib.next;
new_so->objfile = symbol_file_add (name, from_tty, text_addr, 0, 0, 0);
new_so->abfd = new_so->objfile->obfd;
if (!bfd_check_format (new_so->abfd, bfd_object))
{
error ("\"%s\": not in executable format: %s.",
name, bfd_errmsg (bfd_get_error ()));
}
/* Now we need to build a section table for this library since
we might be debugging a core file from a dynamically linked
executable in which the libraries were not privately mapped. */
if (build_section_table (new_so->abfd,
&new_so->sections,
&new_so->sections_end))
{
error ("Unable to build section table for shared library\n.");
return;
}
/* Relocate all the sections based on where they got loaded. */
for (p = new_so->sections; p < new_so->sections_end; p++)
{
if (p->the_bfd_section->flags & SEC_CODE)
{
p->addr += text_addr - new_so->som_solib.text_link_addr;
p->endaddr += text_addr - new_so->som_solib.text_link_addr;
}
else if (p->the_bfd_section->flags & SEC_DATA)
{
p->addr += new_so->som_solib.data_start;
p->endaddr += new_so->som_solib.data_start;
}
}
/* Now see if we need to map in the text and data for this shared
library (for example debugging a core file which does not use
private shared libraries.).
Carefully peek at the first text address in the library. If the
read succeeds, then the libraries were privately mapped and were
included in the core dump file.
If the peek failed, then the libraries were not privately mapped
and are not in the core file, we'll have to read them in ourselves. */
status = target_read_memory (text_addr, buf, 4);
if (status != 0)
{
int old, new;
int update_coreops;
/* We must update the to_sections field in the core_ops structure
here, otherwise we dereference a potential dangling pointer
for each call to target_read/write_memory within this routine. */
update_coreops = core_ops.to_sections == target->to_sections;
new = new_so->sections_end - new_so->sections;
/* Add sections from the shared library to the core target. */
if (target->to_sections)
{
old = target->to_sections_end - target->to_sections;
target->to_sections = (struct section_table *)
xrealloc ((char *)target->to_sections,
((sizeof (struct section_table)) * (old + new)));
}
else
{
old = 0;
target->to_sections = (struct section_table *)
xmalloc ((sizeof (struct section_table)) * new);
}
target->to_sections_end = (target->to_sections + old + new);
/* Update the to_sections field in the core_ops structure
if needed. */
if (update_coreops)
{
core_ops.to_sections = target->to_sections;
core_ops.to_sections_end = target->to_sections_end;
}
/* Copy over the old data before it gets clobbered. */
memcpy ((char *)(target->to_sections + old),
new_so->sections,
((sizeof (struct section_table)) * new));
}
}
/* Getting new symbols may change our opinion about what is
frameless. */
reinit_frame_cache ();
return;
old_dld:
error ("Debugging dynamic executables loaded via the hpux8 dld.sl is not supported.\n");
return;
err:
error ("Error while reading dynamic library list.\n");
return;
}
/* This hook gets called just before the first instruction in the
inferior process is executed.
This is our opportunity to set magic flags in the inferior so
that GDB can be notified when a shared library is mapped in and
to tell the dynamic linker that a private copy of the library is
needed (so GDB can set breakpoints in the library).
__dld_flags is the location of the magic flags; as of this implementation
there are 3 flags of interest:
bit 0 when set indicates that private copies of the libraries are needed
bit 1 when set indicates that the callback hook routine is valid
bit 2 when set indicates that the dynamic linker should maintain the
__dld_list structure when loading/unloading libraries.
Note that shared libraries are not mapped in at this time, so we have
run the inferior until the libraries are mapped in. Typically this
means running until the "_start" is called. */
void
som_solib_create_inferior_hook()
{
struct minimal_symbol *msymbol;
unsigned int dld_flags, status, have_endo;
asection *shlib_info;
char shadow_contents[BREAKPOINT_MAX], buf[4];
struct objfile *objfile;
CORE_ADDR anaddr;
/* First, remove all the solib event breakpoints. Their addresses
may have changed since the last time we ran the program. */
remove_solib_event_breakpoints ();
if (symfile_objfile == NULL)
return;
/* First see if the objfile was dynamically linked. */
shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
if (!shlib_info)
return;
/* It's got a $SHLIB_INFO$ section, make sure it's not empty. */
if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
return;
have_endo = 0;
/* Slam the pid of the process into __d_pid; failing is only a warning! */
msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
if (msymbol == NULL)
{
warning ("Unable to find __d_pid symbol in object file.");
warning ("Suggest linking with /usr/lib/end.o.");
warning ("GDB will be unable to track shl_load/shl_unload calls");
goto keep_going;
}
anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
store_unsigned_integer (buf, 4, inferior_pid);
status = target_write_memory (anaddr, buf, 4);
if (status != 0)
{
warning ("Unable to write __d_pid");
warning ("Suggest linking with /usr/lib/end.o.");
warning ("GDB will be unable to track shl_load/shl_unload calls");
goto keep_going;
}
/* Get the value of _DLD_HOOK (an export stub) and put it in __dld_hook;
This will force the dynamic linker to call __d_trap when significant
events occur. */
msymbol = lookup_minimal_symbol ("_DLD_HOOK", NULL, symfile_objfile);
if (msymbol == NULL)
{
warning ("Unable to find _DLD_HOOK symbol in object file.");
warning ("Suggest linking with /usr/lib/end.o.");
warning ("GDB will be unable to track shl_load/shl_unload calls");
goto keep_going;
}
anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
/* Grrr, this might not be an export symbol! We have to find the
export stub. */
ALL_OBJFILES (objfile)
{
struct unwind_table_entry *u;
extern struct unwind_table_entry *find_unwind_entry PARAMS ((CORE_ADDR pc));
/* What a crock. */
msymbol = lookup_minimal_symbol_solib_trampoline (SYMBOL_NAME (msymbol),
NULL, objfile);
/* Found a symbol with the right name. */
if (msymbol)
{
struct unwind_table_entry *u;
/* It must be a shared library trampoline. */
if (SYMBOL_TYPE (msymbol) != mst_solib_trampoline)
continue;
/* It must also be an export stub. */
u = find_unwind_entry (SYMBOL_VALUE (msymbol));
if (!u || u->stub_type != EXPORT)
continue;
/* OK. Looks like the correct import stub. */
anaddr = SYMBOL_VALUE (msymbol);
break;
}
}
store_unsigned_integer (buf, 4, anaddr);
msymbol = lookup_minimal_symbol ("__dld_hook", NULL, symfile_objfile);
if (msymbol == NULL)
{
warning ("Unable to find __dld_hook symbol in object file.");
warning ("Suggest linking with /usr/lib/end.o.");
warning ("GDB will be unable to track shl_load/shl_unload calls");
goto keep_going;
}
anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
status = target_write_memory (anaddr, buf, 4);
/* Now set a shlib_event breakpoint at __d_trap so we can track
significant shared library events. */
msymbol = lookup_minimal_symbol ("__d_trap", NULL, symfile_objfile);
if (msymbol == NULL)
{
warning ("Unable to find __dld_d_trap symbol in object file.");
warning ("Suggest linking with /usr/lib/end.o.");
warning ("GDB will be unable to track shl_load/shl_unload calls");
goto keep_going;
}
create_solib_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol));
/* We have all the support usually found in end.o, so we can track
shl_load and shl_unload calls. */
have_endo = 1;
keep_going:
/* Get the address of __dld_flags, if no such symbol exists, then we can
not debug the shared code. */
msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
if (msymbol == NULL)
{
error ("Unable to find __dld_flags symbol in object file.\n");
goto keep_going;
return;
}
anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
/* Read the current contents. */
status = target_read_memory (anaddr, buf, 4);
if (status != 0)
{
error ("Unable to read __dld_flags\n");
return;
}
dld_flags = extract_unsigned_integer (buf, 4);
/* Turn on the flags we care about. */
dld_flags |= (0x5 | (have_endo << 1));
store_unsigned_integer (buf, 4, dld_flags);
status = target_write_memory (anaddr, buf, 4);
if (status != 0)
{
error ("Unable to write __dld_flags\n");
return;
}
/* Now find the address of _start and set a breakpoint there.
We still need this code for two reasons:
* Not all sites have /usr/lib/end.o, so it's not always
possible to track the dynamic linker's events.
* At this time no events are triggered for shared libraries
loaded at startup time (what a crock). */
msymbol = lookup_minimal_symbol ("_start", NULL, symfile_objfile);
if (msymbol == NULL)
{
error ("Unable to find _start symbol in object file.\n");
return;
}
anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
/* Make the breakpoint at "_start" a shared library event breakpoint. */
create_solib_event_breakpoint (anaddr);
/* Wipe out all knowledge of old shared libraries since their
mapping can change from one exec to another! */
while (so_list_head)
{
struct so_list *temp;
free_objfile (so_list_head->objfile);
temp = so_list_head;
free (so_list_head);
so_list_head = temp->next;
}
clear_symtab_users ();
}
/* Return the GOT value for the shared library in which ADDR belongs. If
ADDR isn't in any known shared library, return zero. */
CORE_ADDR
som_solib_get_got_by_pc (addr)
CORE_ADDR addr;
{
struct so_list *so_list = so_list_head;
CORE_ADDR got_value = 0;
while (so_list)
{
if (so_list->som_solib.text_addr <= addr
&& so_list->som_solib.text_end > addr)
{
got_value = so_list->som_solib.got_value;
break;
}
so_list = so_list->next;
}
return got_value;
}
int
som_solib_section_offsets (objfile, offsets)
struct objfile *objfile;
struct section_offsets *offsets;
{
struct so_list *so_list = so_list_head;
while (so_list)
{
/* Oh what a pain! We need the offsets before so_list->objfile
is valid. The BFDs will never match. Make a best guess. */
if (strstr (objfile->name, so_list->som_solib.name))
{
asection *private_section;
/* The text offset is easy. */
ANOFFSET (offsets, SECT_OFF_TEXT)
= (so_list->som_solib.text_addr
- so_list->som_solib.text_link_addr);
ANOFFSET (offsets, SECT_OFF_RODATA)
= ANOFFSET (offsets, SECT_OFF_TEXT);
/* We should look at presumed_dp in the SOM header, but
that's not easily available. This should be OK though. */
private_section = bfd_get_section_by_name (objfile->obfd,
"$PRIVATE$");
if (!private_section)
{
warning ("Unable to find $PRIVATE$ in shared library!");
ANOFFSET (offsets, SECT_OFF_DATA) = 0;
ANOFFSET (offsets, SECT_OFF_BSS) = 0;
return 1;
}
ANOFFSET (offsets, SECT_OFF_DATA)
= (so_list->som_solib.data_start - private_section->vma);
ANOFFSET (offsets, SECT_OFF_BSS)
= ANOFFSET (offsets, SECT_OFF_DATA);
return 1;
}
so_list = so_list->next;
}
return 0;
}
/* Dump information about all the currently loaded shared libraries. */
static void
som_sharedlibrary_info_command (ignore, from_tty)
char *ignore;
int from_tty;
{
struct so_list *so_list = so_list_head;
if (exec_bfd == NULL)
{
printf_unfiltered ("no exec file.\n");
return;
}
if (so_list == NULL)
{
printf_unfiltered ("No shared libraries loaded at this time.\n");
return;
}
printf_unfiltered ("Shared Object Libraries\n");
printf_unfiltered (" %-12s%-12s%-12s%-12s%-12s%-12s\n",
" flags", " tstart", " tend", " dstart", " dend", " dlt");
while (so_list)
{
unsigned int flags;
flags = so_list->som_solib.struct_version << 24;
flags |= so_list->som_solib.bind_mode << 16;
flags |= so_list->som_solib.library_version;
printf_unfiltered ("%s\n", so_list->som_solib.name);
printf_unfiltered (" %-12s", local_hex_string_custom (flags, "08l"));
printf_unfiltered ("%-12s",
local_hex_string_custom (so_list->som_solib.text_addr, "08l"));
printf_unfiltered ("%-12s",
local_hex_string_custom (so_list->som_solib.text_end, "08l"));
printf_unfiltered ("%-12s",
local_hex_string_custom (so_list->som_solib.data_start, "08l"));
printf_unfiltered ("%-12s",
local_hex_string_custom (so_list->som_solib.data_end, "08l"));
printf_unfiltered ("%-12s\n",
local_hex_string_custom (so_list->som_solib.got_value, "08l"));
so_list = so_list->next;
}
}
static void
som_solib_sharedlibrary_command (args, from_tty)
char *args;
int from_tty;
{
dont_repeat ();
som_solib_add (args, from_tty, (struct target_ops *) 0);
}
void
_initialize_som_solib ()
{
add_com ("sharedlibrary", class_files, som_solib_sharedlibrary_command,
"Load shared object library symbols for files matching REGEXP.");
add_info ("sharedlibrary", som_sharedlibrary_info_command,
"Status of loaded shared object libraries.");
add_show_from_set
(add_set_cmd ("auto-solib-add", class_support, var_zinteger,
(char *) &auto_solib_add,
"Set autoloading of shared library symbols at startup.\n\
If nonzero, symbols from all shared object libraries will be loaded\n\
automatically when the inferior begins execution or when the dynamic linker\n\
informs gdb that a new library has been loaded. Otherwise, symbols\n\
must be loaded manually, using `sharedlibrary'.",
&setlist),
&showlist);
}

View file

@ -1,51 +0,0 @@
/* HP SOM Shared library declarations for GDB, the GNU Debugger.
Copyright (C) 1992 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.
Written by the Center for Software Science at the Univerity of Utah
and by Cygnus Support. */
#ifdef __STDC__ /* Forward decl's for prototypes */
struct target_ops;
struct objfile;
struct section_offsets;
#endif
/* Called to add symbols from a shared library to gdb's symbol table. */
#define SOLIB_ADD(filename, from_tty, targ) \
som_solib_add (filename, from_tty, targ)
extern void
som_solib_add PARAMS ((char *, int, struct target_ops *));
extern CORE_ADDR
som_solib_get_got_by_pc PARAMS ((CORE_ADDR));
extern int
som_solib_section_offsets PARAMS ((struct objfile *, struct section_offsets *));
/* 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) som_solib_create_inferior_hook()
extern void
som_solib_create_inferior_hook PARAMS((void));

View file

@ -1,35 +0,0 @@
/* S-record download support for GDB, the GNU debugger.
Copyright 1995 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 PARAMS ((serial_t desc, const char *file, int maxrecsize,
int flags, int hashmark));
/* 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 */

Some files were not shown because too many files have changed in this diff Show more