mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-28 14:30:48 +00:00
Initial revision
This commit is contained in:
parent
4e1dc65681
commit
07d021a6ae
1677
gdb/convx-opcode.h
Normal file
1677
gdb/convx-opcode.h
Normal file
File diff suppressed because it is too large
Load Diff
18
gdb/doc/all.m4
Normal file
18
gdb/doc/all.m4
Normal file
@ -0,0 +1,18 @@
|
||||
_divert__(-1)
|
||||
_define__(<_ALL_ARCH__>,<1>)
|
||||
_define__(<_GENERIC__>,<1>) In case none.m4 changes its mind abt default
|
||||
|
||||
_define__(<_AOUT__>,<1>)
|
||||
_define__(<_BOUT__>,<1>)
|
||||
_define__(<_COFF__>,<1>)
|
||||
_define__(<_ELF__>,<1>)
|
||||
|
||||
_define__(<_AMD29K__>,<1>)
|
||||
_define__(<_I80386__>,<1>)
|
||||
_define__(<_I960__>,<1>)
|
||||
_define__(<_M680X0__>,<1>)
|
||||
_define__(<_SPARC__>,<1>)
|
||||
_define__(<_VAX__>,<1>)
|
||||
_define__(<_VXWORKS__>,<1>)
|
||||
|
||||
_divert__<>
|
5
gdb/doc/amd29k.m4
Normal file
5
gdb/doc/amd29k.m4
Normal file
@ -0,0 +1,5 @@
|
||||
_divert__(-1)
|
||||
_define__(<_AMD29K__>,<1>)
|
||||
_define__(<_HOST__>,<AMD 29K>)
|
||||
_define__(<_MACH_DEP__>,<AMD29K Dependent>
|
||||
_divert__<>
|
13
gdb/doc/gen.m4
Normal file
13
gdb/doc/gen.m4
Normal file
@ -0,0 +1,13 @@
|
||||
_divert__(-1)
|
||||
_define__(<_GENERIC__>,<1>) In case none.m4 changes its mind abt default
|
||||
|
||||
_define__(<_AOUT__>,<1>)
|
||||
_define__(<_COFF__>,<1>)
|
||||
_define__(<_ELF__>,<1>)
|
||||
|
||||
_define__(<_I80386__>,<1>)
|
||||
_define__(<_M680X0__>,<1>)
|
||||
_define__(<_SPARC__>,<1>)
|
||||
_define__(<_VAX__>,<1>)
|
||||
|
||||
_divert__<>
|
5
gdb/doc/i80386.m4
Normal file
5
gdb/doc/i80386.m4
Normal file
@ -0,0 +1,5 @@
|
||||
_divert__(-1)
|
||||
_define__(<_I80386__>,<1>)
|
||||
_define__(<_HOST__>,<Intel 80386>)
|
||||
_define__(<_MACH_DEP__>,<80386 Dependent>
|
||||
_divert__<>
|
12
gdb/doc/i960.m4
Normal file
12
gdb/doc/i960.m4
Normal file
@ -0,0 +1,12 @@
|
||||
_divert__(-1)
|
||||
_define__(<_I960__>,<1>)
|
||||
_define__(<_AOUT__>,<0>)
|
||||
_define__(<_BOUT__>,<1>)
|
||||
_define__(<_COFF__>,<1>)
|
||||
_define__(<_AS__>,<gas960>)
|
||||
_define__(<_GCC__>,<gcc960>)
|
||||
_define__(<_LD__>,<gld960>)
|
||||
_define__(<_GDB__>,<gdb960>)
|
||||
_define__(<_HOST__>,<Intel 960>)
|
||||
_define__(<_MACH_DEP__>,<i960 Dependent>)
|
||||
_divert__<>
|
5
gdb/doc/m680x0.m4
Normal file
5
gdb/doc/m680x0.m4
Normal file
@ -0,0 +1,5 @@
|
||||
_divert__(-1)
|
||||
_define__(<_M680X0__>,<1>)
|
||||
_define__(<_HOST__>,<Motorola 680x0>)
|
||||
_define__(<_MACH_DEP__>,<M680x0 Dependent>)
|
||||
_divert__<>
|
49
gdb/doc/none.m4
Normal file
49
gdb/doc/none.m4
Normal file
@ -0,0 +1,49 @@
|
||||
_divert__(-1)
|
||||
|
||||
Switches:
|
||||
|
||||
_define__(<_ALL_ARCH__>,<0>) (Meant as most inclusive; file turning
|
||||
it on is expected to also turn on
|
||||
all arch-related switches including
|
||||
"_GENERIC__")
|
||||
_define__(<_GENERIC__>,<1>) (may not be quite all configs;
|
||||
meant for "most vanilla" manual)
|
||||
_define__(<_INTERNALS__>,<0>)
|
||||
|
||||
_define__(<_AOUT__>,<1>) Object formats. Note we turn on one.
|
||||
_define__(<_BOUT__>,<0>)
|
||||
_define__(<_COFF__>,<0>)
|
||||
_define__(<_ELF__>,<0>)
|
||||
|
||||
_define__(<_AMD29K__>,<0>) Specific architectures. Note none
|
||||
_define__(<_I80386__>,<0>) starts out on.
|
||||
_define__(<_I960__>,<0>)
|
||||
_define__(<_M680X0__>,<0>)
|
||||
_define__(<_SPARC__>,<0>)
|
||||
_define__(<_VAX__>,<0>)
|
||||
_define__(<_VXWORKS__>,<0>)
|
||||
|
||||
Text:
|
||||
|
||||
Default names; individual configs may override
|
||||
Assembler:
|
||||
_define__(<_AS__>,<as>)
|
||||
C Compiler:
|
||||
_define__(<_GCC__>,<gcc>)
|
||||
Linker:
|
||||
_define__(<_LD__>,<ld>)
|
||||
Debugger name:
|
||||
_define__(<_GDBN__>,<GDB>)
|
||||
Debugger program:
|
||||
_define__(<_GDBP__>,<gdb>)
|
||||
Debugger init file:
|
||||
_define__(<_GDBINIT__>,<.gdbinit>)
|
||||
|
||||
Text for host; individual configs *should* override, but this may
|
||||
catch some flubs
|
||||
_define__(<_HOST__>,<machine specific>)
|
||||
|
||||
"Machine Dependent" nodename
|
||||
_define__(<_MACH_DEP__>,<Machine Dependent>)
|
||||
|
||||
_divert__<>
|
252
gdb/doc/pretex.m4
Normal file
252
gdb/doc/pretex.m4
Normal file
@ -0,0 +1,252 @@
|
||||
divert(-1) -*-Text-*-
|
||||
|
||||
I. INTRODUCTION
|
||||
|
||||
This collection of M4 macros is meant to help in pre-processing texinfo
|
||||
files to allow configuring them by hosts; for example, the reader of an
|
||||
as manual who only has access to a 386 may not really want to see crud about
|
||||
VAXen.
|
||||
|
||||
A preprocessor is used, rather than extending texinfo, because this
|
||||
way we can hack the conditionals in only one place; otherwise we would
|
||||
have to write TeX macros, update makeinfo, and update the Emacs
|
||||
info-formatting functions.
|
||||
|
||||
II. COMPATIBILITY
|
||||
|
||||
These macros should work with GNU m4 and System V m4; they do not work
|
||||
with Sun or Berkeley M4.
|
||||
|
||||
III. USAGE
|
||||
|
||||
A. M4 INVOCATION
|
||||
Assume this file is called "pretex.m4". Then, to preprocess a
|
||||
document "mybook.texinfo" you might do something like the following:
|
||||
|
||||
m4 pretex.m4 none.m4 PARTIC.m4 mybook.texinfo >mybook-PARTIC.texinfo
|
||||
|
||||
---where your path is set to find GNU or SysV "m4", and the other m4
|
||||
files mentioned are as follows:
|
||||
|
||||
none.m4: A file that defines, as 0, all the options you might
|
||||
want to turn on using the conditionals defined below.
|
||||
Unlike the C preprocessor, m4 does not default
|
||||
undefined macros to 0. For example, here is a "none.m4"
|
||||
I have been using:
|
||||
_divert__(-1)
|
||||
|
||||
_define__(<_ALL_ARCH__>,<0>)
|
||||
_define__(<_INTERNALS__>,<0>)
|
||||
|
||||
_define__(<_AMD29K__>,<0>)
|
||||
_define__(<_I80386__>,<0>)
|
||||
_define__(<_I960__>,<0>)
|
||||
_define__(<_M680X0__>,<0>)
|
||||
_define__(<_SPARC__>,<0>)
|
||||
_define__(<_VAX__>,<0>)
|
||||
|
||||
_divert__<>
|
||||
|
||||
PARTIC.m4: A file that turns on whichever options you actually
|
||||
want the manual configured for, in this particular
|
||||
instance. Its contents are similar to one or more of
|
||||
the lines in "none.m4", but of course the second
|
||||
argument to _define__ is <1> rather than <0>.
|
||||
|
||||
This is also a convenient place to define any macros
|
||||
that you want to expand to different text for
|
||||
different configurations---for example, the name of
|
||||
the program being described.
|
||||
|
||||
Naturally, these are just suggested conventions; you could put your macro
|
||||
definitions in any files or combinations of files you like.
|
||||
|
||||
These macros use the characters < and > as m4 quotes; if you need
|
||||
these characters in your text, you will also want to use the macros
|
||||
_0__ and _1__ from this package---see the description of "Quote
|
||||
Handling" in the "Implementation" section below.
|
||||
|
||||
B. WHAT GOES IN THE PRE-TEXINFO SOURCE
|
||||
|
||||
For the most part, the text of your book. In addition, you can
|
||||
include text that is included only conditionally, using the macros
|
||||
_if__ and _fi__ defined below. They BOTH take an argument! This is
|
||||
primarily meant for readability (so a human can more easily see what
|
||||
conditional end matches what conditional beginning), but the argument
|
||||
is actually used in the _fi__ as well as the _if__ implementation.
|
||||
You should always give a _fi__ the same argument as its matching
|
||||
_if__. Other arguments may appear to work for a while, but are almost
|
||||
certain to produce the wrong output for some configurations.
|
||||
|
||||
For example, here is an excerpt from the very beginning of the
|
||||
documentation for GNU as, to name the info file appropriately for
|
||||
different configurations:
|
||||
_if__(_ALL_ARCH__)
|
||||
@setfilename as.info
|
||||
_fi__(_ALL_ARCH__)
|
||||
_if__(_M680X0__ && !_ALL_ARCH__)
|
||||
@setfilename as-m680x0.info
|
||||
_fi__(_M680X0__ && !_ALL_ARCH__)
|
||||
_if__(_AMD29K__ && !_ALL_ARCH__)
|
||||
@setfilename as-29k.info
|
||||
_fi__(_AMD29K__ && !_ALL_ARCH__)
|
||||
|
||||
Note that you can use Boolean expressions in the arguments; the
|
||||
expression language is that of the builtin m4 macro "eval", described
|
||||
in the m4 manual.
|
||||
|
||||
IV. IMPLEMENTATION
|
||||
|
||||
A.PRIMITIVE RENAMING
|
||||
First, we redefine m4's built-ins to avoid conflict with plain text.
|
||||
The naming convention used is that our macros all begin with a single
|
||||
underbar and end with two underbars. The asymmetry is meant to avoid
|
||||
conflict with some other conventions (which we may want to document) that
|
||||
are intended to avoid conflict, like ANSI C predefined macros.
|
||||
|
||||
define(`_undefine__',defn(`undefine'))
|
||||
define(`_define__',defn(`define'))
|
||||
define(`_defn__',defn(`defn'))
|
||||
define(`_ppf__',`_define__(`_$1__',_defn__(`$1'))_undefine__(`$1')')
|
||||
_ppf__(`builtin')
|
||||
_ppf__(`changecom')
|
||||
_ppf__(`changequote')
|
||||
_ppf__(`decr')
|
||||
_ppf__(`define')
|
||||
_ppf__(`defn')
|
||||
_ppf__(`divert')
|
||||
_ppf__(`dnl')
|
||||
_ppf__(`dumpdef')
|
||||
_ppf__(`errprint')
|
||||
_ppf__(`eval')
|
||||
_ppf__(`ifdef')
|
||||
_ppf__(`ifelse')
|
||||
_ppf__(`include')
|
||||
_ppf__(`incr')
|
||||
_ppf__(`index')
|
||||
_ppf__(`len')
|
||||
_ppf__(`m4exit')
|
||||
_ppf__(`m4wrap')
|
||||
_ppf__(`maketemp')
|
||||
_ppf__(`popdef')
|
||||
_ppf__(`pushdef')
|
||||
_ppf__(`shift')
|
||||
_ppf__(`sinclude')
|
||||
_ppf__(`substr')
|
||||
_ppf__(`syscmd')
|
||||
_ppf__(`sysval')
|
||||
_ppf__(`traceoff')
|
||||
_ppf__(`traceon')
|
||||
_ppf__(`translit')
|
||||
_ppf__(`undefine')
|
||||
_ppf__(`undivert')
|
||||
|
||||
B. QUOTE HANDLING.
|
||||
|
||||
The characters used as quotes by M4, by default, are unfortunately
|
||||
quite likely to occur in ordinary text. To avoid surprises, we will
|
||||
use the characters <> ---which are just as suggestive (more so to
|
||||
Francophones, perhaps) but a little less common in text (save for
|
||||
those poor Francophones. You win some, you lose some). Still, we
|
||||
expect also to have to set < and > occasionally in text; to do that,
|
||||
we define a macro to turn off quote handling (_0__) and a macro to
|
||||
turn it back on (_1__), according to our convention.
|
||||
|
||||
BEWARE: This seems to make < and > unusable as relational operations
|
||||
in calls to the builtin "eval". So far I've gotten
|
||||
along without; but a better choice may be possible.
|
||||
|
||||
Note that we postponed this for a while, for convenience in discussing
|
||||
the issue and in the primitive renaming---not to mention in defining
|
||||
_0__ and _1__ themselves! However, the quote redefinitions MUST
|
||||
precede the _if__ / _fi__ definitions, because M4 will expand the text
|
||||
as given---if we use the wrong quotes here, we will get the wrong
|
||||
quotes when we use the conditionals.
|
||||
|
||||
_define__(_0__,`_changequote__(,)')_define__(_1__,`_changequote__(<,>)')
|
||||
_1__
|
||||
|
||||
C. CONDITIONALS
|
||||
|
||||
We define two macros, _if__ and _fi__. BOTH take arguments! This is
|
||||
meant both to help the human reader match up a _fi__ with its
|
||||
corresponding _if__ and to aid in the implementation. You may use the
|
||||
full expression syntax supported by M4 (see docn of `eval' builtin in
|
||||
the m4 manual).
|
||||
|
||||
The conditional macros are carefully defined to avoid introducing
|
||||
extra whitespace (i.e., blank lines or blank characters). One side
|
||||
effect exists---
|
||||
|
||||
BEWARE: text following an `_if__' on the same line is
|
||||
DISCARDED even if the condition is true; text
|
||||
following a `_fi__' on the same line is also
|
||||
always discarded.
|
||||
|
||||
The recommended convention is to always place _if__ and _fi__ on a
|
||||
line by themselves. This will also aid the human reader. TeX won't
|
||||
care about the line breaks; as for info, you may want to insert calls
|
||||
to `@refill' at the end of paragraphs containing conditionalized text,
|
||||
where you don't want line breaks separating unconditional from
|
||||
conditional text. info formatting will then give you nice looking
|
||||
paragraphs in the info file.
|
||||
|
||||
Nesting: conditionals are designed to nest, in the following way:
|
||||
*nothing* is output between an outer pair of false conditionals, even
|
||||
if there are true conditionals inside. A false conditional "defeats"
|
||||
all conditionals within it. The counter _IF_FS__ is used to
|
||||
implement this; kindly avoid redefining it directly.
|
||||
|
||||
_define__(<_IF_FS__>,<0>)
|
||||
_define__(
|
||||
<_pushf__>,
|
||||
<_define__(<_IF_FS__>,
|
||||
_incr__(_IF_FS__))>)
|
||||
_define__(
|
||||
<_popf__>,
|
||||
<_ifelse__(0,_IF_FS__,
|
||||
<<>_dnl__<>>,
|
||||
<_define__(<_IF_FS__>,_decr__(_IF_FS__))>)>)
|
||||
|
||||
_define__(
|
||||
<_if__>,
|
||||
<_ifelse__(1,_eval__( ($1) ),
|
||||
<<>_dnl__<>>,
|
||||
<_pushf__<>_divert__(-1)>)>)
|
||||
_define__(
|
||||
<_fi__>,
|
||||
<_ifelse__(1,_eval__( ($1) ),
|
||||
<<>_dnl__<>>,
|
||||
<_popf__<>_ifelse__(0,_IF_FS__,
|
||||
<_divert__<>_dnl__<>>,<>)>)>)
|
||||
|
||||
D. CHAPTER/SECTION MACRO
|
||||
In a parametrized manual, the heading level may need to be calculated;
|
||||
for example, a manual that has a chapter on machine dependencies
|
||||
should be conditionally structured as follows:
|
||||
- IF the manual is configured for a SINGLE machine type, use
|
||||
the chapter heading for that machine type, and run headings down
|
||||
from there (top level for a particular machine is chapter, then within
|
||||
that we have section, subsection etc);
|
||||
- ELSE, if MANY machine types are described in the chapter,
|
||||
use a generic chapter heading such as "@chapter Machine Dependencies",
|
||||
use "section" for the top level description of EACH machine, and run
|
||||
headings down from there (top level for a particular machine is
|
||||
section, then within that we have subsection, subsubsection etc).
|
||||
|
||||
The macro <_CHAPSEC__> is for this purpose: its argument is evaluated (so
|
||||
you can construct expressions to express choices such as above), then
|
||||
expands as follows:
|
||||
0: @chapter
|
||||
1: @section
|
||||
2: @subsection
|
||||
3: @subsubsection
|
||||
...and so on.
|
||||
|
||||
_define__(<_CHAPSEC__>,<@_cs__(_eval__($1))>)
|
||||
_define__(<_cs__>,<_ifelse__(
|
||||
0, $1, <chapter>,
|
||||
1, $1, <section>,
|
||||
<sub<>_cs__(_eval__($1 - 1))>)>)
|
||||
|
||||
_divert__<>_dnl__<>
|
5
gdb/doc/sparc.m4
Normal file
5
gdb/doc/sparc.m4
Normal file
@ -0,0 +1,5 @@
|
||||
_divert__(-1)
|
||||
_define__(<_SPARC__>,<1>)
|
||||
_define__(<_HOST__>,<SPARC>)
|
||||
_define__(<_MACH_DEP__>,<SPARC Dependent>)
|
||||
_divert__<>
|
5
gdb/doc/vax.m4
Normal file
5
gdb/doc/vax.m4
Normal file
@ -0,0 +1,5 @@
|
||||
_divert__(-1)
|
||||
_define__(<_VAX__>,<1>)
|
||||
_define__(<_HOST__>,<VAX>)
|
||||
_define__(<_MACH_DEP__>,<VAX Dependent>)
|
||||
_divert__<>
|
230
gdb/hp300ux-xdep.c
Normal file
230
gdb/hp300ux-xdep.c
Normal file
@ -0,0 +1,230 @@
|
||||
/* HP/UX interface for HP 300's, for GDB when running under Unix.
|
||||
Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
GDB 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 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
GDB 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 GDB; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
#include "param.h"
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
|
||||
/* Defining this means some system include files define some extra stuff. */
|
||||
#define WOPR
|
||||
#include <sys/param.h>
|
||||
#include <sys/dir.h>
|
||||
#include <signal.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/reg.h>
|
||||
#include <sys/trap.h>
|
||||
|
||||
#include "gdbcore.h"
|
||||
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define INFERIOR_AR0(u) \
|
||||
((ptrace \
|
||||
(PT_RUAREA, inferior_pid, ((char *) &u.u_ar0 - (char *) &u), 0)) \
|
||||
- KERNEL_U_ADDR)
|
||||
|
||||
static void
|
||||
fetch_inferior_register (regno, regaddr)
|
||||
register int regno;
|
||||
register unsigned int regaddr;
|
||||
{
|
||||
#ifndef HPUX_VERSION_5
|
||||
if (regno == PS_REGNUM)
|
||||
{
|
||||
union { int i; short s[2]; } ps_val;
|
||||
int regval;
|
||||
|
||||
ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
|
||||
regval = ps_val.s[0];
|
||||
supply_register (regno, ®val);
|
||||
}
|
||||
else
|
||||
#endif /* not HPUX_VERSION_5 */
|
||||
{
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
|
||||
{
|
||||
*(int *) &buf[i] = ptrace (PT_RUAREA, inferior_pid, regaddr, 0);
|
||||
regaddr += sizeof (int);
|
||||
}
|
||||
supply_register (regno, buf);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
store_inferior_register_1 (regno, regaddr, value)
|
||||
int regno;
|
||||
unsigned int regaddr;
|
||||
int value;
|
||||
{
|
||||
errno = 0;
|
||||
ptrace (PT_WUAREA, inferior_pid, regaddr, value);
|
||||
#if 0
|
||||
/* HP-UX randomly sets errno to non-zero for regno == 25.
|
||||
However, the value is correctly written, so ignore errno. */
|
||||
if (errno != 0)
|
||||
{
|
||||
char string_buf[64];
|
||||
|
||||
sprintf (string_buf, "writing register number %d", regno);
|
||||
perror_with_name (string_buf);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
store_inferior_register (regno, regaddr)
|
||||
register int regno;
|
||||
register unsigned int regaddr;
|
||||
{
|
||||
#ifndef HPUX_VERSION_5
|
||||
if (regno == PS_REGNUM)
|
||||
{
|
||||
union { int i; short s[2]; } ps_val;
|
||||
|
||||
ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
|
||||
ps_val.s[0] = (read_register (regno));
|
||||
store_inferior_register_1 (regno, regaddr, ps_val.i);
|
||||
}
|
||||
else
|
||||
#endif /* not HPUX_VERSION_5 */
|
||||
{
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
register int i;
|
||||
extern char registers[];
|
||||
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
|
||||
{
|
||||
store_inferior_register_1
|
||||
(regno, regaddr,
|
||||
(*(int *) ®isters[(REGISTER_BYTE (regno)) + i]));
|
||||
regaddr += sizeof (int);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
fetch_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
struct user u;
|
||||
register int regno;
|
||||
register unsigned int ar0_offset;
|
||||
|
||||
ar0_offset = (INFERIOR_AR0 (u));
|
||||
if (regno == -1)
|
||||
{
|
||||
for (regno = 0; (regno < FP0_REGNUM); regno++)
|
||||
fetch_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
|
||||
for (; (regno < NUM_REGS); regno++)
|
||||
fetch_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
|
||||
}
|
||||
else
|
||||
fetch_inferior_register (regno,
|
||||
(regno < FP0_REGNUM
|
||||
? REGISTER_ADDR (ar0_offset, regno)
|
||||
: FP_REGISTER_ADDR (u, regno)));
|
||||
}
|
||||
|
||||
/* 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). */
|
||||
|
||||
store_inferior_registers (regno)
|
||||
register int regno;
|
||||
{
|
||||
struct user u;
|
||||
register unsigned int ar0_offset;
|
||||
extern char registers[];
|
||||
|
||||
if (regno >= FP0_REGNUM)
|
||||
{
|
||||
store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
|
||||
return;
|
||||
}
|
||||
|
||||
ar0_offset = (INFERIOR_AR0 (u));
|
||||
if (regno >= 0)
|
||||
{
|
||||
store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
|
||||
return;
|
||||
}
|
||||
|
||||
for (regno = 0; (regno < FP0_REGNUM); regno++)
|
||||
store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
|
||||
for (; (regno < NUM_REGS); regno++)
|
||||
store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Take the register values out of a core file and store
|
||||
them where `read_register' will find them. */
|
||||
|
||||
#ifdef HPUX_VERSION_5
|
||||
#define e_PS e_regs[PS]
|
||||
#define e_PC e_regs[PC]
|
||||
#endif /* HPUX_VERSION_5 */
|
||||
|
||||
void
|
||||
fetch_core_registers (core_reg_sect, core_reg_size, which)
|
||||
char *core_reg_sect;
|
||||
int core_reg_size;
|
||||
int which;
|
||||
{
|
||||
int val, regno;
|
||||
struct user u;
|
||||
struct exception_stack *pes = (struct exception_stack *) core_reg_sect;
|
||||
#define es (*pes)
|
||||
char *buf;
|
||||
|
||||
if (which == 0) {
|
||||
if (core_reg_size <
|
||||
((char *) &es.e_offset - (char *) &es.e_regs[R0]))
|
||||
error ("Not enough registers in core file");
|
||||
for (regno = 0; (regno < PS_REGNUM); regno++)
|
||||
supply_register (regno, &es.e_regs[regno + R0]);
|
||||
val = es.e_PS;
|
||||
supply_register (regno++, &val);
|
||||
supply_register (regno++, &es.e_PC);
|
||||
|
||||
} else if (which == 2) {
|
||||
|
||||
/* FIXME: This may not work if the float regs and control regs are
|
||||
discontinuous. */
|
||||
for (regno = FP0_REGNUM, buf = core_reg_sect;
|
||||
(regno < NUM_REGS);
|
||||
buf += REGISTER_RAW_SIZE (regno), regno++)
|
||||
{
|
||||
supply_register (regno, buf);
|
||||
}
|
||||
}
|
||||
}
|
1707
gdb/infrun.hacked.c
Normal file
1707
gdb/infrun.hacked.c
Normal file
File diff suppressed because it is too large
Load Diff
36
gdb/mtrace.awk
Executable file
36
gdb/mtrace.awk
Executable file
@ -0,0 +1,36 @@
|
||||
#
|
||||
# Awk program to analyze mtrace.c output.
|
||||
#
|
||||
$1 == "+" { if (allocated[$2] != "")
|
||||
print "+", $2, "Alloc", NR, "duplicate:", allocated[$2];
|
||||
else
|
||||
allocated[$2] = $3;
|
||||
}
|
||||
$1 == "-" { if (allocated[$2] != "") {
|
||||
allocated[$2] = "";
|
||||
if (allocated[$2] != "")
|
||||
print "DELETE FAILED", $2, allocated[$2];
|
||||
} else
|
||||
print "-", $2, "Free", NR, "was never alloc'd";
|
||||
}
|
||||
$1 == "<" { if (allocated[$2] != "")
|
||||
allocated[$2] = "";
|
||||
else
|
||||
print "-", $2, "Realloc", NR, "was never alloc'd";
|
||||
}
|
||||
$1 == ">" { if (allocated[$2] != "")
|
||||
print "+", $2, "Realloc", NR, "duplicate:", allocated[$2];
|
||||
else
|
||||
allocated[$2] = $3;
|
||||
}
|
||||
|
||||
# Ignore "= Start"
|
||||
$1 == "=" { }
|
||||
# Ignore failed realloc attempts for now
|
||||
$1 == "!" { }
|
||||
|
||||
|
||||
END { for (x in allocated)
|
||||
if (allocated[x] != "")
|
||||
print "+", x, allocated[x];
|
||||
}
|
129
gdb/mtrace.c
Executable file
129
gdb/mtrace.c
Executable file
@ -0,0 +1,129 @@
|
||||
/* More debugging hooks for `malloc'.
|
||||
Copyright 1991 Free Software Foundation
|
||||
Written April 2, 1991 by John Gilmore of Cygnus Support
|
||||
Based on mcheck.c by Mike Haertel.
|
||||
|
||||
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 1, 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 author may be reached (Email) at the address mike@ai.mit.edu,
|
||||
or (US mail) as Mike Haertel c/o Free Software Foundation. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "ansidecl.h"
|
||||
#include <stdlib.h>
|
||||
#include "gmalloc.h"
|
||||
|
||||
extern char *getenv();
|
||||
|
||||
FILE *mallstream;
|
||||
char mallenv[] = "MALLOC_TRACE";
|
||||
static char mallbuf[BUFSIZ]; /* Buffer for the output */
|
||||
|
||||
/* Address to breakpoint on accesses to... */
|
||||
PTR mallwatch;
|
||||
|
||||
/* Old hook values. */
|
||||
static void EXFUN((*old_free_hook), (PTR ptr));
|
||||
static PTR EXFUN((*old_malloc_hook), (size_t size));
|
||||
static PTR EXFUN((*old_realloc_hook), (PTR ptr, size_t size));
|
||||
|
||||
/* This function is called when the block being alloc'd, realloc'd, or
|
||||
freed has an address matching the variable "mallwatch". In a debugger,
|
||||
set "mallwatch" to the address of interest, then put a breakpoint on
|
||||
tr_break. */
|
||||
|
||||
void
|
||||
tr_break()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void
|
||||
DEFUN(tr_freehook, (ptr), PTR ptr)
|
||||
{
|
||||
fprintf(mallstream, "- %08x\n", ptr); /* Be sure to print it first */
|
||||
if (ptr == mallwatch)
|
||||
tr_break();
|
||||
__free_hook = old_free_hook;
|
||||
free(ptr);
|
||||
__free_hook = tr_freehook;
|
||||
}
|
||||
|
||||
static PTR
|
||||
DEFUN(tr_mallochook, (size), size_t size)
|
||||
{
|
||||
PTR hdr;
|
||||
|
||||
__malloc_hook = old_malloc_hook;
|
||||
hdr = malloc(size);
|
||||
__malloc_hook = tr_mallochook;
|
||||
|
||||
/* We could be printing a NULL here; that's OK */
|
||||
fprintf (mallstream, "+ %08x %x\n", hdr, size);
|
||||
|
||||
if (hdr == mallwatch)
|
||||
tr_break();
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
static PTR
|
||||
DEFUN(tr_reallochook, (ptr, size), PTR ptr AND size_t size)
|
||||
{
|
||||
PTR hdr;
|
||||
|
||||
if (ptr == mallwatch)
|
||||
tr_break();
|
||||
|
||||
__free_hook = old_free_hook;
|
||||
__malloc_hook = old_malloc_hook;
|
||||
__realloc_hook = old_realloc_hook;
|
||||
hdr = realloc(ptr, size);
|
||||
__free_hook = tr_freehook;
|
||||
__malloc_hook = tr_mallochook;
|
||||
__realloc_hook = tr_reallochook;
|
||||
if (hdr == NULL) {
|
||||
fprintf (mallstream, "! %08x %x\n", ptr, size); /* Failed realloc */
|
||||
} else {
|
||||
fprintf (mallstream, "< %08x\n> %08x %x\n", ptr, hdr, size);
|
||||
}
|
||||
|
||||
if (hdr == mallwatch)
|
||||
tr_break();
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
void
|
||||
mtrace()
|
||||
{
|
||||
char *mallfile;
|
||||
|
||||
mallfile = getenv (mallenv);
|
||||
if (mallfile) {
|
||||
mallstream = fopen (mallfile, "w");
|
||||
if (mallstream) {
|
||||
/* Be sure it doesn't malloc its buffer! */
|
||||
setbuf (mallstream, mallbuf);
|
||||
fprintf (mallstream, "= Start\n");
|
||||
old_free_hook = __free_hook;
|
||||
__free_hook = tr_freehook;
|
||||
old_malloc_hook = __malloc_hook;
|
||||
__malloc_hook = tr_mallochook;
|
||||
old_realloc_hook = __realloc_hook;
|
||||
__realloc_hook = tr_reallochook;
|
||||
}
|
||||
}
|
||||
}
|
893
gdb/rem-m68k.shar
Executable file
893
gdb/rem-m68k.shar
Executable file
@ -0,0 +1,893 @@
|
||||
# This is a shell archive. Remove anything before this line,
|
||||
# then unpack it by saving it in a file and typing "sh file".
|
||||
#
|
||||
# Wrapped by Glenn Engel <glenne@labgre> on Mon Jun 12 15:19:20 1989
|
||||
#
|
||||
# This archive contains:
|
||||
# remcom.c
|
||||
#
|
||||
|
||||
LANG=""; export LANG
|
||||
PATH=/bin:/usr/bin:$PATH; export PATH
|
||||
|
||||
echo x - remcom.c
|
||||
cat >remcom.c <<'@EOF'
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
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$
|
||||
*
|
||||
* $Module name: remcom.c $
|
||||
* $Revision$
|
||||
* $Date$
|
||||
* $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 $
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Some explanation is probably necessary to explain how exceptions are
|
||||
* handled. When an exception is encountered the 68000 pushes the current
|
||||
* program counter and status register onto the supervisor stack and then
|
||||
* transfers execution to a location specified in it's vector table.
|
||||
* The handlers for the exception vectors are hardwired to jmp to an address
|
||||
* given by the relation: (exception - 256) * 6. These are decending
|
||||
* addresses starting from -6, -12, -18, ... By allowing 6 bytes for
|
||||
* each entry, a jsr, jmp, bsr, ... can be used to enter the exception
|
||||
* handler. Using a jsr to handle an exception has an added benefit of
|
||||
* allowing a single handler to service several exceptions and use the
|
||||
* return address as the key differentiation. The vector number can be
|
||||
* computed from the return address by [ exception = (addr + 1530) / 6 ].
|
||||
* The sole purpose of the routine _catchException is to compute the
|
||||
* exception number and push it on the stack in place of the return address.
|
||||
* The external function exceptionHandler() is
|
||||
* used to attach a specific handler to a specific 68k exception.
|
||||
* For 68020 machines, the ability to have a return address around just
|
||||
* so the vector can be determined is not necessary because the '020 pushes an
|
||||
* extra word onto the stack containing the vector offset
|
||||
*
|
||||
* 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>
|
||||
#include <setjmp.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 = 0;
|
||||
/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
|
||||
|
||||
char hexchars[]="0123456789abcdef";
|
||||
|
||||
/* there are 180 bytes of registers on a 68020 w/68881 */
|
||||
/* many of the fpa registers are 12 byte (96 bit) registers */
|
||||
#define NUMREGBYTES 180
|
||||
enum regnames {D0,D1,D2,D3,D4,D5,D6,D7,
|
||||
A0,A1,A2,A3,A4,A5,A6,A7,
|
||||
PS,PC,
|
||||
FP0,FP1,FP2,FP3,FP4,FP5,FP6,FP7,
|
||||
FPCONTROL,FPSTATUS,FPIADDR
|
||||
};
|
||||
|
||||
typedef struct FrameStruct
|
||||
{
|
||||
struct FrameStruct *previous;
|
||||
int exceptionPC; /* pc value when this frame created */
|
||||
int exceptionVector; /* cpu vector causing exception */
|
||||
short frameSize; /* size of cpu frame in words */
|
||||
short sr; /* for 68000, this not always sr */
|
||||
int pc;
|
||||
short format;
|
||||
int fsaveHeader;
|
||||
int morejunk[0]; /* exception frame, fp save... */
|
||||
} Frame;
|
||||
|
||||
#define FRAMESIZE 500
|
||||
static Frame *lastFrame;
|
||||
static int frameStack[FRAMESIZE];
|
||||
|
||||
/*
|
||||
* these should not be static cuz they can be used outside this module
|
||||
*/
|
||||
int registers[NUMREGBYTES/4];
|
||||
int superStack;
|
||||
|
||||
static int remcomStack[400];
|
||||
static int* stackPtr = &remcomStack[399];
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/* the size of the exception stack on the 68020 varies with the type of
|
||||
* exception. The following table is the number of WORDS used
|
||||
* for each exception format.
|
||||
*/
|
||||
static short exceptionSize[] = { 4,4,6,4,4,4,4,4,29,10,16,46,4,4,4,4 };
|
||||
|
||||
/************* jump buffer used for setjmp/longjmp **************************/
|
||||
jmp_buf env;
|
||||
|
||||
/*************************** ASSEMBLY CODE MACROS *************************/
|
||||
/* */
|
||||
|
||||
#ifdef __HAVE_68881__
|
||||
/* do an fsave, then remember the address to begin a restore from */
|
||||
#define SAVE_FP_REGS() asm(" fsave a0@-"); \
|
||||
asm(" fmovemx fp0-fp7,_registers+72"); \
|
||||
asm(" fmoveml fpcr/fpsr/fpi,_registers+168");
|
||||
#define RESTORE_FP_REGS() asm(" fmoveml _registers+168,fpcr/fpsr/fpi"); \
|
||||
asm(" fmovemx _registers+72,fp0-fp7"); \
|
||||
asm(" frestore a0@+");
|
||||
#else
|
||||
#define SAVE_FP_REGS()
|
||||
#define RESTORE_FP_REGS()
|
||||
#endif /* __HAVE_68881__ */
|
||||
|
||||
asm("
|
||||
.text
|
||||
.globl _return_to_super
|
||||
_return_to_super:
|
||||
movel _registers+60,sp /* get new stack pointer */
|
||||
movel _lastFrame,a0 /* get last frame info */
|
||||
bra return_to_any
|
||||
|
||||
.globl _return_to_user
|
||||
_return_to_user:
|
||||
movel _registers+60,a0 /* get usp */
|
||||
movel a0,usp /* set usp */
|
||||
movel _superStack,sp /* get original stack pointer */
|
||||
|
||||
return_to_any:
|
||||
movel _lastFrame,a0 /* get last frame info */
|
||||
movel a0@+,_lastFrame /* link in previous frame */
|
||||
addql #8,a0 /* skip over pc, vector#*/
|
||||
movew a0@+,d0 /* get # of words in cpu frame */
|
||||
addw d0,a0 /* point to end of data */
|
||||
addw d0,a0 /* point to end of data */
|
||||
movel a0,a1
|
||||
#
|
||||
# copy the stack frame
|
||||
subql #1,d0
|
||||
copyUserLoop:
|
||||
movew a1@-,sp@-
|
||||
dbf d0,copyUserLoop
|
||||
");
|
||||
RESTORE_FP_REGS()
|
||||
asm(" moveml _registers,d0-d7/a0-a6");
|
||||
asm(" rte"); /* pop and go! */
|
||||
|
||||
#define DISABLE_INTERRUPTS() asm(" oriw #0x0700,sr");
|
||||
#define BREAKPOINT() asm(" trap #1");
|
||||
|
||||
/* this function is called immediately when a level 7 interrupt occurs */
|
||||
/* if the previous interrupt level was 7 then we're already servicing */
|
||||
/* this interrupt and an rte is in order to return to the debugger. */
|
||||
/* For the 68000, the offset for sr is 6 due to the jsr return address */
|
||||
asm("
|
||||
.text
|
||||
.globl __debug_level7
|
||||
__debug_level7:
|
||||
movew d0,sp@-");
|
||||
#ifdef mc68020
|
||||
asm(" movew sp@(2),d0");
|
||||
#else
|
||||
asm(" movew sp@(6),d0");
|
||||
#endif
|
||||
asm(" andiw #0x700,d0
|
||||
cmpiw #0x700,d0
|
||||
beq _already7
|
||||
movew sp@+,d0
|
||||
bra __catchException
|
||||
_already7:
|
||||
movew sp@+,d0");
|
||||
#ifndef mc68020
|
||||
asm(" lea sp@(4),sp"); /* pull off 68000 return address */
|
||||
#endif
|
||||
asm(" rte");
|
||||
|
||||
extern void _catchException();
|
||||
|
||||
#ifdef mc68020
|
||||
/* This function is called when a 68020 exception occurs. It saves
|
||||
* all the cpu and fpcp regs in the _registers array, creates a frame on a
|
||||
* linked list of frames which has the cpu and fpcp stack frames needed
|
||||
* to properly restore the context of these processors, and invokes
|
||||
* an exception handler (remcom_handler).
|
||||
*
|
||||
* stack on entry: stack on exit:
|
||||
* N bytes of junk exception # MSWord
|
||||
* Exception Format Word exception # MSWord
|
||||
* Program counter LSWord
|
||||
* Program counter MSWord
|
||||
* Status Register
|
||||
*
|
||||
*
|
||||
*/
|
||||
asm("
|
||||
.text
|
||||
.globl __catchException
|
||||
__catchException:");
|
||||
DISABLE_INTERRUPTS();
|
||||
asm("
|
||||
moveml d0-d7/a0-a6,_registers /* save registers */
|
||||
movel _lastFrame,a0 /* last frame pointer */
|
||||
");
|
||||
SAVE_FP_REGS();
|
||||
asm("
|
||||
lea _registers,a5 /* get address of registers */
|
||||
movew sp@,d1 /* get status register */
|
||||
movew d1,a5@(66) /* save sr */
|
||||
movel sp@(2),a4 /* save pc in a4 for later use */
|
||||
movel a4,a5@(68) /* save pc in _regisers[] */
|
||||
|
||||
#
|
||||
# figure out how many bytes in the stack frame
|
||||
movew sp@(6),d0 /* get '020 exception format */
|
||||
movew d0,d2 /* make a copy of format word */
|
||||
andiw #0xf000,d0 /* mask off format type */
|
||||
rolw #5,d0 /* rotate into the low byte *2 */
|
||||
lea _exceptionSize,a1
|
||||
addw d0,a1 /* index into the table */
|
||||
movew a1@,d0 /* get number of words in frame */
|
||||
movew d0,d3 /* save it */
|
||||
subw d0,a0 /* adjust save pointer */
|
||||
subw d0,a0 /* adjust save pointer(bytes) */
|
||||
movel a0,a1 /* copy save pointer */
|
||||
subql #1,d0 /* predecrement loop counter */
|
||||
#
|
||||
# copy the frame
|
||||
saveFrameLoop:
|
||||
movew sp@+,a1@+
|
||||
dbf d0,saveFrameLoop
|
||||
#
|
||||
# now that the stack has been clenaed,
|
||||
# save the a7 in use at time of exception
|
||||
movel sp,_superStack /* save supervisor sp */
|
||||
andiw #0x2000,d1 /* were we in supervisor mode ? */
|
||||
beq userMode
|
||||
movel a7,a5@(60) /* save a7 */
|
||||
bra a7saveDone
|
||||
userMode:
|
||||
movel usp,a1
|
||||
movel a1,a5@(60) /* save user stack pointer */
|
||||
a7saveDone:
|
||||
|
||||
#
|
||||
# save size of frame
|
||||
movew d3,a0@-
|
||||
|
||||
#
|
||||
# compute exception number
|
||||
andl #0xfff,d2 /* mask off vector offset */
|
||||
lsrw #2,d2 /* divide by 4 to get vect num */
|
||||
movel d2,a0@- /* save it */
|
||||
#
|
||||
# save pc causing exception
|
||||
movel a4,a0@-
|
||||
#
|
||||
# save old frame link and set the new value
|
||||
movel _lastFrame,a1 /* last frame pointer */
|
||||
movel a1,a0@- /* save pointer to prev frame */
|
||||
movel a0,_lastFrame
|
||||
|
||||
movel d2,sp@- /* push exception num */
|
||||
movel _exceptionHook,a0 /* get address of handler */
|
||||
jbsr a0@ /* and call it */
|
||||
jmp __returnFromException /* now, return */
|
||||
");
|
||||
#else /* mc68000 */
|
||||
/* This function is called when an exception occurs. It translates the
|
||||
* return address found on the stack into an exception vector # which
|
||||
* is then handled by either handle_exception or a system handler.
|
||||
* _catchException provides a front end for both.
|
||||
*
|
||||
* stack on entry: stack on exit:
|
||||
* Program counter MSWord exception # MSWord
|
||||
* Program counter LSWord exception # MSWord
|
||||
* Status Register
|
||||
* Return Address MSWord
|
||||
* Return Address LSWord
|
||||
*/
|
||||
asm("
|
||||
.text
|
||||
.globl __catchException
|
||||
__catchException:");
|
||||
DISABLE_INTERRUPTS();
|
||||
asm("
|
||||
moveml d0-d7/a0-a6,_registers /* save registers */
|
||||
movel _lastFrame,a0 /* last frame pointer */
|
||||
");
|
||||
SAVE_FP_REGS();
|
||||
asm("
|
||||
lea _registers,a5 /* get address of registers */
|
||||
movel sp@+,d2 /* pop return address */
|
||||
addl #1530,d2 /* convert return addr to */
|
||||
divs #6,d2 /* exception number */
|
||||
extl d2
|
||||
|
||||
moveql #3,d3 /* assume a three word frame */
|
||||
|
||||
cmpiw #3,d2 /* bus error or address error ? */
|
||||
bgt normal /* if >3 then normal error */
|
||||
movel sp@+,a0@- /* copy error info to frame buff*/
|
||||
movel sp@+,a0@- /* these are never used */
|
||||
moveql #7,d3 /* this is a 7 word frame */
|
||||
|
||||
normal:
|
||||
movew sp@+,d1 /* pop status register */
|
||||
movel sp@+,a4 /* pop program counter */
|
||||
movew d1,a5@(66) /* save sr */
|
||||
movel a4,a5@(68) /* save pc in _regisers[] */
|
||||
movel a4,a0@- /* copy pc to frame buffer */
|
||||
movew d1,a0@- /* copy sr to frame buffer */
|
||||
|
||||
movel sp,_superStack /* save supervisor sp */
|
||||
|
||||
andiw #0x2000,d1 /* were we in supervisor mode ? */
|
||||
beq userMode
|
||||
movel a7,a5@(60) /* save a7 */
|
||||
bra saveDone
|
||||
userMode:
|
||||
movel usp,a1 /* save user stack pointer */
|
||||
movel a1,a5@(60) /* save user stack pointer */
|
||||
saveDone:
|
||||
|
||||
movew d3,a0@- /* push frame size in words */
|
||||
movel d2,a0@- /* push vector number */
|
||||
movel a4,a0@- /* push exception pc */
|
||||
|
||||
#
|
||||
# save old frame link and set the new value
|
||||
movel _lastFrame,a1 /* last frame pointer */
|
||||
movel a1,a0@- /* save pointer to prev frame */
|
||||
movel a0,_lastFrame
|
||||
|
||||
movel d2,sp@- /* push exception num */
|
||||
movel _exceptionHook,a0 /* get address of handler */
|
||||
jbsr a0@ /* and call it */
|
||||
jmp __returnFromException /* now, return */
|
||||
");
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* remcomHandler is a front end for handle_exception. It moves the
|
||||
* stack pointer into an area reserved for debugger use in case the
|
||||
* breakpoint happened in supervisor mode.
|
||||
*/
|
||||
asm("_remcomHandler:");
|
||||
asm(" addl #4,sp"); /* pop off return address */
|
||||
asm(" movel sp@+,d0"); /* get the exception number */
|
||||
asm(" movel _stackPtr,sp"); /* move to remcom stack area */
|
||||
asm(" movel d0,sp@-"); /* push exception onto stack */
|
||||
asm(" jbsr _handle_exception"); /* this never returns */
|
||||
asm(" rts"); /* return */
|
||||
|
||||
void _returnFromException( Frame *frame )
|
||||
{
|
||||
/* if no existing frame, dummy one up */
|
||||
if (! frame)
|
||||
{
|
||||
frame = lastFrame -1;
|
||||
frame->frameSize = 4;
|
||||
frame->format = 0;
|
||||
frame->fsaveHeader = 0;
|
||||
frame->previous = lastFrame;
|
||||
}
|
||||
|
||||
#ifndef mc68020
|
||||
/* a 68000 cannot use the internal info pushed onto a bus error
|
||||
* or address error frame when doing an RTE so don't put this info
|
||||
* onto the stack or the stack will creep every time this happens.
|
||||
*/
|
||||
frame->frameSize=3;
|
||||
#endif
|
||||
|
||||
/* throw away any frames in the list after this frame */
|
||||
lastFrame = frame;
|
||||
|
||||
frame->sr = registers[(int) PS];
|
||||
frame->pc = registers[(int) PC];
|
||||
|
||||
if (registers[(int) PS] & 0x2000)
|
||||
{
|
||||
/* return to supervisor mode... */
|
||||
return_to_super();
|
||||
}
|
||||
else
|
||||
{ /* return to user mode */
|
||||
return_to_user();
|
||||
}
|
||||
}
|
||||
|
||||
int hex(ch)
|
||||
char ch;
|
||||
{
|
||||
if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
|
||||
if ((ch >= '0') && (ch <= '9')) return (ch-'0');
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/* 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()) != '$');
|
||||
checksum = 0;
|
||||
count = 0;
|
||||
|
||||
/* now, read until a # or end of buffer is found */
|
||||
while (count < BUFMAX) {
|
||||
ch = getDebugChar();
|
||||
if (ch == '#') break;
|
||||
checksum = checksum + ch;
|
||||
buffer[count] = ch;
|
||||
count = count + 1;
|
||||
}
|
||||
buffer[count] = 0;
|
||||
|
||||
if (ch == '#') {
|
||||
xmitcsum = hex(getDebugChar()) << 4;
|
||||
xmitcsum += hex(getDebugChar());
|
||||
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. The host get's one chance to read it.
|
||||
This routine does not wait for a positive acknowledge. */
|
||||
|
||||
|
||||
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 (1 == 0); /* (getDebugChar() != '+'); */
|
||||
|
||||
}
|
||||
|
||||
static char inbuffer[BUFMAX];
|
||||
static char outbuffer[BUFMAX];
|
||||
static short error;
|
||||
|
||||
|
||||
void debug_error(format, parm)
|
||||
char * format;
|
||||
char * parm;
|
||||
{
|
||||
if (remote_debug) fprintf(stderr,format,parm);
|
||||
}
|
||||
|
||||
/* convert the memory pointed to by mem into hex, placing result in buf */
|
||||
/* return a pointer to the last char put in buf (null) */
|
||||
char* mem2hex(mem, buf, count)
|
||||
char* mem;
|
||||
char* buf;
|
||||
int count;
|
||||
{
|
||||
int i;
|
||||
unsigned char ch;
|
||||
for (i=0;i<count;i++) {
|
||||
ch = *mem++;
|
||||
*buf++ = hexchars[ch >> 4];
|
||||
*buf++ = hexchars[ch % 16];
|
||||
}
|
||||
*buf = 0;
|
||||
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)
|
||||
char* buf;
|
||||
char* mem;
|
||||
int count;
|
||||
{
|
||||
int i;
|
||||
unsigned char ch;
|
||||
for (i=0;i<count;i++) {
|
||||
ch = hex(*buf++) << 4;
|
||||
ch = ch + hex(*buf++);
|
||||
*mem++ = ch;
|
||||
}
|
||||
return(mem);
|
||||
}
|
||||
|
||||
/* a bus error has occurred, perform a longjmp
|
||||
to return execution and allow handling of the error */
|
||||
|
||||
void handle_buserror()
|
||||
{
|
||||
longjmp(env,1);
|
||||
}
|
||||
|
||||
/* this function takes the 68000 exception number and attempts to
|
||||
translate this number into a unix compatible signal value */
|
||||
int computeSignal( exceptionVector )
|
||||
int exceptionVector;
|
||||
{
|
||||
int sigval;
|
||||
switch (exceptionVector) {
|
||||
case 2 : sigval = 10; break; /* bus error */
|
||||
case 3 : sigval = 10; break; /* address error */
|
||||
case 4 : sigval = 4; break; /* illegal instruction */
|
||||
case 5 : sigval = 8; break; /* zero divide */
|
||||
case 6 : sigval = 16; break; /* chk instruction */
|
||||
case 7 : sigval = 16; break; /* trapv instruction */
|
||||
case 8 : sigval = 11; break; /* privilege violation */
|
||||
case 9 : sigval = 5; break; /* trace trap */
|
||||
case 10: sigval = 4; break; /* line 1010 emulator */
|
||||
case 11: sigval = 4; break; /* line 1111 emulator */
|
||||
case 31: sigval = 2; break; /* interrupt */
|
||||
case 33: sigval = 5; break; /* breakpoint */
|
||||
case 40: sigval = 8; break; /* floating point err */
|
||||
case 48: sigval = 8; break; /* floating point err */
|
||||
case 49: sigval = 8; break; /* floating point err */
|
||||
case 50: sigval = 8; break; /* zero divide */
|
||||
case 51: sigval = 8; break; /* underflow */
|
||||
case 52: sigval = 8; break; /* operand error */
|
||||
case 53: sigval = 8; break; /* overflow */
|
||||
case 54: sigval = 8; break; /* NAN */
|
||||
default:
|
||||
sigval = 7; /* "software generated"*/
|
||||
}
|
||||
return (sigval);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function does all command procesing for interfacing to gdb.
|
||||
*/
|
||||
void handle_exception(int exceptionVector)
|
||||
{
|
||||
int sigval;
|
||||
int addr, length;
|
||||
char * ptr;
|
||||
int newPC;
|
||||
Frame *frame;
|
||||
|
||||
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 );
|
||||
sprintf(outbuffer,"S%02x",sigval);
|
||||
putpacket(outbuffer);
|
||||
|
||||
while (1==1) {
|
||||
error = 0;
|
||||
outbuffer[0] = 0;
|
||||
getpacket(inbuffer);
|
||||
switch (inbuffer[0]) {
|
||||
case '?' : sprintf(outbuffer,"S%02x",sigval);
|
||||
break;
|
||||
case 'd' : remote_debug = !(remote_debug); /* toggle debug flag */
|
||||
break;
|
||||
case 'g' : /* return the value of the CPU registers */
|
||||
mem2hex((char*) registers, outbuffer, NUMREGBYTES);
|
||||
break;
|
||||
case 'G' : /* set the value of the CPU registers - return OK */
|
||||
hex2mem(&inbuffer[1], (char*) registers, NUMREGBYTES);
|
||||
strcpy(outbuffer,"OK");
|
||||
break;
|
||||
|
||||
/* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
|
||||
case 'm' :
|
||||
if (setjmp(env) == 0) {
|
||||
exceptionHandler(2,handle_buserror);
|
||||
|
||||
if (2 == sscanf(&inbuffer[1],"%x,%x",&addr,&length)) {
|
||||
mem2hex((char*) addr, outbuffer, length);
|
||||
}
|
||||
else {
|
||||
strcpy(outbuffer,"E01");
|
||||
debug_error("malformed read memory command: %s",inbuffer);
|
||||
}
|
||||
}
|
||||
else {
|
||||
exceptionHandler(2,_catchException);
|
||||
strcpy(outbuffer,"E03");
|
||||
debug_error("bus error");
|
||||
}
|
||||
|
||||
/* restore handler for bus error */
|
||||
exceptionHandler(2,_catchException);
|
||||
break;
|
||||
|
||||
/* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
|
||||
case 'M' :
|
||||
if (setjmp(env) == 0) {
|
||||
exceptionHandler(2,handle_buserror);
|
||||
|
||||
if (2 == sscanf(&inbuffer[1],"%x,%x:",&addr,&length)) {
|
||||
ptr = strchr(inbuffer,':');
|
||||
ptr += 1; /* point 1 past the colon */
|
||||
hex2mem(ptr, (char*) addr, length);
|
||||
strcpy(outbuffer,"OK");
|
||||
}
|
||||
else {
|
||||
strcpy(outbuffer,"E02");
|
||||
debug_error("malformed write memory command: %s",inbuffer);
|
||||
}
|
||||
}
|
||||
else {
|
||||
exceptionHandler(2,_catchException);
|
||||
strcpy(outbuffer,"E03");
|
||||
debug_error("bus error");
|
||||
}
|
||||
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, addr unchanged if no parm */
|
||||
if (1 == sscanf(&inbuffer[1],"%x",®isters[ PC ]));
|
||||
newPC = registers[ PC];
|
||||
|
||||
/* clear the trace bit */
|
||||
registers[ PS ] &= 0x7fff;
|
||||
|
||||
/* set the trace bit if we're stepping */
|
||||
if (inbuffer[0] == 's') registers[ PS ] |= 0x8000;
|
||||
|
||||
/*
|
||||
* look for newPC in the linked list of exception frames.
|
||||
* if it is found, use the old frame it. otherwise,
|
||||
* fake up a dummy frame in returnFromException().
|
||||
*/
|
||||
if (remote_debug) printf("new pc = 0x%x\n",newPC);
|
||||
frame = lastFrame;
|
||||
while (frame)
|
||||
{
|
||||
if (remote_debug)
|
||||
printf("frame at 0x%x has pc=0x%x, except#=%d\n",
|
||||
frame,frame->exceptionPC,
|
||||
frame->exceptionVector);
|
||||
if (frame->exceptionPC == newPC) break; /* bingo! a match */
|
||||
/*
|
||||
* for a breakpoint instruction, the saved pc may
|
||||
* be off by two due to re-executing the instruction
|
||||
* replaced by the trap instruction. Check for this.
|
||||
*/
|
||||
if ((frame->exceptionVector == 33) &&
|
||||
(frame->exceptionPC == (newPC+2))) break;
|
||||
frame = frame->previous;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 (frame)
|
||||
{
|
||||
if ((frame->exceptionVector != 9) &&
|
||||
(frame->exceptionVector != 31) &&
|
||||
(frame->exceptionVector != 33))
|
||||
{
|
||||
/*
|
||||
* invoke the previous handler.
|
||||
*/
|
||||
if (oldExceptionHook)
|
||||
(*oldExceptionHook) (frame->exceptionVector);
|
||||
newPC = registers[ PC ]; /* pc may have changed */
|
||||
if (newPC != frame->exceptionPC)
|
||||
{
|
||||
if (remote_debug)
|
||||
printf("frame at 0x%x has pc=0x%x, except#=%d\n",
|
||||
frame,frame->exceptionPC,
|
||||
frame->exceptionVector);
|
||||
/* dispose of this frame, we're skipping it (longjump?)*/
|
||||
lastFrame = frame->previous;
|
||||
frame = (Frame *) 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_returnFromException( frame );
|
||||
|
||||
break;
|
||||
|
||||
/* kill the program */
|
||||
case 'k' : /* do nothing */
|
||||
break;
|
||||
} /* switch */
|
||||
|
||||
/* reply to the request */
|
||||
putpacket(outbuffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* this function is used to set up exception handlers for tracing and
|
||||
breakpoints */
|
||||
void set_debug_traps()
|
||||
{
|
||||
extern void _debug_level7();
|
||||
extern void remcomHandler();
|
||||
int exception;
|
||||
|
||||
for (exception = 2; exception <= 23; exception++)
|
||||
exceptionHandler(exception,_catchException);
|
||||
|
||||
/* level 7 interrupt */
|
||||
exceptionHandler(31,_debug_level7);
|
||||
|
||||
/* breakpoint exception (trap #1) */
|
||||
exceptionHandler(33,_catchException);
|
||||
|
||||
/* floating point error (trap #8) */
|
||||
exceptionHandler(40,_catchException);
|
||||
|
||||
/* 48 to 54 are floating point coprocessor errors */
|
||||
for (exception = 48; exception <= 54; exception++)
|
||||
exceptionHandler(exception,_catchException);
|
||||
|
||||
if (oldExceptionHook != remcomHandler)
|
||||
{
|
||||
oldExceptionHook = exceptionHook;
|
||||
exceptionHook = remcomHandler;
|
||||
}
|
||||
|
||||
initialized = 1;
|
||||
|
||||
lastFrame = (Frame *) &frameStack[FRAMESIZE-1];
|
||||
lastFrame->previous = (Frame *) 0;
|
||||
}
|
||||
|
||||
/* 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) BREAKPOINT();
|
||||
}
|
||||
|
||||
@EOF
|
||||
|
||||
chmod 444 remcom.c
|
||||
|
||||
exit 0
|
||||
|
1313
gdb/rem-multi.shar
Normal file
1313
gdb/rem-multi.shar
Normal file
File diff suppressed because it is too large
Load Diff
1146
gdb/remote-sa.sparc.c
Normal file
1146
gdb/remote-sa.sparc.c
Normal file
File diff suppressed because it is too large
Load Diff
1527
gdb/remote-vx.68.c
Normal file
1527
gdb/remote-vx.68.c
Normal file
File diff suppressed because it is too large
Load Diff
494
gdb/symm-tdep.c
Normal file
494
gdb/symm-tdep.c
Normal file
@ -0,0 +1,494 @@
|
||||
/* Sequent Symmetry target interface, for GDB when running under Unix.
|
||||
Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
GDB 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 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
GDB 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 GDB; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* many 387-specific items of use taken from i386-dep.c */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
#include "param.h"
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
#include "symtab.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/dir.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include "gdbcore.h"
|
||||
#include <fcntl.h>
|
||||
|
||||
static long i386_get_frame_setup ();
|
||||
static i386_follow_jump ();
|
||||
|
||||
#include <sgtty.h>
|
||||
#define TERMINAL struct sgttyb
|
||||
|
||||
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;
|
||||
text_end = 0;
|
||||
exec_data_start = 0;
|
||||
exec_data_end = 0;
|
||||
if (execchan >= 0)
|
||||
close (execchan);
|
||||
execchan = -1;
|
||||
|
||||
/* 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);
|
||||
|
||||
#ifdef COFF_FORMAT
|
||||
{
|
||||
int aout_hdrsize;
|
||||
int num_sections;
|
||||
|
||||
if (read_file_hdr (execchan, &file_hdr) < 0)
|
||||
error ("\"%s\": not in executable format.", execfile);
|
||||
|
||||
aout_hdrsize = file_hdr.f_opthdr;
|
||||
num_sections = file_hdr.f_nscns;
|
||||
|
||||
if (read_aout_hdr (execchan, &exec_aouthdr, aout_hdrsize) < 0)
|
||||
error ("\"%s\": can't read optional aouthdr", execfile);
|
||||
|
||||
if (read_section_hdr (execchan, _TEXT, &text_hdr, num_sections,
|
||||
aout_hdrsize) < 0)
|
||||
error ("\"%s\": can't read text section header", execfile);
|
||||
|
||||
if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections,
|
||||
aout_hdrsize) < 0)
|
||||
error ("\"%s\": can't read data section header", execfile);
|
||||
|
||||
text_start = exec_aouthdr.text_start;
|
||||
text_end = text_start + exec_aouthdr.tsize;
|
||||
text_offset = text_hdr.s_scnptr;
|
||||
exec_data_start = exec_aouthdr.data_start;
|
||||
exec_data_end = exec_data_start + exec_aouthdr.dsize;
|
||||
exec_data_offset = data_hdr.s_scnptr;
|
||||
data_start = exec_data_start;
|
||||
data_end += exec_data_start;
|
||||
exec_mtime = file_hdr.f_timdat;
|
||||
}
|
||||
#else /* not COFF_FORMAT */
|
||||
{
|
||||
struct stat st_exec;
|
||||
|
||||
val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
|
||||
|
||||
if (val < 0)
|
||||
perror_with_name (filename);
|
||||
|
||||
text_start = N_ADDRADJ(exec_aouthdr);
|
||||
exec_data_start = round(exec_aouthdr.a_text, NBPG*CLSIZE);
|
||||
text_offset = N_TXTOFF (exec_aouthdr);
|
||||
exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
|
||||
text_end = exec_aouthdr.a_text;
|
||||
exec_data_end = exec_data_start + exec_aouthdr.a_data;
|
||||
data_start = exec_data_start;
|
||||
data_end = data_start + exec_aouthdr.a_data;
|
||||
exec_data_offset = N_TXTOFF(exec_aouthdr);
|
||||
fstat (execchan, &st_exec);
|
||||
exec_mtime = st_exec.st_mtime;
|
||||
}
|
||||
#endif /* not COFF_FORMAT */
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* rounds 'one' up to divide evenly by 'two' */
|
||||
|
||||
int
|
||||
round(one,two)
|
||||
register int one, two;
|
||||
|
||||
{
|
||||
register int temp;
|
||||
temp = (one/two)*two;
|
||||
if (one != temp) {
|
||||
temp += two;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
static CORE_ADDR codestream_next_addr;
|
||||
static CORE_ADDR codestream_addr;
|
||||
static unsigned char codestream_buf[sizeof (int)];
|
||||
static int codestream_off;
|
||||
static int codestream_cnt;
|
||||
|
||||
#define codestream_tell() (codestream_addr + codestream_off)
|
||||
#define codestream_peek() (codestream_cnt == 0 ? \
|
||||
codestream_fill(1): codestream_buf[codestream_off])
|
||||
#define codestream_get() (codestream_cnt-- == 0 ? \
|
||||
codestream_fill(0) : codestream_buf[codestream_off++])
|
||||
|
||||
|
||||
static unsigned char
|
||||
codestream_fill (peek_flag)
|
||||
{
|
||||
codestream_addr = codestream_next_addr;
|
||||
codestream_next_addr += sizeof (int);
|
||||
codestream_off = 0;
|
||||
codestream_cnt = sizeof (int);
|
||||
read_memory (codestream_addr,
|
||||
(unsigned char *)codestream_buf,
|
||||
sizeof (int));
|
||||
|
||||
if (peek_flag)
|
||||
return (codestream_peek());
|
||||
else
|
||||
return (codestream_get());
|
||||
}
|
||||
|
||||
static void
|
||||
codestream_seek (place)
|
||||
{
|
||||
codestream_next_addr = place & -sizeof (int);
|
||||
codestream_cnt = 0;
|
||||
codestream_fill (1);
|
||||
while (codestream_tell() != place)
|
||||
codestream_get ();
|
||||
}
|
||||
|
||||
static void
|
||||
codestream_read (buf, count)
|
||||
unsigned char *buf;
|
||||
{
|
||||
unsigned char *p;
|
||||
int i;
|
||||
p = buf;
|
||||
for (i = 0; i < count; i++)
|
||||
*p++ = codestream_get ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Following macro translates i386 opcode register numbers to Symmetry
|
||||
* register numbers. This is used by FRAME_FIND_SAVED_REGS.
|
||||
*
|
||||
* %eax %ecx %edx %ebx %esp %ebp %esi %edi
|
||||
* i386 0 1 2 3 4 5 6 7
|
||||
* Symmetry 0 2 1 5 14 15 6 7
|
||||
*
|
||||
*/
|
||||
#define I386_REGNO_TO_SYMMETRY(n) \
|
||||
((n)==0?0 :(n)==1?2 :(n)==2?1 :(n)==3?5 :(n)==4?14 :(n)==5?15 :(n))
|
||||
|
||||
/* from i386-dep.c */
|
||||
i386_frame_find_saved_regs (fip, fsrp)
|
||||
struct frame_info *fip;
|
||||
struct frame_saved_regs *fsrp;
|
||||
{
|
||||
unsigned long locals;
|
||||
unsigned char *p;
|
||||
unsigned char op;
|
||||
CORE_ADDR dummy_bottom;
|
||||
CORE_ADDR adr;
|
||||
int i;
|
||||
|
||||
bzero (fsrp, sizeof *fsrp);
|
||||
|
||||
/* if frame is the end of a dummy, compute where the
|
||||
* beginning would be
|
||||
*/
|
||||
dummy_bottom = fip->frame - 4 - NUM_REGS*4 - CALL_DUMMY_LENGTH;
|
||||
|
||||
/* check if the PC is in the stack, in a dummy frame */
|
||||
if (dummy_bottom <= fip->pc && fip->pc <= fip->frame)
|
||||
{
|
||||
/* all regs were saved by push_call_dummy () */
|
||||
adr = fip->frame - 4;
|
||||
for (i = 0; i < NUM_REGS; i++)
|
||||
{
|
||||
fsrp->regs[i] = adr;
|
||||
adr -= 4;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
locals = i386_get_frame_setup (get_pc_function_start (fip->pc));
|
||||
|
||||
if (locals >= 0)
|
||||
{
|
||||
adr = fip->frame - 4 - locals;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
op = codestream_get ();
|
||||
if (op < 0x50 || op > 0x57)
|
||||
break;
|
||||
fsrp->regs[I386_REGNO_TO_SYMMETRY(op - 0x50)] = adr;
|
||||
adr -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
fsrp->regs[PC_REGNUM] = fip->frame + 4;
|
||||
fsrp->regs[FP_REGNUM] = fip->frame;
|
||||
}
|
||||
|
||||
static long
|
||||
i386_get_frame_setup (pc)
|
||||
{
|
||||
unsigned char op;
|
||||
|
||||
codestream_seek (pc);
|
||||
|
||||
i386_follow_jump ();
|
||||
|
||||
op = codestream_get ();
|
||||
|
||||
if (op == 0x58) /* popl %eax */
|
||||
{
|
||||
/*
|
||||
* this function must start with
|
||||
*
|
||||
* popl %eax 0x58
|
||||
* xchgl %eax, (%esp) 0x87 0x04 0x24
|
||||
* or xchgl %eax, 0(%esp) 0x87 0x44 0x24 0x00
|
||||
*
|
||||
* (the system 5 compiler puts out the second xchg
|
||||
* inst, and the assembler doesn't try to optimize it,
|
||||
* so the 'sib' form gets generated)
|
||||
*
|
||||
* this sequence is used to get the address of the return
|
||||
* buffer for a function that returns a structure
|
||||
*/
|
||||
int pos;
|
||||
unsigned char buf[4];
|
||||
static unsigned char proto1[3] = { 0x87,0x04,0x24 };
|
||||
static unsigned char proto2[4] = { 0x87,0x44,0x24,0x00 };
|
||||
pos = codestream_tell ();
|
||||
codestream_read (buf, 4);
|
||||
if (bcmp (buf, proto1, 3) == 0)
|
||||
pos += 3;
|
||||
else if (bcmp (buf, proto2, 4) == 0)
|
||||
pos += 4;
|
||||
|
||||
codestream_seek (pos);
|
||||
op = codestream_get (); /* update next opcode */
|
||||
}
|
||||
|
||||
if (op == 0x55) /* pushl %esp */
|
||||
{
|
||||
if (codestream_get () != 0x8b) /* movl %esp, %ebp (2bytes) */
|
||||
return (-1);
|
||||
if (codestream_get () != 0xec)
|
||||
return (-1);
|
||||
/*
|
||||
* check for stack adjustment
|
||||
*
|
||||
* subl $XXX, %esp
|
||||
*
|
||||
* note: you can't subtract a 16 bit immediate
|
||||
* from a 32 bit reg, so we don't have to worry
|
||||
* about a data16 prefix
|
||||
*/
|
||||
op = codestream_peek ();
|
||||
if (op == 0x83) /* subl with 8 bit immed */
|
||||
{
|
||||
codestream_get ();
|
||||
if (codestream_get () != 0xec)
|
||||
return (-1);
|
||||
/* subl with signed byte immediate
|
||||
* (though it wouldn't make sense to be negative)
|
||||
*/
|
||||
return (codestream_get());
|
||||
}
|
||||
else if (op == 0x81) /* subl with 32 bit immed */
|
||||
{
|
||||
int locals;
|
||||
if (codestream_get () != 0xec)
|
||||
return (-1);
|
||||
/* subl with 32 bit immediate */
|
||||
codestream_read ((unsigned char *)&locals, 4);
|
||||
return (locals);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
else if (op == 0xc8)
|
||||
{
|
||||
/* enter instruction: arg is 16 unsigned immed */
|
||||
unsigned short slocals;
|
||||
codestream_read ((unsigned char *)&slocals, 2);
|
||||
codestream_get (); /* flush final byte of enter instruction */
|
||||
return (slocals);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* next instruction is a jump, move to target */
|
||||
static
|
||||
i386_follow_jump ()
|
||||
{
|
||||
int long_delta;
|
||||
short short_delta;
|
||||
char byte_delta;
|
||||
int data16;
|
||||
int pos;
|
||||
|
||||
pos = codestream_tell ();
|
||||
|
||||
data16 = 0;
|
||||
if (codestream_peek () == 0x66)
|
||||
{
|
||||
codestream_get ();
|
||||
data16 = 1;
|
||||
}
|
||||
|
||||
switch (codestream_get ())
|
||||
{
|
||||
case 0xe9:
|
||||
/* relative jump: if data16 == 0, disp32, else disp16 */
|
||||
if (data16)
|
||||
{
|
||||
codestream_read ((unsigned char *)&short_delta, 2);
|
||||
pos += short_delta + 3; /* include size of jmp inst */
|
||||
}
|
||||
else
|
||||
{
|
||||
codestream_read ((unsigned char *)&long_delta, 4);
|
||||
pos += long_delta + 5;
|
||||
}
|
||||
break;
|
||||
case 0xeb:
|
||||
/* relative jump, disp8 (ignore data16) */
|
||||
codestream_read ((unsigned char *)&byte_delta, 1);
|
||||
pos += byte_delta + 2;
|
||||
break;
|
||||
}
|
||||
codestream_seek (pos + data16);
|
||||
}
|
||||
|
||||
/* return pc of first real instruction */
|
||||
/* from i386-dep.c */
|
||||
|
||||
i386_skip_prologue (pc)
|
||||
{
|
||||
unsigned char op;
|
||||
int i;
|
||||
|
||||
if (i386_get_frame_setup (pc) < 0)
|
||||
return (pc);
|
||||
|
||||
/* found valid frame setup - codestream now points to
|
||||
* start of push instructions for saving registers
|
||||
*/
|
||||
|
||||
/* skip over register saves */
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
op = codestream_peek ();
|
||||
/* break if not pushl inst */
|
||||
if (op < 0x50 || op > 0x57)
|
||||
break;
|
||||
codestream_get ();
|
||||
}
|
||||
|
||||
i386_follow_jump ();
|
||||
|
||||
return (codestream_tell ());
|
||||
}
|
||||
|
||||
symmetry_extract_return_value(type, regbuf, valbuf)
|
||||
struct type *type;
|
||||
char *regbuf;
|
||||
char *valbuf;
|
||||
{
|
||||
union {
|
||||
double d;
|
||||
int l[2];
|
||||
} xd;
|
||||
int i;
|
||||
float f;
|
||||
|
||||
if (TYPE_CODE_FLT == TYPE_CODE(type)) {
|
||||
for (i = 0; i < misc_function_count; i++) {
|
||||
if (!strcmp(misc_function_vector[i].name, "1167_flt"))
|
||||
break;
|
||||
}
|
||||
if (i < misc_function_count) {
|
||||
/* found "1167_flt" means 1167, %fp2-%fp3 */
|
||||
/* float & double; 19= %fp2, 20= %fp3 */
|
||||
/* no single precision on 1167 */
|
||||
xd.l[1] = *((int *)®buf[REGISTER_BYTE(19)]);
|
||||
xd.l[0] = *((int *)®buf[REGISTER_BYTE(20)]);
|
||||
switch (TYPE_LENGTH(type)) {
|
||||
case 4:
|
||||
f = (float) xd.d;
|
||||
bcopy(&f, valbuf, TYPE_LENGTH(type));
|
||||
break;
|
||||
case 8:
|
||||
bcopy(&xd.d, valbuf, TYPE_LENGTH(type));
|
||||
break;
|
||||
default:
|
||||
error("Unknown floating point size");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* 387 %st(0), gcc uses this */
|
||||
i387_to_double(((int *)®buf[REGISTER_BYTE(3)]),
|
||||
&xd.d);
|
||||
switch (TYPE_LENGTH(type)) {
|
||||
case 4: /* float */
|
||||
f = (float) xd.d;
|
||||
bcopy(&f, valbuf, 4);
|
||||
break;
|
||||
case 8: /* double */
|
||||
bcopy(&xd.d, valbuf, 8);
|
||||
break;
|
||||
default:
|
||||
error("Unknown floating point size");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bcopy (regbuf, valbuf, TYPE_LENGTH (type));
|
||||
}
|
||||
}
|
557
gdb/symm-xdep.c
Normal file
557
gdb/symm-xdep.c
Normal file
@ -0,0 +1,557 @@
|
||||
/* Sequent Symmetry host interface, for GDB when running under Unix.
|
||||
Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
GDB 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 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
GDB 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 GDB; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* many 387-specific items of use taken from i386-dep.c */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
#include "param.h"
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
#include "symtab.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/dir.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include "gdbcore.h"
|
||||
#include <fcntl.h>
|
||||
|
||||
static long i386_get_frame_setup ();
|
||||
static i386_follow_jump ();
|
||||
|
||||
#include <sgtty.h>
|
||||
#define TERMINAL struct sgttyb
|
||||
|
||||
store_inferior_registers(regno)
|
||||
int regno;
|
||||
{
|
||||
struct pt_regset regs;
|
||||
int reg_tmp, i;
|
||||
extern char registers[];
|
||||
|
||||
#if 0
|
||||
/* PREPARE_TO_STORE deals with this. */
|
||||
if (-1 == regno)
|
||||
{
|
||||
#endif
|
||||
regs.pr_eax = *(int *)®isters[REGISTER_BYTE(0)];
|
||||
regs.pr_ebx = *(int *)®isters[REGISTER_BYTE(5)];
|
||||
regs.pr_ecx = *(int *)®isters[REGISTER_BYTE(2)];
|
||||
regs.pr_edx = *(int *)®isters[REGISTER_BYTE(1)];
|
||||
regs.pr_esi = *(int *)®isters[REGISTER_BYTE(6)];
|
||||
regs.pr_edi = *(int *)®isters[REGISTER_BYTE(7)];
|
||||
regs.pr_esp = *(int *)®isters[REGISTER_BYTE(14)];
|
||||
regs.pr_ebp = *(int *)®isters[REGISTER_BYTE(15)];
|
||||
regs.pr_eip = *(int *)®isters[REGISTER_BYTE(16)];
|
||||
regs.pr_flags = *(int *)®isters[REGISTER_BYTE(17)];
|
||||
for (i = 0; i < 31; i++) {
|
||||
regs.pr_fpa.fpa_regs[i] =
|
||||
*(int *)®isters[REGISTER_BYTE(FP1_REGNUM+i)];
|
||||
}
|
||||
#if 0
|
||||
}
|
||||
else
|
||||
{
|
||||
reg_tmp = *(int *)®isters[REGISTER_BYTE(regno)];
|
||||
ptrace(XPT_RREGS, inferior_pid, ®s, 0);
|
||||
switch (regno)
|
||||
{
|
||||
case 0:
|
||||
regs.pr_eax = *(int *)®isters[REGISTER_BYTE(0)];
|
||||
break;
|
||||
case 5:
|
||||
regs.pr_ebx = *(int *)®isters[REGISTER_BYTE(5)];
|
||||
break;
|
||||
case 2:
|
||||
regs.pr_ecx = *(int *)®isters[REGISTER_BYTE(2)];
|
||||
break;
|
||||
case 1:
|
||||
regs.pr_edx = *(int *)®isters[REGISTER_BYTE(1)];
|
||||
break;
|
||||
case 6:
|
||||
regs.pr_esi = *(int *)®isters[REGISTER_BYTE(6)];
|
||||
break;
|
||||
case 7:
|
||||
regs.pr_edi = *(int *)®isters[REGISTER_BYTE(7)];
|
||||
break;
|
||||
case 15:
|
||||
regs.pr_ebp = *(int *)®isters[REGISTER_BYTE(15)];
|
||||
break;
|
||||
case 14:
|
||||
regs.pr_esp = *(int *)®isters[REGISTER_BYTE(14)];
|
||||
break;
|
||||
case 16:
|
||||
regs.pr_eip = *(int *)®isters[REGISTER_BYTE(16)];
|
||||
break;
|
||||
case 17:
|
||||
regs.pr_flags = *(int *)®isters[REGISTER_BYTE(17)];
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* 0 */
|
||||
ptrace(XPT_WREGS, inferior_pid, ®s, 0);
|
||||
}
|
||||
|
||||
void
|
||||
fetch_inferior_registers()
|
||||
{
|
||||
int i;
|
||||
struct pt_regset regs;
|
||||
extern char registers[];
|
||||
|
||||
registers_fetched ();
|
||||
|
||||
ptrace(XPT_RREGS, inferior_pid, ®s, 0);
|
||||
*(int *)®isters[REGISTER_BYTE(0)] = regs.pr_eax;
|
||||
*(int *)®isters[REGISTER_BYTE(5)] = regs.pr_ebx;
|
||||
*(int *)®isters[REGISTER_BYTE(2)] = regs.pr_ecx;
|
||||
*(int *)®isters[REGISTER_BYTE(1)] = regs.pr_edx;
|
||||
*(int *)®isters[REGISTER_BYTE(6)] = regs.pr_esi;
|
||||
*(int *)®isters[REGISTER_BYTE(7)] = regs.pr_edi;
|
||||
*(int *)®isters[REGISTER_BYTE(15)] = regs.pr_ebp;
|
||||
*(int *)®isters[REGISTER_BYTE(14)] = regs.pr_esp;
|
||||
*(int *)®isters[REGISTER_BYTE(16)] = regs.pr_eip;
|
||||
*(int *)®isters[REGISTER_BYTE(17)] = regs.pr_flags;
|
||||
for (i = 0; i < FPA_NREGS; i++) {
|
||||
*(int *)®isters[REGISTER_BYTE(FP1_REGNUM+i)] = regs.pr_fpa.fpa_regs[i];
|
||||
}
|
||||
bcopy(regs.pr_fpu.fpu_stack[0], ®isters[REGISTER_BYTE(3)], 10);
|
||||
bcopy(regs.pr_fpu.fpu_stack[1], ®isters[REGISTER_BYTE(4)], 10);
|
||||
bcopy(regs.pr_fpu.fpu_stack[2], ®isters[REGISTER_BYTE(8)], 10);
|
||||
bcopy(regs.pr_fpu.fpu_stack[3], ®isters[REGISTER_BYTE(9)], 10);
|
||||
bcopy(regs.pr_fpu.fpu_stack[4], ®isters[REGISTER_BYTE(10)], 10);
|
||||
bcopy(regs.pr_fpu.fpu_stack[5], ®isters[REGISTER_BYTE(11)], 10);
|
||||
bcopy(regs.pr_fpu.fpu_stack[6], ®isters[REGISTER_BYTE(12)], 10);
|
||||
bcopy(regs.pr_fpu.fpu_stack[7], ®isters[REGISTER_BYTE(13)], 10);
|
||||
}
|
||||
|
||||
|
||||
/* Work with core dump and executable files, for GDB.
|
||||
This code would be in core.c if it weren't machine-dependent. */
|
||||
|
||||
#include "gdbcore.h"
|
||||
|
||||
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 inferior 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;
|
||||
int reg_offset;
|
||||
|
||||
val = myread (corechan, &u, sizeof u);
|
||||
if (val < 0)
|
||||
perror_with_name (filename);
|
||||
data_start = exec_data_start;
|
||||
|
||||
data_end = data_start + NBPG * (u.u_dsize - u.u_tsize);
|
||||
stack_start = stack_end - NBPG * u.u_ssize;
|
||||
data_offset = NBPG * UPAGES;
|
||||
stack_offset = ctob(UPAGES + u.u_dsize - u.u_tsize);
|
||||
reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
|
||||
printf("u.u_tsize= %#x, u.u_dsize= %#x, u.u_ssize= %#x, stack_off= %#x\n",
|
||||
u.u_tsize, u.u_dsize, u.u_ssize, stack_offset);
|
||||
|
||||
core_aouthdr.a_magic = 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];
|
||||
|
||||
val = lseek (corechan, register_addr (regno, reg_offset), 0);
|
||||
if (val < 0)
|
||||
perror_with_name (filename);
|
||||
|
||||
val = myread (corechan, buf, sizeof buf);
|
||||
if (val < 0)
|
||||
perror_with_name (filename);
|
||||
supply_register (regno, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filename[0] == '/')
|
||||
corefile = savestring (filename, strlen (filename));
|
||||
else
|
||||
{
|
||||
corefile = concat (current_directory, "/", filename);
|
||||
}
|
||||
|
||||
set_current_frame(create_new_frame(read_register(FP_REGNUM),
|
||||
read_pc()));
|
||||
/* set_current_frame (read_register (FP_REGNUM));*/
|
||||
select_frame (get_current_frame (), 0);
|
||||
validate_files ();
|
||||
}
|
||||
else if (from_tty)
|
||||
printf ("No core file now.\n");
|
||||
}
|
||||
|
||||
/* from i386-dep.c */
|
||||
static
|
||||
print_387_control_word (control)
|
||||
unsigned short control;
|
||||
{
|
||||
printf ("control 0x%04x: ", control);
|
||||
printf ("compute to ");
|
||||
switch ((control >> 8) & 3)
|
||||
{
|
||||
case 0: printf ("24 bits; "); break;
|
||||
case 1: printf ("(bad); "); break;
|
||||
case 2: printf ("53 bits; "); break;
|
||||
case 3: printf ("64 bits; "); break;
|
||||
}
|
||||
printf ("round ");
|
||||
switch ((control >> 10) & 3)
|
||||
{
|
||||
case 0: printf ("NEAREST; "); break;
|
||||
case 1: printf ("DOWN; "); break;
|
||||
case 2: printf ("UP; "); break;
|
||||
case 3: printf ("CHOP; "); break;
|
||||
}
|
||||
if (control & 0x3f)
|
||||
{
|
||||
printf ("mask:");
|
||||
if (control & 0x0001) printf (" INVALID");
|
||||
if (control & 0x0002) printf (" DENORM");
|
||||
if (control & 0x0004) printf (" DIVZ");
|
||||
if (control & 0x0008) printf (" OVERF");
|
||||
if (control & 0x0010) printf (" UNDERF");
|
||||
if (control & 0x0020) printf (" LOS");
|
||||
printf (";");
|
||||
}
|
||||
printf ("\n");
|
||||
if (control & 0xe080) printf ("warning: reserved bits on 0x%x\n",
|
||||
control & 0xe080);
|
||||
}
|
||||
|
||||
static
|
||||
print_387_status_word (status)
|
||||
unsigned short status;
|
||||
{
|
||||
printf ("status %#04x: ", status);
|
||||
if (status & 0xff) {
|
||||
printf ("exceptions:"); /* exception names match <machine/fpu.h> */
|
||||
if (status & 0x0001) printf (" FLTINV");
|
||||
if (status & 0x0002) printf (" FLTDEN");
|
||||
if (status & 0x0004) printf (" FLTDIV");
|
||||
if (status & 0x0008) printf (" FLTOVF");
|
||||
if (status & 0x0010) printf (" FLTUND");
|
||||
if (status & 0x0020) printf (" FLTPRE");
|
||||
if (status & 0x0040) printf (" FLTSTK");
|
||||
printf ("; ");
|
||||
}
|
||||
printf ("flags: %d%d%d%d; ",
|
||||
(status & 0x4000) != 0,
|
||||
(status & 0x0400) != 0,
|
||||
(status & 0x0200) != 0,
|
||||
(status & 0x0100) != 0);
|
||||
|
||||
printf ("top %d\n", (status >> 11) & 7);
|
||||
}
|
||||
|
||||
static
|
||||
print_fpu_status(ep)
|
||||
struct pt_regset ep;
|
||||
|
||||
{
|
||||
int i;
|
||||
int bothstatus;
|
||||
int top;
|
||||
int fpreg;
|
||||
unsigned char *p;
|
||||
|
||||
printf("80387:");
|
||||
if (ep.pr_fpu.fpu_ip == 0) {
|
||||
printf(" not in use.\n");
|
||||
return;
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
if (ep.pr_fpu.fpu_status != 0) {
|
||||
print_387_status_word (ep.pr_fpu.fpu_status);
|
||||
}
|
||||
print_387_control_word (ep.pr_fpu.fpu_control);
|
||||
printf ("last exception: ");
|
||||
printf ("opcode 0x%x; ", ep.pr_fpu.fpu_rsvd4);
|
||||
printf ("pc 0x%x:0x%x; ", ep.pr_fpu.fpu_cs, ep.pr_fpu.fpu_ip);
|
||||
printf ("operand 0x%x:0x%x\n", ep.pr_fpu.fpu_data_offset, ep.pr_fpu.fpu_op_sel);
|
||||
|
||||
top = (ep.pr_fpu.fpu_status >> 11) & 7;
|
||||
|
||||
printf ("regno tag msb lsb value\n");
|
||||
for (fpreg = 7; fpreg >= 0; fpreg--)
|
||||
{
|
||||
double val;
|
||||
|
||||
printf ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
|
||||
|
||||
switch ((ep.pr_fpu.fpu_tag >> (fpreg * 2)) & 3)
|
||||
{
|
||||
case 0: printf ("valid "); break;
|
||||
case 1: printf ("zero "); break;
|
||||
case 2: printf ("trap "); break;
|
||||
case 3: printf ("empty "); break;
|
||||
}
|
||||
for (i = 9; i >= 0; i--)
|
||||
printf ("%02x", ep.pr_fpu.fpu_stack[fpreg][i]);
|
||||
|
||||
i387_to_double (ep.pr_fpu.fpu_stack[fpreg], (char *)&val);
|
||||
printf (" %g\n", val);
|
||||
}
|
||||
if (ep.pr_fpu.fpu_rsvd1)
|
||||
printf ("warning: rsvd1 is 0x%x\n", ep.pr_fpu.fpu_rsvd1);
|
||||
if (ep.pr_fpu.fpu_rsvd2)
|
||||
printf ("warning: rsvd2 is 0x%x\n", ep.pr_fpu.fpu_rsvd2);
|
||||
if (ep.pr_fpu.fpu_rsvd3)
|
||||
printf ("warning: rsvd3 is 0x%x\n", ep.pr_fpu.fpu_rsvd3);
|
||||
if (ep.pr_fpu.fpu_rsvd5)
|
||||
printf ("warning: rsvd5 is 0x%x\n", ep.pr_fpu.fpu_rsvd5);
|
||||
}
|
||||
|
||||
|
||||
print_1167_control_word(pcr)
|
||||
unsigned int pcr;
|
||||
|
||||
{
|
||||
int pcr_tmp;
|
||||
|
||||
pcr_tmp = pcr & FPA_PCR_MODE;
|
||||
printf("\tMODE= %#x; RND= %#x ", pcr_tmp, pcr_tmp & 12);
|
||||
switch (pcr_tmp & 12) {
|
||||
case 0:
|
||||
printf("RN (Nearest Value)");
|
||||
break;
|
||||
case 1:
|
||||
printf("RZ (Zero)");
|
||||
break;
|
||||
case 2:
|
||||
printf("RP (Positive Infinity)");
|
||||
break;
|
||||
case 3:
|
||||
printf("RM (Negative Infinity)");
|
||||
break;
|
||||
}
|
||||
printf("; IRND= %d ", pcr_tmp & 2);
|
||||
if (0 == pcr_tmp & 2) {
|
||||
printf("(same as RND)\n");
|
||||
} else {
|
||||
printf("(toward zero)\n");
|
||||
}
|
||||
pcr_tmp = pcr & FPA_PCR_EM;
|
||||
printf("\tEM= %#x", pcr_tmp);
|
||||
if (pcr_tmp & FPA_PCR_EM_DM) printf(" DM");
|
||||
if (pcr_tmp & FPA_PCR_EM_UOM) printf(" UOM");
|
||||
if (pcr_tmp & FPA_PCR_EM_PM) printf(" PM");
|
||||
if (pcr_tmp & FPA_PCR_EM_UM) printf(" UM");
|
||||
if (pcr_tmp & FPA_PCR_EM_OM) printf(" OM");
|
||||
if (pcr_tmp & FPA_PCR_EM_ZM) printf(" ZM");
|
||||
if (pcr_tmp & FPA_PCR_EM_IM) printf(" IM");
|
||||
printf("\n");
|
||||
pcr_tmp = FPA_PCR_CC;
|
||||
printf("\tCC= %#x", pcr_tmp);
|
||||
if (pcr_tmp & FPA_PCR_20MHZ) printf(" 20MHZ");
|
||||
if (pcr_tmp & FPA_PCR_CC_Z) printf(" Z");
|
||||
if (pcr_tmp & FPA_PCR_CC_C2) printf(" C2");
|
||||
if (pcr_tmp & FPA_PCR_CC_C1) printf(" C1");
|
||||
switch (pcr_tmp) {
|
||||
case FPA_PCR_CC_Z:
|
||||
printf(" (Equal)");
|
||||
break;
|
||||
case FPA_PCR_CC_C1:
|
||||
printf(" (Less than)");
|
||||
break;
|
||||
case 0:
|
||||
printf(" (Greater than)");
|
||||
break;
|
||||
case FPA_PCR_CC_Z | FPA_PCR_CC_C1 | FPA_PCR_CC_C2:
|
||||
printf(" (Unordered)");
|
||||
break;
|
||||
default:
|
||||
printf(" (Undefined)");
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
pcr_tmp = pcr & FPA_PCR_AE;
|
||||
printf("\tAE= %#x", pcr_tmp);
|
||||
if (pcr_tmp & FPA_PCR_AE_DE) printf(" DE");
|
||||
if (pcr_tmp & FPA_PCR_AE_UOE) printf(" UOE");
|
||||
if (pcr_tmp & FPA_PCR_AE_PE) printf(" PE");
|
||||
if (pcr_tmp & FPA_PCR_AE_UE) printf(" UE");
|
||||
if (pcr_tmp & FPA_PCR_AE_OE) printf(" OE");
|
||||
if (pcr_tmp & FPA_PCR_AE_ZE) printf(" ZE");
|
||||
if (pcr_tmp & FPA_PCR_AE_EE) printf(" EE");
|
||||
if (pcr_tmp & FPA_PCR_AE_IE) printf(" IE");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
print_1167_regs(regs)
|
||||
long regs[FPA_NREGS];
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
union {
|
||||
double d;
|
||||
long l[2];
|
||||
} xd;
|
||||
union {
|
||||
float f;
|
||||
long l;
|
||||
} xf;
|
||||
|
||||
|
||||
for (i = 0; i < FPA_NREGS; i++) {
|
||||
xf.l = regs[i];
|
||||
printf("%%fp%d: raw= %#x, single= %f", i+1, regs[i], xf.f);
|
||||
if (!(i & 1)) {
|
||||
printf("\n");
|
||||
} else {
|
||||
xd.l[1] = regs[i];
|
||||
xd.l[0] = regs[i+1];
|
||||
printf(", double= %f\n", xd.d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print_fpa_status(ep)
|
||||
struct pt_regset ep;
|
||||
|
||||
{
|
||||
|
||||
printf("WTL 1167:");
|
||||
if (ep.pr_fpa.fpa_pcr !=0) {
|
||||
printf("\n");
|
||||
print_1167_control_word(ep.pr_fpa.fpa_pcr);
|
||||
print_1167_regs(ep.pr_fpa.fpa_regs);
|
||||
} else {
|
||||
printf(" not in use.\n");
|
||||
}
|
||||
}
|
||||
|
||||
i386_float_info ()
|
||||
|
||||
{
|
||||
char ubuf[UPAGES*NBPG];
|
||||
struct pt_regset regset;
|
||||
extern int corechan;
|
||||
|
||||
if (have_inferior_p()) {
|
||||
call_ptrace(XPT_RREGS, inferior_pid, ®set, 0);
|
||||
} else {
|
||||
if (lseek (corechan, 0, 0) < 0) {
|
||||
perror ("seek on core file");
|
||||
}
|
||||
if (myread (corechan, ubuf, UPAGES*NBPG) < 0) {
|
||||
perror ("read on core file");
|
||||
}
|
||||
/* only interested in the floating point registers */
|
||||
regset.pr_fpu = ((struct user *) ubuf)->u_fpusave;
|
||||
regset.pr_fpa = ((struct user *) ubuf)->u_fpasave;
|
||||
}
|
||||
print_fpu_status(regset);
|
||||
print_fpa_status(regset);
|
||||
}
|
||||
|
||||
i387_to_double (from, to)
|
||||
char *from;
|
||||
char *to;
|
||||
{
|
||||
long *lp;
|
||||
/* push extended mode on 387 stack, then pop in double mode
|
||||
*
|
||||
* first, set exception masks so no error is generated -
|
||||
* number will be rounded to inf or 0, if necessary
|
||||
*/
|
||||
asm ("pushl %eax"); /* grab a stack slot */
|
||||
asm ("fstcw (%esp)"); /* get 387 control word */
|
||||
asm ("movl (%esp),%eax"); /* save old value */
|
||||
asm ("orl $0x3f,%eax"); /* mask all exceptions */
|
||||
asm ("pushl %eax");
|
||||
asm ("fldcw (%esp)"); /* load new value into 387 */
|
||||
|
||||
asm ("movl 8(%ebp),%eax");
|
||||
asm ("fldt (%eax)"); /* push extended number on 387 stack */
|
||||
asm ("fwait");
|
||||
asm ("movl 12(%ebp),%eax");
|
||||
asm ("fstpl (%eax)"); /* pop double */
|
||||
asm ("fwait");
|
||||
|
||||
asm ("popl %eax"); /* flush modified control word */
|
||||
asm ("fnclex"); /* clear exceptions */
|
||||
asm ("fldcw (%esp)"); /* restore original control word */
|
||||
asm ("popl %eax"); /* flush saved copy */
|
||||
}
|
||||
|
||||
double_to_i387 (from, to)
|
||||
char *from;
|
||||
char *to;
|
||||
{
|
||||
/* push double mode on 387 stack, then pop in extended mode
|
||||
* no errors are possible because every 64-bit pattern
|
||||
* can be converted to an extended
|
||||
*/
|
||||
asm ("movl 8(%ebp),%eax");
|
||||
asm ("fldl (%eax)");
|
||||
asm ("fwait");
|
||||
asm ("movl 12(%ebp),%eax");
|
||||
asm ("fstpt (%eax)");
|
||||
asm ("fwait");
|
||||
}
|
48
gdb/tm-vx68.h
Normal file
48
gdb/tm-vx68.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* Parameters for execution on VxWorks 68k's, for GDB, the GNU debugger.
|
||||
Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
GDB 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 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
GDB 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 GDB; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#define GDBINIT_FILENAME ".vxgdbinit"
|
||||
|
||||
#define DEFAULT_PROMPT "(vxgdb) "
|
||||
|
||||
/* Kludge... */
|
||||
#include "tm-sun3.h"
|
||||
|
||||
/* We have more complex, useful breakpoints on the target. */
|
||||
#undef DECR_PC_AFTER_BREAK
|
||||
#define DECR_PC_AFTER_BREAK 0
|
||||
|
||||
/* We are guaranteed to have a zero frame pointer at bottom of stack, too. */
|
||||
#undef FRAME_CHAIN
|
||||
#undef FRAME_CHAIN_VALID
|
||||
|
||||
/* Takes the current frame-struct pointer and returns the chain-pointer
|
||||
to get to the calling frame.
|
||||
|
||||
If our current frame pointer is zero, we're at the top; else read out
|
||||
the saved FP from memory pointed to by the current FP. */
|
||||
|
||||
#define FRAME_CHAIN(thisframe) ((thisframe)->frame? read_memory_integer ((thisframe)->frame, 4): 0)
|
||||
|
||||
/* If the chain pointer is zero (either because the saved value fetched
|
||||
by FRAME_CHAIN was zero, or because the current FP was zero so FRAME_CHAIN
|
||||
never fetched anything), we are at the top of the stack. */
|
||||
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) (chain != 0)
|
48
gdb/tm-vx960.h
Normal file
48
gdb/tm-vx960.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* Parameters for VxWorks Intel 960's, for GDB, the GNU debugger.
|
||||
Copyright (C) 1986-1991 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
GDB 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 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
GDB 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 GDB; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include "tm-i960.h"
|
||||
|
||||
#define GDBINIT_FILENAME ".vxgdbinit"
|
||||
|
||||
#define DEFAULT_PROMPT "(vxgdb) "
|
||||
|
||||
/* We have more complex, useful breakpoints on the target.
|
||||
Amount ip must be decremented by after a breakpoint. */
|
||||
|
||||
#define DECR_PC_AFTER_BREAK 0
|
||||
|
||||
/* We are guaranteed to have a zero frame pointer at bottom of stack, too. */
|
||||
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) (chain != 0)
|
||||
|
||||
/* Breakpoint patching is handled at the target end in VxWorks. */
|
||||
/* #define BREAKPOINT {0x00, 0x3e, 0x00, 0x66} */
|
||||
|
||||
/* Not needed, because we don't support core files:
|
||||
#define KERNEL_U_ADDR
|
||||
#define REGISTER_U_ADDR(addr, blockend, regno)
|
||||
*/
|
||||
|
||||
/* Address of end of stack space.
|
||||
This doesn't matter for VxWorks, because it's only used
|
||||
in manipulation of core files, which we don't support. */
|
||||
|
||||
/* #define STACK_END_ADDR (0xfe000000) */
|
37
gdb/xm-i386sco.h
Normal file
37
gdb/xm-i386sco.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* Macro defintions for i386, running SCO Unix System V/386 3.2.
|
||||
Copyright (C) 1989 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
GDB 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 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
GDB 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 GDB; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include "xm-i386v.h"
|
||||
|
||||
/* Apparently there is inconsistency among various System V's about what
|
||||
the name of this field is. */
|
||||
#define U_FPSTATE(u) u.u_fps.u_fpstate
|
||||
|
||||
/* TIOCGETC is defined in System V 3.2 termio.h, but struct tchars
|
||||
is not. This makes problems for inflow.c. */
|
||||
#define TIOCGETC_BROKEN
|
||||
|
||||
/* All the job control definitions exist in SCO Unix, but the standard
|
||||
shells don't use them. So we must disable job control. */
|
||||
#define NO_JOB_CONTROL
|
||||
|
||||
/* SCO's assembler doesn't grok dollar signs in identifiers.
|
||||
So we use dots instead. This item must be coordinated with G++. */
|
||||
#undef CPLUS_MARKER
|
||||
#define CPLUS_MARKER '.'
|
Loading…
Reference in New Issue
Block a user