gdb-2.5.1

This commit is contained in:
gdb-2.5.1 1988-05-02 01:00:00 +01:00 committed by Pedro Alves
parent 7b4ac7e1ed
commit 632ea0ccc5
99 changed files with 10537 additions and 21792 deletions

View File

@ -1,108 +0,0 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; gdb code changes
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
/*
* Core Problem: when gdb says something like (../src/file.c 1234), the
* real file might be in any of the active dirs in use by gdb and thus
* emacs can not always find the file at "../src". Emacs cannot just
* scan for GDB dir commands because these might be given in the .gdbinit
* file or other scripts. The only solution is to have gdb be a bit more
* specific when it prints file names.
*
* Remaining defects:
*
* 1. Do I really have to open the file to find out if it exists?
* There should be a faster way.
*
* 2. Should there be a bdb command to toggle between short and absolute
* forms of the file name?
*/
/* Add this to ~emacs/gdb/source.c after the openp function */
char *
get_absolute_filename(table)
/* Added by Lynn Slater, Silvar-Lisco 10/6/87
returns the address of the best possible name to use for the file
in the passed symtab. Returns the filename if the path cannot be
resolved.
Please remember to free the absolute name after use.*/
struct symtab *table;
{
register int desc;
char *absolute_name;
desc = openp (source_path, 0, table->filename, O_RDONLY, 0, &absolute_name);
if (desc < 0)
return( savestring(table->filename, strlen(table->filename)));
close (desc);
return(absolute_name);
}
/* Replace this fcn in ~emacs/gdb/stack.c */
void
print_frame_info (fi, level, source, args)
struct frame_info *fi;
register int level;
int source;
int args;
{
register FRAME frame = fi->frame;
struct symtab_and_line sal;
struct symbol *func;
register char *funname = 0;
int numargs;
sal = find_pc_line (fi->pc, fi->next_frame);
func = get_frame_function (frame);
if (func)
funname = SYMBOL_NAME (func);
else
{
register int misc_index = find_pc_misc_function (fi->pc);
if (misc_index >= 0)
funname = misc_function_vector[misc_index].name;
}
if (source >= 0 || !sal.symtab)
{
/* This avoids a bug in cc on the sun. */
struct frame_info tem;
tem = *fi;
if (level >= 0)
printf ("#%-2d ", level);
if (fi->pc != sal.pc || !sal.symtab)
printf ("0x%x in ", fi->pc);
printf ("%s (", funname ? funname : "??");
if (args)
{
FRAME_NUM_ARGS (numargs, tem);
print_frame_args (func, FRAME_ARGS_ADDRESS (tem), numargs, stdout);
}
printf (")");
if (sal.symtab)
{
char * absolute_filename;
absolute_filename = (char *) get_absolute_filename(sal.symtab);
printf (" (%s line %d)", absolute_filename, sal.line);
free(absolute_filename);
}
printf ("\n");
}
if (source != 0 && sal.symtab)
{
if (source < 0 && fi->pc != sal.pc)
printf ("0x%x\t", fi->pc);
print_source_lines (sal.symtab, sal.line, sal.line + 1);
current_source_line = max (sal.line - 5, 1);
}
if (source != 0)
set_default_breakpoint (1, fi->pc, sal.symtab, sal.line);
fflush (stdout);
}

136
gdb/=news
View File

@ -1,136 +0,0 @@
===================================================================
RCS file: RCS/printcmd.c,v
retrieving revision 1.1
diff -c3 -r1.1 printcmd.c
*** /tmp/,RCSt1011248 Tue Jan 12 14:06:06 1988
--- printcmd.c Mon Sep 21 21:33:39 1987
***************
*** 174,179
VALUE_TYPE (val) = builtin_type_float;
if (TYPE_LENGTH (VALUE_TYPE (val)) == sizeof (double))
VALUE_TYPE (val) = builtin_type_double;
printf ("%g", value_as_double (val));
break;
--- 174,185 -----
VALUE_TYPE (val) = builtin_type_float;
if (TYPE_LENGTH (VALUE_TYPE (val)) == sizeof (double))
VALUE_TYPE (val) = builtin_type_double;
+ #ifdef PRINTF_BUG
+ if (is_nan(value_as_double (val)))
+ printf ("Nan");
+ else
+ printf ("%g", value_as_double (val));
+ #else
printf ("%g", value_as_double (val));
#endif
break;
***************
*** 175,180
if (TYPE_LENGTH (VALUE_TYPE (val)) == sizeof (double))
VALUE_TYPE (val) = builtin_type_double;
printf ("%g", value_as_double (val));
break;
case 0:
--- 181,187 -----
printf ("%g", value_as_double (val));
#else
printf ("%g", value_as_double (val));
+ #endif
break;
case 0:
===================================================================
RCS file: RCS/valprint.c,v
retrieving revision 1.1
diff -c3 -r1.1 valprint.c
*** /tmp/,RCSt1011248 Tue Jan 12 14:06:09 1988
--- valprint.c Mon Sep 21 21:35:45 1987
***************
*** 21,26
#include <stdio.h>
#include "defs.h"
#include "initialize.h"
#include "symtab.h"
#include "value.h"
--- 21,27 -----
#include <stdio.h>
#include "defs.h"
#include "initialize.h"
+ #include "param.h"
#include "symtab.h"
#include "value.h"
***************
*** 249,255
break;
case TYPE_CODE_FLT:
! fprintf (stream, "%g", unpack_double (type, valaddr));
break;
case TYPE_CODE_VOID:
--- 250,265 -----
break;
case TYPE_CODE_FLT:
! { double d = unpack_double (type, valaddr);
! #ifdef PRINTF_BUG
! if (is_nan(d))
! fprintf (stream, "Nan");
! else
! fprintf (stream, "%g", d);
! #else
! fprintf (stream, "%g", d);
! #endif
! }
break;
case TYPE_CODE_VOID:
***************
*** 559,563
float_type_table[sizeof (float)] = "float";
float_type_table[sizeof (double)] = "double";
}
END_FILE
--- 569,599 -----
float_type_table[sizeof (float)] = "float";
float_type_table[sizeof (double)] = "double";
}
+
+
+ #ifdef PRINTF_BUG
+
+ struct ieee { /* IEEE floating format */
+ unsigned int s:1;
+ unsigned int e:11;
+ unsigned int f1:20;
+ unsigned int f2;
+ };
+
+ #define ZERO_F(x) ((x.f1 == 0) && (x.f2 == 0)) /* zero fraction ? */
+ #define ZERO_E(x) (x.e == 0) /* zero exponential ? */
+ #define MAX_E(x) (x.e == 0x7ff) /* max exponential ? */
+ #define MINUS_S(x) (x.s == 1) /* minus ? */
+
+ int
+ is_nan(arg) /* Not a Number ? */
+ struct ieee arg;
+ {
+ if (MAX_E(arg) && !ZERO_F(arg))
+ return (1);
+ else
+ return (0);
+ }
+ #endif
END_FILE

File diff suppressed because it is too large Load Diff

View File

@ -1,103 +0,0 @@
BABYL OPTIONS:
Version: 5
Labels:
Note: This is the header of an rmail file.
Note: If you are seeing it in rmail,
Note: it means the file has no messages in it.

1,answered,,
Received: by PREP.AI.MIT.EDU; Tue, 26 May 87 14:03:00 EDT
Received: by po2.andrew.cmu.edu (5.54/3.15) id <AA00274> for rms@PREP.AI.MIT.EDU; Tue, 26 May 87 13:12:52 EDT
Received: via switchmail; Tue, 26 May 87 13:12:49 edt
Received: FROM mooncrest VIA qmail
ID </cmu/common/mailqs/q004/QF.mooncrest.20b9cce3.d0134>;
Tue, 26 May 87 13:12:08 edt
Received: FROM mooncrest VIA qmail
ID </cmu/itc/kazar/.Outgoing/QF.mooncrest.20b9ccb0.1b570>;
Tue, 26 May 87 13:11:14 edt
Message-Id: <0UiQmky00UkA06w0Ci@andrew.cmu.edu>
X-Trace: MS Version 3.24 on ibm032 host mooncrest, by kazar (71).
Date: Tue, 26 May 87 13:11:12 edt
From: kazar#@andrew.cmu.edu (Mike Kazar)
To: rms@PREP.AI.MIT.EDU (Richard M. Stallman)
Subject: Re: Fwd: RT diffs for gdb version 2.1
Cc: zs01#@andrew.cmu.edu (Zalman Stern)
In-Reply-To: <4UiN0ly00Vs8Njw0PC@andrew.cmu.edu>
*** EOOH ***
X-Trace: MS Version 3.24 on ibm032 host mooncrest, by kazar (71).
Date: Tue, 26 May 87 13:11:12 edt
From: kazar#@andrew.cmu.edu (Mike Kazar)
To: rms@PREP.AI.MIT.EDU (Richard M. Stallman)
Subject: Re: Fwd: RT diffs for gdb version 2.1
Cc: zs01#@andrew.cmu.edu (Zalman Stern)
In-Reply-To: <4UiN0ly00Vs8Njw0PC@andrew.cmu.edu>
I'm afraid that neither of your proposed simplifications to the gdb RT port
actually work.
First, the trace table problem. The fundamental problem is that gdb expects
to be able to pass in a frame pointer and get that frame's parent. This is
the purpose of FRAME_CHAIN, a macro whose one parameter is the frame whose
parent is desired.
This is simply insufficient information with which to compute the preceding
frame's address. In order to truly appreciate how bad things are, let me
describe the procedure involved in going from a set of saved registers
(including the pc), say after a core dump occurs, to the address of the
preceding frame. I assure you that you'll be shocked by its complexity....
I start off knowing only one thing: the PC of the guy who pushed the last
stack frame. At the time of a core dump, this is in the saved PC, and for
other stack frames, it is in register R15 (the return address is put in R15
by the procedure call sequence). My first goal is to compute the frame
register number! Not the contents of the frame register, but the register
number itself, because the RT calling convention lets you change frame
pointers from procedure to procedure! So, I scan for the trace table, based
on the PC, and obtain a structure that gives the frame register number (for
both of our C compilers, this is R13, but it doesn't have to be), the number
of arguments to the procedure, the space used by the locals and the number of
registers saved by the procedure prolog. This enables me to take the frame
pointer, compute the offset of the saved registers off of this frame pointer
and essentially restore the registers to the state they were at the time this
procedure was called. R15 now contains *its* callers PC, and I can redo this
procedure again to back up another frame.
In essence, in order to compute the preceding frame's address, I need more
than just the current frame's address. I need the full machine state at the
time of the call, including all of the registers since I don't know which one
will even turn out to be the frame pointer for the preceding procedure.
This is why I put in the frame caching code. Note that even were I to assume
that the frame pointer is always in R13 (and this is almost certainly a
mistake; IBM will surely eventually come up with a compiler where the frame
pointer is NOT r13), I still either need r15 or the PC (depending upon which
frame we're dealing with) in order to compute the preceding frame address.
As for the _foo v.s. _.foo issue, there are two problems. First, we can not
simply ignore _foo symbols, since an _foo symbol is only "junk" if there is
(possibly later) an _.foo symbol. We might be able to have the processing
for the "_.foo" change the value in the symbol table placed under the name
_foo. I do not know if this will work, since I do not know what processing
is done when a symbol is first encountered, and how much can be done a second
time. The second problem is that sometimes we need to see what is in the
variable named _foo, and we can't if it actually refers to _.foo. I
personally might be willing to live with this loss of functionality, but
other people probably would not.
As for initialize.h, we simply have no guarantees that IBM won't again change
the junk they stick in front of procedures in the text segment. Already,
depending upon which compiler (and we use both), pcc puts a funny string (and
maybe an integer, too) in front of every procedure, while the metaware hc
compiler puts a funny string in front of the first procedure in a file, but
nothing in front of the others. IBM has made it clear to us that they feel
free to change this at any time, so I feel quite strongly that it would be a
mistake to assume that they've finished playing around with junk at the start
of the text. BTW, for all I know, some of these magic text strings disappear
when you compile with -O. They certainly *should*.
Mike


View File

@ -1,147 +0,0 @@
X-Trace: MS Version 3.24 on ibm032 host dublin.itc.cmu.edu, by zs01 (623).
Date: Mon, 25 May 87 10:30:10 edt
From: zs01#@andrew.cmu.edu (Zalman Stern)
To: rms@PREP.AI.MIT.EDU (Richard M. Stallman)
Subject: Re: RT diffs for gdb version 2.1
Cc: kazar#@andrew.cmu.edu (Mike Kazar), zs01#@andrew.cmu.edu (Zalman Stern)
In-Reply-To: <8705250107.AA13256@prep.ai.mit.edu>
Richard,
First I will cover the easy questions.
Either of our fixes to environ.c (i.e. with respect to version 1.9 which was
broken) will work. As I understand it, the intent of init_environ is to fill
in the environment and leave a little extra space for later additions. I do
not understand why you would want to only leave the extra space when the
original size was within 10 elements of the final size.
add_com returning something is probably left over from a fix I put in which
is superceeded by the "user" class to distinguish command lists from function
pointers. I should have removed it.
We use csh instead of sh because I got tired of putting up with sh's crapping
out on large environments.
The change to inferior_args involves putting an explicit initializer of NULL
on it, and testing it for NULL before freeing it. I guess most
implementations of free ignore NULL pointers. The one we have on our Sun-2's
does not.
I can't remember why the alloca's were moved out of the variable
initializations. It may have been to avoid a compiler problem. In any event,
ignoring this modification shouldn't hurt.
Now for the hard ones...
The RT is a very different architecture from either a Sun or a VAX. It does
not use a self-describing stack frame and it does not use the same
conventions for symbols within object modules. There are also certain
subtleties to the way it lays out its address space that cause problems. Many
people at the ITC, including myself, are very impressed with the quality of
the port Mike did in spite of these obstacles. You may feel that these
problems are not worth effort. I have attempted to describe the differences
involved with the RT in case you choose to address them. If not, we are still
quite happy with the debugger we have and thank you for providing us with the
code...
Both the 68k family and the VAX have a frame pointer and a stack pointer.
Using these to values and the information on the stack, one can do a complete
stack trace. The RT on the other hand has only a stack pointer and a very
loose concept of a frame pointer. The stack pointer will point just below a
section of the stack dedicated to the maximum number of outgoing parameters
minus 4 (the first 4 are in registers). The frame pointer will point
somewhere in the stack where the compiler has deemed it optimal for
addressing locals and parameters. There are variable length fields in the
stack frame, such as the register save areas. In all, the thing looks like
so:
Higher Address
-----------------
a) Incoming args 5 through N <---- Previous sp was here
(part of previous function's stack frame)
b) Four words to save register passed arguments.
c) Four words of linkage area (reserved).
d) 1 word static link.
e) 1 - 16 words of register save area.
(Variable length, return address is at the top of this since it was in
r15)
f) 0 -8 words of floating point reg. save area. (Variable length)
g) Local variables (variable length)
h) Outgoing arguments, words 5 - N <---- Current sp points to bottom of this.
Lower Address
----------------
These and the stack contents are not enough to get back to the previous stack
frame because you do not know how far back it is to the register save area.
The code works because each function has been compiled to know how to pop its
stack frame (i.e. it has embedded constants). In order to facilitate
debugging, there is a trace table at the end of each function containing all
the necessary information. (Namely the offset from the frame pointer to the
top of the stack frame b in the above diagram) The trace table is located by
starting at the beginning of the function and looking for the illegal
instruction sequence 0xdf07df. Since the RT does not have 32bit constants in
the instruction stream, this actually works. In general, the iar and the
stack pointer are needed to do frame manipulations. The cache is necessary
because finding the trace table is very expensive. In short, the machinery
present in gdb was not up to handling this system, so we added what we
thought would work. It is interesting to note that similar calling
conventions are used on other RISC machines, notably the MIPS R2000. If you
wish to take advantage of these high performance machines, you will have to
do something like what we have done.
The POP_DUMMY_FRAME problem is related to this. The RT stores return address
in r15. We can not use this location to store the current iar since we must
store r15 for later restoration. This rules out using the same function for
popping both kinds of frames. There is also some hassle involved in getting
the stack and frame pointers correct, but I think this might be fixed by
generating an appropriate trace back table for the dummy function.
The other problem we faced is the non-standard use of symbols within object
modules. The RT defines two symbols for a function foo. There is "_.foo"
which corresponds to the actual code in the text segment (just like "_foo" on
a Sun or VAX), and "_foo" which points to the data area for the function in
the data segment. The first word of the data area contains a pointer to the
code. A function pointer (i.e. int (*foo)()) points to the data area (_foo),
not the code (_.foo). This is what the TYPE_CODE_PTR modification in valops.c
is for. Since both of these symbols are used for certain things, we cannot
simply remove the dots. This is a bogus IBM feature and we do not like it any
better than you do. We have to live with it if we want a working debugger.
The "fix" to find_pc_misc function handles a special case on the RT where
certain functions are in the high end of the address space. The RT uses the
top 4 bits of an address as a segment number. The text segment is seg. 0, the
data segment is seg. 1, and the kernel is mapped into seg. 14. Certain kernel
functions (i.e. floating point functions) are directly callable by user code
and so occur in the misc_function_vector. I realize this is bogus.
The initialization code will not run because both the RT compilers (pcc and
hc) output ascii data in the text section preceding the first function. Pcc
outputs the name of each function before the function. Hc outputs the name of
the source file at the beginning of the object module. Coding around this may
be possible, but what is the point? I see no reason for this hackery. I have
had problems getting it to work not only on the RT, but on the Sun-3. It is
guaranteed to be a portability headache on many other machines as well. If
you intend for gdb to only work when compiled with gcc, I suppose you may be
able to use this method.
I strongly agree with your statements that cleaner solutions are better in
every way. Unfortunately, we did not write gdb, nor is the system we are
working with particularly supportive of symbolic debugging. We were faced
with the task of both figuring out gdb, and hacking our way around a
contorted system (featuring among other things, a plethora of compiler bugs).
The fact that our version of gdb is the only working symbolic debugger on the
IBM RT (despite much effort by IBM) is proof that we have done something
right. I am willing to discuss what would make this port better. However, it
is not our intent to maintain or rewrite gdb. We merely wish to use it, and
if not a terrible hassle, let other people use it too. Mike and I would
prefer a copyright assignment. I would appreciate it if you would send me
info on what we need to do.
-Z-

File diff suppressed because it is too large Load Diff

View File

@ -1,84 +0,0 @@
BABYL OPTIONS:
Version: 5
Labels:
Note: This is the header of an rmail file.
Note: If you are seeing it in rmail,
Note: it means the file has no messages in it.

1,,
Received: by PREP.AI.MIT.EDU; Mon, 25 May 87 04:03:20 EDT
Message-Id: <8705250803.AA14993@prep.ai.mit.edu>
Received: by po2.andrew.cmu.edu (5.54/3.15) id <AA00199> for rms@prep.ai.mit.edu; Mon, 25 May 87 04:02:41 EDT
Received: via switchmail; Mon, 25 May 87 04:02:29 edt
Received: FROM z.itc.cmu.edu VIA qmail
ID </cmu/common/mailqs/q004/QF.z.itc.cmu.edu.20b7fa53.6bb39>;
Mon, 25 May 87 04:01:27 edt
Received: FROM z.itc.cmu.edu VIA qmail
ID </cmu/itc/zs01/.Outgoing/QF.z.itc.cmu.edu.20b7fa49.a49502>;
Mon, 25 May 87 04:01:15 edt
From: zs01#@andrew.cmu.edu (Zalman Stern)
Date: Mon, 25 May 87 04:01:13 edt
To: rms@prep.ai.mit.edu
Subject: Small diff to yesterdays gdb diffs.
*** EOOH ***
From: zs01#@andrew.cmu.edu (Zalman Stern)
Date: Mon, 25 May 87 04:01:13 edt
To: rms@prep.ai.mit.edu
Subject: Small diff to yesterdays gdb diffs.
Richard,
Here is another minor diff to the diassembler to get certain conditional
branches instructions correct...
Also, I noticed that gcc.tar.Z is out of date with respect to gcc.tar .
When I go to get these files, should I go ahead and replace the compressed
version with a newer one or should I leave it alone? Likewise, should I try and
make a split version on prep?
-Z-
*** ibm032-pinsn.c.old Mon May 25 03:31:04 1987
--- ibm032-pinsn.c Mon May 25 03:47:12 1987
***************
*** 101,112 ****
}
}
else { /* Conditional branches are hacked. */
! switch (type & 0x0f) {
int displacement;
case ibm032_JI:
! fprintf(stream, ibm032_opcodes[opcodeIndex].mnemonic, mapCondition(type & ibm032_negative, buffer[0] & LOW4));
putc('\t', stream);
print_address((buffer[1] << 1) + memaddr, stream);
return 2;
--- 101,112 ----
}
}
else { /* Conditional branches are hacked. */
! switch (type & LOW4) {
int displacement;
case ibm032_JI:
! fprintf(stream, ibm032_opcodes[opcodeIndex].mnemonic, mapCondition(type & ibm032_negative, (buffer[0] & LOW3) + 8));
putc('\t', stream);
print_address((buffer[1] << 1) + memaddr, stream);
return 2;
*** ibm032-opcode.h.old Mon May 25 03:33:19 1987
--- ibm032-opcode.h Mon May 25 03:33:24 1987
***************
*** 11,16 ****
--- 11,17 ----
/* Various useful bit masks. */
#define ibm032_typeMask 0x0f /* Mask to get actual type info out of instruction type. */
+ #define LOW3 0x07
#define LOW4 0x0f
#define HIGH4 0xf0
#define LOW16 0x0000ffff


View File

@ -1,997 +0,0 @@
From beatty@unh.cs.cmu.edu Sat Jul 4 12:04:01 1987
Received: by PREP.AI.MIT.EDU; Sat, 4 Jul 87 12:03:37 EDT
Message-Id: <8707041603.AA08600@prep.ai.mit.edu>
To: phr@prep.ai.mit.edu (Paul Rubin)
Date: Sat, 4 Jul 87 12:03:01 EDT
From: Derek Beatty <beatty@unh.cs.cmu.edu>
Subject: Re: gdb and X (msg 1 of 3)
Status: R
This is part 1 of 3 parts. It consists of the cursor I used, and a message
I sent to Zalman Stern at Andrew regarding what I did, and why. The
code and context diffs will follow in other messages.
#define gdb_width 16
#define gdb_height 16
#define gdb_x_hot 7
#define gdb_y_hot 0
static short gdb_bits[] = {
0x0000, 0x0140, 0x0220, 0x0220,
0x23e2, 0x13e4, 0x09c8, 0x0ff8,
0x0220, 0x3ffe, 0x0630, 0x03e0,
0x0220, 0x1ffc, 0x2632, 0x01c0};
#define gdb_mask_width 16
#define gdb_mask_height 16
#define gdb_mask_x_hot 7
#define gdb_mask_y_hot 0
static short gdb_mask_bits[] = {
0x0360, 0x07f0, 0x07f0, 0x77f7,
0x7fff, 0x7fff, 0x1ffc, 0x1ffc,
0x7fff, 0x7fff, 0x7fff, 0x0ff8,
0x3ffe, 0x7fff, 0x7fff, 0x7fff};
>
> The X support I added is minimal; it was inspired by Suntools' dbxtool,
> together with the availability of the V10 implementation of the X V11
> toolkit specification. Design was guided by simplicity and the facilities
> of the toolkit. The debugger window provides a view into the code
> corresponding to the current stack frame, and several buttons for the
> breakpoint, print, step, next, continue, finish, up, and down commands.
> The standard gdb command interface remains available in the tty window from
> which gdb was started. The breakpoint and print buttons make use of the
> current selection, so you can do simple things like click at text in the
> source window, then click the "Go 'til" button to continue until that
> point.
>
> Such an interface is simple to program ( ~ 20 hours, about 700 lines),
> but it has some drawbacks. First, I didn't take the time to understand
> the longjmp's in gdb, and I'm not exactly happy with the idea of them
> jumping out of my callback procedures that were invoked by toolkit routines.
> There's one core dump bug (it shows up when gdb can't find a source
> file) that I haven't tracked down, and it may be related to this. Second,
> selection in the text window is not particularly graceful: double-clicking
> highlights one word of text, as the toolkit defines a word. It would
> be much more graceful were double-clicking to highlight a C identifier.
> Finally, and most seriously, most buttons operate by building textual
> command lines and passing them to gdb's execute_command function. This
> means that all selected expressions are evaluated and printed in the
> lexical scope corresponding to the current stack frame, although the
> selected text may be in a different lexical scope. This serious bug would
> require work to fix.
>
> I wrote the X support out of frustration at not having dbxtool available
> when I work on a vax. The hope of portability to V11 via the toolkit
> also helped motivate me to write V10 code at this late date. Finally,
> I'd never written any nontrivial code that ran on a windowing system
> (although that turns out still to be the case). Were I to make a more
> serious effort at this project, I would probably add a general "define-button"
> command akin to gdb's "define" command.
>
> Look in /usr/beatty/gnu/gdb on vlsi.cs.cmu.edu. All files I have modified
> are marked, and also have associated backups (.B extensions). Bennet
> Yee has a copy of the toolkit library; see /usr/bsy/Xtlib on f.gp.cs.cmu.edu.
>
> -- Derek
>
-- Derek Beatty
From beatty@unh.cs.cmu.edu Sat Jul 4 12:12:47 1987
Received: by PREP.AI.MIT.EDU; Sat, 4 Jul 87 12:09:20 EDT
Message-Id: <8707041609.AA08643@prep.ai.mit.edu>
To: phr@PREP.AI.MIT.EDU (Paul Rubin)
Date: Sat, 4 Jul 87 12:07:25 EDT
From: Derek Beatty <beatty@unh.cs.cmu.edu>
Subject: Re: gdb and X (msg 2 of 3)
In-Reply-To: Message from "Paul Rubin" of Jul 4, 87 at 1:22 am
Status: R
The following is "tool.c". I hereby grant permission to do anything you
like with it.
-- Derek Beatty
[nosave]
/*
* gdb tool for X V10R4 (using V11-compatible toolkit).
* Derek Beatty 30 June 87.
*/
#include <X/Xlib.h>
#include <X/Xt/Xtlib.h>
#include <stdio.h>
#include "defs.h"
#include "symtab.h"
#include "gdb.cursor"
#include "gdb_mask.cursor"
/* forward refs */
static Window createFileText();
/*
* Windows manipulated by this package.
*/
static Window
icon,
frame,
srcLabelStrip,
srcText,
ctlPanel,
execLabelStrip;
static Cursor curse;
/*
* Source text display.
*/
static struct symtab *displayedSymtab= 0;
extern struct symtab *current_source_symtab;
extern int current_source_line;
toolDisplaySource()
{
char *fullName;
static Arg labelArgs[1];
int linenumbers_changed= 0;
static int newWidget= 1;
struct symtab_and_line get_selected_frame_sal();
struct symtab_and_line sal;
/* we could be called before we are initialized */
if (!frame) return;
sal= get_selected_frame_sal();
/* strictly this is wrong, but better than a blank display */
if (sal.symtab==NULL) {
sal.symtab= current_source_symtab;
/* current_source_line may be off by a small number like 4 */
sal.line= current_source_line;
}
/*
* Switch to a new file if necessary.
*/
if (sal.symtab)
linenumbers_changed= get_filename_and_charpos(sal.symtab,
sal.line,
&fullName);
if (!fullName) sal.symtab= NULL;
/* if the display may be wrong, destroy it */
if (linenumbers_changed || displayedSymtab != sal.symtab) {
XtVPanedWindowDeletePane( srcText);
XtSendDestroyNotify( srcText);
XDestroyWindow( srcText);
srcText= 0;
}
/* if there's no display, create one */
if (!srcText) {
newWidget= 1;
/* if there's no valid display, create a dummy display */
if (!sal.symtab ) {
displayedSymtab= NULL;
srcText= createFileText(frame, "/dev/null");
XtVPanedWindowAddPane(frame, srcText, 1, 20, 1000, 1);
/* create /dev/null text widget */
XtSetArg(labelArgs[0], XtNlabel, "No source displayed.");
XtLabelSetValues(srcLabelStrip, labelArgs, XtNumber(labelArgs));
} else {
displayedSymtab= sal.symtab;
srcText= createFileText(frame, fullName);
XtVPanedWindowAddPane(frame, srcText, 1, 20, 1000, 1);
XtSetArg(labelArgs[0], XtNlabel, fullName);
XtLabelSetValues(srcLabelStrip, labelArgs, XtNumber(labelArgs));
/* free filename (maybe: check gdb code!) */
}
}
/*
* Update display and cursor positions as necessary.
* Cursor should be placed on line sal.line.
*/
{
static int prevTop= 0, highWaterMark= 0;
int currentTop;
Arg textArgs[1];
/* get positions of start of display, and caret */
XtSetArg(textArgs[0], XtNdisplayPosition, NULL);
XtTextGetValues(srcText, textArgs, XtNumber(textArgs));
currentTop= cvtCharToLine(displayedSymtab,
(int) textArgs[0].value);
highWaterMark += currentTop - prevTop;
if ( sal.line < currentTop
|| sal.line > highWaterMark
|| newWidget) {
/* warp the display */
newWidget= 0;
/* yes, these magic numbers are ugly, but I don't know how
* to get the height of a text widget in a V11-portable way
*/
currentTop= (sal.line > 15) ? sal.line - 15 : 0;
highWaterMark= currentTop + 35;
XtSetArg(textArgs[0], XtNdisplayPosition,
cvtLineToChar(displayedSymtab, currentTop));
XtTextSetValues(srcText, textArgs, XtNumber(textArgs));
}
XtSetArg(textArgs[0], XtNinsertPosition,
cvtLineToChar(displayedSymtab, sal.line));
XtTextSetValues(srcText, textArgs, XtNumber(textArgs));
prevTop= currentTop;
}
}
/* return the character position of a line */
int
cvtLineToChar( s, line)
struct symtab *s;
int line;
{
if (!s) return 0;
if (!s->line_charpos) return 0;
if (line < 0) line= 0;
if (line > s->nlines) line= s->nlines;
return *(s->line_charpos + line-1);
}
/* return the line position of a character */
int
cvtCharToLine( s, chr)
register struct symtab *s;
register int chr;
{
register int lineNumber= 0;
register int *lnp;
if (!s) return 0;
lnp= s->line_charpos;
/* files are usually short, so sequential search is Ok */
while ( lineNumber < s->nlines && *lnp <= chr) {
lineNumber++;
lnp++;
}
if (lineNumber >= s->nlines)
lineNumber= s->nlines;
return lineNumber;
}
/*
* title bar at bottom
*/
static char *execFileName;
toolSetExecFile(s)
char *s;
{
execFileName= s;
if (execLabelStrip) {
static Arg labelArgs[1];
XtSetArg(labelArgs[0], XtNlabel, execFileName);
XtLabelSetValues(execLabelStrip, labelArgs, XtNumber(labelArgs));
}
}
/*
* Command line into which command are placed for execution.
* There's some ugly interaction between this and readline in main.c.
*/
extern char *line;
extern int linesize;
/*
* Do any necessary prompting, etc.
*/
static char *gdbPrompt;
static void
printPrompt()
{
if (gdbPrompt) {
printf("%s", gdbPrompt);
fflush(stdout);
}
}
/*
* Callback procedures for control panel.
*/
/* used by "print" and "print*" buttons */
static void printButnProc_1( starflag)
int starflag;
{
int selnLen;
char *seln;
char *cmd= starflag ? "print * " : "print ";
register int cmdlen= strlen(cmd);
seln= XFetchBytes(&selnLen);
if (selnLen) {
if (selnLen+cmdlen >= linesize-1) {
linesize= (selnLen+cmdlen > linesize*2-1) ? selnLen+cmdlen+1 : linesize*2;
line= (char *) xrealloc(line, linesize);
}
strcpy(line, cmd);
strncpy(line+cmdlen, seln, selnLen);
*(line+cmdlen+selnLen)= '\0';
execute_command(line, 0);
free(seln);
}
printPrompt();
}
static void printButnProc()
{
printButnProc_1( 0);
}
static void printStarButnProc()
{
printButnProc_1( 1);
}
static void nextButnProc()
{
strcpy(line, "next");
execute_command(line, 0);
toolDisplaySource();
printPrompt();
}
static void stepButnProc()
{
strcpy(line, "step");
execute_command(line, 0);
toolDisplaySource();
printPrompt();
}
static void contButnProc()
{
strcpy(line, "cont");
execute_command(line, 0);
toolDisplaySource();
printPrompt();
}
static void finButnProc()
{
strcpy(line, "finish");
execute_command(line, 0);
toolDisplaySource();
printPrompt();
}
/* used by "stop at" and "go till" buttons */
static void stopAtButnProc_1( gotillFlag)
int gotillFlag;
{
XtTextPosition start, finish;
static int lineNumber;
XtTextGetSelectionPos(srcText, &start, &finish);
if (!displayedSymtab)
printf("No source file displayed.\n");
else {
break_command_for_tool( displayedSymtab,
cvtCharToLine(displayedSymtab, start),
gotillFlag);
if (gotillFlag) {
strcpy(line, "cont");
execute_command(line, 0);
toolDisplaySource();
}
}
printPrompt();
}
static void stopAtButnProc()
{
stopAtButnProc_1( 0);
}
static void untilButnProc()
{
stopAtButnProc_1( 1);
}
/* decide if a character is trash */
static int
garbage(c)
char c;
{
if ('a' <= c && c <= 'z') return 0;
if ('A' <= c && c <= 'Z') return 0;
if ('0' <= c && c <= '9') return 0;
if (c == '_') return 0;
return 1;
}
static void stopInButnProc()
{
static int selnLen;
static char *seln;
char *sp, *selnp;
seln= XFetchBytes(&selnLen);
if (selnLen) {
if (selnLen+6 >= linesize-1) {
linesize= (selnLen+6 > linesize*2-1) ? selnLen+7 : linesize*2;
line= (char *) xrealloc(line, linesize);
}
strcpy(line, "break ");
/* copy selection but not garbage */
selnp= seln;
sp= line+strlen(line);
while (garbage(*selnp) && selnLen) selnp++, selnLen--;
while (!garbage(*selnp) && selnLen) {
*sp++= *selnp++;
selnLen--;
}
*sp= '\0';
execute_command(line, 0);
free(seln);
}
printPrompt();
}
static void deIconifyButnProc()
{
XUnmapWindow(icon);
XMapWindow(frame);
}
static void iconifyButnProc()
{
static Arg iconArgs[1];
XtSetArg(iconArgs[0], XtNlabel, gdbPrompt);
XtCommandSetValues(icon, iconArgs, XtNumber(iconArgs));
XUnmapWindow(frame);
XMapWindow(icon);
}
static void upButnProc()
{
strcpy(line, "up");
execute_command(line, 0);
toolDisplaySource();
printPrompt();
}
static void downButnProc()
{
strcpy(line, "down");
execute_command(line, 0);
toolDisplaySource();
printPrompt();
}
#define addbutton(w) XtSetArg(buttons[buttoncount], XtNwindow, w); \
buttoncount++;
static Arg buttons[20];
static int buttoncount= 0;
/*
* Create control panel buttons.
*/
static createButtons(parent)
Window parent;
{
static Window button;
static Arg commandArgs[2];
#define crButn(label,fn) \
XtSetArg(commandArgs[0], XtNlabel, label);\
XtSetArg(commandArgs[1], XtNfunction, fn);\
button= XtCommandCreate(parent, commandArgs, XtNumber(commandArgs));\
addbutton(button);
crButn("Brk At", stopAtButnProc);
crButn("Brk In", stopInButnProc);
crButn("Go 'til", untilButnProc);
crButn("Print", printButnProc);
crButn("Print*", printStarButnProc);
crButn("Next", nextButnProc);
crButn("Step", stepButnProc);
crButn("Cont", contButnProc);
crButn("Finish", finButnProc);
crButn("Up", upButnProc);
crButn("Down", downButnProc);
crButn("Iconify", iconifyButnProc);
#undef crButn
}
static Window createLabel(parent, name, label)
Window parent;
char *name, *label;
{
static Arg labelArgs[2];
XtSetArg(labelArgs[0], XtNname, name);
XtSetArg(labelArgs[1], XtNlabel, label);
return XtLabelCreate(frame, labelArgs, XtNumber(labelArgs));
}
static Window createFileText( parent, filename)
Window parent;
char *filename;
{
static Arg fileArgs[2];
XtSetArg(fileArgs[0], XtNfile, filename);
XtSetArg(fileArgs[1], XtNtextOptions, scrollVertical);
return XtTextDiskCreate(parent, fileArgs, XtNumber(fileArgs));
}
/***************** Externally referenced routine **************/
int createTool()
{
static Arg frameArgs[]= {
{XtNwidth, (XtArgVal) 600},
{XtNheight, (XtArgVal) 700},
};
ResourceDataBase db;
FILE *rdbFile;
/*
* init and database stuff... this is wrong but what the heck
*/
if (XOpenDisplay("") == NULL)
return 0;
printf("Initializing tool..."); fflush(stdout);
XtInitialize();
/* should be checking .Xdefaults in $HOME */
if ((rdbFile= fopen(".Xresources", "r")) != NULL) {
XtGetDataBase(rdbFile, &db);
XtSetCurrentDataBase(db);
fclose(rdbFile);
}
/*
* create the frame
*/
frame= XtVPanedWindowCreate(RootWindow, frameArgs, XtNumber(frameArgs));
/* create source label strip and add to frame */
srcLabelStrip= createLabel(frame, "Source File", "No source file yet.");
XtVPanedWindowAddPane(frame, srcLabelStrip, 0, 15, 15, 0);
/* create text widget and add to frame */
srcText= createFileText(frame, "/dev/null");
XtVPanedWindowAddPane(frame, srcText, 1, 20, 1000, 1);
/* create button box */
ctlPanel= XtButtonBoxCreate(frame, NULL, 0);
createButtons( ctlPanel);
XtButtonBoxAddButton(ctlPanel, buttons, buttoncount);
XtVPanedWindowAddPane(frame, ctlPanel, 2, 30, 30, 0);
/* create exec label strip and add */
execLabelStrip= createLabel(frame, "Executable",
execFileName ? execFileName : "No executable specified.");
XtVPanedWindowAddPane(frame, execLabelStrip, 3, 15, 15, 0);
/* create icon */
{
static Arg iconArgs[2];
XtSetArg(iconArgs[0], XtNlabel, "(gdb)");
XtSetArg(iconArgs[1], XtNfunction, deIconifyButnProc);
icon= XtCommandCreate(RootWindow, iconArgs, XtNumber(iconArgs));
XMoveWindow(icon, 100, 100); /* HACK */
XSetIconWindow(frame, icon);
}
/* throw it onto the display */
curse= XCreateCursor(gdb_width, gdb_height, gdb_bits, gdb_mask_bits,
gdb_x_hot, gdb_y_hot,
BlackPixel, WhitePixel, GXcopy);
XDefineCursor(frame, curse);
XDefineCursor(icon, curse);
XMapWindow(frame);
XMapSubwindows(frame);
XFlush();
printf("done\n");
return 1;
}
/**************** Externally referenced routine. ***********/
/* toolDispatcher -- dispatch events until data is available on fp */
toolDispatcher(fp, prompt)
FILE *fp;
char *prompt;
{
int inMask= 1 << fileno(fp);
int xMask= 1 << dpyno();
int rfds= 0;
int nfds;
XEvent ev;
int pend;
gdbPrompt= prompt;
while (! (rfds & inMask)) {
pend= XPending();
if (!pend) {
rfds= inMask | xMask;
/* this isn't right for 4.3 but it works 'cuz of 4.2 compatibility */
nfds= select( 32, &rfds, 0, 0, (struct timeval *) 0);
}
if (pend || rfds & xMask) {
XNextEvent(&ev);
XtDispatchEvent(&ev);
}
}
}
From beatty@unh.cs.cmu.edu Sat Jul 4 12:17:44 1987
Received: by PREP.AI.MIT.EDU; Sat, 4 Jul 87 12:15:18 EDT
Message-Id: <8707041615.AA08691@prep.ai.mit.edu>
To: phr@PREP.AI.MIT.EDU (Paul Rubin)
Date: Sat, 4 Jul 87 12:14:08 EDT
From: Derek Beatty <beatty@unh.cs.cmu.edu>
Subject: Re: gdb and X (msg 3 of 3)
In-Reply-To: Message from "Paul Rubin" of Jul 4, 87 at 1:22 am
Status: R
Context diffs follow. The original files are from GDB 2.1 (emacs distribution
18.40).
-- Derek Beatty
[nosave]
*** /usr/misc/.gdb/src/core.c Fri Mar 27 12:20:14 1987
--- core.c Sat Jul 4 11:12:16 1987
***************
*** 1,3
/* Work with core dump and executable files, for GDB.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
--- 1,5 -----
+ /* modified by Beatty 1 Jul 87 for gdb tool. */
+
/* Work with core dump and executable files, for GDB.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
***************
*** 257,262
}
else if (from_tty)
printf ("No exec file now.\n");
}
/* If we have both a core file and an exec file,
--- 259,267 -----
}
else if (from_tty)
printf ("No exec file now.\n");
+ #ifdef TOOL
+ toolSetExecFile( filename ? filename : "No executable specified.\n");
+ #endif /* def TOOL */
}
/* If we have both a core file and an exec file,
*** /usr/misc/.gdb/src/breakpoint.c Fri Mar 27 12:20:11 1987
--- breakpoint.c Wed Jul 1 11:27:31 1987
***************
*** 1,3
/* Everything about breakpoints, for GDB.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
--- 1,5 -----
+ /* modified by Beatty 1 Jul 87 for gdbtool */
+
/* Everything about breakpoints, for GDB.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
***************
*** 513,518
break;
}
}
/* Set a breakpoint according to ARG (function, linenum or *address)
and make it temporary if TEMPFLAG is nonzero. */
--- 515,571 -----
break;
}
}
+
+ #ifdef TOOL
+ /* set a breakpoint from a symtab and line */
+ void break_command_for_tool( s, line, tempflag)
+ struct symtab *s;
+ int line;
+ int tempflag;
+ {
+ register struct breakpoint *b;
+ struct symtab_and_line sal;
+
+ sal.symtab= s;
+ sal.line= line;
+ sal.pc= find_line_pc( sal.symtab, sal.line);
+ if (sal.pc==0) {
+ error("No line %d in file \"%s\".\n", sal.line, sal.symtab->filename);
+ } else {
+ b= set_raw_breakpoint( sal);
+ b->number= ++breakpoint_count;
+ b->cond= 0;
+ if (tempflag)
+ b->enable= temporary;
+
+ printf ("Breakpoint %d at 0x%x", b->number, b->address);
+ if (b->symtab)
+ printf (": file %s, line %d.", b->symtab->filename, b->line_number);
+ printf ("\n");
+
+ {
+ int others = 0;
+ ALL_BREAKPOINTS (b)
+ if (b->address == sal.pc && b->number != breakpoint_count)
+ others++;
+ if (others > 0)
+ {
+ printf ("Note: breakpoint%s ", (others > 1) ? "s" : "");
+ ALL_BREAKPOINTS (b)
+ if (b->address == sal.pc && b->number != breakpoint_count)
+ {
+ others--;
+ printf ("%d%s%s ",
+ b->number,
+ (b->enable == disabled) ? " (disabled)" : "",
+ (others > 1) ? "," : ((others == 1) ? " and" : ""));
+ }
+ printf (" also set at pc 0x%x\n", sal.pc);
+ }
+ }
+ }
+ }
+ #endif /* def TOOL */
/* Set a breakpoint according to ARG (function, linenum or *address)
and make it temporary if TEMPFLAG is nonzero. */
*** /usr/misc/.gdb/src/main.c Fri Mar 27 12:20:45 1987
--- main.c Sat Jul 4 11:13:32 1987
***************
*** 1,3
/* Top level for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
--- 1,5 -----
+ /* modified by Beatty 30 june 87 for gdb tool */
+
/* Top level for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
***************
*** 42,47
FILE *instream;
void free_command_lines ();
char *read_line ();
static void initialize_main ();
--- 44,54 -----
FILE *instream;
+ #ifdef TOOL
+ /* flag indicating whether we are running in a window system */
+ int isaTool= 0;
+ #endif /* def TOOL */
+
void free_command_lines ();
char *read_line ();
static void initialize_main ();
***************
*** 214,219
while (1)
{
if (!setjmp (to_top_level))
command_loop ();
clearerr (stdin); /* Don't get hung if C-d is typed. */
--- 221,232 -----
while (1)
{
+
+ #ifdef TOOL
+ if (!isaTool)
+ isaTool= createTool();
+ #endif /* def TOOL */
+
if (!setjmp (to_top_level))
command_loop ();
clearerr (stdin); /* Don't get hung if C-d is typed. */
***************
*** 270,275
printf ("%s", prompt);
fflush (stdout);
quit_flag = 0;
execute_command (read_line (instream == stdin), instream == stdin);
/* Do any commands attached to breakpoint we stopped at. */
--- 283,294 -----
printf ("%s", prompt);
fflush (stdout);
+ #ifdef TOOL
+ toolDisplaySource();
+ if (isaTool) toolDispatcher(instream,
+ instream==stdin ? prompt : NULL);
+ #endif /* def TOOL */
+
quit_flag = 0;
execute_command (read_line (instream == stdin), instream == stdin);
/* Do any commands attached to breakpoint we stopped at. */
***************
*** 320,325
while (1)
{
c = fgetc (instream);
if (c == -1 || c == '\n')
break;
--- 339,345 -----
while (1)
{
+
c = fgetc (instream);
if (c == -1 || c == '\n')
break;
***************
*** 765,770
GDB is free software and you are welcome to distribute copies of it\n\
under certain conditions; type \"info copying\" to see the conditions.\n",
version);
}
static void
--- 785,793 -----
GDB is free software and you are welcome to distribute copies of it\n\
under certain conditions; type \"info copying\" to see the conditions.\n",
version);
+ #ifdef TOOL
+ printf( "(CMU X support is available in this version.)\n");
+ #endif
}
static void
*** /usr/misc/.gdb/src/source.c Fri Mar 27 12:20:50 1987
--- source.c Wed Jul 1 17:56:58 1987
***************
*** 1,3
/* List lines of source files for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
--- 1,5 -----
+ /* modified 1 July 87 by Beatty for gdbtool */
+
/* List lines of source files for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
***************
*** 295,300
s->nlines = nlines;
s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int));
}
/* Print source lines from the file of symtab S,
starting with line number LINE and stopping before line number STOPLINE. */
--- 297,328 -----
s->nlines = nlines;
s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int));
}
+
+ #ifdef TOOL
+ /* Get full pathname and line number positions for a symtab
+ * return nonzero if line numbers may have changed
+ * set full pathname to NULL if no file found
+ */
+ int
+ get_filename_and_charpos(s, line, fullname)
+ struct symtab *s;
+ int line;
+ char **fullname;
+ {
+ register int desc, linenums_changed= 0;
+
+ desc= openp(source_path, 0, s->filename, O_RDONLY, 0, fullname);
+ if (desc < 0) {
+ *fullname= NULL;
+ return 0;
+ }
+ if (s->line_charpos==0) linenums_changed= 1;
+ if (linenums_changed) find_source_lines(s, desc);
+ close(desc);
+ return linenums_changed;
+ }
+ #endif /* def TOOL */
+
/* Print source lines from the file of symtab S,
starting with line number LINE and stopping before line number STOPLINE. */
*** /usr/misc/.gdb/src/stack.c Fri Mar 27 12:20:51 1987
--- stack.c Wed Jul 1 17:27:34 1987
***************
*** 1,3
/* Print and select stack frames for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
--- 1,5 -----
+ /* modified by Beatty 1 Jul 87 for gdbtool */
+
/* Print and select stack frames for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
***************
*** 42,47
static void select_calling_frame ();
void print_frame_info ();
/* Print a stack frame briefly. FRAME should be the frame address
and LEVEL should be its level in the stack (or -1 for level not defined).
--- 44,62 -----
static void select_calling_frame ();
void print_frame_info ();
+
+ #ifdef TOOL
+ /* get symtab and line of selected frame, for tool display */
+ struct symtab_and_line
+ get_selected_frame_sal()
+ {
+ struct frame_info fi;
+
+ fi= get_frame_info( selected_frame);
+ return find_pc_line(fi.pc, fi.next_frame);
+ }
+
+ #endif /* TOOL */
/* Print a stack frame briefly. FRAME should be the frame address
and LEVEL should be its level in the stack (or -1 for level not defined).
End of context diffs. The presence of this line verifies that this message
has not been truncated.

View File

@ -1,138 +0,0 @@
GDB GENERAL PUBLIC LICENSE
(Clarified 20 March 1987)
Copyright (C) 1986 Richard M. Stallman
Everyone is permitted to copy and distribute verbatim copies
of this license, but changing it is not allowed.
The license agreements of most software companies keep you at the
mercy of those companies. By contrast, our general public license is
intended to give everyone the right to share GDB. To make sure that
you get the rights we want you to have, we need to make restrictions
that forbid anyone to deny you these rights or to ask you to surrender
the rights. Hence this license agreement.
Specifically, we want to make sure that you have the right to give
away copies of GDB, that you receive source code or else can get it
if you want it, that you can change GDB or use pieces of it in new
free programs, and that you know you can do these things.
To make sure that everyone has such rights, we have to forbid you to
deprive anyone else of these rights. For example, if you distribute
copies of GDB, you must give the recipients all the rights that you
have. You must make sure that they, too, receive or can get the
source code. And you must tell them their rights.
Also, for our own protection, we must make certain that everyone
finds out that there is no warranty for GDB. If GDB is modified by
someone else and passed on, we want its recipients to know that what
they have is not what we distributed, so that any problems introduced
by others will not reflect on our reputation.
Therefore we (Richard Stallman and the Free Software Foundation,
Inc.) make the following terms which say what you must do to be
allowed to distribute or change GDB.
COPYING POLICIES
1. You may copy and distribute verbatim copies of GDB source code as
you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy a valid copyright notice "Copyright
(C) 1986 Free Software Foundation, Inc." (or with the year updated if
that is appropriate); keep intact the notices on all files that refer
to this License Agreement and to the absence of any warranty; and give
any other recipients of the GDB program a copy of this License
Agreement along with the program. You may charge a distribution fee
for the physical act of transferring a copy.
2. You may modify your copy or copies of GDB or any portion of it,
and copy and distribute such modifications under the terms of
Paragraph 1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating
that you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish,
that in whole or in part contains or is a derivative of GDB or any
part thereof, to be licensed at no charge to all third parties on
terms identical to those contained in this License Agreement
(except that you may choose to grant more extensive warranty
protection to third parties, at your option).
c) if the modified program serves as a debugger, cause it
when started running in the simplest and usual way, to print
an announcement including a valid copyright notice
"Copyright (C) 1986 Free Software Foundation, Inc." (or with
the year updated if appropriate), saying that there
is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of
this License Agreement.
d) You may charge a distribution fee for the physical act of
transferring a copy, and you may at your option offer warranty
protection in exchange for a fee.
3. You may copy and distribute GDB or any portion of it in
compiled, executable or object code form under the terms of Paragraphs
1 and 2 above provided that you do the following:
a) cause each such copy to be accompanied by the
corresponding machine-readable source code, which must
be distributed under the terms of Paragraphs 1 and 2 above; or,
b) cause each such copy to be accompanied by a
written offer, with no time limit, to give any third party
free (except for a nominal shipping charge) a machine readable
copy of the corresponding source code, to be distributed
under the terms of Paragraphs 1 and 2 above; or,
c) in the case of a recipient of GDB in compiled, executable
or object code form (without the corresponding source code) you
shall cause copies you distribute to be accompanied by a copy
of the written offer of source code which you received along
with the copy you received.
4. You may not copy, sublicense, distribute or transfer GDB
except as expressly provided under this License Agreement. Any attempt
otherwise to copy, sublicense, distribute or transfer GDB is void and
your rights to use the program under this License agreement shall be
automatically terminated. However, parties who have received computer
software programs from you with this License Agreement will not have
their licenses terminated so long as such parties remain in full compliance.
5. If you wish to incorporate parts of GDB into other free
programs whose distribution conditions are different, write to the Free
Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet
worked out a simple rule that can be stated here, but we will often permit
this. We will be guided by the two goals of preserving the free status of
all derivatives of our free software and of promoting the sharing and reuse
of software.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
NO WARRANTY
BECAUSE GDB IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO
WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE GDB "AS IS" WITHOUT
WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
PERFORMANCE OF GDB IS WITH YOU. SHOULD GDB PROVE DEFECTIVE, YOU
ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
WHO MAY MODIFY AND REDISTRIBUTE GDB AS PERMITTED ABOVE, BE LIABLE TO
YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER
SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GDB, EVEN
IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR
ANY CLAIM BY ANY OTHER PARTY.

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,20 @@
# -I. for "#include <obstack.h>"
CFLAGS = -g -I. -Dvfork=fork -DDEBUG
CFLAGS = -g -I.
# NOTE!!! -O may FAIL TO WORK! See initialize.h for some weird hacks.
CC = cc
BISON = bison
# define this to be "obstack.o" if you don't have the obstack library installed
# you must at the same time define OBSTACK1 as "obstack.o"
# so that the dependencies work right.
OBSTACK = obstack.o alloca.o -lPW
OBSTACK1 = obstack.o alloca.o
OBSTACK = obstack.o
OBSTACK1 = obstack.o
STARTOBS = main.o firstfile.o
OBS = blockframe.o breakpoint.o findvar.o stack.o source.o \
values.o eval.o valops.o valarith.o valprint.o printcmd.o \
symtab.o symmisc.o coffread.o dbxread.o infcmd.o infrun.o
symtab.o symmisc.o coffread.o dbxread.o infcmd.o infrun.o remote.o
TSOBS = core.o inflow.o
@ -25,20 +27,16 @@ TSSTART = /lib/crt0.o
NTSSTART = kdb-start.o
gdb : $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(OBSTACK1)
$(CC) -o gdb $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) -lg $(OBSTACK)
gdb+: $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(OBSTACK1)
$(CC) -o gdb+ $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) -lc -lg $(OBSTACK)
xgdb : $(STARTOBS) $(OBS) xgdb.o $(TSOBS) $(ENDOBS) $(OBSTACK1)
$(CC) -o xgdb $(STARTOBS) $(OBS) xgdb.o $(TSOBS) $(ENDOBS) \
xgdb+ : $(STARTOBS) $(OBS) xgdb.o $(TSOBS) $(ENDOBS) $(OBSTACK1)
$(CC) -o xgdb+ $(STARTOBS) $(OBS) xgdb.o $(TSOBS) $(ENDOBS) \
-lXtk11 -lXrm -lX11 -lg $(OBSTACK)
kdb : $(NTSSTART) $(STARTOBS) $(OBS) $(NTSOBS) $(ENDOBS) $(OBSTACK1)
ld -o kdb $(NTSSTART) $(STARTOBS) $(OBS) $(NTSOBS) $(ENDOBS) -lc -lg $(OBSTACK)
clean:
rm -f $(STARTOBS) $(OBS) $(TSOBS) $(OBSTACK1) $(NTSSTART) $(NTSOBS)
rm -f xgdb.o gdb xgdb kdb tags errs expread.tab.c
blockframe.o : blockframe.c defs.h initialize.h param.h symtab.h frame.h
breakpoint.o : breakpoint.c defs.h initialize.h param.h symtab.h frame.h
command.o : command.c command.h
@ -48,9 +46,8 @@ dbxread.o : dbxread.c defs.h initialize.h param.h symtab.h
environ.o : environ.c environ.h
expprint.o : expprint.c defs.h symtab.h expression.h
expread.tab.c : expread.y
@echo 'Expect 96 shift/reduce conflicts.'
yacc expread.y
mv y.tab.c expread.tab.c
@echo 'Expect 101 shift/reduce conflicts and 1 reduce/reduce conflict.'
$(BISON) -v expread.y
expread.o : expread.tab.c defs.h param.h symtab.h frame.h expression.h
$(CC) -c ${CFLAGS} expread.tab.c
mv expread.tab.o expread.o
@ -68,6 +65,7 @@ main.o : main.c defs.h command.h
pinsn.o : pinsn.c defs.h param.h symtab.h \
vax-opcode.h vax-pinsn.c m68k-opcode.h m68k-pinsn.c
printcmd.o : printcmd.c defs.h initialize.h param.h symtab.h value.h expression.h
remote.o : remote.c defs.h initialize.h param.h frame.h inferior.h
source.o : source.c defs.h initialize.h symtab.h
stack.o : stack.c defs.h initialize.h param.h symtab.h frame.h
standalone.o : standalone.c defs.h initialize.h param.h symtab.h frame.h inferior.h wait.h

View File

@ -1,160 +0,0 @@
head 1.4;
access ;
symbols RMS-has:1.2;
locks ; strict;
comment @# @;
1.4
date 88.06.08.23.14.28; author gnu; state Exp;
branches ;
next 1.3;
1.3
date 88.02.28.03.38.17; author gnu; state Exp;
branches ;
next 1.2;
1.2
date 88.01.26.05.14.43; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 88.01.26.05.14.07; author gnu; state Exp;
branches ;
next ;
desc
@Original from RMS's wheaties devl dirs
@
1.4
log
@Add -DEBUG
@
text
@# -I. for "#include <obstack.h>"
CFLAGS = -g -I. -Dvfork=fork -DDEBUG
# NOTE!!! -O may FAIL TO WORK! See initialize.h for some weird hacks.
# define this to be "obstack.o" if you don't have the obstack library installed
# you must at the same time define OBSTACK1 as "obstack.o"
# so that the dependencies work right.
OBSTACK = obstack.o alloca.o -lPW
OBSTACK1 = obstack.o alloca.o
STARTOBS = main.o firstfile.o
OBS = blockframe.o breakpoint.o findvar.o stack.o source.o \
values.o eval.o valops.o valarith.o valprint.o printcmd.o \
symtab.o symmisc.o coffread.o dbxread.o infcmd.o infrun.o
TSOBS = core.o inflow.o
NTSOBS = standalone.o
ENDOBS = lastfile.o command.o utils.o expread.o expprint.o pinsn.o \
environ.o version.o
TSSTART = /lib/crt0.o
NTSSTART = kdb-start.o
gdb : $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(OBSTACK1)
$(CC) -o gdb $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) -lg $(OBSTACK)
xgdb : $(STARTOBS) $(OBS) xgdb.o $(TSOBS) $(ENDOBS) $(OBSTACK1)
$(CC) -o xgdb $(STARTOBS) $(OBS) xgdb.o $(TSOBS) $(ENDOBS) \
-lXtk11 -lXrm -lX11 -lg $(OBSTACK)
kdb : $(NTSSTART) $(STARTOBS) $(OBS) $(NTSOBS) $(ENDOBS) $(OBSTACK1)
ld -o kdb $(NTSSTART) $(STARTOBS) $(OBS) $(NTSOBS) $(ENDOBS) -lc -lg $(OBSTACK)
clean:
rm -f $(STARTOBS) $(OBS) $(TSOBS) $(OBSTACK1) $(NTSSTART) $(NTSOBS)
rm -f xgdb.o gdb xgdb kdb tags errs expread.tab.c
blockframe.o : blockframe.c defs.h initialize.h param.h symtab.h frame.h
breakpoint.o : breakpoint.c defs.h initialize.h param.h symtab.h frame.h
command.o : command.c command.h
coffread.o : coffread.c defs.h initialize.h param.h symtab.h
core.o : core.c defs.h initialize.h param.h
dbxread.o : dbxread.c defs.h initialize.h param.h symtab.h
environ.o : environ.c environ.h
expprint.o : expprint.c defs.h symtab.h expression.h
expread.tab.c : expread.y
@@echo 'Expect 96 shift/reduce conflicts.'
yacc expread.y
mv y.tab.c expread.tab.c
expread.o : expread.tab.c defs.h param.h symtab.h frame.h expression.h
$(CC) -c ${CFLAGS} expread.tab.c
mv expread.tab.o expread.o
eval.o : eval.c defs.h initialize.h symtab.h value.h expression.h
findvar.o : findvar.c defs.h initialize.h param.h symtab.h frame.h value.h
firstfile.o : firstfile.c initialize.h
infcmd.o : infcmd.c defs.h initialize.h param.h symtab.h frame.h inferior.h environ.h value.h
inflow.o : inflow.c defs.h initialize.h param.h frame.h inferior.h
infrun.o : infrun.c defs.h initialize.h param.h symtab.h frame.h inferior.h wait.h
kdb-start.o : kdb-start.c defs.h param.h
lastfile.o : lastfile.c
main.o : main.c defs.h command.h
# pinsn.o depends on ALL the opcode printers
# since we don't know which one is really being used.
pinsn.o : pinsn.c defs.h param.h symtab.h \
vax-opcode.h vax-pinsn.c m68k-opcode.h m68k-pinsn.c
printcmd.o : printcmd.c defs.h initialize.h param.h symtab.h value.h expression.h
source.o : source.c defs.h initialize.h symtab.h
stack.o : stack.c defs.h initialize.h param.h symtab.h frame.h
standalone.o : standalone.c defs.h initialize.h param.h symtab.h frame.h inferior.h wait.h
symmisc.o : symmisc.c defs.h initialize.h symtab.h
symtab.o : symtab.c defs.h initialize.h param.h symtab.h
utils.o : utils.c defs.h
valarith.o : valarith.c defs.h initialize.h param.h symtab.h value.h expression.h
valops.o : valops.c defs.h initialize.h param.h symtab.h value.h
valprint.o : valprint.c defs.h initialize.h symtab.h value.h
values.o : values.c defs.h initialize.h param.h symtab.h value.h
version.o : version.c
xgdb.o : xgdb.c defs.h initialize.h param.h symtab.h frame.h
$(CC) -c $(CFLAGS) xgdb.c -o $@@
obstack.o : obstack.c
@
1.3
log
@Make clean
@
text
@d2 1
a2 1
CFLAGS = -g -I. -Dvfork=fork
@
1.2
log
@We don't have vfork or alloca, and regexp routines are in libPW.a for
no good reason.
@
text
@d38 4
@
1.1
log
@Initial revision
@
text
@d2 1
a2 1
CFLAGS = -g -I.
d8 2
a9 2
OBSTACK = obstack.o
OBSTACK1 = obstack.o
@

View File

@ -1,304 +0,0 @@
head 1.4;
access ;
symbols RMS-has:1.2;
locks ; strict;
comment @ * @;
1.4
date 88.06.08.23.13.40; author gnu; state Exp;
branches ;
next 1.3;
1.3
date 88.02.28.03.37.53; author gnu; state Exp;
branches ;
next 1.2;
1.2
date 88.01.26.05.02.32; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 88.01.26.00.38.04; author gnu; state Exp;
branches ;
next ;
desc
@Original from RMS's work dirs on Wheaties
@
1.4
log
@Half reasonable reading of coff files. Problem was that it assumed
that a .text would show up sometime, and it never did. We have to close
out each source file's symtab as we hit the next one.
@
text
@/* Read coff symbol tables and convert to internal format, for GDB.
Design and support routines derived from dbxread.c, and UMAX COFF
specific routines written 9/1/87 by David D. Johnson, Brown University.
Revised 11/27/87 ddj@@cs.brown.edu
Copyright (C) 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "defs.h"
#include "param.h"
#ifdef COFF_FORMAT
#include "initialize.h"
#include "symtab.h"
#include <a.out.h>
#include <stdio.h>
#include <obstack.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/file.h>
static void add_symbol_to_list ();
static void read_coff_symtab ();
static void patch_opaque_types ();
static struct type *decode_function_type ();
static struct type *decode_type ();
static struct type *decode_base_type ();
static struct type *read_enum_type ();
static struct type *read_struct_type ();
static void finish_block ();
static struct blockvector *make_blockvector ();
static struct symbol *process_coff_symbol ();
static int init_stringtab ();
static void free_stringtab ();
static char *getfilename ();
static char *getsymname ();
static int init_lineno ();
static void enter_linenos ();
START_FILE
/* Name of source file whose symbol data we are now processing.
This comes from a symbol named ".file". */
static char *last_source_file;
/* Core address of start and end of text of current source file.
This comes from a ".text" symbol where x_nlinno > 0. */
static CORE_ADDR cur_src_start_addr;
static CORE_ADDR cur_src_end_addr;
/* End of the text segment of the executable file,
as found in the symbol _etext. */
static CORE_ADDR end_of_text_addr;
/* The addresses of the symbol table stream and number of symbols
of the object file we are reading (as copied into core). */
static FILE *nlist_stream_global;
static int nlist_nsyms_global;
/* The file and text section headers of the symbol file */
static FILHDR file_hdr;
static SCNHDR text_hdr;
/* The index in the symbol table of the last coff symbol that was processed. */
static int symnum;
/* Vector of types defined so far, indexed by their coff symnum. */
static struct typevector *type_vector;
/* Number of elements allocated for type_vector currently. */
static int type_vector_length;
/* Vector of line number information. */
static struct linetable *line_vector;
/* Index of next entry to go in line_vector_index. */
static int line_vector_index;
/* Last line number recorded in the line vector. */
static int prev_line_number;
/* Number of elements allocated for line_vector currently. */
static int line_vector_length;
/* Chain of typedefs of pointers to empty struct/union types.
They are chained thru the SYMBOL_VALUE. */
#define HASHSIZE 127
static struct symbol *opaque_type_chain[HASHSIZE];
/* Record the symbols defined for each context in a list.
We don't create a struct block for the context until we
know how long to make it. */
struct pending
{
struct pending *next;
struct symbol *symbol;
};
/* Here are the three lists that symbols are put on. */
struct pending *file_symbols; /* static at top level, and types */
struct pending *global_symbols; /* global functions and variables */
struct pending *local_symbols; /* everything local to lexical context */
/* List of unclosed lexical contexts
(that will become blocks, eventually). */
struct context_stack
{
struct context_stack *next;
struct pending *locals;
struct pending_block *old_blocks;
struct symbol *name;
CORE_ADDR start_addr;
int depth;
};
struct context_stack *context_stack;
/* Nonzero if within a function (so symbols should be local,
if nothing says specifically). */
int within_function;
/* List of blocks already made (lexical contexts already closed).
This is used at the end to make the blockvector. */
struct pending_block
{
struct pending_block *next;
struct block *block;
};
struct pending_block *pending_blocks;
extern CORE_ADDR first_object_file_end; /* From blockframe.c */
/* File name symbols were loaded from. */
static char *symfile;
int debug = 1;
/* Look up a coff type-number index. Return the address of the slot
where the type for that index is stored.
The type-number is in INDEX.
This can be used for finding the type associated with that index
or for associating a new type with the index. */
static struct type **
coff_lookup_type (index)
register int index;
{
if (index >= type_vector_length)
{
type_vector_length *= 2;
type_vector = (struct typevector *)
xrealloc (type_vector, sizeof (struct typevector)
+ type_vector_length * sizeof (struct type *));
bzero (&type_vector->type[type_vector_length / 2],
type_vector_length * sizeof (struct type *) / 2);
}
return &type_vector->type[index];
}
/* Make sure there is a type allocated for type number index
and return the type object.
This can create an empty (zeroed) type object. */
static struct type *
coff_alloc_type (index)
int index;
{
register struct type **type_addr = coff_lookup_type (index);
register struct type *type = *type_addr;
/* If we are referring to a type not known at all yet,
allocate an empty type for it.
We will fill it in later if we find out how. */
if (type == 0)
{
type = (struct type *) obstack_alloc (symbol_obstack,
sizeof (struct type));
bzero (type, sizeof (struct type));
*type_addr = type;
}
return type;
}
/* maintain the lists of symbols and blocks */
/* Add a symbol to one of the lists of symbols. */
static void
add_symbol_to_list (symbol, listhead)
struct symbol *symbol;
struct pending **listhead;
{
register struct pending *link
= (struct pending *) xmalloc (sizeof (struct pending));
link->next = *listhead;
link->symbol = symbol;
*listhead = link;
}
/* Take one of the lists of symbols and make a block from it.
Put the block on the list of pending blocks. */
static void
finish_block (symbol, listhead, old_blocks, start, end)
struct symbol *symbol;
struct pending **listhead;
struct pending_block *old_blocks;
CORE_ADDR start, end;
{
register struct pending *next, *next1;
register struct block *block;
register struct pending_block *pblock;
struct pending_block *opblock;
register int i;
/* Count the length of the list of symbols. */
for (next = *listhead, i = 0; next; next = next->next, i++);
block = (struct block *) xmalloc (sizeof (struct block) + (i - 1) * sizeof (struct symbol *));
/* Copy the symbols into the block. */
BLOCK_NSYMS (block) = i;
for (next = *listhead; next; next = next->next

View File

@ -1,763 +0,0 @@
head 1.2;
access ;
symbols RMS-has:1.2;
locks ; strict;
comment @ * @;
1.2
date 88.01.26.05.04.52; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 88.01.21.05.04.03; author gnu; state Exp;
branches ;
next ;
desc
@From RMS's development version on wheaties, 20Jan88
@
1.2
log
@Hacks to get it to compile on a/ux. Needs work at finding the registers
in a core file.
@
text
@/* Work with core dump and executable files, for GDB.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "initialize.h"
#include "defs.h"
#include "param.h"
#include <a.out.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/file.h>
#include <sys/stat.h>
/* Recognize COFF format systems because a.out.h defines AOUTHDR. */
#ifdef AOUTHDR
#define COFF_FORMAT
#endif
#ifdef NEW_SUN_CORE
#include <sys/core.h>
#else /* not NEW_SUN_CORE */
#ifdef UMAX_CORE
#include <sys/ptrace.h>
#else /* not UMAX_CORE */
#ifdef mac_aux
#include <sys/seg.h>
#include <sys/mmu.h>
#include <sys/signal.h>
#include <sys/time.h>
#include <sys/user.h>
#else
#include <sys/user.h>
#endif /* mac_aux */
#endif /* UMAX_CORE */
#endif /* NEW_SUN_CORE */
#ifndef N_TXTADDR
#define N_TXTADDR(hdr) 0
#endif /* no N_TXTADDR */
#ifndef N_DATADDR
#define N_DATADDR(hdr) hdr.a_text
#endif /* no N_DATADDR */
/* Make COFF and non-COFF names for things a little more compatible
to reduce conditionals later. */
#ifdef COFF_FORMAT
#define a_magic magic
#endif
#ifndef COFF_FORMAT
#define AOUTHDR struct exec
#endif
START_FILE
/* Hook for `exec_file_command' command to call. */
void (*exec_file_display_hook) ();
/* File names of core file and executable file. */
static char *corefile;
static char *execfile;
/* Descriptors on which core file and executable file are open.
Note that the execchan is closed when an inferior is created
and reopened if the inferior dies or is killed. */
static int corechan;
static int execchan;
/* Last modification time of executable file.
Also used in source.c to compare against mtime of a source file. */
int exec_mtime;
/* Virtual addresses of bounds of the two areas of memory in the core file. */
static CORE_ADDR data_start;
static CORE_ADDR data_end;
static CORE_ADDR stack_start;
static CORE_ADDR stack_end;
/* Virtual addresses of bounds of two areas of memory in the exec file.
Note that the data area in the exec file is used only when there is no core file. */
static CORE_ADDR text_start;
static CORE_ADDR text_end;
static CORE_ADDR exec_data_start;
static CORE_ADDR exec_data_end;
/* Address in executable file of start of text area data. */
static int text_offset;
/* Address in executable file of start of data area data. */
static int exec_data_offset;
/* Address in core file of start of data area data. */
static int data_offset;
/* Address in core file of start of stack area data. */
static int stack_offset;
#ifdef COFF_FORMAT
/* various coff data structures */
static FILHDR file_hdr;
static SCNHDR text_hdr;
static SCNHDR data_hdr;
#endif /* not COFF_FORMAT */
/* a.out header saved in core file. */
static AOUTHDR core_aouthdr;
/* a.out header of exec file. */
static AOUTHDR exec_aouthdr;
static void validate_files ();
unsigned int register_addr ();
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)
{
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);
#ifdef NEW_SUN_CORE
{
struct core corestr;
val = myread (corechan, &corestr, sizeof corestr);
if (val < 0)
perror_with_name (filename);
if (corestr.c_magic != CORE_MAGIC)
error ("\"%s\" does not appear to be a core dump file (magic 0x%x, expected 0x%x)",
filename, corestr.c_magic, (int) CORE_MAGIC);
else if (sizeof (struct core) != corestr.c_len)
error ("\"%s\" has an invalid struct core length (%d, expected %d)",
filename, corestr.c_len, (int) sizeof (struct core));
data_start = exec_data_start;
data_end = data_start + corestr.c_dsize;
stack_start = stack_end - corestr.c_ssize;
data_offset = sizeof corestr;
stack_offset = sizeof corestr + corestr.c_dsize;
bcopy (&corestr.c_regs, registers, 16 * 4);
*(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps;
*(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc;
bcopy (corestr.c_fpstatus.fps_regs,
&registers[REGISTER_BYTE (FP0_REGNUM)],
sizeof corestr.c_fpstatus.fps_regs);
bcopy (&corestr.c_fpstatus.fps_control,
&registers[REGISTER_BYTE (FPC_REGNUM)],
sizeof corestr.c_fpstatus - sizeof corestr.c_fpstatus.fps_regs);
bcopy (&corestr.c_aouthdr, &core_aouthdr, sizeof (struct exec));
printf ("Core file is from \"%s\".\n", corestr.c_cmdname);
}
#else /* not NEW_SUN_CORE */
/* 4.2-style (and perhaps also sysV-style) core dump file. */
{
#ifdef UMAX_CORE
struct ptrace_user u;
#else
struct user u;
#endif
int reg_offset;
val = myread (corechan, &u, sizeof u);
if (val < 0)
perror_with_name (filename);
data_start = exec_data_start;
#ifdef UMAX_CORE
data_end = data_start + u.pt_dsize;
stack_start = stack_end - u.pt_ssize;
data_offset = sizeof u;
stack_offset = data_offset + u.pt_dsize;
reg_offset = 0;
bcopy (&u.pt_aouthdr, &core_aouthdr, sizeof (AOUTHDR));
#else /* not UMAX_CORE */
#ifdef mac_aux
/* This may well not work for 0407 (nonshared text) a.out's */
data_end = data_start + u.u_dsize << PAGESHIFT;
stack_start = stack_end - u.u_ssize << PAGESHIFT;
data_offset = USIZE;
stack_offset = USIZE + u.u_dsize << PAGESHIFT;
reg_offset = (int) &u.u_ar0[0] - (int) &u;
core_aouthdr.a_magic = u.u_exdata.ux_mag;
#else
data_end = data_start + NBPG * u.u_dsize;
stack_start = stack_end - NBPG * u.u_ssize;
data_offset = NBPG * UPAGES;
stack_offset = NBPG * (UPAGES + u.u_dsize);
reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
/* I don't know where to find this info.
So, for now, mark it as not available. */
core_aouthdr.a_magic = 0;
#endif /* not mac_aux */
#endif /* not UMAX_CORE */
/* 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);
}
}
}
#endif /* not NEW_SUN_CORE */
if (filename[0] == '/')
corefile = savestring (filename, strlen (filename));
else
{
char dirname[MAXPATHLEN];
getwd (dirname);
corefile = concat (dirname, "/", filename);
}
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");
}
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)
{
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) < 0)
error ("\"%s\": can't read text section header", execfile);
if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections) < 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_TXTADDR (exec_aouthdr);
text_end = text_start + exec_aouthdr.a_text;
text_offset = N_TXTOFF (exec_aouthdr);
exec_data_start = N_DATADDR (exec_aouthdr);
exec_data_end = exec_data_start + exec_aouthdr.a_data;
exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
data_start = exec_data_start;
data_end += exec_data_start;
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 ? filename : "No executable specified.\n");
}
/* Call this to specify the hook for exec_file_command to call back.
This is called from the x-window display code. */
specify_exec_file_hook (hook)
void (*hook) ();
{
exec_file_display_hook = hook;
}
/* The exec file must be closed before running an inferior.
If it is needed again after the inferior dies, it must
be reopened. */
close_exec_file ()
{
if (execchan >= 0)
close (execchan);
execchan = -1;
}
reopen_exec_file ()
{
if (execchan < 0 && execfile != 0)
{
char *filename = concat (execfile, "", "");
exec_file_command (filename, 0);
free (filename);
}
}
/* If we have both a core file and an exec file,
print a warning if they don't go together.
This should really check that the core file came
from that exec file, but I don't know how to do it. */
static void
validate_files ()
{
if (execfile != 0 && corefile != 0)
{
struct stat st_core;
fstat (corechan, &st_core);
if (core_aouthdr.a_magic != 0
&& bcmp (&core_aouthdr, &exec_aouthdr, sizeof core_aouthdr))
printf ("Warning: core file does not match specified executable file.\n");
else if (exec_mtime > st_core.st_mtime)
printf ("Warning: exec file is newer than core file.\n");
}
}
char *
get_exec_file ()
{
if (execfile == 0)
error ("No executable file specified.\n\
Use the \"exec-file\" and \"symbol-file\" commands.");
return execfile;
}
int
have_core_file_p ()
{
return corefile != 0;
}
static void
files_info ()
{
char *symfile;
extern char *get_sym_file ();
if (execfile)
printf ("Executable file \"%s\".\n", execfile);
else
printf ("No executable file\n");
if (corefile == 0)
printf ("No core dump file\n");
else
printf ("Core dump file \"%s\".\n", corefile);
if (have_inferior_p ())
printf ("Using the running image of the program, rather than these files.\n");
symfile = get_sym_file ();
if (symfile != 0)
printf ("Symbols loaded from \"%s\".\n", symfile);
if (! have_inferior_p ())
{
if (execfile)
{
printf ("Text segment from 0x%x to 0x%x.\n",
text_start, text_end);
}
if (corefile)
{
printf ("Data segment from 0x%x to 0x%x.\nStack segment from 0x%x to 0x%x.\n",
data_start, data_end, stack_start, stack_end);
}
else
{
printf ("Data segment in executable from 0x%x to 0x%x.\n",
exec_data_start, exec_data_end);
}
}
}
/* Read "memory data" from core file and/or executable file */
read_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
if (have_inferior_p ())
read_inferior_memory (memaddr, myaddr, len);
else
xfer_core_file (memaddr, myaddr, len, 0);
}
/* Write LEN bytes of data starting at address MYADDR
into debugged program memory at address MEMADDR.
Returns zero if successful, or an errno value if ptrace failed. */
int
write_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
if (have_inferior_p ())
return write_inferior_memory (memaddr, myaddr, len);
else
error ("Can write memory only when program being debugged is running.");
}
xfer_core_file (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
register int i;
register int val;
int xferchan;
char **xferfile;
int fileptr;
while (len > 0)
{
xferfile = 0;
xferchan = 0;
/* Determine which file the next bunch of addresses reside in,
and where in the file. Set the file's read/write pointer
to point at the proper place for the desired address
and set xferfile and xferchan for the correct file.
If desired address is nonexistent, leave them zero.
i is set to the number of bytes that can be handled
along with the next address. */
if (memaddr < text_start)
{
i = min (len, text_start - memaddr);
}
else if (memaddr >= text_end && memaddr < data_start)
{
i = min (len, data_start - memaddr);
}
else if (memaddr >= (corechan >= 0 ? data_end : exec_data_end)
&& memaddr < stack_start)
{
i = min (len, stack_start - memaddr);
}
else if (memaddr >= stack_end && stack_end != 0)
{
i = min (len, - memaddr);
}
/* Note that if there is no core file
data_start and data_end are equal. */
else if (memaddr >= data_start && memaddr < data_end)
{
i = min (len, data_end - memaddr);
fileptr = memaddr - data_start + data_offset;
xferfile = &corefile;
xferchan = corechan;
}
/* Note that if there is no core file
stack_start and stack_end are equal. */
else if (memaddr >= stack_start && memaddr < stack_end)
{
i = min (len, stack_end - memaddr);
fileptr = memaddr - stack_start + stack_offset;
xferfile = &corefile;
xferchan = corechan;
}
else if (corechan < 0
&& memaddr >= exec_data_start && memaddr < exec_data_end)
{
i = min (len, exec_data_end - memaddr);
fileptr = memaddr - exec_data_start + exec_data_offset;
xferfile = &execfile;
xferchan = execchan;
}
else if (memaddr >= text_start && memaddr < text_end)
{
i = min (len, text_end - memaddr);
fileptr = memaddr - text_start + text_offset;
xferfile = &execfile;
xferchan = execchan;
}
/* Now we know which file to use.
Set up its pointer and transfer the data. */
if (xferfile)
{
if (*xferfile == 0)
if (xferfile == &execfile)
error ("No program file to examine.");
else
error ("No core dump file or running program to examine.");
val = lseek (xferchan, fileptr, 0);
if (val < 0)
perror_with_name (*xferfile);
val = myread (xferchan, myaddr, i);
if (val < 0)
perror_with_name (*xferfile);
}
/* If this address is for nonexistent memory,
read zeros if reading, or do nothing if writing. */
else
bzero (myaddr, i);
memaddr += i;
myaddr += i;
len -= i;
}
}
/* My replacement for the read system call.
Used like `read' but keeps going if `read' returns too soon. */
myread (desc, addr, len)
int desc;
char *addr;
int len;
{
register int val;
int orglen = len;
while (len > 0)
{
val = read (desc, addr, len);
if (val < 0)
return val;
if (val == 0)
return orglen - len;
len -= val;
addr += val;
}
}
#ifndef NEW_SUN_CORE
/* Return the address in the core dump or inferior of register REGNO.
BLOCKEND is the address of the end of the user structure. */
unsigned int
register_addr (regno, blockend)
int regno;
int blockend;
{
int addr;
if (regno < 0 || regno >= NUM_REGS)
error ("Invalid register number %d.", regno);
#ifdef mac_aux
/* FIXME, we don't know where the regs are. Maybe the test command
* that tests what parts of the upage are writeable will find 'em for us.
*/
#define REGISTER_U_ADDR(addr, foo, bar) addr = 0;
#endif
REGISTER_U_ADDR (addr, blockend, regno);
return addr;
}
#endif /* not NEW_SUN_CORE */
static
initialize ()
{
corechan = -1;
execchan = -1;
corefile = 0;
execfile = 0;
exec_file_display_hook = 0;
text_start = 0;
text_end = 0;
data_start = 0;
data_end = 0;
exec_data_start = 0;
exec_data_end = 0;
stack_start = STACK_END_ADDR;
stack_end = STACK_END_ADDR;
add_com ("core-file", class_files, core_file_command,
"Use FILE as core dump for examining memory and registers.\n\
No arg means have no core file.");
add_com ("exec-file", class_files, exec_file_command,
"Use FILE as program for getting contents of pure memory.\n\
If FILE cannot be found as specified, your execution directory path\n\
is searched for a command of that name.\n\
No arg means have no executable file.");
add_info ("files", files_info, "Names of files being debugged.");
}
END_FILE
@
1.1
log
@Initial revision
@
text
@d27 1
d44 5
d50 4
a53 1
#endif
d240 10
d259 1
d675 6
@

View File

@ -1,966 +0,0 @@
head 1.2;
access ;
symbols RMS-has:1.2;
locks ; strict;
comment @ * @;
1.2
date 88.01.26.05.06.19; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 88.01.26.01.19.05; author gnu; state Exp;
branches ;
next ;
desc
@Original from RMS's wheaties devl sources
@
1.2
log
@Add local sys_siglist for a/ux because they don't provide one, sigh.
@
text
@/* Memory-access and commands for inferior process, for GDB.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "defs.h"
#include "initialize.h"
#include "symtab.h"
#include "param.h"
#include "frame.h"
#include "inferior.h"
#include "environ.h"
#include "value.h"
#include <stdio.h>
#include <signal.h>
#include <sys/param.h>
#ifdef mac_aux
/* Warning! This table is positional and highly dependent on the local
system. Check it closely against <sys/signal.h> when porting. */
char *sys_siglist[] = {
"Signal 0",
"Hangup",
"Interrupt",
"Quit",
"Invalid instruction",
"Trace/breakpoint trap",
"IOT trap",
"EMT trap",
"Floating point exception",
"Killed",
"Bus error",
"Segmentation fault",
"Bad system call",
"Broken pipe",
"Alarm clock",
"Terminated",
"User signal 1",
"User signal 2",
"Child exited",
"Power-fail restart",
"Stopped",
"Stopped (tty input)",
"Stopped (tty output)",
"Stopped (signal)",
"Cputime limit exceeded",
"File size limit exceeded",
"Virtual timer expired",
"Profiling timer expired",
"Window changed",
"Continued",
"Urgent I/O condition",
"I/O possible",
};
#else
/* More portable systems do it for you */
extern char *sys_siglist[];
#endif
#define ERROR_NO_INFERIOR \
if (inferior_pid == 0) error ("The program is not being run.");
/* String containing arguments to give to the program,
with a space added at the front. Just a space means no args. */
static char *inferior_args;
/* File name for default use for standard in/out in the inferior. */
char *inferior_io_terminal;
/* Pid of our debugged inferior, or 0 if no inferior now. */
int inferior_pid;
/* Last signal that the inferior received (why it stopped). */
int stop_signal;
/* Address at which inferior stopped. */
CORE_ADDR stop_pc;
/* Stack frame when program stopped. */
FRAME stop_frame;
/* Number of breakpoint it stopped at, or 0 if none. */
int stop_breakpoint;
/* Nonzero if stopped due to a step command. */
int stop_step;
/* Nonzero if stopped due to completion of a stack dummy routine. */
int stop_stack_dummy;
/* Range to single step within.
If this is nonzero, respond to a single-step signal
by continuing to step if the pc is in this range. */
CORE_ADDR step_range_start; /* Inclusive */
CORE_ADDR step_range_end; /* Exclusive */
/* Stack frame address as of when stepping command was issued.
This is how we know when we step into a subroutine call,
and how to set the frame for the breakpoint used to step out. */
CORE_ADDR step_frame;
/* 1 means step over all subroutine calls.
-1 means step over calls to undebuggable functions. */
int step_over_calls;
/* If stepping, nonzero means step count is > 1
so don't print frame next time inferior stops
if it stops due to stepping. */
int step_multi;
/* Environment to use for running inferior,
in format described in environ.h. */
struct environ *inferior_environ;
CORE_ADDR read_pc ();
struct command_line *get_breakpoint_commands ();
START_FILE
int
have_inferior_p ()
{
return inferior_pid != 0;
}
static void
set_args_command (args)
char *args;
{
free (inferior_args);
if (!args) args = "";
inferior_args = concat (" ", args, "");
}
void
tty_command (file)
char *file;
{
if (file == 0)
error_no_arg ("terminal name for running target process");
inferior_io_terminal = savestring (file, strlen (file));
}
static void
run_command (args, from_tty)
char *args;
int from_tty;
{
extern char **environ;
register int i;
char *exec_file;
char *allargs;
extern int sys_nerr;
extern char *sys_errlist[];
extern int errno;
dont_repeat ();
if (inferior_pid)
{
if (query ("The program being debugged has been started already.\n\
Start it from the beginning? "))
kill_inferior ();
else
error ("Program already started.");
}
if (args)
set_args_command (args);
exec_file = (char *) get_exec_file ();
if (from_tty)
{
printf ("Starting program: %s%s\n",
exec_file, inferior_args);
fflush (stdout);
}
allargs = concat ("exec ", exec_file, inferior_args);
inferior_pid = create_inferior (allargs, environ_vector (inferior_environ));
clear_proceed_status ();
start_inferior ();
}
void
cont_command (proc_count_exp, from_tty)
char *proc_count_exp;
int from_tty;
{
ERROR_NO_INFERIOR;
clear_proceed_status ();
/* If have argument, set proceed count of breakpoint we stopped at. */
if (stop_breakpoint && proc_count_exp)
{
set_ignore_count (stop_breakpoint,
parse_and_eval_address (proc_count_exp) - 1,
from_tty);
if (from_tty)
printf (" ");
}
if (from_tty)
printf ("Continuing.\n");
proceed (-1, -1, 0);
}
/* Step until outside of current statement. */
static void step_1 ();
static void
step_command (count_string)
{
step_1 (0, 0, count_string);
}
/* Likewise, but skip over subroutine calls as if single instructions. */
static void
next_command (count_string)
{
step_1 (1, 0, count_string);
}
/* Likewise, but step only one instruction. */
static void
stepi_command (count_string)
{
step_1 (0, 1, count_string);
}
static void
nexti_command (count_string)
{
step_1 (1, 1, count_string);
}
static void
step_1 (skip_subroutines, single_inst, count_string)
int skip_subroutines;
int single_inst;
char *count_string;
{
register int count = 1;
ERROR_NO_INFERIOR;
count = count_string ? parse_and_eval_address (count_string) : 1;
for (; count > 0; count--)
{
clear_proceed_status ();
step_frame = get_current_frame ();
if (! single_inst)
{
find_pc_line_pc_range (stop_pc, &step_range_start, &step_range_end);
if (step_range_end == 0)
{
terminal_ours ();
error ("Current function has no line number information.");
}
}
else
{
/* Say we are stepping, but stop after one insn whatever it does.
Don't step through subroutine calls even to undebuggable functions. */
step_range_start = step_range_end = 1;
if (!skip_subroutines)
step_over_calls = 0;
}
if (skip_subroutines)
step_over_calls = 1;
step_multi = (count > 1);
proceed (-1, -1, 1);
if (! stop_step)
break;
}
}
/* Continue program at specified address. */
static void
jump_command (arg, from_tty)
char *arg;
int from_tty;
{
register CORE_ADDR addr;
struct symtab_and_line sal;
ERROR_NO_INFERIOR;
if (!arg)
error_no_arg ("starting address");
sal = decode_line_spec (arg, 1);
if (sal.symtab == 0 && sal.pc == 0)
error ("No source file has been specified.");
if (sal.pc == 0)
sal.pc = find_line_pc (sal.symtab, sal.line);
{
struct symbol *fn = get_frame_function (get_current_frame ());
struct symbol *sfn = find_pc_function (sal.pc);
if (fn != 0 && sfn != fn
&& ! query ("That is not in function %s. Continue there? ",
sal.line, SYMBOL_NAME (fn)))
error ("Not confirmed.");
}
if (sal.pc == 0)
error ("No line %d in file \"%s\".", sal.line, sal.symtab->filename);
addr = sal.pc;
clear_proceed_status ();
if (from_tty)
printf ("Continuing at 0x%x.\n", addr);
proceed (addr, 0, 0);
}
/* Continue program giving it specified signal. */
static void
signal_command (signum_exp, from_tty)
char *signum_exp;
int from_tty;
{
register int signum;
dont_repeat (); /* Too dangerous. */
ERROR_NO_INFERIOR;
if (!signum_exp)
error_no_arg ("signal number");
signum = parse_and_eval_address (signum_exp);
clear_proceed_status ();
if (from_tty)
printf ("Continuing with signal %d.\n", signum);
proceed (stop_pc, signum, 0);
}
/* Execute a "stack dummy", a piece of code stored in the stack
by the debugger to be executed in the inferior.
To call: first, do PUSH_DUMMY_FRAME.
Then push the contents of the dummy. It should end with a breakpoint insn.
Then call here, passing address at which to start the dummy.
The contents of all registers are saved before the dummy frame is popped
and copied into the buffer BUFFER.
The dummy's frame is automatically popped whenever that break is hit.
If that is the first time the program stops, run_stack_dummy
returns to its caller with that frame already gone.
Otherwise, the caller never gets returned to. */
/* 4 => return instead of letting the stack dummy run. */
static int stack_dummy_testing = 0;
void
run_stack_dummy (addr, buffer)
CORE_ADDR addr;
REGISTER_TYPE *buffer;
{
int saved_pc_changed = pc_changed;
int saved_stop_signal = stop_signal;
int saved_stop_pc = stop_pc;
int saved_stop_frame = stop_frame;
int saved_stop_breakpoint = stop_breakpoint;
int saved_stop_step = stop_step;
int saved_stop_stack_dummy = stop_stack_dummy;
FRAME saved_selected_frame;
int saved_selected_level;
struct command_line *saved_breakpoint_commands
= get_breakpoint_commands ();
record_selected_frame (&saved_selected_frame, &saved_selected_level);
/* Now proceed, having reached the desired place. */
clear_proceed_status ();
if (stack_dummy_testing & 4)
{
POP_FRAME;
return;
}
proceed (addr, 0, 0);
if (!stop_stack_dummy)
error ("Cannot continue previously requested operation.");
set_breakpoint_commands (saved_breakpoint_commands);
select_frame (saved_selected_frame, saved_selected_level);
stop_signal = saved_stop_signal;
stop_pc = saved_stop_pc;
stop_frame = saved_stop_frame;
stop_breakpoint = saved_stop_breakpoint;
stop_step = saved_stop_step;
stop_stack_dummy = saved_stop_stack_dummy;
pc_changed = saved_pc_changed;
/* On return, the stack dummy has been popped already. */
bcopy (stop_registers, buffer, sizeof stop_registers);
}
/* "finish": Set a temporary breakpoint at the place
the selected frame will return to, then continue. */
static void
finish_command (arg, from_tty)
char *arg;
int from_tty;
{
struct symtab_and_line sal;
register FRAME frame;
struct frame_info fi;
register struct symbol *function;
if (!have_inferior_p ())
error ("The program is not being run.");
if (arg)
error ("The \"finish\" command does not take any arguments.");
frame = get_prev_frame (selected_frame);
if (frame == 0)
error ("\"finish\" not meaningful in the outermost frame.");
clear_proceed_status ();
fi = get_frame_info (frame);
sal = find_pc_line (fi.pc, 0);
sal.pc = fi.pc;
set_momentary_breakpoint (sal, frame);
/* Find the function we will return from. */
fi = get_frame_info (fi.next_frame);
function = find_pc_function (fi.pc);
if (from_tty)
{
printf ("Run till exit from ");
print_selected_frame ();
}
proceed (-1, -1, 0);
if (stop_breakpoint == -3 && function != 0)
{
struct type *value_type;
register value val;
if (TYPE_CODE (SYMBOL_TYPE (function)) != TYPE_CODE_VOID)
value_type = SYMBOL_TYPE (function);
else
return;
val = value_being_returned (value_type, stop_registers);
printf ("Value returned is $%d = ", record_latest_value (val));
value_print (val, stdout);
putchar ('\n');
}
}
static void
program_info ()
{
if (inferior_pid == 0)
{
printf ("The program being debugged is not being run.\n");
return;
}
printf ("Program being debugged is in process %d, stopped at 0x%x.\n",
inferior_pid, stop_pc);
if (stop_step)
printf ("It stopped after being stepped.\n");
else if (stop_breakpoint)
printf ("It stopped at breakpoint %d.\n", stop_breakpoint);
else if (stop_signal)
printf ("It stopped with signal %d (%s).\n",
stop_signal, sys_siglist[stop_signal]);
printf ("\nType \"info stack\" or \"info reg\" for more information.\n");
}
static void
environment_info (var)
char *var;
{
if (var)
{
register char *val = get_in_environ (inferior_environ, var);
if (val)
printf ("%s = %s\n", var, val);
else
printf ("Environment variable \"%s\" not defined.\n", var);
}
else
{
register char **vector = environ_vector (inferior_environ);
while (*vector)
printf ("%s\n", *vector++);
}
}
static void
set_environment_command (arg)
char *arg;
{
register char *p, *val, *var;
if (arg == 0)
error_no_arg ("environment variable and value");
p = (char *) index (arg, '=');
val = (char *) index (arg, ' ');
if (p != 0 && val != 0)
p = arg + min (p - arg, val - arg);
else if (val != 0 && p == 0)
p = val;
if (p == 0)
error ("Space or \"=\" must separate variable name and its value");
if (p[1] == 0)
error_no_arg ("value for the variable");
if (p == arg)
error_no_arg ("environment variable to set");
val = p + 1;
while (*val == ' ' || *val == '\t') val++;
while (p != arg && (p[-1] == ' ' || p[-1] == '\t')) p--;
var = savestring (arg, p - arg);
set_in_environ (inferior_environ, var, val);
free (var);
}
static void
unset_environment_command (var)
char *var;
{
if (var == 0)
error_no_arg ("environment variable");
unset_in_environ (inferior_environ, var);
}
/* Read an integer from debugged memory, given address and number of bytes. */
read_memory_integer (memaddr, len)
CORE_ADDR memaddr;
int len;
{
char cbuf;
short sbuf;
int ibuf;
long lbuf;
if (len == sizeof (char))
{
read_memory (memaddr, &cbuf, len);
return cbuf;
}
if (len == sizeof (short))
{
read_memory (memaddr, &sbuf, len);
return sbuf;
}
if (len == sizeof (int))
{
read_memory (memaddr, &ibuf, len);
return ibuf;
}
if (len == sizeof (lbuf))
{
read_memory (memaddr, &lbuf, len);
return lbuf;
}
error ("Cannot handle integers of %d bytes.", len);
}
CORE_ADDR
read_pc ()
{
return (CORE_ADDR) read_register (PC_REGNUM);
}
write_pc (val)
CORE_ADDR val;
{
write_register (PC_REGNUM, (long) val);
}
char *reg_names[] = REGISTER_NAMES;
static void
registers_info (addr_exp)
char *addr_exp;
{
register int i;
int regnum;
if (addr_exp)
{
if (*addr_exp >= '0' && *addr_exp <= '9')
regnum = atoi (addr_exp);
else
{
register char *p = addr_exp;
if (p[0] == '$')
p++;
for (regnum = 0; regnum < NUM_REGS; regnum++)
if (!strcmp (p, reg_names[regnum]))
break;
if (regnum == NUM_REGS)
error ("%s: invalid register name.", addr_exp);
}
}
else
printf ("Reg\tContents\n\n");
for (i = 0; i < NUM_REGS; i++)
{
unsigned char raw_buffer[MAX_REGISTER_RAW_SIZE];
unsigned char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
REGISTER_TYPE val;
if (addr_exp != 0 && i != regnum)
continue;
/* On machines with lots of registers, pause every 16 lines
so user can read the output. */
if (addr_exp == 0 && i > 0 && i % 16 == 0)
{
printf ("--Type Return to print more--");
fflush (stdout);
read_line ();
}
/* Get the data in raw format, then convert also to virtual format. */
read_relative_register_raw_bytes (i, raw_buffer);
REGISTER_CONVERT_TO_VIRTUAL (i, raw_buffer, virtual_buffer);
printf ("%s\t", reg_names[i]);
/* If virtual format is floating, print it that way. */
if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT
&& ! INVALID_FLOAT (virtual_buffer, REGISTER_VIRTUAL_SIZE (i)))
val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, stdout);
/* Else if virtual format is too long for printf,
print in hex a byte at a time. */
else if (REGISTER_VIRTUAL_SIZE (i) > sizeof (long))
{
register int j;
printf ("0x");
for (j = 0; j < REGISTER_VIRTUAL_SIZE (i); j++)
printf ("%02x", virtual_buffer[j]);
}
/* Else print as integer in hex and in decimal. */
else
{
long val;
bcopy (virtual_buffer, &val, sizeof (long));
if (val == 0)
printf ("0");
else
printf ("0x%08x %d", val, val);
}
/* If register has different raw and virtual formats,
print the raw format in hex now. */
if (REGISTER_CONVERTIBLE (i))
{
register int j;
printf (" (raw 0x");
for (j = 0; j < REGISTER_RAW_SIZE (i); j++)
printf ("%02x", raw_buffer[j]);
printf (")");
}
printf ("\n");
}
printf ("Contents are relative to selected stack frame.\n");
}
#ifdef ATTACH_DETACH
/*
* TODO:
* Should save/restore the tty state since it might be that the
* program to be debugged was started on this tty and it wants
* the tty in some state other than what we want. If it's running
* on another terminal or without a terminal, then saving and
* restoring the tty state is a harmless no-op.
*/
/*
* attach_command --
* takes a program started up outside of gdb and ``attaches'' to it.
* This stops it cold in it's tracks and allows us to start tracing
* it. For this to work, we must be able to send the process a
* signal and we must have the same effective uid as the program.
*/
static void
attach_command (args, from_tty)
char *args;
int from_tty;
{
char *exec_file;
int pid;
dont_repeat();
if (!args)
error_no_arg ("process-id to attach");
else
pid = atoi (args);
if (inferior_pid)
{
if (query ("A program is being debugged already. Kill it? "))
kill_inferior ();
else
error ("Inferior not killed.");
}
exec_file = (char *) get_exec_file ();
if (from_tty)
{
printf ("Attaching program: %s pid %d\n",
exec_file, pid);
fflush (stdout);
}
attach_program (pid);
}
/*
* detach_command --
* takes a program previously attached to and detaches it.
* The program resumes execution and will no longer stop
* on signals, etc. We better not have left any breakpoints
* in the program or it'll die when it hits one. For this
* to work, it may be necessary for the process to have been
* previously attached. It *might* work if the program was
* started via the normal ptrace (PTRACE_TRACEME).
*/
static void
detach_command (args, from_tty)
char *args;
int from_tty;
{
char *exec_file = (char *)get_exec_file ();
int signal = 0;
if (!inferior_pid)
error ("Not currently tracing a program\n");
if (from_tty)
{
printf ("Detaching program: %s pid %d\n",
exec_file, inferior_pid);
fflush (stdout);
}
if (args)
signal = atoi (args);
detach (signal);
inferior_pid = 0;
}
#endif /* ATTACH_DETACH */
static
initialize ()
{
add_com ("tty", class_run, tty_command,
"Set terminal for future runs of program being debugged.");
add_com ("set-args", class_run, set_args_command,
"Specify arguments to give program being debugged when it is started.\n\
Follow this command with any number of args, to be passed to the program.");
add_info ("environment", environment_info,
"The environment to give the program, or one variable's value.\n\
With an argument VAR, prints the value of environment variable VAR to\n\
give the program being debugged. With no arguments, prints the entire\n\
environment to be given to the program.");
add_com ("unset-environment", class_run, unset_environment_command,
"Cancel environment variable VAR for the program.\n\
This does not affect the program until the next \"run\" command.");
add_com ("set-environment", class_run, set_environment_command,
"Set environment variable value to give the program.\n\
Arguments are VAR VALUE where VAR is variable name and VALUE is value.\n\
VALUES of environment variables are uninterpreted strings.\n\
This does not affect the program until the next \"run\" command.");
#ifdef ATTACH_DETACH
add_com ("attach", class_run, attach_command,
"Attach to a process that was started up outside of GDB.\n\
To do this, you must have permission to send the process a signal.\n\
And it must have the same effective uid as the debugger.\n\n\
Before using \"attach\", you must use the \"exec-file\" command\n\
to specify the program running in the process,\n\
and the \"symbol-file\" command to load its symbol table.");
add_com ("detach", class_run, detach_command,
"Detach the process previously attached.\n\
The process is no longer traced and continues its execution.");
#endif /* ATTACH_DETACH */
add_com ("signal", class_run, signal_command,
"Continue program giving it signal number SIGNUMBER.");
add_com ("stepi", class_run, stepi_command,
"Step one instruction exactly.\n\
Argument N means do this N times (or till program stops for another reason).");
add_com_alias ("si", "stepi", class_alias, 0);
add_com ("nexti", class_run, nexti_command,
"Step one instruction, but proceed through subroutine calls.\n\
Argument N means do this N times (or till program stops for another reason).");
add_com_alias ("ni", "nexti", class_alias, 0);
add_com ("finish", class_run, finish_command,
"Execute until selected stack frame returns.\n\
Upon return, the value returned is printed and put in the value history.");
add_com ("next", class_run, next_command,
"Step program, proceeding through subroutine calls.\n\
Like the \"step\" command as long as subroutine calls do not happen;\n\
when they do, the call is treated as one instruction.\n\
Argument N means do this N times (or till program stops for another reason).");
add_com_alias ("n", "next", class_run, 1);
add_com ("step", class_run, step_command,
"Step program until it reaches a different source line.\n\
Argument N means do this N times (or till program stops for another reason).");
add_com_alias ("s", "step", class_run, 1);
add_com ("jump", class_run, jump_command,
"Continue program being debugged at specified line or address.\n\
Give as argument either LINENUM or *ADDR, where ADDR is an expression\n\
for an address to start at.");
add_com ("cont", class_run, cont_command,
"Continue program being debugged, after signal or breakpoint.\n\
If proceeding from breakpoint, a number N may be used as an argument:\n\
then the same breakpoint won't break until the Nth time it is reached.");
add_com_alias ("c", "cont", class_run, 1);
add_com ("run", class_run, run_command,
"Start debugged program. You may specify arguments to give it.\n\
Args may include \"*\", or \"[...]\"; they are expanded using \"sh\".\n\
Input and output redirection with \">\", \"<\", or \">>\" are also allowed.\n\n\
With no arguments, uses arguments last specified (with \"run\" or \"set-args\".\n\
To cancel previous arguments and run with no arguments,\n\
use \"set-args\" without arguments.");
add_com_alias ("r", "run", class_run, 1);
add_info ("registers", registers_info,
"List of registers and their contents, for selected stack frame.\n\
Register name as argument means describe only that register.");
add_info ("program", program_info,
"Execution status of the program.");
inferior_args = savestring (" ", 1); /* By default, no args. */
inferior_environ = make_environ ();
init_environ (inferior_environ);
}
END_FILE
@
1.1
log
@Initial revision
@
text
@d34 39
d74 1
@

View File

@ -1,731 +0,0 @@
head 1.2;
access ;
symbols RMS-has:1.2;
locks ; strict;
comment @ * @;
1.2
date 88.01.26.05.07.38; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 88.01.21.05.04.57; author gnu; state Exp;
branches ;
next ;
desc
@From RMS's development sources on wheaties, 20Jan88
@
1.2
log
@Major Sys V tty changes, and a few changes to try to find the registers
in the upage (untested yet).
@
text
@/* Low level interface to ptrace, for GDB when running under Unix.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "defs.h"
#include "initialize.h"
#include "param.h"
#include "frame.h"
#include "inferior.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sgtty.h>
#include <fcntl.h>
#ifdef mac_aux
#include <sys/seg.h>
#include <sys/mmu.h>
#include <sys/signal.h>
#include <sys/time.h>
#include <sys/user.h>
#else
#include <sys/user.h>
#endif /* mac_aux */
#ifdef UMAX_PTRACE
#include <a.out.h>
#endif
#ifdef NEW_SUN_PTRACE
#include <sys/ptrace.h>
#include <machine/reg.h>
#endif
#ifdef SYSV_TTYS
#include <termio.h>
#endif
extern int errno;
/* Nonzero if we are debugging an attached outside process
rather than an inferior. */
static int attach_flag;
#define UPAGE_MASK 0x00003FFF
START_FILE
/* Record terminal status separately for debugger and inferior. */
#ifdef SYSV_TTYS
static struct termio ti_inferior;
#else
static struct sgttyb sg_inferior;
static struct tchars tc_inferior;
static struct ltchars ltc_inferior;
static int lmode_inferior;
#endif
static int tflags_inferior;
static int pgrp_inferior;
#ifdef SYSV_TTYS
static struct termio ti_ours;
#else
static struct sgttyb sg_ours;
static struct tchars tc_ours;
static struct ltchars ltc_ours;
static int lmode_ours;
#endif
static int tflags_ours;
static int pgrp_ours;
/* Copy of inferior_io_terminal when inferior was last started. */
static char *inferior_thisrun_terminal;
static void terminal_ours_1 ();
/* Nonzero if our terminal settings are in effect.
Zero if the inferior's settings are in effect. */
static int terminal_is_ours;
/* Initialize the terminal settings we record for the inferior,
before we actually run the inferior. */
void
terminal_init_inferior ()
{
#ifdef SYSV_TTYS
ti_inferior = ti_ours;
#else
sg_inferior = sg_ours;
tc_inferior = tc_ours;
ltc_inferior = ltc_ours;
lmode_inferior = lmode_ours;
#endif
tflags_inferior = tflags_ours;
pgrp_inferior = inferior_pid;
terminal_is_ours = 1;
}
/* Put the inferior's terminal settings into effect.
This is preparation for starting or resuming the inferior. */
void
terminal_inferior ()
{
if (terminal_is_ours) /* && inferior_thisrun_terminal == 0) */
{
fcntl (0, F_SETFL, tflags_inferior);
fcntl (0, F_SETFL, tflags_inferior);
#ifdef SYSV_TTYS
ioctl (0, TCSETA, &ti_inferior);
#else
ioctl (0, TIOCSETN, &sg_inferior);
ioctl (0, TIOCSETC, &tc_inferior);
ioctl (0, TIOCSLTC, &ltc_inferior);
ioctl (0, TIOCLSET, &lmode_inferior);
#endif
ioctl (0, TIOCSPGRP, &pgrp_inferior);
}
terminal_is_ours = 0;
}
/* Put some of our terminal settings into effect,
enough to get proper results from our output,
but do not change into or out of RAW mode
so that no input is discarded.
After doing this, either terminal_ours or terminal_inferior
should be called to get back to a normal state of affairs. */
void
terminal_ours_for_output ()
{
terminal_ours_1 (1);
}
/* Put our terminal settings into effect.
First record the inferior's terminal settings
so they can be restored properly later. */
void
terminal_ours ()
{
terminal_ours_1 (0);
}
static void
terminal_ours_1 (output_only)
int output_only;
{
/* Ignore this signal since it will happen when we try to set the pgrp. */
int (*osigttou) ();
if (!terminal_is_ours) /* && inferior_thisrun_terminal == 0) */
{
terminal_is_ours = 1;
osigttou = signal (SIGTTOU, SIG_IGN);
ioctl (0, TIOCGPGRP, &pgrp_inferior);
ioctl (0, TIOCSPGRP, &pgrp_ours);
signal (SIGTTOU, osigttou);
tflags_inferior = fcntl (0, F_GETFL, 0);
#ifdef SYSV_TTYS
ioctl (0, TCGETA, &ti_inferior);
#else
ioctl (0, TIOCGETP, &sg_inferior);
ioctl (0, TIOCGETC, &tc_inferior);
ioctl (0, TIOCGLTC, &ltc_inferior);
ioctl (0, TIOCLGET, &lmode_inferior);
#endif
}
fcntl (0, F_SETFL, tflags_ours);
fcntl (0, F_SETFL, tflags_ours);
#ifdef SYSV_TTYS
ti_ours.c_lflag |= ICANON | ISIG;
if (output_only)
ti_ours.c_lflag &= ~((ICANON|ISIG)&ti_inferior.c_lflag);
ioctl (0, TCSETA, &ti_ours);
ti_ours.c_lflag |= ICANON | ISIG;
#else
sg_ours.sg_flags &= ~RAW & ~CBREAK;
if (output_only)
sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags;
ioctl (0, TIOCSETN, &sg_ours);
ioctl (0, TIOCSETC, &tc_ours);
ioctl (0, TIOCSLTC, &ltc_ours);
ioctl (0, TIOCLSET, &lmode_ours);
sg_ours.sg_flags &= ~RAW & ~CBREAK;
#endif
}
static void
term_status_command ()
{
register int i;
printf ("Inferior's terminal status (currently saved by GDB):\n");
#ifdef SYSV_TTYS
printf ("fcntl flags = 0x%x, owner pid = %d.\n",
tflags_inferior, pgrp_inferior);
printf ("iflag = 0x%04x, oflag = 0x%04x, cflag = 0x%04x, lflag = 0x%04x\n",
ti_inferior.c_iflag, ti_inferior.c_oflag,
ti_inferior.c_cflag, ti_inferior.c_lflag);
printf ("line discipline = %d\n", ti_inferior.c_line);
printf ("control chars: ");
for (i = 0; i < NCC; i++)
printf ("0x%x ", ti_inferior.c_cc[i]);
printf ("\n");
#else
printf ("fcntl flags = 0x%x, lmode = 0x%x,\nsgttyb.sg_flags = 0x%x, owner pid = %d.\n",
tflags_inferior, lmode_inferior,
sg_inferior.sg_flags, pgrp_inferior);
printf ("tchars: ");
for (i = 0; i < sizeof (struct tchars); i++)
printf ("0x%x ", ((char *)&tc_inferior)[i]);
printf ("\n");
printf ("ltchars: ");
for (i = 0; i < sizeof (struct ltchars); i++)
printf ("0x%x ", ((char *)&ltc_inferior)[i]);
printf ("\n");
#endif
}
static void
new_tty (ttyname)
char *ttyname;
{
register int tty;
register int fd;
#if 0
/* I think it is better not to do this. Then C-z on the GDB terminal
will still stop the program, while C-z on the data terminal
will be input. */
/* Disconnect the child process from our controlling terminal. */
tty = open("/dev/tty", O_RDWR);
if (tty > 0)
{
ioctl(tty, TIOCNOTTY, 0);
close(tty);
}
#endif
/* Now open the specified new terminal. */
tty = open(ttyname, O_RDWR);
if (tty == -1)
_exit(1);
dup2(tty, 0);
dup2(tty, 1);
dup2(tty, 2);
close(tty);
}
/* Start an inferior process and returns its pid.
ALLARGS is a vector of program-name and args.
ENV is the environment vector to pass. */
int
create_inferior (allargs, env)
char **allargs;
char **env;
{
int pid;
extern int sys_nerr;
extern char *sys_errlist[];
extern int errno;
/* exec is said to fail if the executable is open. */
close_exec_file ();
pid = vfork ();
if (pid < 0)
perror_with_name ("vfork");
if (pid == 0)
{
/* Run inferior in a separate process group. */
setpgrp (getpid (), getpid ());
inferior_thisrun_terminal = inferior_io_terminal;
if (inferior_io_terminal != 0)
new_tty (inferior_io_terminal);
/* Not needed on Sun, at least, and loses there
because it clobbers the superior. */
/*??? signal (SIGQUIT, SIG_DFL);
signal (SIGINT, SIG_DFL); */
ptrace (0);
execle ("/bin/sh", "sh", "-c", allargs, 0, env);
fprintf (stderr, "Cannot exec /bin/sh: %s.\n",
errno < sys_nerr ? sys_errlist[errno] : "unknown error");
fflush (stderr);
_exit (0177);
}
return pid;
}
/* Kill the inferior process. Make us have no inferior. */
static void
kill_command ()
{
if (inferior_pid == 0)
error ("The program is not being run.");
if (!query ("Kill the inferior process? "))
error ("Not confirmed.");
kill_inferior ();
}
kill_inferior ()
{
if (inferior_pid == 0)
return;
ptrace (8, inferior_pid, 0, 0);
wait (0);
inferior_died ();
}
inferior_died ()
{
inferior_pid = 0;
attach_flag = 0;
mark_breakpoints_out ();
reopen_exec_file ();
if (have_core_file_p ())
set_current_frame (read_register (FP_REGNUM));
}
/* Resume execution of the inferior process.
If STEP is nonzero, single-step it.
If SIGNAL is nonzero, give it that signal. */
void
resume (step, signal)
int step;
int signal;
{
errno = 0;
ptrace (step ? 9 : 7, inferior_pid, 1, signal);
if (errno)
perror_with_name ("ptrace");
}
#ifdef NEW_SUN_PTRACE
/* Start debugging the process whose number is PID. */
attach (pid)
int pid;
{
errno = 0;
ptrace (PTRACE_ATTACH, pid, 0, 0);
if (errno)
perror_with_name ("ptrace");
attach_flag = 1;
return pid;
}
/* Stop debugging the process whose number is PID
and continue it with signal number SIGNAL.
SIGNAL = 0 means just continue it. */
void
detach (signal)
int signal;
{
errno = 0;
ptrace (PTRACE_DETACH, inferior_pid, 1, signal);
if (errno)
perror_with_name ("ptrace");
attach_flag = 0;
}
#endif
#ifdef NEW_SUN_PTRACE
void
fetch_inferior_registers ()
{
struct regs inferior_registers;
struct fp_status inferior_fp_registers;
extern char registers[];
ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers);
ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
bcopy (&inferior_registers, registers, 16 * 4);
bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
sizeof inferior_fp_registers.fps_regs);
*(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
*(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
bcopy (&inferior_fp_registers.fps_control,
&registers[REGISTER_BYTE (FPC_REGNUM)],
sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
}
/* 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)
int regno;
{
struct regs inferior_registers;
struct fp_status inferior_fp_registers;
extern char registers[];
bcopy (registers, &inferior_registers, 16 * 4);
bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
sizeof inferior_fp_registers.fps_regs);
inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
&inferior_fp_registers.fps_control,
sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
}
#else
void
fetch_inferior_registers ()
{
register int regno;
register unsigned int regaddr;
char buf[MAX_REGISTER_RAW_SIZE];
register int i;
#ifdef UMAX_PTRACE
unsigned int offset = 0;
#else
struct user u;
unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
offset = ptrace (3, inferior_pid, offset, 0) & UPAGE_MASK;
#endif
for (regno = 0; regno < NUM_REGS; regno++)
{
regaddr = register_addr (regno, offset);
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
{
*(int *) &buf[i] = ptrace (3, inferior_pid, regaddr, 0);
regaddr += sizeof (int);
}
supply_register (regno, buf);
}
}
/* Store our register values back into the inferior.
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
store_inferior_registers (regno)
int regno;
{
register unsigned int regaddr;
char buf[80];
#ifdef UMAX_PTRACE
unsigned int offset = 0;
#else
struct user u;
unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
offset = ptrace (3, inferior_pid, offset, 0) & UPAGE_MASK;
#endif
if (regno >= 0)
{
regaddr = register_addr (regno, offset);
errno = 0;
ptrace (6, inferior_pid, regaddr, read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing register number %d", regno);
perror_with_name (buf);
}
}
else for (regno = 0; regno < NUM_REGS; regno++)
{
regaddr = register_addr (regno, offset);
errno = 0;
ptrace (6, inferior_pid, regaddr, read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing register number %d", regno);
perror_with_name (buf);
}
}
}
#endif /* not NEW_SUN_PTRACE */
/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
in the NEW_SUN_PTRACE case.
It ought to be straightforward. But it appears that writing did
not write the data that I specified. I cannot understand where
it got the data that it actually did write. */
/* Copy LEN bytes from inferior's memory starting at MEMADDR
to debugger memory starting at MYADDR. */
read_inferior_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
register int i;
/* Round starting address down to longword boundary. */
register CORE_ADDR addr = memaddr & - sizeof (int);
/* Round ending address up; get number of longwords that makes. */
register int count
= (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
/* Allocate buffer of that many longwords. */
register int *buffer = (int *) alloca (count * sizeof (int));
/* Read all the longwords */
for (i = 0; i < count; i++, addr += sizeof (int))
buffer[i] = ptrace (1, inferior_pid, addr, 0);
/* Copy appropriate bytes out of the buffer. */
bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
}
/* Copy LEN bytes of data from debugger memnory at MYADDR
to inferior's memory at MEMADDR.
On failure (cannot write the inferior)
returns the value of errno. */
int
write_inferior_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
register int i;
/* Round starting address down to longword boundary. */
register CORE_ADDR addr = memaddr & - sizeof (int);
/* Round ending address up; get number of longwords that makes. */
register int count
= (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
/* Allocate buffer of that many longwords. */
register int *buffer = (int *) alloca (count * sizeof (int));
extern int errno;
/* Fill start and end extra bytes of buffer with existing memory data. */
buffer[0] = ptrace (1, inferior_pid, addr, 0);
if (count > 1)
buffer[count - 1]
= ptrace (1, inferior_pid,
addr + (count - 1) * sizeof (int), 0);
/* Copy data to be written over corresponding part of buffer */
bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
/* Write the entire buffer. */
for (i = 0; i < count; i++, addr += sizeof (int))
{
errno = 0;
ptrace (4, inferior_pid, addr, buffer[i]);
if (errno)
return errno;
}
return 0;
}
static void
try_writing_regs_command ()
{
register int i;
register int value;
extern int errno;
if (inferior_pid == 0)
error ("The program is not being run.");
for (i = 0; ; i += 2)
{
QUIT;
errno = 0;
value = ptrace (3, inferior_pid, i, 0);
ptrace (6, inferior_pid, i, value);
if (errno == 0)
{
printf (" Succeeded with address 0x%x; value 0x%x (%d).\n",
i, value, value);
}
else if ((i & 0377) == 0)
printf (" Failed at 0x%x.\n", i);
}
}
static
initialize ()
{
add_com ("term-status", class_obscure, term_status_command,
"Print info on inferior's saved terminal status.");
add_com ("try-writing-regs", class_obscure, try_writing_regs_command,
"Try writing all locations in inferior's system block.\n\
Report which ones can be written.");
add_com ("kill", class_run, kill_command,
"Kill execution of program being debugged.");
inferior_pid = 0;
#ifdef SYSV_TTYS
ioctl (0, TCGETA, &ti_ours);
#else
ioctl (0, TIOCGETP, &sg_ours);
ioctl (0, TIOCGETC, &tc_ours);
ioctl (0, TIOCGLTC, &ltc_ours);
ioctl (0, TIOCLGET, &lmode_ours);
#endif
fcntl (0, F_GETFL, tflags_ours);
ioctl (0, TIOCGPGRP, &pgrp_ours);
terminal_is_ours = 1;
}
END_FILE
@
1.1
log
@Initial revision
@
text
@d28 1
a30 1
#include <sys/user.h>
d36 11
d56 4
d67 2
d73 3
d80 1
d84 3
d91 1
d110 4
d118 1
d135 3
d142 1
d191 3
d198 1
d201 11
a214 3
fcntl (0, F_SETFL, tflags_ours);
fcntl (0, F_SETFL, tflags_ours);
d220 1
d228 12
d251 1
d470 1
a470 1
offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
d500 1
a500 1
offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
d647 3
d654 1
@

View File

@ -1,523 +0,0 @@
head 1.2;
access ;
symbols RMS-has:1.2;
locks ; strict;
comment @ * @;
1.2
date 88.01.26.05.16.06; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 88.01.26.05.15.44; author gnu; state Exp;
branches ;
next ;
desc
@Originally nonexistent, I create it.
@
1.2
log
@Original new config file for Mac-II running A/UX.
@
text
@/* Parameters for execution on Macintosh under A/UX, for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#ifndef mac_aux
#define mac_aux
#endif
/* Get rid of any system-imposed stack limit if possible. */
#undef SET_STACK_LIMIT_HUGE
/* Define this if the C compiler puts an underscore at the front
of external names before giving them to the linker. */
#undef NAMES_HAVE_UNDERSCORE
/* COFF format object files */
#define COFF_FORMAT
/* System eVil ttys */
#define SYSV_TTYS
/* Debugger information will not be in DBX format. */
#undef READ_DBX_FORMAT
/* Offset from address of function to start of its code.
Zero on most machines. */
#define FUNCTION_START_OFFSET 0
/* Advance PC across any function entry prologue instructions
to reach some "real" code. */
#define SKIP_PROLOGUE(pc) \
{ register int op = read_memory_integer (pc, 2); \
if (op == 0047126) \
pc += 4; /* Skip link #word */ \
else if (op == 0044016) \
pc += 6; /* Skip link #long */ \
}
/* Immediately after a function call, return the saved pc.
Can't go through the frames for this because on some machines
the new frame is not set up until the new function executes
some instructions. */
#define SAVED_PC_AFTER_CALL(frame) \
read_memory_integer (read_register (SP_REGNUM), 4)
/* Address of end of stack space. */
#define STACK_END_ADDR 0x20000000
/* Stack grows downward. */
#define INNER_THAN <
/* Sequence of bytes for breakpoint instruction. */
#define BREAKPOINT {0x4e, 0x4f}
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
#define DECR_PC_AFTER_BREAK 2
/* Nonzero if instruction at PC is a return instruction. */
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e76)
/* Return 1 if P points to an invalid floating point value. */
#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */
/* Say how long (ordinary) registers are. */
#define REGISTER_TYPE long
/* Number of machine registers */
#define NUM_REGS 31
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
#define REGISTER_NAMES \
{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
"a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \
"ps", "pc", \
"fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \
"fpcontrol", "fpstatus", "fpiaddr", "fpcode", "fpflags" }
/* Register numbers of various important registers.
Note that some of these values are "real" register numbers,
and correspond to the general registers of the machine,
and some are "phony" register numbers which are too large
to be actual register numbers as far as the user is concerned
but do serve to get the desired values when passed to read_register. */
#define FP_REGNUM 14 /* Contains address of executing stack frame */
#define SP_REGNUM 15 /* Contains address of top of stack */
#define PS_REGNUM 16 /* Contains processor status */
#define PC_REGNUM 17 /* Contains program counter */
#define FP0_REGNUM 18 /* Floating point register 0 */
#define FPC_REGNUM 26 /* 68881 control register */
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (16*4+8*12+8+20)
/* Index within `registers' of the first byte of the space for
register N. */
#define REGISTER_BYTE(N) \
((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168 \
: (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \
: (N) * 4)
/* Number of bytes of storage in the actual machine representation
for register N. On the 68000, all regs are 4 bytes
except the floating point regs which are 12 bytes. */
#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4)
/* Number of bytes of storage in the program's representation
for register N. On the 68000, all regs are 4 bytes
except the floating point regs which are 8-byte doubles. */
#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4)
/* Largest value REGISTER_RAW_SIZE can have. */
#define MAX_REGISTER_RAW_SIZE 12
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
#define MAX_REGISTER_VIRTUAL_SIZE 8
/* Nonzero if register N requires conversion
from raw format to virtual format. */
#define REGISTER_CONVERTIBLE(N) (((unsigned)(N) - FP0_REGNUM) < 8)
/* Convert data from raw format for register REGNUM
to virtual format for register REGNUM. */
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
convert_from_68881 ((FROM), (TO)); \
else \
bcopy ((FROM), (TO), 4); }
/* Convert data from virtual format for register REGNUM
to raw format for register REGNUM. */
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
convert_to_68881 ((FROM), (TO)); \
else \
bcopy ((FROM), (TO), 4); }
/* Return the GDB type object for the "standard" data type
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) \
(((unsigned)(N) - FP0_REGNUM) < 8 ? builtin_type_double : builtin_type_int)
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
into VALBUF. */
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
/* Extract from an array REGBUF containing the (raw) register state
the address in which a function should return its structure value,
as a CORE_ADDR (or an expression that can be used as one). */
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
/* Enable use of alternate code to read and write registers. */
#undef NEW_SUN_PTRACE
/* Enable use of alternate code for Sun's format of core dump file. */
#undef NEW_SUN_CORE
/* Do implement the attach and detach commands. */
#undef ATTACH_DETACH
/* It is safe to look for symsegs on a Sun, because Sun's ld
does not screw up with random garbage at end of file. */
#define READ_GDB_SYMSEGS
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
/* FRAME_CHAIN takes a frame's nominal address
and produces the frame's chain-pointer.
FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
and produces the nominal address of the caller frame.
However, if FRAME_CHAIN_VALID returns zero,
it means the given frame is the outermost one and has no caller.
In that case, FRAME_CHAIN_COMBINE is not used. */
/* In the case of the Sun, the frame's nominal address
is the address of a 4-byte word containing the calling frame's address. */
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
#define FRAME_SAVED_PC(frame) (read_memory_integer (frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) (fi.frame)
#define FRAME_LOCALS_ADDRESS(fi) (fi.frame)
/* Set VAL to the number of args passed to frame described by FI.
Can set VAL to -1, meaning no way to tell. */
/* We can't tell how many args there are
now that the C compiler delays popping them. */
#define FRAME_NUM_ARGS(val,fi) (val = -1)
#if 0
#define FRAME_NUM_ARGS(val, fi) \
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame); \
register int insn = 0177777 & read_memory_integer (pc, 2); \
val = 0; \
if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \
val = read_memory_integer (pc + 2, 2); \
else if ((insn & 0170777) == 0050217 /* addql #N, sp */ \
|| (insn & 0170777) == 0050117) /* addqw */ \
{ val = (insn >> 9) & 7; if (val == 0) val = 8; } \
else if (insn == 0157774) /* addal #WW, sp */ \
val = read_memory_integer (pc + 2, 4); \
val >>= 2; }
#endif
/* Return number of bytes at start of arglist that are not really args. */
#define FRAME_ARGS_SKIP 8
/* Put here the code to store, into a struct frame_saved_regs,
the addresses of the saved registers of frame described by FRAME_INFO.
This includes special registers such as pc and fp saved in special
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame. */
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
{ register int regnum; \
register int regmask; \
register CORE_ADDR next_addr; \
register CORE_ADDR pc; \
int nextinsn; \
bzero (&frame_saved_regs, sizeof frame_saved_regs); \
if ((frame_info).pc >= (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \
&& (frame_info).pc <= (frame_info).frame) \
{ next_addr = (frame_info).frame; \
pc = (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\
else \
{ pc = get_pc_function_start ((frame_info).pc); \
/* Verify we have a link a6 instruction next; \
if not we lose. If we win, find the address above the saved \
regs using the amount of storage from the link instruction. */\
if (044016 == read_memory_integer (pc, 2)) \
next_addr = (frame_info).frame + read_memory_integer (pc += 2, 4), pc+=4; \
else if (047126 == read_memory_integer (pc, 2)) \
next_addr = (frame_info).frame + read_memory_integer (pc += 2, 2), pc+=2; \
else goto lose; \
/* If have an addal #-n, sp next, adjust next_addr. */ \
if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \
next_addr += read_memory_integer (pc += 2, 4), pc += 4; \
} \
/* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \
regmask = read_memory_integer (pc + 2, 2); \
/* But before that can come an fmovem. Check for it. */ \
nextinsn = 0xffff & read_memory_integer (pc, 2); \
if (0xf227 == nextinsn \
&& (regmask & 0xff00) == 0xe000) \
{ pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \
if (regmask & 1) \
(frame_saved_regs).regs[regnum] = (next_addr -= 12); \
regmask = read_memory_integer (pc + 2, 2); } \
if (0044327 == read_memory_integer (pc, 2)) \
{ pc += 4; /* Regmask's low bit is for register 0, the first written */ \
for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \
if (regmask & 1) \
(frame_saved_regs).regs[regnum] = (next_addr += 4) - 4; } \
else if (0044347 == read_memory_integer (pc, 2)) \
{ pc += 4; /* Regmask's low bit is for register 15, the first pushed */ \
for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \
if (regmask & 1) \
(frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
else if (0x2f00 == 0xfff0 & read_memory_integer (pc, 2)) \
{ regnum = 0xf & read_memory_integer (pc, 2); pc += 2; \
(frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
/* fmovemx to index of sp may follow. */ \
regmask = read_memory_integer (pc + 2, 2); \
nextinsn = 0xffff & read_memory_integer (pc, 2); \
if (0xf236 == nextinsn \
&& (regmask & 0xff00) == 0xf000) \
{ pc += 10; /* Regmask's low bit is for register fp0, the first written */ \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \
if (regmask & 1) \
(frame_saved_regs).regs[regnum] = (next_addr += 12) - 12; \
regmask = read_memory_integer (pc + 2, 2); } \
/* clrw -(sp); movw ccr,-(sp) may follow. */ \
if (0x426742e7 == read_memory_integer (pc, 4)) \
(frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \
lose: ; \
(frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 8; \
(frame_saved_regs).regs[FP_REGNUM] = (frame_info).frame; \
(frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4; \
}
/* Things needed for making the inferior call functions. */
/* Push an empty stack frame, to record the current PC, etc. */
#define PUSH_DUMMY_FRAME \
{ register CORE_ADDR sp = read_register (SP_REGNUM); \
register int regnum; \
char raw_buffer[12]; \
sp = push_word (sp, read_register (PC_REGNUM)); \
sp = push_word (sp, read_register (FP_REGNUM)); \
write_register (FP_REGNUM, sp); \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
{ read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \
sp = push_bytes (sp, raw_buffer, 12); } \
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
sp = push_word (sp, read_register (regnum)); \
sp = push_word (sp, read_register (PS_REGNUM)); \
write_register (SP_REGNUM, sp); }
/* Discard from the stack the innermost frame,
restoring all saved registers. */
#define POP_FRAME \
{ register CORE_ADDR fp = read_register (FP_REGNUM); \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info fi; \
char raw_buffer[12]; \
fi = get_frame_info (fp); \
get_frame_saved_regs (&fi, &fsr); \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
if (fsr.regs[regnum]) \
{ read_memory (fsr.regs[regnum], raw_buffer, 12); \
write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
if (fsr.regs[regnum]) \
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
if (fsr.regs[PS_REGNUM]) \
write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
write_register (SP_REGNUM, fp + 8); \
set_current_frame (read_register (FP_REGNUM)); }
/* This sequence of words is the instructions
fmovem 0xff,-(sp)
moveml 0xfffc,-(sp)
clrw -(sp)
movew ccr,-(sp)
/..* The arguments are pushed at this point by GDB;
no code is needed in the dummy for this.
The CALL_DUMMY_START_OFFSET gives the position of
the following jsr instruction. *../
jsr @@#32323232
addl #69696969,sp
bpt
nop
Note this is 28 bytes.
We actually start executing at the jsr, since the pushing of the
registers is done by PUSH_DUMMY_FRAME. If this were real code,
the arguments for the function called by the jsr would be pushed
between the moveml and the jsr, and we could allow it to execute through.
But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
and we cannot allow the moveml to push the registers again lest they be
taken for the arguments. */
#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
#define CALL_DUMMY_LENGTH 28
#define CALL_DUMMY_START_OFFSET 12
/* Insert the specified number of args and function address
into a call sequence of the above form stored at DUMMYNAME. */
#define FIX_CALL_DUMMY(dummyname, fun, nargs) \
{ *(int *)((char *) dummyname + 20) = nargs * 4; \
*(int *)((char *) dummyname + 14) = fun; }
/* Interface definitions for kernel debugger KDB. */
/* Map machine fault codes into signal numbers.
First subtract 0, divide by 4, then index in a table.
Faults for which the entry in this table is 0
are not handled by KDB; the program's own trap handler
gets to handle then. */
#define FAULT_CODE_ORIGIN 0
#define FAULT_CODE_UNITS 4
#define FAULT_TABLE \
{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
0, 0, 0, 0, 0, 0, 0, 0, \
SIGILL }
/* Start running with a stack stretching from BEG to END.
BEG and END should be symbols meaningful to the assembler.
This is used only for kdb. */
#define INIT_STACK(beg, end) \
{ asm (".globl end"); \
asm ("movel #end, sp"); \
asm ("movel #0,a6"); }
/* Push the frame pointer register on the stack. */
#define PUSH_FRAME_PTR \
asm ("movel a6,sp@@-");
/* Copy the top-of-stack to the frame pointer register. */
#define POP_FRAME_PTR \
asm ("movl sp@@,a6");
/* After KDB is entered by a fault, push all registers
that GDB thinks about (all NUM_REGS of them),
so that they appear in order of ascending GDB register number.
The fault code will be on the stack beyond the last register. */
#define PUSH_REGISTERS \
{ asm ("clrw -(sp)"); \
asm ("pea sp@@(10)"); \
asm ("movem #0xfffe,sp@@-"); }
/* Assuming the registers (including processor status) have been
pushed on the stack in order of ascending GDB register number,
restore them and return to the address in the saved PC register. */
#define POP_REGISTERS \
{ asm ("subil #8,sp@@(28)"); \
asm ("movem sp@@,#0xffff"); \
asm ("rte"); }
@
1.1
log
@Initial revision
@
text
@d1 485
@

View File

@ -1,43 +0,0 @@
head 1.2;
access ;
symbols RMS-has:1.2;
locks ; strict;
comment @ * @;
1.2
date 88.01.26.05.19.09; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 88.01.26.05.18.45; author gnu; state Exp;
branches ;
next ;
desc
@Originally nonexistent.
@
1.2
log
@Created by John Gilmore for Mac A/UX
@
text
@
/* This is how the size of an individual .o file's text segment
is rounded on a mac under a/ux. */
#define FILEADDR_ROUND(addr) (addr)
@
1.1
log
@Initial revision
@
text
@d1 5
@

View File

@ -1,828 +0,0 @@
head 1.2;
access ;
symbols RMS-has:1.2;
locks ; strict;
comment @ * @;
1.2
date 88.01.26.05.08.29; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 88.01.21.22.04.55; author gnu; state Exp;
branches ;
next ;
desc
@From RMS's development sources on wheaties, 20Jan88
@
1.2
log
@Avoid the so-called "portable" preassembled instructions; call a macro
to generate them, since a/ux assembler uses a different syntax (grumble)
@
text
@/* Print m68k instructions for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include <stdio.h>
#include "defs.h"
#include "param.h"
#include "symtab.h"
#include "m68k-opcode.h"
/* 68k instructions are never longer than this many bytes. */
#define MAXLEN 22
/* Number of elements in the opcode table. */
#define NOPCODES (sizeof m68k_opcodes / sizeof m68k_opcodes[0])
extern char *reg_names[];
char *fpcr_names[] = { "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr",
"fpiar/fpcr", "fpsr/fpcr", "fpiar-fpcr"};
static unsigned char *print_insn_arg ();
static unsigned char *print_indexed ();
static void print_base ();
static int fetch_arg ();
#define NEXTBYTE(p) (p += 2, ((char *)p)[-1])
#define NEXTWORD(p) \
(p += 2, ((((char *)p)[-2]) << 8) + p[-1])
#define NEXTLONG(p) \
(p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
#define NEXTSINGLE(p) \
(p += 4, *((float *)(p - 4)))
#define NEXTDOUBLE(p) \
(p += 8, *((double *)(p - 8)))
#define NEXTEXTEND(p) \
(p += 12, 0.0) /* Need a function to convert from extended to double
precision... */
#define NEXTPACKED(p) \
(p += 12, 0.0) /* Need a function to convert from packed to double
precision. Actually, it's easier to print a
packed number than a double anyway, so maybe
there should be a special case to handle this... */
/* Print the m68k instruction at address MEMADDR in debugged memory,
on STREAM. Returns length of the instruction, in bytes. */
int
print_insn (memaddr, stream)
CORE_ADDR memaddr;
FILE *stream;
{
unsigned char buffer[MAXLEN];
register int i;
register unsigned char *p;
register char *d;
register int bestmask;
int best;
read_memory (memaddr, buffer, MAXLEN);
bestmask = 0;
best = -1;
for (i = 0; i < NOPCODES; i++)
{
register unsigned int opcode = m68k_opcodes[i].opcode;
register unsigned int match = m68k_opcodes[i].match;
if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
&& ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
&& ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
&& ((0xff & buffer[3] & match) == (0xff & opcode)))
{
/* Don't use for printout the variants of divul and divsl
that have the same register number in two places.
The more general variants will match instead. */
for (d = m68k_opcodes[i].args; *d; d += 2)
if (d[1] == 'D')
break;
/* Don't use for printout the variants of most floating
point coprocessor instructions which use the same
register number in two places, as above. */
if (*d == 0)
for (d = m68k_opcodes[i].args; *d; d += 2)
if (d[1] == 't')
break;
if (*d == 0 && match > bestmask)
{
best = i;
bestmask = match;
}
}
}
/* Handle undefined instructions. */
if (best < 0)
{
fprintf (stream, "0%o", (buffer[0] << 8) + buffer[1]);
return 2;
}
fprintf (stream, "%s", m68k_opcodes[best].name);
/* Point at first word of argument data,
and at descriptor for first argument. */
p = buffer + 2;
/* Why do this this way? -MelloN */
for (d = m68k_opcodes[best].args; *d; d += 2)
{
if (d[0] == '#')
{
if (d[1] == 'l' && p - buffer < 6)
p = buffer + 6;
else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' )
p = buffer + 4;
}
if (d[1] >= '1' && d[1] <= '3' && p - buffer < 4)
p = buffer + 4;
if (d[1] >= '4' && d[1] <= '6' && p - buffer < 6)
p = buffer + 6;
}
d = m68k_opcodes[best].args;
if (*d)
fputc (' ', stream);
while (*d)
{
p = print_insn_arg (d, buffer, p, memaddr + p - buffer, stream);
d += 2;
if (*d && *(d - 2) != 'I' && *d != 'k')
fprintf (stream, ",");
}
return p - buffer;
}
static unsigned char *
print_insn_arg (d, buffer, p, addr, stream)
char *d;
unsigned char *buffer;
register unsigned char *p;
CORE_ADDR addr; /* PC for this arg to be relative to */
FILE *stream;
{
register int val;
register int place = d[1];
int regno;
register char *regname;
register unsigned char *p1;
register double flval;
int flt_p;
switch (*d)
{
case 'C':
fprintf (stream, "ccr");
break;
case 'S':
fprintf (stream, "sr");
break;
case 'U':
fprintf (stream, "usp");
break;
case 'J':
{
static struct { char *name; int value; } names[]
= {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002},
{"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802},
{"msp", 0x803}, {"isp", 0x804}};
val = fetch_arg (buffer, place, 12);
for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
if (names[regno].value == val)
{
fprintf (stream, names[regno].name);
break;
}
if (regno < 0)
fprintf (stream, "%d", val);
}
break;
case 'Q':
val = fetch_arg (buffer, place, 3);
if (val == 0) val = 8;
fprintf (stream, "#%d", val);
break;
case 'M':
val = fetch_arg (buffer, place, 8);
if (val & 0x80)
val = val - 0x100;
fprintf (stream, "#%d", val);
break;
case 'T':
val = fetch_arg (buffer, place, 4);
fprintf (stream, "#%d", val);
break;
case 'D':
fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3)]);
break;
case 'A':
fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3) + 010]);
break;
case 'R':
fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 4)]);
break;
case 'F':
fprintf (stream, "fp%d", fetch_arg (buffer, place, 3));
break;
case 'O':
val = fetch_arg (buffer, place, 6);
if (val & 0x20)
fprintf (stream, "%s", reg_names [val & 7]);
else
fprintf (stream, "%d", val);
break;
case '+':
fprintf (stream, "(%s)+", reg_names[fetch_arg (buffer, place, 3) + 8]);
break;
case '-':
fprintf (stream, "-(%s)", reg_names[fetch_arg (buffer, place, 3) + 8]);
break;
case 'k':
if (place == 'k')
fprintf (stream, "{%s}", reg_names[fetch_arg (buffer, place, 3)]);
else if (place == 'C')
{
val = fetch_arg (buffer, place, 7);
if ( val > 63 ) /* This is a signed constant. */
val -= 128;
fprintf (stream, "{#%d}", val);
}
else
error ("Invalid arg format in opcode table: \"%c%c\".",
*d, place);
break;
case '#':
p1 = buffer + 2;
if (place == 's')
val = fetch_arg (buffer, place, 4);
else if (place == 'C')
val = fetch_arg (buffer, place, 7);
else if (place == '8')
val = fetch_arg (buffer, place, 3);
else if (place == '3')
val = fetch_arg (buffer, place, 8);
else if (place == 'b')
val = NEXTBYTE (p1);
else if (place == 'w')
val = NEXTWORD (p1);
else if (place == 'l')
val = NEXTLONG (p1);
else
error ("Invalid arg format in opcode table: \"%c%c\".",
*d, place);
fprintf (stream, "#%d", val);
break;
case '^':
if (place == 's')
val = fetch_arg (buffer, place, 4);
else if (place == 'C')
val = fetch_arg (buffer, place, 7);
else if (place == '8')
val = fetch_arg (buffer, place, 3);
else if (place == 'b')
val = NEXTBYTE (p);
else if (place == 'w')
val = NEXTWORD (p);
else if (place == 'l')
val = NEXTLONG (p);
else
error ("Invalid arg format in opcode table: \"%c%c\".",
*d, place);
fprintf (stream, "#%d", val);
break;
case 'B':
if (place == 'b')
val = NEXTBYTE (p);
else if (place == 'w')
val = NEXTWORD (p);
else if (place == 'l')
val = NEXTLONG (p);
else if (place == 'g')
{
val = ((char *)buffer)[1];
if (val == 0)
val = NEXTWORD (p);
else if (val == -1)
val = NEXTLONG (p);
}
else if (place == 'c')
{
if (buffer[1] & 0x40) /* If bit six is one, long offset */
val = NEXTLONG (p);
else
val = NEXTWORD (p);
}
else
error ("Invalid arg format in opcode table: \"%c%c\".",
*d, place);
print_address (addr + val, stream);
break;
case 'd':
val = NEXTWORD (p);
fprintf (stream, "%d(%s)", val, fetch_arg (buffer, place, 3));
break;
case 's':
fprintf (stream, "%s", fpcr_names[fetch_arg (buffer, place, 3)]);
break;
case 'I':
val = fetch_arg (buffer, 'd', 3); /* Get coprocessor ID... */
if (val != 1) /* Unusual coprocessor ID? */
fprintf (stream, "(cpid=%d) ", val);
if (place == 'i')
p += 2; /* Skip coprocessor extended operands */
break;
case '*':
case '~':
case '%':
case ';':
case '@@':
case '!':
case '$':
case '?':
case '/':
case '&':
if (place == 'd')
{
val = fetch_arg (buffer, 'x', 6);
val = ((val & 7) << 3) + ((val >> 3) & 7);
}
else
val = fetch_arg (buffer, 's', 6);
/* Get register number assuming address register. */
regno = (val & 7) + 8;
regname = reg_names[regno];
switch (val >> 3)
{
case 0:
fprintf (stream, "%s", reg_names[val]);
break;
case 1:
fprintf (stream, "%s", regname);
break;
case 2:
fprintf (stream, "(%s)", regname);
break;
case 3:
fprintf (stream, "(%s)+", regname);
break;
case 4:
fprintf (stream, "-(%s)", regname);
break;
case 5:
val = NEXTWORD (p);
fprintf (stream, "%d(%s)", val, regname);
break;
case 6:
p = print_indexed (regno, p, addr, stream);
break;
case 7:
switch (val & 7)
{
case 0:
val = NEXTWORD (p);
fprintf (stream, "@@#");
print_address (val, stream);
break;
case 1:
val = NEXTLONG (p);
fprintf (stream, "@@#");
print_address (val, stream);
break;
case 2:
val = NEXTWORD (p);
print_address (addr + val, stream);
break;
case 3:
p = print_indexed (-1, p, addr, stream);
break;
case 4:
flt_p = 1; /* Assume it's a float... */
switch( place )
{
case 'b':
val = NEXTBYTE (p);
flt_p = 0;
break;
case 'w':
val = NEXTWORD (p);
flt_p = 0;
break;
case 'l':
val = NEXTLONG (p);
flt_p = 0;
break;
case 'f':
flval = NEXTSINGLE(p);
break;
case 'F':
flval = NEXTDOUBLE(p);
break;
case 'x':
flval = NEXTEXTEND(p);
break;
case 'p':
flval = NEXTPACKED(p);
break;
default:
error ("Invalid arg format in opcode table: \"%c%c\".",
*d, place);
}
if ( flt_p ) /* Print a float? */
fprintf (stream, "#%g", flval);
else
fprintf (stream, "#%d", val);
break;
default:
fprintf (stream, "<invalid address mode 0%o>", val);
}
}
break;
default:
error ("Invalid arg format in opcode table: \"%c\".", *d);
}
return (unsigned char *) p;
}
/* Fetch BITS bits from a position in the instruction specified by CODE.
CODE is a "place to put an argument", or 'x' for a destination
that is a general address (mode and register).
BUFFER contains the instruction. */
static int
fetch_arg (buffer, code, bits)
unsigned char *buffer;
char code;
int bits;
{
register int val;
switch (code)
{
case 's':
val = buffer[1];
break;
case 'd': /* Destination, for register or quick. */
val = (buffer[0] << 8) + buffer[1];
val >>= 9;
break;
case 'x': /* Destination, for general arg */
val = (buffer[0] << 8) + buffer[1];
val >>= 6;
break;
case 'k':
val = (buffer[3] >> 4);
break;
case 'C':
val = buffer[3];
break;
case '1':
val = (buffer[2] << 8) + buffer[3];
val >>= 12;
break;
case '2':
val = (buffer[2] << 8) + buffer[3];
val >>= 6;
break;
case '3':
case 'j':
val = (buffer[2] << 8) + buffer[3];
break;
case '4':
val = (buffer[4] << 8) + buffer[5];
val >>= 12;
break;
case '5':
val = (buffer[4] << 8) + buffer[5];
val >>= 6;
break;
case '6':
val = (buffer[4] << 8) + buffer[5];
break;
case '7':
val = (buffer[2] << 8) + buffer[3];
val >>= 7;
break;
case '8':
val = (buffer[2] << 8) + buffer[3];
val >>= 10;
break;
default:
abort ();
}
switch (bits)
{
case 3:
return val & 7;
case 4:
return val & 017;
case 5:
return val & 037;
case 6:
return val & 077;
case 7:
return val & 0177;
case 8:
return val & 0377;
case 12:
return val & 07777;
default:
abort ();
}
}
/* Print an indexed argument. The base register is BASEREG (-1 for pc).
P points to extension word, in buffer.
ADDR is the nominal core address of that extension word. */
static unsigned char *
print_indexed (basereg, p, addr, stream)
int basereg;
unsigned char *p;
FILE *stream;
CORE_ADDR addr;
{
register int word;
static char *scales[] = {"", "*2", "*4", "*8"};
register int base_disp;
register int outer_disp;
char buf[40];
word = NEXTWORD (p);
/* Generate the text for the index register.
Where this will be output is not yet determined. */
sprintf (buf, "[%s.%c%s]",
reg_names[(word >> 12) & 0xf],
(word & 0x800) ? 'l' : 'w',
scales[(word >> 9) & 3]);
/* Handle the 68000 style of indexing. */
if ((word & 0x100) == 0)
{
print_base (basereg,
((word & 0x80) ? word | 0xff00 : word & 0xff)
+ ((basereg == -1) ? addr : 0),
stream);
fprintf (stream, "%s", buf);
return p;
}
/* Handle the generalized kind. */
/* First, compute the displacement to add to the base register. */
if (word & 0200)
basereg = -2;
if (word & 0100)
buf[0] = 0;
base_disp = 0;
switch ((word >> 4) & 3)
{
case 2:
base_disp = NEXTWORD (p);
break;
case 3:
base_disp = NEXTLONG (p);
}
if (basereg == -1)
base_disp += addr;
/* Handle single-level case (not indirect) */
if ((word & 7) == 0)
{
print_base (basereg, base_disp, stream);
fprintf (stream, "%s", buf);
return p;
}
/* Two level. Compute displacement to add after indirection. */
outer_disp = 0;
switch (word & 3)
{
case 2:
outer_disp = NEXTWORD (p);
break;
case 3:
outer_disp = NEXTLONG (p);
}
fprintf (stream, "%d(", outer_disp);
print_base (basereg, base_disp, stream);
/* If postindexed, print the closeparen before the index. */
if (word & 4)
fprintf (stream, ")%s", buf);
/* If preindexed, print the closeparen after the index. */
else
fprintf (stream, "%s)", buf);
return p;
}
/* Print a base register REGNO and displacement DISP, on STREAM.
REGNO = -1 for pc, -2 for none (suppressed). */
static void
print_base (regno, disp, stream)
int regno;
int disp;
FILE *stream;
{
if (regno == -2)
fprintf (stream, "%d", disp);
else if (regno == -1)
fprintf (stream, "0x%x", disp);
else
fprintf (stream, "%d(%s)", disp, reg_names[regno]);
}
/* This is not part of insn printing, but it is machine-specific,
so this is a convenient place to put it.
Convert a 68881 extended float to a double.
FROM is the address of the extended float.
Store the double in *TO. */
#ifdef mac_aux
#ifdef __STDC__
#define asm16(str) asm ("short " str#)
#else
#define asm16(str) asm ("short str")
#endif
#else
#ifdef __STDC__
#define asm16(str) asm (".word " str#)
#else
#define asm16(str) asm (".word str")
#endif
#endif
convert_from_68881 (from, to)
char *from;
double *to;
{
#if 0
asm ("movl a6@@(8),a0");
asm ("movl a6@@(12),a1");
asm ("fmovex a0@@,fp0");
asm ("fmoved fp0,a1@@");
#else
/* Hand-assemble those insns since some assemblers lose
and some have different syntax. */
asm16 (020156);
asm16 (8);
asm16 (021156);
asm16 (12);
asm16 (0xf210);
asm16 (0x4800);
asm16 (0xf211);
asm16 (0x7400);
#endif
}
/* The converse: convert the double *FROM to an extended float
and store where TO points. */
convert_to_68881 (from, to)
double *from;
char *to;
{
#if 0
asm ("movl a6@@(8),a0");
asm ("movl a6@@(12),a1");
asm ("fmoved a0@@,fp0");
asm ("fmovex fp0,a1@@");
#else
/* Hand-assemble those insns since some assemblers lose. */
asm16 (020156);
asm16 (8);
asm16 (021156);
asm16 (12);
asm16 (0xf210);
asm16 (0x5400);
asm16 (0xf211);
asm16 (0x6800);
#endif
}
@
1.1
log
@Initial revision
@
text
@d713 14
d739 8
a746 6
asm (".word 020156");
asm (".word 8");
asm (".word 021156");
asm (".word 12");
asm (".long 0xf2104800");
asm (".long 0xf2117400");
d764 8
a771 6
asm (".word 020156");
asm (".word 8");
asm (".word 021156");
asm (".word 12");
asm (".long 0xf2105400");
asm (".long 0xf2116800");
@

File diff suppressed because it is too large Load Diff

View File

@ -1,705 +0,0 @@
head 1.2;
access ;
symbols RMS-has:1.2;
locks ; strict;
comment @ * @;
1.2
date 88.01.26.05.09.34; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 88.01.21.04.30.11; author gnu; state Exp;
branches ;
next ;
desc
@Original from RMS development sources on wheaties, 20Jan88
@
1.2
log
@Add <sys/types.h>
@
text
@/* List lines of source files for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/file.h>
#include "defs.h"
#include "initialize.h"
#include "symtab.h"
/* Path of directories to search for source files.
Same format as the PATH environment variable's value. */
static char *source_path;
/* Symtab of default file for listing lines of. */
struct symtab *current_source_symtab;
/* Default next line to list. */
int current_source_line;
/* Line for "info line" to work on if no line specified. */
static int line_info_default_line;
/* First line number listed by last listing command. */
static int first_line_listed;
START_FILE
/* Set the source file default for the "list" command,
specifying a symtab. */
void
select_source_symtab (s)
register struct symtab *s;
{
if (s)
{
struct symtab_and_line sal;
/* Make the default place to list be the function `main'
if one exists. */
if (lookup_symbol ("main", 0, VAR_NAMESPACE))
{
sal = decode_line_spec ("main", 1);
current_source_symtab = sal.symtab;
current_source_line = sal.line - 9;
return;
}
/* If there is no `main', use the last symtab in the list,
which is actually the first found in the file's symbol table.
But ignore .h files. */
do
{
char *name = s->filename;
int len = strlen (name);
if (! (len > 2 && !strcmp (&name[len - 2], ".h")))
current_source_symtab = s;
s = s->next;
}
while (s);
current_source_line = 1;
}
}
static void
directories_info ()
{
printf ("Source directories searched: %s\n", source_path);
}
static void
init_source_path ()
{
register struct symtab *s;
char wd[MAXPATHLEN];
if (getwd (wd) == NULL)
perror_with_name ("getwd");
source_path = savestring (wd, strlen (wd));
/* Forget what we learned about line positions in source files;
must check again now since files may be found in
a different directory now. */
for (s = symtab_list; s; s = s->next)
if (s->line_charpos != 0)
{
free (s->line_charpos);
s->line_charpos = 0;
}
}
void
directory_command (dirname, from_tty)
char *dirname;
int from_tty;
{
char *old = source_path;
char wd[MAXPATHLEN];
if (getwd (wd) == NULL)
perror_with_name ("getwd");
if (dirname == 0)
{
if (query ("Reinitialize source path to %s? ", wd))
{
init_source_path ();
free (old);
}
}
else
{
struct stat st;
register int len = strlen (dirname);
register char *tem;
extern char *index ();
if (index (dirname, ':'))
error ("Please add one directory at a time to the source path.");
if (dirname[len - 1] == '/')
/* Sigh. "foo/" => "foo" */
dirname[--len] == '\0';
while (dirname[len - 1] == '.')
{
if (len == 1)
{
/* "." => getwd () */
dirname = wd;
goto append;
}
else if (dirname[len - 2] == '/')
{
if (len == 2)
{
/* "/." => "/" */
dirname[--len] = '\0';
goto append;
}
else
{
/* "...foo/." => "...foo" */
dirname[len -= 2] = '\0';
continue;
}
}
break;
}
if (dirname[0] != '/')
dirname = concat (wd, "/", dirname);
else
dirname = savestring (dirname, len);
make_cleanup (free, dirname);
if (stat (dirname, &st) < 0)
perror_with_name (dirname);
if ((st.st_mode & S_IFMT) != S_IFDIR)
error ("%s is not a directory.", dirname);
append:
len = strlen (dirname);
tem = source_path;
while (1)
{
if (!strncmp (tem, dirname, len)
&& (tem[len] == '\0' || tem[len] == ':'))
{
printf ("\"%s\" is already in the source path.\n",
dirname);
break;
}
tem = index (tem, ':');
if (tem)
tem++;
else
{
source_path = concat (old, ":", dirname);
free (old);
break;
}
}
if (from_tty)
directories_info ();
}
}
/* Open a file named STRING, searching path PATH (dir names sep by colons)
using mode MODE and protection bits PROT in the calls to open.
If TRY_CWD_FIRST, try to open ./STRING before searching PATH.
(ie pretend the first element of PATH is ".")
If FILENAMED_OPENED is non-null, set it to a newly allocated string naming
the actual file opened (this string will always start with a "/"
If a file is found, return the descriptor.
Otherwise, return -1, with errno set for the last name we tried to open. */
/* >>>> This should only allow files of certain types,
>>>> eg executable, non-directory */
int
openp (path, try_cwd_first, string, mode, prot, filename_opened)
char *path;
int try_cwd_first;
char *string;
int mode;
int prot;
char **filename_opened;
{
register int fd;
register char *filename;
register char *p, *p1;
register int len;
/* ./foo => foo */
while (string[0] == '.' && string[1] == '/')
string += 2;
if (try_cwd_first || string[0] == '/')
{
filename = string;
fd = open (filename, mode, prot);
if (fd >= 0 || string[0] == '/')
goto done;
}
filename = (char *) alloca (strlen (path) + strlen (string) + 2);
fd = -1;
for (p = path; p; p = p1 ? p1 + 1 : 0)
{
p1 = (char *) index (p, ':');
if (p1)
len = p1 - p;
else
len = strlen (p);
strncpy (filename, p, len);
filename[len] = 0;
strcat (filename, "/");
strcat (filename, string);
fd = open (filename, mode, prot);
if (fd >= 0) break;
}
done:
if (filename_opened)
if (fd < 0)
*filename_opened = (char *) 0;
else if (filename[0] == '/')
*filename_opened = savestring (filename, strlen (filename));
else
{
char dirname[MAXPATHLEN];
if (getwd (dirname) == NULL)
perror_with_name ("getwd");
*filename_opened = concat (dirname, "/", filename);
}
return fd;
}
/* Create and initialize the table S->line_charpos that records
the positions of the lines in the source file, which is assumed
to be open on descriptor DESC.
All set S->nlines to the number of such lines. */
static void
find_source_lines (s, desc)
struct symtab *s;
int desc;
{
struct stat st;
register char *data, *p, *end;
int nlines = 0;
int lines_allocated = 1000;
int *line_charpos = (int *) xmalloc (lines_allocated * sizeof (int));
extern int exec_mtime;
fstat (desc, &st);
if (get_exec_file () != 0 && exec_mtime < st.st_mtime)
printf ("Source file is more recent than executable.\n");
data = (char *) alloca (st.st_size);
myread (desc, data, st.st_size);
end = data + st.st_size;
p = data;
line_charpos[0] = 0;
nlines = 1;
while (p != end)
{
if (*p++ == '\n')
{
if (nlines == lines_allocated)
line_charpos = (int *) xrealloc (line_charpos,
sizeof (int) * (lines_allocated *= 2));
line_charpos[nlines++] = p - data;
}
}
s->nlines = nlines;
s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int));
}
/* Return the character position of a line LINE in symtab S.
Return 0 if anything is invalid. */
int
source_line_charpos (s, line)
struct symtab *s;
int line;
{
if (!s) return 0;
if (!s->line_charpos || line <= 0) return 0;
if (line > s->nlines)
line = s->nlines;
return s->line_charpos[line - 1];
}
/* Return the line number of character position POS in symtab S. */
int
source_charpos_line (s, chr)
register struct symtab *s;
register int chr;
{
register int line = 0;
register int *lnp;
if (s == 0 || s->line_charpos == 0) return 0;
lnp = s->line_charpos;
/* Files are usually short, so sequential search is Ok */
while (line < s->nlines && *lnp <= chr)
{
line++;
lnp++;
}
if (line >= s->nlines)
line = s->nlines;
return line;
}
/* Get full pathname and line number positions for a symtab.
Return nonzero if line numbers may have changed.
Set *FULLNAME to actual name of the file as found by `openp',
or to 0 if the file is not found. */
int
get_filename_and_charpos (s, line, fullname)
struct symtab *s;
int line;
char **fullname;
{
register int desc, linenums_changed = 0;
desc = openp (source_path, 0, s->filename, O_RDONLY, 0, fullname);
if (desc < 0)
{
*fullname = NULL;
return 0;
}
if (s->line_charpos == 0) linenums_changed = 1;
if (linenums_changed) find_source_lines (s, desc);
close (desc);
return linenums_changed;
}
/* Print source lines from the file of symtab S,
starting with line number LINE and stopping before line number STOPLINE. */
void
print_source_lines (s, line, stopline)
struct symtab *s;
int line, stopline;
{
register int c;
register int desc;
register FILE *stream;
int nlines = stopline - line;
desc = openp (source_path, 0, s->filename, O_RDONLY, 0, (char **) 0);
if (desc < 0)
perror_with_name (s->filename);
if (s->line_charpos == 0)
find_source_lines (s, desc);
if (line < 1 || line >= s->nlines)
{
close (desc);
error ("Line number out of range; %s has %d lines.",
s->filename, s->nlines);
}
if (lseek (desc, s->line_charpos[line - 1], 0) < 0)
{
close (desc);
perror_with_name (s->filename);
}
current_source_symtab = s;
current_source_line = line;
first_line_listed = line;
stream = fdopen (desc, "r");
clearerr (stream);
while (nlines-- > 0)
{
c = fgetc (stream);
if (c == EOF) break;
line_info_default_line = current_source_line;
printf ("%d\t", current_source_line++);
do
{
if (c < 040 && c != '\t' && c != '\n')
{
fputc ('^', stdout);
fputc (c + 0100, stdout);
}
else if (c == 0177)
printf ("^?");
else
fputc (c, stdout);
} while (c != '\n' && (c = fgetc (stream)) >= 0);
}
fclose (stream);
}
static void
list_command (arg, from_tty)
char *arg;
int from_tty;
{
struct symtab_and_line sal, sal_end;
struct symbol *sym;
char *arg1;
int no_end = 1;
int dummy_end = 0;
int dummy_beg = 0;
int linenum_beg = 0;
char *p;
if (symtab_list == 0)
error ("Listing source lines requires symbols.");
/* "l" or "l +" lists next ten lines. */
if (arg == 0 || !strcmp (arg, "+"))
{
if (current_source_symtab == 0)
error ("No default source file yet. Do \"help list\".");
print_source_lines (current_source_symtab, current_source_line,
current_source_line + 10);
return;
}
/* "l -" lists previous ten lines, the ones before the ten just listed. */
if (!strcmp (arg, "-"))
{
if (current_source_symtab == 0)
error ("No default source file yet. Do \"help list\".");
print_source_lines (current_source_symtab,
max (first_line_listed - 10, 1),
first_line_listed);
return;
}
/* Now if there is only one argument, decode it in SAL
and set NO_END.
If there are two arguments, decode them in SAL and SAL_END
and clear NO_END; however, if one of the arguments is blank,
set DUMMY_BEG or DUMMY_END to record that fact. */
arg1 = arg;
if (*arg1 == ',')
dummy_beg = 1;
else
sal = decode_line_1 (&arg1, 0, 0, 0);
/* Record whether the BEG arg is all digits. */
for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; p++);
linenum_beg = (p == arg1);
while (*arg1 == ' ' || *arg1 == '\t')
arg1++;
if (*arg1 == ',')
{
no_end = 0;
arg1++;
while (*arg1 == ' ' || *arg1 == '\t')
arg1++;
if (*arg1 == 0)
dummy_end = 1;
else if (dummy_beg)
sal_end = decode_line_1 (&arg1, 0, 0, 0);
else
sal_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line);
}
if (*arg1)
error ("Junk at end of line specification.");
if (!no_end && !dummy_beg && !dummy_end
&& sal.symtab != sal_end.symtab)
error ("Specified start and end are in different files.");
if (dummy_beg && dummy_end)
error ("Two empty args do not say what lines to list.");
/* if line was specified by address,
first print exactly which line, and which file.
In this case, sal.symtab == 0 means address is outside
of all known source files, not that user failed to give a filename. */
if (*arg == '*')
{
if (sal.symtab == 0)
error ("No source file for address 0x%x.", sal.pc);
sym = find_pc_function (sal.pc);
if (sym)
printf ("0x%x is in %s (%s, line %d).\n",
sal.pc, SYMBOL_NAME (sym), sal.symtab->filename, sal.line);
else
printf ("0x%x is in %s, line %d.\n",
sal.pc, sal.symtab->filename, sal.line);
}
/* If line was not specified by just a line number,
and it does not imply a symtab, it must be an undebuggable symbol
which means no source code. */
if (! linenum_beg && sal.symtab == 0)
error ("No line number known for %s.", arg);
/* If this command is repeated with RET,
turn it into the no-arg variant. */
if (from_tty)
*arg = 0;
if (dummy_beg && sal_end.symtab == 0)
error ("No default source file yet. Do \"help list\".");
if (dummy_beg)
print_source_lines (sal_end.symtab, max (sal_end.line - 9, 1),
sal_end.line + 1);
else if (sal.symtab == 0)
error ("No default source file yet. Do \"help list\".");
else if (no_end)
print_source_lines (sal.symtab, max (sal.line - 5, 1), sal.line + 5);
else
print_source_lines (sal.symtab, sal.line,
dummy_end ? sal.line + 10 : sal_end.line + 1);
}
/* Print info on range of pc's in a specified line. */
static void
line_info (arg, from_tty)
char *arg;
int from_tty;
{
struct symtab_and_line sal;
int start_pc, end_pc;
if (arg == 0)
{
sal.symtab = current_source_symtab;
sal.line = line_info_default_line;
}
else
{
sal = decode_line_spec (arg);
/* If this command is repeated with RET,
turn it into the no-arg variant. */
if (from_tty)
*arg = 0;
}
if (sal.symtab == 0)
error ("No source file specified.");
if (sal.line > 0
&& find_line_pc_range (sal.symtab, sal.line, &start_pc, &end_pc))
{
if (start_pc == end_pc)
printf ("Line %d of \"%s\" is at pc 0x%x but contains no code.\n",
sal.line, sal.symtab->filename, start_pc);
else
printf ("Line %d of \"%s\" starts at pc 0x%x and ends at 0x%x.\n",
sal.line, sal.symtab->filename, start_pc, end_pc);
/* x/i should display this line's code. */
set_next_address (start_pc);
/* Repeating "info line" should do the following line. */
line_info_default_line = sal.line + 1;
}
else
printf ("Line number %d is out of range for \"%s\".\n",
sal.line, sal.symtab->filename);
}
static
initialize ()
{
current_source_symtab = 0;
init_source_path ();
add_com ("directory", class_files, directory_command,
"Add directory DIR to end of search path for source files.\n\
With no argument, reset the search path to just the working directory\n\
and forget cached info on line positions in source files.");
add_info ("directories", directories_info,
"Current search path for finding source files.");
add_info ("line", line_info,
"Core addresses of the code for a source line.\n\
Line can be specified as\n\
LINENUM, to list around that line in current file,\n\
FILE:LINENUM, to list around that line in that file,\n\
FUNCTION, to list around beginning of that function,\n\
FILE:FUNCTION, to distinguish among like-named static functions.\n\
Default is to describe the last source line that was listed.\n\n\
This sets the default address for \"x\" to the line's first instruction\n\
so that \"x/i\" suffices to start examining the machine code.\n\
The address is also stored as the value of \"$_\".");
add_com ("list", class_files, list_command,
"List specified function or line.\n\
With no argument, lists ten more lines after or around previous listing.\n\
\"list -\" lists the ten lines before a previous ten-line listing.\n\
One argument specifies a line, and ten lines are listed around that line.\n\
Two arguments with comma between specify starting and ending lines to list.\n\
Lines can be specified in these ways:\n\
LINENUM, to list around that line in current file,\n\
FILE:LINENUM, to list around that line in that file,\n\
FUNCTION, to list around beginning of that function,\n\
FILE:FUNCTION, to distinguish among like-named static functions.\n\
*ADDRESS, to list around the line containing that address.\n\
With two args if one is empty it stands for ten lines away from the other arg.");
}
END_FILE
@
1.1
log
@Initial revision
@
text
@d22 1
@

View File

@ -1,575 +0,0 @@
head 1.2;
access ;
symbols RMS-has:1.2;
locks ; strict;
comment @ * @;
1.2
date 88.01.26.05.09.53; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 88.01.26.04.25.22; author gnu; state Exp;
branches ;
next ;
desc
@Original from RMS's devl sources on wheaties
@
1.2
log
@Check for null pointer passed to free()...
@
text
@/* Do various things to symbol tables (other than lookup)), for GDB.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "defs.h"
#include "initialize.h"
#include "symtab.h"
#include <stdio.h>
#include <obstack.h>
static void free_symtab ();
START_FILE
/* Free all the symtabs that are currently installed,
and all storage associated with them.
Leaves us in a consistent state with no symtabs installed. */
void
free_all_symtabs ()
{
register struct symtab *s, *snext;
/* All values will be invalid because their types will be! */
clear_value_history ();
clear_displays ();
clear_internalvars ();
clear_breakpoints ();
set_default_breakpoint (0, 0, 0, 0);
current_source_symtab = 0;
for (s = symtab_list; s; s = snext)
{
snext = s->next;
free_symtab (s);
}
symtab_list = 0;
obstack_free (symbol_obstack, 0);
obstack_init (symbol_obstack);
if (misc_function_vector)
free (misc_function_vector);
misc_function_count = 0;
misc_function_vector = 0;
}
/* Free a struct block <- B and all the symbols defined in that block. */
static void
free_symtab_block (b)
struct block *b;
{
register int i, n;
n = BLOCK_NSYMS (b);
for (i = 0; i < n; i++)
{
free (SYMBOL_NAME (BLOCK_SYM (b, i)));
free (BLOCK_SYM (b, i));
}
free (b);
}
/* Free all the storage associated with the struct symtab <- S.
Note that some symtabs have contents malloc'ed structure by structure,
while some have contents that all live inside one big block of memory,
and some share the contents of another symbol table and so you should
not free the contents on their behalf (except sometimes the linetable,
which maybe per symtab even when the rest is not).
It is s->free_code that says which alternative to use. */
static void
free_symtab (s)
register struct symtab *s;
{
register int i, n;
register struct blockvector *bv;
register struct type *type;
register struct typevector *tv;
switch (s->free_code)
{
case free_nothing:
/* All the contents are part of a big block of memory
and some other symtab is in charge of freeing that block.
Therefore, do nothing. */
break;
case free_explicit:
/* All the contents are part of a big block of memory
and that is our `free_ptr' and will be freed below. */
break;
case free_contents:
/* Here all the contents were malloc'ed structure by structure
and must be freed that way. */
/* First free the blocks (and their symbols. */
bv = BLOCKVECTOR (s);
n = BLOCKVECTOR_NBLOCKS (bv);
for (i = 0; i < n; i++)
free_symtab_block (BLOCKVECTOR_BLOCK (bv, i));
/* Free the blockvector itself. */
free (bv);
/* Free the type vector. */
tv = TYPEVECTOR (s);
if (tv) /* FIXME, should this happen? It does... */
free (tv);
/* Also free the linetable. */
case free_linetable:
/* Everything will be freed either by our `free_ptr'
or by some other symbatb, except for our linetable.
Free that now. */
free (LINETABLE (s));
break;
}
/* If there is a single block of memory to free, free it. */
if (s->free_ptr)
free (s->free_ptr);
if (s->line_charpos)
free (s->line_charpos);
free (s->filename);
free (s);
}
/* Convert a raw symbol-segment to a struct symtab,
and relocate its internal pointers so that it is valid. */
/* This is how to relocate one pointer, given a name for it.
Works independent of the type of object pointed to. */
#define RELOCATE(slot) (slot ? (* (char **) &slot += relocation) : 0)
/* This is the inverse of RELOCATE. We use it when storing
a core address into a slot that has yet to be relocated. */
#define UNRELOCATE(slot) (slot ? (* (char **) &slot -= relocation) : 0)
/* During the process of relocation, this holds the amount to relocate by
(the address of the file's symtab data, in core in the debugger). */
static int relocation;
#define CORE_RELOCATE(slot) \
((slot) += (((slot) < data_start) ? text_relocation \
: ((slot) < bss_start) ? data_relocation : bss_relocation))
#define TEXT_RELOCATE(slot) ((slot) += text_relocation)
/* Relocation amounts for addresses in the program's core image. */
static int text_relocation, data_relocation, bss_relocation;
/* Boundaries that divide program core addresses into text, data and bss;
used to determine which relocation amount to use. */
static int data_start, bss_start;
static void relocate_typevector ();
static void relocate_blockvector ();
static void relocate_type ();
static void relocate_block ();
static void relocate_symbol ();
/* Relocate a file symbol table so that all the pointers
are valid C pointers. Pass the struct symtab for the file
and the amount to relocate by. */
static struct symtab *
relocate_symtab (root)
struct symbol_root *root;
{
struct symtab *sp = (struct symtab *) xmalloc (sizeof (struct symtab));
bzero (sp, sizeof (struct symtab));
relocation = (int) root;
text_relocation = root->textrel;
data_relocation = root->datarel;
bss_relocation = root->bssrel;
data_start = root->databeg;
bss_start = root->bssbeg;
sp->filename = root->filename;
sp->ldsymoff = root->ldsymoff;
sp->language = root->language;
sp->compilation = root->compilation;
sp->version = root->version;
sp->blockvector = root->blockvector;
sp->typevector = root->typevector;
sp->free_code = free_explicit;
sp->free_ptr = (char *) root;
RELOCATE (TYPEVECTOR (sp));
RELOCATE (BLOCKVECTOR (sp));
RELOCATE (sp->version);
RELOCATE (sp->compilation);
RELOCATE (sp->filename);
relocate_typevector (TYPEVECTOR (sp));
relocate_blockvector (BLOCKVECTOR (sp));
return sp;
}
static void
relocate_typevector (tv)
struct typevector *tv;
{
register int ntypes = TYPEVECTOR_NTYPES (tv);
register int i;
for (i = 0; i < ntypes; i++)
RELOCATE (TYPEVECTOR_TYPE (tv, i));
for (i = 0; i < ntypes; i++)
relocate_type (TYPEVECTOR_TYPE (tv, i));
}
static void
relocate_blockvector (blp)
register struct blockvector *blp;
{
register int nblocks = BLOCKVECTOR_NBLOCKS (blp);
register int i;
for (i = 0; i < nblocks; i++)
RELOCATE (BLOCKVECTOR_BLOCK (blp, i));
for (i = 0; i < nblocks; i++)
relocate_block (BLOCKVECTOR_BLOCK (blp, i));
}
static void
relocate_block (bp)
register struct block *bp;
{
register int nsyms = BLOCK_NSYMS (bp);
register int i;
TEXT_RELOCATE (BLOCK_START (bp));
TEXT_RELOCATE (BLOCK_END (bp));
/* These two should not be recursively processed.
The superblock need not be because all blocks are
processed from relocate_blockvector.
The function need not be because it will be processed
under the block which is its scope. */
RELOCATE (BLOCK_SUPERBLOCK (bp));
RELOCATE (BLOCK_FUNCTION (bp));
for (i = 0; i < nsyms; i++)
RELOCATE (BLOCK_SYM (bp, i));
for (i = 0; i < nsyms; i++)
relocate_symbol (BLOCK_SYM (bp, i));
}
static void
relocate_symbol (sp)
register struct symbol *sp;
{
RELOCATE (SYMBOL_NAME (sp));
if (SYMBOL_CLASS (sp) == LOC_BLOCK)
{
RELOCATE (SYMBOL_BLOCK_VALUE (sp));
/* We can assume the block that belongs to this symbol
is not relocated yet, since it comes after
the block that contains this symbol. */
BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp)) = sp;
UNRELOCATE (BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp)));
}
else if (SYMBOL_CLASS (sp) == LOC_STATIC)
CORE_RELOCATE (SYMBOL_VALUE (sp));
else if (SYMBOL_CLASS (sp) == LOC_LABEL)
TEXT_RELOCATE (SYMBOL_VALUE (sp));
RELOCATE (SYMBOL_TYPE (sp));
}
/* We cannot come up with an a priori spanning tree
for the network of types, since types can be used
for many symbols and also as components of other types.
Therefore, we need to be able to mark types that we
already have relocated (or are already in the middle of relocating)
as in a garbage collector. */
static void
relocate_type (tp)
register struct type *tp;
{
register int nfields = TYPE_NFIELDS (tp);
register int i;
RELOCATE (TYPE_NAME (tp));
RELOCATE (TYPE_TARGET_TYPE (tp));
RELOCATE (TYPE_FIELDS (tp));
RELOCATE (TYPE_POINTER_TYPE (tp));
for (i = 0; i < nfields; i++)
{
RELOCATE (TYPE_FIELD_TYPE (tp, i));
RELOCATE (TYPE_FIELD_NAME (tp, i));
}
}
/* Read symsegs from file named NAME open on DESC,
make symtabs from them, and return a chain of them.
Assumes DESC is prepositioned at the end of the string table,
just before the symsegs if there are any. */
struct symtab *
read_symsegs (desc, name)
int desc;
char *name;
{
struct symbol_root root;
register char *data;
register struct symtab *sp, *chain = 0;
register int len;
while (1)
{
len = myread (desc, &root, sizeof root);
if (len == 0 || root.format == 0)
break;
if (root.format != 1 ||
root.length < sizeof root)
error ("Invalid symbol segment format code");
data = (char *) xmalloc (root.length);
bcopy (&root, data, sizeof root);
len = myread (desc, data + sizeof root,
root.length - sizeof root);
sp = relocate_symtab (data);
sp->next = chain;
chain = sp;
}
return chain;
}
static int block_depth ();
static void print_spaces ();
static void print_symbol ();
print_symtabs (filename)
char *filename;
{
FILE *outfile;
register struct symtab *s;
register int i, j;
int len, line, blen;
register struct linetable *l;
struct blockvector *bv;
register struct block *b;
int depth;
struct cleanup *cleanups;
extern int fclose();
if (filename == 0)
error_no_arg ("file to write symbol data in");
outfile = fopen (filename, "w");
cleanups = make_cleanup (fclose, outfile);
immediate_quit++;
for (s = symtab_list; s; s = s->next)
{
/* First print the line table. */
fprintf (outfile, "Symtab for file %s\n\n", s->filename);
fprintf (outfile, "Line table:\n\n");
l = LINETABLE (s);
len = l->nitems;
for (i = 0; i < len; i++)
{
if (l->item[i] < 0)
line = - l->item[i] - 1;
else
fprintf (outfile, " line %d at %x\n", ++line, l->item[i]);
}
/* Now print the block info. */
fprintf (outfile, "\nBlockvector:\n\n");
bv = BLOCKVECTOR (s);
len = BLOCKVECTOR_NBLOCKS (bv);
for (i = 0; i < len; i++)
{
b = BLOCKVECTOR_BLOCK (bv, i);
depth = block_depth (b) * 2;
print_spaces (depth, outfile);
fprintf (outfile, "block #%03d (object 0x%x) ", i, b);
fprintf (outfile, "[0x%x..0x%x]", BLOCK_START (b), BLOCK_END (b));
if (BLOCK_SUPERBLOCK (b))
fprintf (outfile, " (under 0x%x)", BLOCK_SUPERBLOCK (b));
if (BLOCK_FUNCTION (b))
fprintf (outfile, " %s", SYMBOL_NAME (BLOCK_FUNCTION (b)));
fputc ('\n', outfile);
blen = BLOCK_NSYMS (b);
for (j = 0; j < blen; j++)
{
print_symbol (BLOCK_SYM (b, j), depth + 1, outfile);
}
}
fprintf (outfile, "\n\n");
}
immediate_quit--;
do_cleanups (cleanups);
}
static void
print_symbol (symbol, depth, outfile)
struct symbol *symbol;
int depth;
FILE *outfile;
{
print_spaces (depth, outfile);
if (SYMBOL_NAMESPACE (symbol) == LABEL_NAMESPACE)
{
fprintf (outfile, "label %s at 0x%x", SYMBOL_NAME (symbol),
SYMBOL_VALUE (symbol));
return;
}
if (SYMBOL_NAMESPACE (symbol) == STRUCT_NAMESPACE)
{
if (TYPE_NAME (SYMBOL_TYPE (symbol)))
{
type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
}
else
{
fprintf (outfile, "%s %s = ",
(TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_ENUM
? "enum"
: (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_STRUCT
? "struct" : "union")),
SYMBOL_NAME (symbol));
type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
}
fprintf (outfile, ";\n");
}
else
{
if (SYMBOL_CLASS (symbol) == LOC_TYPEDEF)
fprintf (outfile, "typedef ");
if (SYMBOL_TYPE (symbol))
{
type_print_1 (SYMBOL_TYPE (symbol), SYMBOL_NAME (symbol),
outfile, 1, depth);
fprintf (outfile, "; ");
}
else
fprintf (outfile, "%s ", SYMBOL_NAME (symbol));
switch (SYMBOL_CLASS (symbol))
{
case LOC_CONST:
fprintf (outfile, "const %d (0x%x),",
SYMBOL_VALUE (symbol), SYMBOL_VALUE (symbol));
break;
case LOC_CONST_BYTES:
fprintf (outfile, "const %d hex bytes:",
TYPE_LENGTH (SYMBOL_TYPE (symbol)));
{
int i;
for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (symbol)); i++)
fprintf (outfile, " %2x", SYMBOL_VALUE_BYTES (symbol) [i]);
fprintf (outfile, ",");
}
break;
case LOC_STATIC:
fprintf (outfile, "static at 0x%x,", SYMBOL_VALUE (symbol));
break;
case LOC_REGISTER:
fprintf (outfile, "register %d,", SYMBOL_VALUE (symbol));
break;
case LOC_ARG:
fprintf (outfile, "arg at 0x%x,", SYMBOL_VALUE (symbol));
break;
case LOC_LOCAL:
fprintf (outfile, "local at 0x%x,", SYMBOL_VALUE (symbol));
break;
case LOC_TYPEDEF:
break;
case LOC_LABEL:
fprintf (outfile, "label at 0x%x", SYMBOL_VALUE (symbol));
break;
case LOC_BLOCK:
fprintf (outfile, "block (object 0x%x) starting at 0x%x,",
SYMBOL_VALUE (symbol),
BLOCK_START (SYMBOL_BLOCK_VALUE (symbol)));
break;
}
}
fprintf (outfile, "\n");
}
/* Return the nexting depth of a block within other blocks in its symtab. */
static int
block_depth (block)
struct block *block;
{
register int i = 0;
while (block = BLOCK_SUPERBLOCK (block)) i++;
return i;
}
static
initialize ()
{
add_com ("printsyms", class_obscure, print_symtabs,
"Print dump of current symbol definitions to file OUTFILE.");
}
END_FILE
@
1.1
log
@Initial revision
@
text
@d125 2
a126 1
free (tv);
@

File diff suppressed because it is too large Load Diff

View File

@ -1,461 +0,0 @@
head 1.2;
access ;
symbols RMS-has:1.2;
locks ; strict;
comment @ * @;
1.2
date 88.01.26.05.11.12; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 88.01.21.05.11.11; author gnu; state Exp;
branches ;
next ;
desc
@From RMS's development sources on wheaties, 20Jan88
@
1.2
log
@Avoid using TIOCFLUSH if it is not defined.
@
text
@/* General utility routines for GDB, the GNU debugger.
Copyright (C) 1986 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include <stdio.h>
#include <sys/ioctl.h>
#include "defs.h"
void error ();
void fatal ();
/* Chain of cleanup actions established with make_cleanup,
to be executed if an error happens. */
static struct cleanup *cleanup_chain;
/* Nonzero means a quit has been requested. */
int quit_flag;
/* Nonzero means quit immediately if Control-C is typed now,
rather than waiting until QUIT is executed. */
int immediate_quit;
/* Add a new cleanup to the cleanup_chain,
and return the previous chain pointer
to be passed later to do_cleanups or discard_cleanups.
Args are FUNCTION to clean up with, and ARG to pass to it. */
struct cleanup *
make_cleanup (function, arg)
void (*function) ();
int arg;
{
register struct cleanup *new
= (struct cleanup *) xmalloc (sizeof (struct cleanup));
register struct cleanup *old_chain = cleanup_chain;
new->next = cleanup_chain;
new->function = function;
new->arg = arg;
cleanup_chain = new;
return old_chain;
}
/* Discard cleanups and do the actions they describe
until we get back to the point OLD_CHAIN in the cleanup_chain. */
void
do_cleanups (old_chain)
register struct cleanup *old_chain;
{
register struct cleanup *ptr;
while ((ptr = cleanup_chain) != old_chain)
{
(*ptr->function) (ptr->arg);
cleanup_chain = ptr->next;
free (ptr);
}
}
/* Discard cleanups, not doing the actions they describe,
until we get back to the point OLD_CHAIN in the cleanup_chain. */
void
discard_cleanups (old_chain)
register struct cleanup *old_chain;
{
register struct cleanup *ptr;
while ((ptr = cleanup_chain) != old_chain)
{
cleanup_chain = ptr->next;
free (ptr);
}
}
/* This function is useful for cleanups.
Do
foo = xmalloc (...);
old_chain = make_cleanup (free_current_contents, &foo);
to arrange to free the object thus allocated. */
void
free_current_contents (location)
char **location;
{
free (*location);
}
/* Generally useful subroutines used throughout the program. */
/* Like malloc but get error if no storage available. */
char *
xmalloc (size)
long size;
{
register char *val = (char *) malloc (size);
if (!val)
fatal ("virtual memory exhausted.", 0);
return val;
}
/* Like realloc but get error if no storage available. */
char *
xrealloc (ptr, size)
char *ptr;
long size;
{
register char *val = (char *) realloc (ptr, size);
if (!val)
fatal ("virtual memory exhausted.", 0);
return val;
}
/* Print the system error message for errno, and also mention STRING
as the file name for which the error was encountered.
Then return to command level. */
void
perror_with_name (string)
char *string;
{
extern int sys_nerr;
extern char *sys_errlist[];
extern int errno;
char *err;
char *combined;
if (errno < sys_nerr)
err = sys_errlist[errno];
else
err = "unknown error";
combined = (char *) alloca (strlen (err) + strlen (string) + 3);
strcpy (combined, string);
strcat (combined, ": ");
strcat (combined, err);
error ("%s.", combined);
}
/* Print the system error message for ERRCODE, and also mention STRING
as the file name for which the error was encountered. */
void
print_sys_errmsg (string, errcode)
char *string;
int errcode;
{
extern int sys_nerr;
extern char *sys_errlist[];
char *err;
char *combined;
if (errcode < sys_nerr)
err = sys_errlist[errcode];
else
err = "unknown error";
combined = (char *) alloca (strlen (err) + strlen (string) + 3);
strcpy (combined, string);
strcat (combined, ": ");
strcat (combined, err);
printf ("%s.\n", combined);
}
void
quit ()
{
fflush (stdout);
#ifdef TIOCFLUSH
ioctl (fileno (stdout), TIOCFLUSH, 0);
#endif
error ("Quit");
}
/* Control C comes here */
void
request_quit ()
{
quit_flag = 1;
if (immediate_quit)
quit ();
}
/* Print an error message and return to command level.
STRING is the error message, used as a fprintf string,
and ARG is passed as an argument to it. */
void
error (string, arg1, arg2, arg3)
char *string;
int arg1, arg2, arg3;
{
fflush (stdout);
fprintf (stderr, string, arg1, arg2, arg3);
fprintf (stderr, "\n");
return_to_top_level ();
}
/* Print an error message and exit reporting failure.
This is for a error that we cannot continue from.
STRING and ARG are passed to fprintf. */
void
fatal (string, arg)
char *string;
int arg;
{
fprintf (stderr, "gdb: ");
fprintf (stderr, string, arg);
fprintf (stderr, "\n");
exit (1);
}
/* Make a copy of the string at PTR with SIZE characters
(and add a null character at the end in the copy).
Uses malloc to get the space. Returns the address of the copy. */
char *
savestring (ptr, size)
char *ptr;
int size;
{
register char *p = (char *) xmalloc (size + 1);
bcopy (ptr, p, size);
p[size] = 0;
return p;
}
char *
concat (s1, s2, s3)
char *s1, *s2, *s3;
{
register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1;
register char *val = (char *) xmalloc (len);
strcpy (val, s1);
strcat (val, s2);
strcat (val, s3);
return val;
}
void
print_spaces (n, file)
register int n;
register FILE *file;
{
while (n-- > 0)
fputc (' ', file);
}
/* Ask user a y-or-n question and return 1 iff answer is yes.
Takes three args which are given to printf to print the question.
The first, a control string, should end in "? ".
It should not say how to answer, because we do that. */
int
query (ctlstr, arg1, arg2)
char *ctlstr;
{
register int answer;
/* Automatically answer "yes" if input is not from a terminal. */
if (!input_from_terminal_p ())
return 1;
while (1)
{
printf (ctlstr, arg1, arg2);
printf ("(y or n) ");
fflush (stdout);
answer = fgetc (stdin);
clearerr (stdin); /* in case of C-d */
if (answer != '\n')
while (fgetc (stdin) != '\n') clearerr (stdin);
if (answer >= 'a')
answer -= 040;
if (answer == 'Y')
return 1;
if (answer == 'N')
return 0;
printf ("Please answer y or n.\n");
}
}
/* Parse a C escape sequence. STRING_PTR points to a variable
containing a pointer to the string to parse. That pointer
is updated past the characters we use. The value of the
escape sequence is returned.
A negative value means the sequence \ newline was seen,
which is supposed to be equivalent to nothing at all.
If \ is followed by a null character, we return a negative
value and leave the string pointer pointing at the null character.
If \ is followed by 000, we return 0 and leave the string pointer
after the zeros. A value of 0 does not mean end of string. */
int
parse_escape (string_ptr)
char **string_ptr;
{
register int c = *(*string_ptr)++;
switch (c)
{
case 'a':
return '\a';
case 'b':
return '\b';
case 'e':
return 033;
case 'f':
return '\f';
case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
case 'v':
return '\v';
case '\n':
return -2;
case 0:
(*string_ptr)--;
return 0;
case '^':
c = *(*string_ptr)++;
if (c == '\\')
c = parse_escape (string_ptr);
if (c == '?')
return 0177;
return (c & 0200) | (c & 037);
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
{
register int i = c - '0';
register int count = 0;
while (++count < 3)
{
if ((c = *(*string_ptr)++) >= '0' && c <= '7')
{
i *= 8;
i += c - '0';
}
else
{
(*string_ptr)--;
break;
}
}
return i;
}
default:
return c;
}
}
void
printchar (ch, stream)
unsigned char ch;
FILE *stream;
{
register int c = ch;
if (c < 040 || c >= 0177)
{
if (c == '\n')
fprintf (stream, "\\n");
else if (c == '\b')
fprintf (stream, "\\b");
else if (c == '\t')
fprintf (stream, "\\t");
else if (c == '\f')
fprintf (stream, "\\f");
else if (c == '\r')
fprintf (stream, "\\r");
else if (c == 033)
fprintf (stream, "\\e");
else if (c == '\a')
fprintf (stream, "\\a");
else
fprintf (stream, "\\%03o", c);
}
else
{
if (c == '\\' || c == '"' || c == '\'')
fputc ('\\', stream);
fputc (c, stream);
}
}
@
1.1
log
@Initial revision
@
text
@d194 1
d196 1
@

View File

@ -1,29 +0,0 @@
This is GDB, a source-level debugger intended for GNU,
presently running under un*x.
Before compiling GDB, you must set three files according to
the kind of machine you are running on.
param.h must be set up to #include an m- file for the machine.
The m- files written so far are m-vax.h, m-sun2.h and m-sun3.h.
(I believe that it is the operating system version and not
the cpu type which determines which of the two is right on a Sun.)
This file contains macro definitions that express information
about the machine's registers, stack frame format and instructions.
initialize.h must be set up to #include an m-...init.h file.
There are two of them written: m-vaxinit.h and m-suninit.h.
This file defines one macro, which says how to round up from the
address of the end of the text of one .o file to the beginning of
the text of the next .o file.
pinsn.c must be set up to include the instruction printer for
your cpu type. The two printers that exist are vax-pinsn.c
and m68k-pinsn.c.
`Makefile' must be changed to say `OBSTACK = obstack.o' instead of
`OBSTACK=-lobstack' (unless you want to install obstack.o as
/lib/libobstack.a).
Once these files are set up, just `make' will do everything,
producing an executable `gdb' in this directory.

852
gdb/TAGS
View File

@ -1,852 +0,0 @@
blockframe.c,436
block_for_pc 221,5337
block_innermost_frame 308,7200
find_pc_function 276,6473
find_pc_misc_function 290,6806
get_current_block 182,4485
get_current_frame 47,1553
get_frame_block 172,4336
get_frame_function 208,5053
get_frame_info 90,2661
get_frame_pc 150,3800
get_frame_saved_regs 161,3986
get_pc_function_start 188,4557
get_prev_frame 66,1893
get_prev_frame_info 128,3455
initialize 329,7603
set_current_frame 56,1705
breakpoint.c,1102
#define ALL_BREAKPOINTS(71,2545
break_command 604,14937
break_command_1 528,13121
breakpoint_1 360,9438
breakpoint_auto_delete 687,16916
breakpoint_here_p 288,7887
breakpoint_stop_status 308,8410
breakpoints_info 409,10520
check_duplicates 443,11290
clear_breakpoint_commands 218,6186
clear_breakpoints 757,18298
clear_command 620,15179
clear_momentary_breakpoints 513,12821
commands_command 154,4443
condition_command 109,3533
delete_breakpoint 704,17221
delete_command 733,17741
disable_breakpoint 873,20658
disable_command 882,20791
do_breakpoint_commands 200,5626
enable_breakpoint 857,20419
enable_command 866,20550
enable_delete_breakpoint 910,21276
enable_delete_command 919,21413
enable_once_breakpoint 894,21020
enable_once_command 903,21158
ignore_command 797,19190
initialize 933,21666
insert_breakpoints 230,6503
map_breakpoint_numbers 822,19738
mark_breakpoints_out 275,7576
remove_breakpoints 251,7042
set_default_breakpoint 426,10820
set_ignore_count 767,18523
set_momentary_breakpoint 501,12597
set_raw_breakpoint 464,11810
tbreak_command 612,15057
command.c,151
add_alias_cmd 141,6077
add_cmd 116,5529
add_prefix_cmd 177,7140
delete_cmd 198,7681
help_cmd 230,8515
lookup_cmd 336,11651
savestring 446,13891
core.c,397
#define N_DATADDR(41,1348
#define N_TXTADDR(37,1278
close_exec_file 268,7417
core_file_command 104,2838
exec_file_command 221,6183
files_info 330,8673
get_exec_file 315,8446
have_core_file_p 324,8612
initialize 548,13957
myread 505,13219
read_memory 373,9666
register_addr 531,13685
reopen_exec_file 275,7501
validate_files 291,7907
write_memory 389,10073
xfer_core_file 400,10338
dbxread.c,1108
add_new_header_file 346,10622
add_old_header_file 317,9604
add_symbol_to_list 496,14905
add_this_object_header_file 297,8977
compare_misc_functions 931,26566
compare_symbols 1000,28016
condense_misc_bunches 957,27070
dbx_alloc_type 454,13833
dbx_lookup_type 404,12394
define_symbol 1516,42011
discard_misc_bunches 944,26878
end_symtab 756,22240
explicit_lookup_type 475,14373
finish_block 512,15299
free_header_files 273,8395
get_sym_file 1174,32423
hash_symsegs 1343,36983
hashname 1318,36533
init_header_files 260,8046
init_misc_functions 903,25961
initialize 2078,57588
make_blockvector 590,17428
new_object_header_files 286,8705
next_symbol_text 1309,36368
pop_subfile 861,25120
process_one_symbol 1374,37801
push_subfile 847,24770
read_dbx_symtab 1186,32790
read_enum_type 1892,52804
read_number 2041,57023
read_range_type 1962,54881
read_struct_type 1809,50421
read_type 1685,47313
read_type_number 1658,46658
record_line 627,18511
record_misc_function 911,26075
sort_syms 1012,28407
start_subfile 699,20484
start_symtab 662,19485
symbol_file_command 1036,28951
environ.c,213
environ_vector 164,6337
free_environ 118,5334
get_in_environ 173,6472
init_environ 134,5661
make_environ 103,5036
#define max(96,4912
#define min(95,4870
set_in_environ 192,6807
unset_in_environ 232,7561
eval.c,309
evaluate_expression 95,2716
evaluate_subexp 114,3104
evaluate_subexp_for_address 440,13032
evaluate_subexp_for_sizeof 509,14789
evaluate_subexp_with_coercion 477,13979
evaluate_type 106,2961
initialize 550,15888
parse_and_eval 64,1977
parse_and_eval_address 33,1188
parse_and_eval_address_1 50,1650
expprint.c,49
print_expression 88,3265
print_subexp 102,3660
expread.tab.c,358
copy_name 538,12121
end_arglist 125,2565
free_funcalls 139,2867
length_of_subexp 572,13025
parse_c_1 751,17140
parse_c_expression 790,18194
parse_number 217,5038
prefixify_expression 552,12457
prefixify_subexp 644,14362
start_arglist 111,2206
write_exp_elt 156,3206
write_exp_string 173,3660
yyerror 529,11966
yylex 315,7081
yyparse(985,25972
findvar.c,309
find_saved_register 38,1432
initialize 386,10456
locate_var_value 334,9235
read_register 165,4621
read_register_bytes 140,4050
read_relative_register_raw_bytes 68,2095
read_var_value 202,5600
supply_register 190,5277
value_of_register 102,2842
write_register 175,4862
write_register_bytes 151,4328
firstfile.c,89
initialize_all_files 128,6009
initialize_dummy_1 140,6338
initialize_dummy_2 148,6497
infcmd.c,550
cont_command 165,3979
environment_info 479,11280
finish_command 397,9291
have_inferior_p 106,2907
initialize 682,15823
jump_command 269,6035
next_command 202,4695
nexti_command 216,4897
program_info 457,10675
read_memory_integer 542,12697
read_pc 575,13293
registers_info 589,13488
run_command 121,3120
run_stack_dummy 355,8179
set_args_command 112,2972
set_environment_command 499,11682
signal_command 314,7007
step_1 222,4974
step_command 194,4543
stepi_command 210,4820
unset_environment_command 531,12458
write_pc 580,13357
inflow.c,551
create_inferior 187,5073
fetch_inferior_registers 271,6793
fetch_inferior_registers 317,8482
inferior_died 244,6286
initialize 483,13062
kill_command 226,5974
kill_inferior 235,6161
read_inferior_memory 388,10475
resume 258,6596
store_inferior_registers 294,7707
store_inferior_registers 343,9249
term_status_command 165,4365
terminal_inferior 87,2428
terminal_init_inferior 71,2074
terminal_ours 121,3326
terminal_ours_1 127,3383
terminal_ours_for_output 111,3126
try_writing_regs_command 457,12556
write_inferior_memory 416,11420
infrun.c,286
clear_proceed_status 111,3347
handle_command 728,21384
initialize 848,24793
insert_step_breakpoint 706,20807
normal_stop 618,18254
proceed 138,4172
remove_step_breakpoint 718,21109
signals_info 810,23832
start_inferior 214,6079
wait_for_inferior 242,7039
writing_pc 202,5763
kdb-start.c,14
start 10,140
lastfile.c,28
initialize_last_file 4,144
m68k-pinsn.c,361
#define NEXTBYTE(43,1554
#define NEXTDOUBLE(54,1819
#define NEXTEXTEND(57,1877
#define NEXTLONG(48,1671
#define NEXTPACKED(61,1995
#define NEXTSINGLE(51,1762
#define NEXTWORD(45,1602
convert_from_68881 713,16392
convert_to_68881 732,16806
fetch_arg 504,12082
print_base 693,15890
print_indexed 603,13871
print_insn 71,2389
print_insn_arg 163,4738
main.c,841
add_com 487,11896
add_com_alias 499,12123
add_info 455,11186
add_info_alias 466,11372
cd_command 885,24375
command_loop 288,7462
copying_info 628,14816
define_command 545,12933
do_nothing 281,7362
document_command 583,13895
dont_repeat 323,8255
dump_me_command 961,25608
echo_command 935,25224
error_no_arg 509,12321
execute_command 245,6496
free_command_lines 437,10877
help_command 516,12415
info_command 478,11700
initialize_main 972,25764
input_from_terminal_p 869,24072
main 81,2147
print_gdb_version 800,22767
pwd_command 875,24143
quit_command 856,23880
read_command_lines 386,9603
read_line 334,8514
return_to_top_level 71,1965
set_prompt_command 818,23215
source_cleanup 904,24752
source_command 912,24854
stop_sig 307,7915
validate_comname 524,12566
version_info 810,23117
warranty_info 770,21356
obstack.c,77
_obstack_begin 101,4993
_obstack_free 148,6461
_obstack_newchunk 121,5631
pinsn.c,0
printcmd.c,585
address_info 385,9015
clear_displays 661,15183
decode_format 70,2061
display_command 606,14214
display_info 769,17310
do_displays 731,16450
do_examine 231,5522
free_display 649,14965
initialize 888,20497
output_command 346,8219
print_address 208,4990
print_command 306,7398
print_formatted 109,2860
print_frame_args 810,18392
print_frame_nameless_args 870,20125
print_variable_value 795,17951
ptype_command 525,12189
set_command 374,8765
set_next_address 193,4626
undisplay_command 677,15445
validate_format 291,6959
whatis_command 500,11716
x_command 452,10410
source.c,249
directories_info 53,1637
directory_command 79,2168
find_source_lines 264,6263
init_source_path 59,1735
initialize 535,13376
line_info 490,12220
list_command 363,8569
openp 186,4596
print_source_lines 303,7291
select_source_symtab 250,5960
stack.c,502
args_info 350,8833
backtrace_command 232,6280
down_command 498,12939
find_relative_frame 391,10010
frame_command 444,11623
frame_info 149,4137
get_selected_block 371,9306
initialize 542,13968
locals_info 312,8132
print_block_frame_locals 257,6820
print_frame_arg_vars 318,8214
print_frame_info 70,2167
print_frame_local_vars 291,7614
print_sel_frame 131,3689
print_selected_frame 140,3894
print_stack_frame 57,1964
return_command 516,13439
select_frame 359,9033
up_command 477,12347
standalone.c,1165
_exit 436,8533
_flsbuf 326,6852
access 76,1743
chdir 62,1588
close 164,4224
core_file_command 340,7028
exec_file_command 337,7003
execle 433,8519
exit 81,1771
fault 514,9963
fclose 189,4597
fdopen 183,4539
fflush 331,6910
fgetc 247,5466
fopen 175,4414
fprintf 298,6263
fputc 314,6593
fread 229,5154
fstat 195,4647
fwrite 305,6422
get_exec_file 344,7060
getpid 54,1543
getrlimit 474,9005
getwd 66,1608
have_core_file_p 350,7176
initialize 585,11686
ioctl 45,1478
kill 51,1531
kill_command 355,7213
lseek 266,5714
malloc_warning 441,8575
myread 208,4831
open 129,3606
printf 291,6110
ptrace 427,8490
read_inferior_register 372,7361
read_memory 375,7391
read_register 397,7764
restore_gdb 528,10282
resume 490,9429
save_frame_pointer 502,9633
save_registers 540,10627
sbrk 451,8691
setpgrp 430,8504
int (* signal 48,1506
sigsetmask 59,1570
int kdb_stack_beg[STACK_SIZE / sizeof 581,11613
terminal_inferior 360,7254
terminal_init_inferior 366,7300
terminal_ours 363,7279
ulimit 463,8913
vfork 417,8200
vlimit 469,8955
wait 554,10975
write_inferior_register 369,7330
write_memory 385,7564
write_register 406,7933
stuff.c,70
err 162,5253
find_symbol 141,4686
get_offset 97,3038
main 32,1184
symmisc.c,473
#define CORE_RELOCATE(158,4817
#define RELOCATE(148,4378
#define TEXT_RELOCATE(162,4972
#define UNRELOCATE(152,4573
block_depth 499,13854
free_all_symtabs 38,1310
free_symtab 92,2701
free_symtab_block 70,1994
initialize 508,13995
print_symbol 413,11786
print_symtabs 353,10199
read_symsegs 320,9451
relocate_block 243,7195
relocate_blockvector 231,6886
relocate_symbol 268,7855
relocate_symtab 182,5675
relocate_type 296,8833
relocate_typevector 218,6602
symtab.c,716
block_function 383,10928
decode_line_1 694,18782
decode_line_spec 853,22739
find_line_pc 624,16888
find_line_pc_range 565,15457
find_pc_line 425,11975
find_pc_line_pc_range 655,17363
find_pc_symtab 395,11161
functions_info 995,26000
init_type 1012,26230
initialize 1032,26680
list_symbols 916,24143
lookup_block_symbol 330,9572
lookup_enum 166,4758
lookup_function_type 211,6260
lookup_pointer_type 182,5269
lookup_struct 134,3824
lookup_symbol 285,8458
lookup_symtab 58,1929
lookup_typename 85,2559
lookup_union 150,4293
lookup_unsigned_typename 116,3346
smash_to_function_type 262,7816
smash_to_pointer_type 241,7206
sources_info 868,23119
types_info 1002,26088
variables_info 988,25912
test2.c,11
main 6,86
test3.c,25
bar 12,123
newfun 5,51
testbit.c,11
main 7,58
testfun.c,44
do_add 7,62
do_float_add 13,104
main 1,0
testkill.c,11
main(2,1
testrec.c,20
foo 6,24
main 1,0
testreg.c,22
foo 19,341
main 1,0
testregs.c,23
foo 2,11
main 15,321
utils.c,382
concat 254,5912
discard_cleanups 84,2483
do_cleanups 68,2104
error 213,5038
fatal 228,5397
free_current_contents 104,2893
make_cleanup 48,1636
parse_escape 323,7736
perror_with_name 142,3676
print_spaces 266,6154
print_sys_errmsg 168,4235
printchar 390,8781
query 280,6518
quit 191,4675
request_quit 201,4799
savestring 243,5745
xmalloc 115,3106
xrealloc 127,3326
valarith.c,215
initialize 352,8246
value_add 31,1128
value_binop 116,3276
value_equal 257,5535
value_less 301,6746
value_lognot 342,7998
value_neg 328,7619
value_sub 70,2102
value_subscript 105,2971
value_zerop 233,5184
valops.c,395
call_function 388,10791
initialize 594,16295
push_bytes 314,9135
push_word 294,8769
value_addr 247,7400
value_arg_coerce 354,9928
value_arg_push 373,10344
value_assign 85,2697
value_at 68,2289
value_cast 34,1302
value_coerce_array 219,6610
value_ind 274,8155
value_of_variable 209,6404
value_push 333,9476
value_repeat 186,5819
value_string 485,13581
value_struct_elt 555,15503
valprint.c,237
initialize 533,13661
set_maximum_command 525,13515
type_print 272,7365
type_print_1 283,7591
type_print_base 403,10889
type_print_varspec_prefix 316,8617
type_print_varspec_suffix 352,9476
val_print 113,3308
value_print 46,1539
values.c,762
access_value_history 212,5551
allocate_repeat_value 83,2505
allocate_value 59,1948
clear_internalvars 371,9239
clear_value_history 251,6511
convenience_info 386,9475
free_all_values 108,3143
history_info 270,6920
initialize 737,18259
internalvar_name 361,9048
lookup_internalvar 308,7852
modify_field 602,14750
record_latest_value 178,4634
release_value 125,3410
set_internalvar 351,8879
set_internalvar_component 336,8485
set_return_value 709,17666
unpack_double 486,11851
unpack_field_as_long 578,14176
unpack_long 430,10615
value_as_double 418,10252
value_as_long 411,10132
value_being_returned 688,17121
value_copy 151,3834
value_field 542,13135
value_from_double 654,16089
value_from_long 626,15329
value_of_internalvar 327,8298
vax-pinsn.c,44
print_insn 42,1456
print_insn_arg 86,2396
version.c,0
command.h,0
defs.h,42
#define max(24,1043
#define min(23,1001
environ.h,0
expression.h,0
frame.h,0
inferior.h,0
initialize.h,0
m-isi-ov.h,852
#define ABOUT_TO_RETURN(136,4974
#define FIX_CALL_DUMMY(447,17543
#define FRAME_ARGS_ADDRESS(275,9997
#define FRAME_CHAIN(264,9636
#define FRAME_CHAIN_COMBINE(269,9825
#define FRAME_CHAIN_VALID(266,9706
#define FRAME_FIND_SAVED_REGS(305,11191
#define FRAME_LOCALS_ADDRESS(277,10040
#define FRAME_NUM_ARGS(282,10176
#define FRAME_SAVED_PC(273,9929
#define INIT_STACK(471,18339
#define INVALID_FLOAT(140,5108
#define N_DATADDR(120,4437
#define N_TXTADDR(125,4616
#define REGISTER_BYTE(194,7220
#define REGISTER_CONVERTIBLE(222,8151
#define REGISTER_CONVERT_TO_RAW(236,8614
#define REGISTER_CONVERT_TO_VIRTUAL(227,8318
#define REGISTER_RAW_SIZE(203,7555
#define REGISTER_U_ADDR(174,6379
#define REGISTER_VIRTUAL_SIZE(209,7811
#define REGISTER_VIRTUAL_TYPE(245,8895
#define SAVED_PC_AFTER_CALL(97,3881
#define SKIP_PROLOGUE(77,3210
m-sun2.h,824
#define ABOUT_TO_RETURN(79,2505
#define FIX_CALL_DUMMY(344,12862
#define FRAME_ARGS_ADDRESS(196,6448
#define FRAME_CHAIN(185,6087
#define FRAME_CHAIN_COMBINE(190,6276
#define FRAME_CHAIN_VALID(187,6157
#define FRAME_FIND_SAVED_REGS(232,7817
#define FRAME_LOCALS_ADDRESS(198,6491
#define FRAME_NUM_ARGS(205,6746
#define FRAME_NUM_ARGS(208,6795
#define FRAME_SAVED_PC(194,6380
#define INIT_STACK(368,13658
#define INVALID_FLOAT(83,2639
#define REGISTER_BYTE(121,3997
#define REGISTER_CONVERTIBLE(144,4615
#define REGISTER_CONVERT_TO_RAW(154,4927
#define REGISTER_CONVERT_TO_VIRTUAL(149,4749
#define REGISTER_RAW_SIZE(126,4162
#define REGISTER_U_ADDR(166,5375
#define REGISTER_VIRTUAL_SIZE(131,4317
#define REGISTER_VIRTUAL_TYPE(159,5092
#define SAVED_PC_AFTER_CALL(51,1836
#define SKIP_PROLOGUE(38,1400
m-sun3.h,790
#define ABOUT_TO_RETURN(78,2454
#define FIX_CALL_DUMMY(392,15189
#define FRAME_ARGS_ADDRESS(213,7102
#define FRAME_CHAIN(202,6741
#define FRAME_CHAIN_COMBINE(207,6930
#define FRAME_CHAIN_VALID(204,6811
#define FRAME_FIND_SAVED_REGS(249,8471
#define FRAME_LOCALS_ADDRESS(215,7145
#define FRAME_NUM_ARGS(222,7400
#define FRAME_NUM_ARGS(225,7449
#define FRAME_SAVED_PC(211,7034
#define INIT_STACK(416,15985
#define INVALID_FLOAT(82,2588
#define REGISTER_BYTE(123,4130
#define REGISTER_CONVERTIBLE(151,5061
#define REGISTER_CONVERT_TO_RAW(165,5524
#define REGISTER_CONVERT_TO_VIRTUAL(156,5228
#define REGISTER_RAW_SIZE(132,4465
#define REGISTER_VIRTUAL_SIZE(138,4721
#define REGISTER_VIRTUAL_TYPE(174,5805
#define SAVED_PC_AFTER_CALL(55,1929
#define SKIP_PROLOGUE(42,1493
m-suninit.h,29
#define FILEADDR_ROUND(5,94
m-vax.h,791
#define ABOUT_TO_RETURN(80,2551
#define FIX_CALL_DUMMY(294,10681
#define FRAME_ARGS_ADDRESS(199,6661
#define FRAME_CHAIN(185,6120
#define FRAME_CHAIN_COMBINE(190,6314
#define FRAME_CHAIN_VALID(187,6195
#define FRAME_FIND_SAVED_REGS(222,7517
#define FRAME_LOCALS_ADDRESS(204,6836
#define FRAME_NUM_ARGS(209,6972
#define FRAME_SAVED_PC(194,6418
#define INIT_STACK(317,11455
#define INVALID_FLOAT(84,2681
#define REGISTER_BYTE(127,4329
#define REGISTER_CONVERTIBLE(150,4942
#define REGISTER_CONVERT_TO_RAW(161,5257
#define REGISTER_CONVERT_TO_VIRTUAL(155,5076
#define REGISTER_RAW_SIZE(132,4491
#define REGISTER_U_ADDR(112,3753
#define REGISTER_VIRTUAL_SIZE(137,4644
#define REGISTER_VIRTUAL_TYPE(167,5425
#define SAVED_PC_AFTER_CALL(53,1877
#define SKIP_PROLOGUE(42,1480
m-vaxinit.h,29
#define FILEADDR_ROUND(5,94
m68k-opcode.h,138
#define one(130,5680
int numopcodes=sizeof(1270,68164
struct m68k_opcode *endop = m68k_opcodes+sizeof(1272,68226
#define two(131,5707
obstack.h,618
#define obstack_1grow(252,11387
#define obstack_1grow_fast(275,12190
#define obstack_alignment_mask(228,10489
#define obstack_alloc(263,11796
#define obstack_base(216,10145
#define obstack_begin(232,10606
#define obstack_blank(257,11569
#define obstack_blank_fast(277,12257
#define obstack_copy(266,11889
#define obstack_copy0(269,11994
#define obstack_finish(279,12314
#define obstack_free(290,12730
#define obstack_grow(237,10784
#define obstack_grow0(244,11064
#define obstack_init(230,10547
#define obstack_next_free(220,10254
#define obstack_object_size(224,10341
#define obstack_room(272,12101
param.h,0
symseg.h,0
symtab.h,1291
#define BLOCKLIST(108,3923
#define BLOCKLIST_BLOCK(137,4911
#define BLOCKLIST_NBLOCKS(136,4853
#define BLOCKVECTOR(109,3971
#define BLOCKVECTOR_BLOCK(139,5030
#define BLOCKVECTOR_NBLOCKS(138,4970
#define BLOCK_END(145,5244
#define BLOCK_FUNCTION(148,5354
#define BLOCK_NSYMS(146,5280
#define BLOCK_START(144,5204
#define BLOCK_SUPERBLOCK(149,5396
#define BLOCK_SYM(147,5316
#define LINELIST(113,4071
#define LINETABLE(114,4116
#define SYMBOL_BLOCK_VALUE(155,5635
#define SYMBOL_CLASS(153,5539
#define SYMBOL_NAME(151,5443
#define SYMBOL_NAMESPACE(152,5486
#define SYMBOL_TYPE(156,5692
#define SYMBOL_VALUE(154,5584
#define TYPEVECTOR(111,4022
#define TYPEVECTOR_NTYPES(141,5092
#define TYPEVECTOR_TYPE(142,5147
#define TYPE_CODE(170,6307
#define TYPE_FIELD(174,6453
#define TYPE_FIELDS(172,6403
#define TYPE_FIELD_BITPOS(178,6712
#define TYPE_FIELD_BITSIZE(179,6780
#define TYPE_FIELD_NAME(176,6571
#define TYPE_FIELD_PACKED(180,6850
#define TYPE_FIELD_TYPE(175,6507
#define TYPE_FIELD_VALUE(177,6635
#define TYPE_FLAGS(168,6187
#define TYPE_FUNCTION_TYPE(166,6075
#define TYPE_LENGTH(167,6138
#define TYPE_NAME(163,5910
#define TYPE_NFIELDS(171,6352
#define TYPE_POINTER_TYPE(165,6014
#define TYPE_TARGET_TYPE(164,5955
#define TYPE_UNSIGNED(169,6234
value.h,399
#define COERCE_ARRAY(58,1961
#define VALUE_ADDRESS(48,1560
#define VALUE_BITPOS(52,1752
#define VALUE_BITSIZE(51,1710
#define VALUE_CONTENTS(46,1469
#define VALUE_INTERNALVAR(49,1611
#define VALUE_LVAL(47,1524
#define VALUE_NEXT(53,1792
#define VALUE_OFFSET(50,1670
#define VALUE_REGNO(56,1922
#define VALUE_REPEATED(54,1828
#define VALUE_REPETITIONS(55,1872
#define VALUE_TYPE(45,1433
vax-opcode.h,0
wait.h,331
#define WCOREDUMP(13,439
#define WCOREDUMP(21,690
#define WIFEXITED(10,338
#define WIFSIGNALED(9,274
#define WIFSTOPPED(8,231
#define WRETCODE(11,377
#define WRETCODE(19,622
#define WSETSTOP(15,511
#define WSETSTOP(23,760
#define WSTOPSIG(12,408
#define WSTOPSIG(20,656
#define WTERMSIG(14,478
#define WTERMSIG(22,726
expread.y,349
copy_name 929,20955
end_arglist 516,11399
free_funcalls 530,11701
length_of_subexp 963,21859
parse_c_1 1142,25974
parse_c_expression 1181,27028
parse_number 608,13872
prefixify_expression 943,21291
prefixify_subexp 1035,23196
start_arglist 502,11040
write_exp_elt 547,12040
write_exp_string 564,12494
yyerror 920,20800
yylex 706,15915

View File

@ -1,191 +0,0 @@
/*
alloca -- (mostly) portable public-domain implementation -- D A Gwyn
last edit: 86/05/30 rms
include config.h, since on VMS it renames some symbols.
Use xmalloc instead of malloc.
This implementation of the PWB library alloca() function,
which is used to allocate space off the run-time stack so
that it is automatically reclaimed upon procedure exit,
was inspired by discussions with J. Q. Johnson of Cornell.
It should work under any C implementation that uses an
actual procedure stack (as opposed to a linked list of
frames). There are some preprocessor constants that can
be defined when compiling for your specific system, for
improved efficiency; however, the defaults should be okay.
The general concept of this implementation is to keep
track of all alloca()-allocated blocks, and reclaim any
that are found to be deeper in the stack than the current
invocation. This heuristic does not reclaim storage as
soon as it becomes invalid, but it will do so eventually.
As a special case, alloca(0) reclaims storage without
allocating any. It is a good idea to use alloca(0) in
your main control loop, etc. to force garbage collection.
*/
#ifndef lint
static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
#endif
#ifdef emacs
#include "config.h"
#ifdef static
/* actually, only want this if static is defined as ""
-- this is for usg, in which emacs must undefine static
in order to make unexec workable
*/
#ifndef STACK_DIRECTION
you
lose
-- must know STACK_DIRECTION at compile-time
#endif /* STACK_DIRECTION undefined */
#endif static
#endif emacs
#ifdef X3J11
typedef void *pointer; /* generic pointer type */
#else
typedef char *pointer; /* generic pointer type */
#endif
#define NULL 0 /* null pointer constant */
extern void free();
extern pointer xmalloc();
/*
Define STACK_DIRECTION if you know the direction of stack
growth for your system; otherwise it will be automatically
deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
#ifndef STACK_DIRECTION
#define STACK_DIRECTION 0 /* direction unknown */
#endif
#if STACK_DIRECTION != 0
#define STACK_DIR STACK_DIRECTION /* known at compile-time */
#else /* STACK_DIRECTION == 0; need run-time code */
static int stack_dir; /* 1 or -1 once known */
#define STACK_DIR stack_dir
static void
find_stack_direction (/* void */)
{
static char *addr = NULL; /* address of first
`dummy', once known */
auto char dummy; /* to get stack address */
if (addr == NULL)
{ /* initial entry */
addr = &dummy;
find_stack_direction (); /* recurse once */
}
else /* second entry */
if (&dummy > addr)
stack_dir = 1; /* stack grew upward */
else
stack_dir = -1; /* stack grew downward */
}
#endif /* STACK_DIRECTION == 0 */
/*
An "alloca header" is used to:
(a) chain together all alloca()ed blocks;
(b) keep track of stack depth.
It is very important that sizeof(header) agree with malloc()
alignment chunk size. The following default should work okay.
*/
#ifndef ALIGN_SIZE
#define ALIGN_SIZE sizeof(double)
#endif
typedef union hdr
{
char align[ALIGN_SIZE]; /* to force sizeof(header) */
struct
{
union hdr *next; /* for chaining headers */
char *deep; /* for stack depth measure */
} h;
} header;
/*
alloca( size ) returns a pointer to at least `size' bytes of
storage which will be automatically reclaimed upon exit from
the procedure that called alloca(). Originally, this space
was supposed to be taken from the current stack frame of the
caller, but that method cannot be made to work for some
implementations of C, for example under Gould's UTX/32.
*/
static header *last_alloca_header = NULL; /* -> last alloca header */
pointer
alloca (size) /* returns pointer to storage */
unsigned size; /* # bytes to allocate */
{
auto char probe; /* probes stack depth: */
register char *depth = &probe;
#if STACK_DIRECTION == 0
if (STACK_DIR == 0) /* unknown growth direction */
find_stack_direction ();
#endif
/* Reclaim garbage, defined as all alloca()ed storage that
was allocated from deeper in the stack than currently. */
{
register header *hp; /* traverses linked list */
for (hp = last_alloca_header; hp != NULL;)
if (STACK_DIR > 0 && hp->h.deep > depth
|| STACK_DIR < 0 && hp->h.deep < depth)
{
register header *np = hp->h.next;
free ((pointer) hp); /* collect garbage */
hp = np; /* -> next header */
}
else
break; /* rest are not deeper */
last_alloca_header = hp; /* -> last valid storage */
}
if (size == 0)
return NULL; /* no allocation required */
/* Allocate combined header + user data storage. */
{
register pointer new = xmalloc (sizeof (header) + size);
/* address of header */
((header *)new)->h.next = last_alloca_header;
((header *)new)->h.deep = depth;
last_alloca_header = (header *)new;
/* User storage begins just after header. */
return (pointer)((char *)new + sizeof(header));
}
}

View File

@ -1,13 +0,0 @@
main() {
int i;
for (i = 0; i >= 0; i++)
bar();
}
bar()
{
int i;
i = 10;
}

View File

@ -1,65 +0,0 @@
0000003e - 00 0002 RBRAC
000020de - 00 000d SLINE
000020d6 - 00 000c SLINE
000020c8 - 00 0009 SLINE
000020c4 - 00 0006 SLINE
00000024 - 00 0002 RBRAC
000020be - 00 0004 SLINE
000020b8 - 00 0005 SLINE
000020ae - 00 0004 SLINE
0000000e - 00 0002 LBRAC
000020d6 - 00 0009 SLINE
000020e4 - 00 ffff SLINE
000020ae - 00 0001 SLINE
000020a0 - 00 0001 SLINE
00000036 - 00 0002 LBRAC
000020e4 t -lg
00000000 - 00 0000 LSYM ???:t(0,12)=(0,1)
00002098 t Fcrt1.o
0002001c D _Fmode
00020020 D _Fstatus
0000215c T __cleanup
00002164 T __exit
00020052 D __exit_nhandlers
00020056 D __exit_tnames
00020018 D __skybase
000020c8 T _bar
00020000 D _environ
00020118 D _errno
00002110 T _exit
00002164 t _exit.o
000020e4 T _finitfp_
00020010 D _fp_state_mc68881
0002000c D _fp_state_skyffp
00020008 D _fp_state_software
00020014 D _fp_state_sunfpa
00020004 D _fp_switch
000020a0 T _main
000020a0 - 00 0000 SO bar.c
000020a0 t bar.o
000020c8 - 00 0004 FUN bar:F(0,1)
0000216c T cerror
0000216c t cerror.o
00000000 - 00 0000 LSYM char:t(0,2)=r(0,2);0;127;
00002020 t crt0.o
00000000 - 00 0000 LSYM double:t(0,10)=r(0,1);8;0;
00002110 t exit.o
0000215c t fakcu.o
000020e4 t finitfp.o
00000000 - 00 0000 LSYM float:t(0,9)=r(0,1);4;0;
00002110 t fp_globals.o
00002098 T fsoft_used
fffffffc - 00 0004 LSYM i:(0,1)
fffffffc - 00 0004 LSYM i:(0,1)
00000000 - 00 0000 LSYM int:t(0,1)=r(0,1);-2147483648;2147483647;
000020e4 - 00 0000 SO libg.s
00000000 - 00 0000 LSYM long:t(0,3)=r(0,1);-2147483648;2147483647;
000020a0 - 00 0004 FUN main:F(0,1)
00000000 - 00 0000 LSYM short:t(0,4)=r(0,1);-32768;32767;
00002020 T start
00002098 T start_float
00000000 - 00 0000 LSYM unsigned char:t(0,5)=r(0,1);0;255;
00000000 - 00 0000 LSYM unsigned int:t(0,8)=r(0,1);0;-1;
00000000 - 00 0000 LSYM unsigned long:t(0,7)=r(0,1);0;-1;
00000000 - 00 0000 LSYM unsigned short:t(0,6)=r(0,1);0;65535;
00000000 - 00 0000 LSYM void:t(0,11)=(0,11)

View File

@ -1,93 +0,0 @@
.stabs "bar.c",0144,0,0,LL0
LL0:
.data
.stabs "int:t(0,1)=r(0,1);-2147483648;2147483647;",0x80,0,0,0
.stabs "char:t(0,2)=r(0,2);0;127;",0x80,0,0,0
.stabs "long:t(0,3)=r(0,1);-2147483648;2147483647;",0x80,0,0,0
.stabs "short:t(0,4)=r(0,1);-32768;32767;",0x80,0,0,0
.stabs "unsigned char:t(0,5)=r(0,1);0;255;",0x80,0,0,0
.stabs "unsigned short:t(0,6)=r(0,1);0;65535;",0x80,0,0,0
.stabs "unsigned long:t(0,7)=r(0,1);0;-1;",0x80,0,0,0
.stabs "unsigned int:t(0,8)=r(0,1);0;-1;",0x80,0,0,0
.stabs "float:t(0,9)=r(0,1);4;0;",0x80,0,0,0
.stabs "double:t(0,10)=r(0,1);8;0;",0x80,0,0,0
.stabs "void:t(0,11)=(0,11)",0x80,0,0,0
.stabs "???:t(0,12)=(0,1)",0x80,0,0,0
.stabs "main:F(0,1)",0x24,0,4,_main
.text
.stabn 0104,0,1,LL1
LL1:
|#PROC# 04
.globl _main
_main:
|#PROLOGUE# 0
link a6,#0
addl #-LF12,sp
moveml #LS12,sp@
|#PROLOGUE# 1
.stabn 0104,0,1,LL2
LL2:
.stabs "i:(0,1)",0x80,0,4,-4
.stabn 0300,0,2,LL3
LL3:
.stabn 0104,0,4,LL4
LL4:
clrl a6@(-0x4)
L16:
tstl a6@(-0x4)
jlt L15
.stabn 0104,0,5,LL5
LL5:
jbsr _bar
L14:
.stabn 0104,0,4,LL6
LL6:
addql #0x1,a6@(-0x4)
jra L16
L15:
.stabn 0340,0,2,LL7
LL7:
.stabn 0104,0,6,LL8
LL8:
LE12:
unlk a6
rts
LF12 = 4
LS12 = 0x0
LFF12 = 4
LSS12 = 0x0
LP12 = 0x8
.data
.stabs "bar:F(0,1)",0x24,0,4,_bar
.text
.stabn 0104,0,9,LL9
LL9:
|#PROC# 04
.globl _bar
_bar:
|#PROLOGUE# 0
link a6,#0
addl #-LF18,sp
moveml #LS18,sp@
|#PROLOGUE# 1
.stabn 0104,0,9,LL10
LL10:
.stabs "i:(0,1)",0x80,0,4,-4
.stabn 0300,0,2,LL11
LL11:
.stabn 0104,0,12,LL12
LL12:
movl #0xa,a6@(-0x4)
.stabn 0340,0,2,LL13
LL13:
.stabn 0104,0,13,LL14
LL14:
LE18:
unlk a6
rts
LF18 = 4
LS18 = 0x0
LFF18 = 4
LSS18 = 0x0
LP18 = 0x8
.data

View File

@ -1,51 +0,0 @@
Symtab for file libg.s
Line table:
line 2 at 20e4
Blockvector:
block #000 (object 0x56f90) [0x20e4..0x20e4]
block #001 (object 0x56f7c) [0x20e4..0x20e4] (under 0x56f90)
Symtab for file bar.c
Line table:
line 1 at 20a0
line 1 at 20ae
line 4 at 20ae
line 5 at 20b8
line 4 at 20be
line 6 at 20c4
line 9 at 20c8
line 9 at 20d6
line 12 at 20d6
line 13 at 20de
Blockvector:
block #000 (object 0x56f4c) [0x20a0..0x20e4]
int bar; block (object 0x56ef0) starting at 0x20c8,
int main; block (object 0x56ea8) starting at 0x20a0,
block #001 (object 0x56f08) [0x20a0..0x20e4] (under 0x56f4c)
typedef int ???;
typedef char char;
typedef double double;
typedef float float;
typedef int int;
typedef int long;
typedef short short;
typedef unsigned char unsigned char;
typedef unsigned int unsigned int;
typedef unsigned int unsigned long;
typedef unsigned short unsigned short;
typedef void void;
block #002 (object 0x56ea8) [0x20a0..0x20c8] (under 0x56f08) main
int i; local at 0xfffffffc,
block #003 (object 0x56ef0) [0x20c8..0x20e4] (under 0x56f08) bar
int i; local at 0xfffffffc,

View File

@ -1,6 +1,6 @@
/* Get info from stack frames;
convert between frames, blocks, functions and pc values.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
@ -288,17 +288,33 @@ find_pc_function (pc)
int
find_pc_misc_function (pc)
CORE_ADDR pc;
register CORE_ADDR pc;
{
register int i;
register int lo = 0;
register int hi = misc_function_count-1;
register int new;
register int distance;
/* Note that the last thing in the vector is always _etext. */
for (i = 0; i < misc_function_count; i++)
{
if (pc < misc_function_vector[i].address)
return i - 1;
}
return -1;
/* trivial reject range test */
if (pc < misc_function_vector[0].address ||
pc > misc_function_vector[hi].address)
return -1;
do {
new = (lo + hi) >> 1;
distance = misc_function_vector[new].address - pc;
if (distance == 0)
return new; /* an exact match */
else if (distance > 0)
hi = new;
else
lo = new;
} while (hi-lo != 1);
/* if here, we had no exact match, so return the lower choice */
return lo;
}
/* Return the innermost stack frame executing inside of the specified block,

View File

@ -142,7 +142,9 @@ condition_command (arg, from_tty)
while (*p == ' ' || *p == '\t') p++;
arg = p;
b->cond = (struct expression *) parse_c_1 (&arg, block_for_pc (b->address));
b->cond = (struct expression *) parse_c_1 (&arg, block_for_pc (b->address), 0);
if (*arg)
error ("Junk at end of expression");
}
return;
}
@ -605,63 +607,96 @@ set_breakpoint (s, line, tempflag)
}
/* Set a breakpoint according to ARG (function, linenum or *address)
and make it temporary if TEMPFLAG is nonzero. */
and make it temporary if TEMPFLAG is nonzero.
LINE_NUM is for C++. */
static void
break_command_1 (arg, tempflag, from_tty)
break_command_1 (arg, tempflag, from_tty, line_num)
char *arg;
int tempflag, from_tty;
int tempflag, from_tty, line_num;
{
struct symtabs_and_lines sals;
struct symtab_and_line sal;
register struct expression *cond = 0;
register struct breakpoint *b;
char *save_arg;
int i;
sal.pc = 0;
sals.sals = NULL;
sals.nelts = 0;
sal.line = sal.pc = sal.end = 0;
sal.symtab = 0;
if (arg)
{
sal = decode_line_1 (&arg, 1, 0, 0);
CORE_ADDR pc;
sals = decode_line_1 (&arg, 1, 0, 0);
if (sal.pc == 0 && sal.symtab != 0)
if (! sals.nelts) return;
save_arg = arg;
for (i = 0; i < sals.nelts; i++)
{
sal.pc = find_line_pc (sal.symtab, sal.line);
if (sal.pc == 0)
error ("No line %d in file \"%s\".",
sal.line, sal.symtab->filename);
}
sal = sals.sals[i];
if (sal.pc == 0 && sal.symtab != 0)
{
pc = find_line_pc (sal.symtab, sal.line);
if (pc == 0)
error ("No line %d in file \"%s\".",
sal.line, sal.symtab->filename);
}
else pc = sal.pc;
while (*arg)
{
if (arg[0] == 'i' && arg[1] == 'f'
&& (arg[2] == ' ' || arg[2] == '\t'))
cond = (struct expression *) parse_c_1 ((arg += 2, &arg),
block_for_pc (sal.pc));
else
error ("Junk at end of arguments.");
while (*arg)
{
if (arg[0] == 'i' && arg[1] == 'f'
&& (arg[2] == ' ' || arg[2] == '\t'))
cond = (struct expression *) parse_c_1 ((arg += 2, &arg),
block_for_pc (pc), 0);
else
error ("Junk at end of arguments.");
}
arg = save_arg;
sals.sals[i].pc = pc;
}
}
else if (default_breakpoint_valid)
{
sals.sals = (struct symtab_and_line *) malloc (sizeof (struct symtab_and_line));
sal.pc = default_breakpoint_address;
sal.line = default_breakpoint_line;
sal.symtab = default_breakpoint_symtab;
sals.sals[0] = sal;
sals.nelts = 1;
}
else
error ("No default breakpoint address now.");
if (from_tty)
describe_other_breakpoints (sal.pc);
for (i = 0; i < sals.nelts; i++)
{
sal = sals.sals[i];
sal.line += line_num; /** C++ **/
if (line_num != 0)
{ /* get the pc for a particular line */
sal.pc = find_line_pc (sal.symtab, sal.line);
}
b = set_raw_breakpoint (sal);
b->number = ++breakpoint_count;
b->cond = cond;
if (tempflag)
b->enable = temporary;
if (from_tty)
describe_other_breakpoints (sal.pc);
printf ("Breakpoint %d at 0x%x", b->number, b->address);
if (b->symtab)
printf (": file %s, line %d.", b->symtab->filename, b->line_number);
printf ("\n");
b = set_raw_breakpoint (sal);
b->number = ++breakpoint_count;
b->cond = cond;
if (tempflag)
b->enable = temporary;
printf ("Breakpoint %d at 0x%x", b->number, b->address);
if (b->symtab)
printf (": file %s, line %d.", b->symtab->filename, b->line_number);
printf ("\n");
}
free (sals.sals);
}
static void
@ -669,7 +704,7 @@ break_command (arg, from_tty)
char *arg;
int from_tty;
{
break_command_1 (arg, 0, from_tty);
break_command_1 (arg, 0, from_tty, 0);
}
static void
@ -677,7 +712,7 @@ tbreak_command (arg, from_tty)
char *arg;
int from_tty;
{
break_command_1 (arg, 1, from_tty);
break_command_1 (arg, 1, from_tty, 0);
}
static void
@ -686,60 +721,72 @@ clear_command (arg, from_tty)
int from_tty;
{
register struct breakpoint *b, *b1;
struct symtabs_and_lines sals;
struct symtab_and_line sal;
register struct breakpoint *found;
int i;
if (arg)
sal = decode_line_spec (arg, 1);
{
sals = decode_line_spec (arg, 1);
}
else
{
sals.sals = (struct symtab_and_line *) malloc (sizeof (struct symtab_and_line));
sal.line = default_breakpoint_line;
sal.symtab = default_breakpoint_symtab;
sal.pc = 0;
if (sal.symtab == 0)
error ("No source file specified.");
sals.sals[0] = sal;
sals.nelts = 1;
}
/* If exact pc given, clear bpts at that pc.
But if sal.pc is zero, clear all bpts on specified line. */
found = (struct breakpoint *) 0;
while (breakpoint_chain
&& (sal.pc ? breakpoint_chain->address == sal.pc
: (breakpoint_chain->symtab == sal.symtab
&& breakpoint_chain->line_number == sal.line)))
for (i = 0; i < sals.nelts; i++)
{
b1 = breakpoint_chain;
breakpoint_chain = b1->next;
b1->next = found;
found = b1;
/* If exact pc given, clear bpts at that pc.
But if sal.pc is zero, clear all bpts on specified line. */
sal = sals.sals[i];
found = (struct breakpoint *) 0;
while (breakpoint_chain
&& (sal.pc ? breakpoint_chain->address == sal.pc
: (breakpoint_chain->symtab == sal.symtab
&& breakpoint_chain->line_number == sal.line)))
{
b1 = breakpoint_chain;
breakpoint_chain = b1->next;
b1->next = found;
found = b1;
}
ALL_BREAKPOINTS (b)
while (b->next
&& (sal.pc ? b->next->address == sal.pc
: (b->next->symtab == sal.symtab
&& b->next->line_number == sal.line)))
{
b1 = b->next;
b->next = b1->next;
b1->next = found;
found = b1;
}
if (found == 0)
error ("No breakpoint at %s.", arg);
if (found->next) from_tty = 1; /* Always report if deleted more than one */
if (from_tty) printf ("Deleted breakpoint%s ", found->next ? "s" : "");
while (found)
{
if (from_tty) printf ("%d ", found->number);
b1 = found->next;
delete_breakpoint (found);
found = b1;
}
if (from_tty) putchar ('\n');
}
ALL_BREAKPOINTS (b)
while (b->next
&& (sal.pc ? b->next->address == sal.pc
: (b->next->symtab == sal.symtab
&& b->next->line_number == sal.line)))
{
b1 = b->next;
b->next = b1->next;
b1->next = found;
found = b1;
}
if (found == 0)
error ("No breakpoint at %s.", arg);
if (found->next) from_tty = 1; /* Alwats report if deleted more than one */
if (from_tty) printf ("Deleted breakpoint%s ", found->next ? "s" : "");
while (found)
{
if (from_tty) printf ("%d ", found->number);
b1 = found->next;
delete_breakpoint (found);
found = b1;
}
if (from_tty) putchar ('\n');
free (sals.sals);
}
/* Delete breakpoint number BNUM if it is a `delete' breakpoint.

View File

@ -30,7 +30,6 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include <a.out.h>
#include <stdio.h>
#include <obstack.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/file.h>
@ -169,9 +168,6 @@ extern CORE_ADDR first_object_file_end; /* From blockframe.c */
/* File name symbols were loaded from. */
static char *symfile;
int debug = 1;
/* Look up a coff type-number index. Return the address of the slot
where the type for that index is stored.
@ -785,7 +781,7 @@ read_coff_symtab (desc, nsyms)
static AUXENT main_aux;
int num_object_files = 0;
int next_file_symnum = 0;
int next_file_symnum;
char *filestring;
int depth;
int fcn_first_line;
@ -810,10 +806,6 @@ read_coff_symtab (desc, nsyms)
{
read_one_sym (cs, &main_sym, &main_aux);
/*
* If we are finished with the previous file's symbols, and the
* next thing is not a C_FILE, then we have hit the global symbols.
*/
if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE)
{
CORE_ADDR last_file_end = cur_src_end_addr;
@ -826,6 +818,10 @@ read_coff_symtab (desc, nsyms)
/* done with all files, everything from here on out is globals */
}
/* Special case for file with type declarations only, no text. */
if (!last_source_file && cs->c_type != T_NULL && cs->c_secnum == N_DEBUG)
complete_symtab (filestring, 0, 0);
if (ISFCN (cs->c_type))
{
/*
@ -877,7 +873,6 @@ read_coff_symtab (desc, nsyms)
end_symtab ();
start_symtab ();
}
complete_symtab (filestring, 0, 0); /* FIXME, 0 0 is wrong */
num_object_files++;
break;
@ -902,12 +897,8 @@ read_coff_symtab (desc, nsyms)
case C_STAT:
if (cs->c_type == T_NULL && cs->c_secnum > N_UNDEF)
{
/* These ".text", ".data", ".bss" entries don't seem to
* appear in A/UX COFF output. -- gnu@toad.com 4Apr88
*/
if (strcmp (cs->c_name, _TEXT) == 0)
{
/* We have a ".text" symbol */
if (num_object_files == 1)
{
/* Record end address of first file, crt0.s */
@ -1020,9 +1011,15 @@ read_file_hdr (chan, file_hdr)
if (myread (chan, (char *)file_hdr, FILHSZ) < 0)
return -1;
if (BADMAG(file_hdr))
return -1; /* Non understood file */
return file_hdr->f_nsyms; /* OK magic number, return # syms */
switch (file_hdr->f_magic)
{
case NS32GMAGIC:
case NS32SMAGIC:
return file_hdr->f_nsyms;
default:
return -1;
}
}
read_aout_hdr (chan, aout_hdr, size)
@ -1081,17 +1078,6 @@ read_one_sym (cs, sym, aux)
cs->c_secnum = sym->n_scnum;
cs->c_type = (unsigned) sym->n_type;
#ifdef DEBUG
if (debug) {
fprintf(stderr, "sym %3x: %2x %s %x %x %x", cs->c_symnum,
cs->c_sclass, cs->c_name, cs->c_value, cs->c_secnum, cs->c_type);
if (cs->c_nsyms > 1)
fprintf(stderr, " +aux %s\n", (char *)aux);
else
fprintf(stderr, "\n");
}
#endif
symnum += cs->c_nsyms;
}
@ -1111,13 +1097,6 @@ init_stringtab (chan, offset)
return -1;
val = myread (chan, (char *)&buffer, sizeof buffer);
/* If no string table, we get 0 bytes back from the read. That's OK. */
if (val == 0) {
free_stringtab();
return 0;
}
if (val != sizeof buffer)
return -1;
@ -1150,8 +1129,6 @@ getsymname (symbol_entry)
if (symbol_entry->n_zeroes == 0)
{
if (!stringtab)
error("Symbol entry references nonexistent string table");
result = stringtab + symbol_entry->n_offset;
}
else
@ -1172,11 +1149,9 @@ getfilename (aux_entry)
char *result;
extern char *rindex ();
#ifndef mac_aux
if (aux_entry->x_file.x_foff != 0)
strcpy (buffer, stringtab + aux_entry->x_file.x_foff);
else
#endif
{
strncpy (buffer, aux_entry->x_file.x_fname, FILNMLEN);
buffer[FILNMLEN] = '\0';
@ -1578,8 +1553,7 @@ decode_base_type (cs, c_type, aux)
switch (c_type)
{
case T_NULL:
/* NULL seems to be used as the basic type of void functions */
return builtin_type_void;
/* shouldn't show up here */
break;
case T_ARG:
@ -1663,8 +1637,7 @@ decode_base_type (cs, c_type, aux)
case T_ULONG:
return builtin_type_unsigned_long;
}
printf ("unexpected type %d at symnum %d, name %s\n", c_type, cs->c_symnum,
cs->c_name);
printf ("unexpected type %d at symnum %d\n", c_type, cs->c_symnum);
return builtin_type_void;
}

View File

@ -46,32 +46,40 @@ the terms of Paragraph 1 above, provided that you also do the following:
that in whole or in part contains or is a derivative of this
program or any part thereof, to be licensed at no charge to all
third parties on terms identical to those contained in this
License Agreement (except that you may choose to grant more
extensive warranty protection to third parties, at your option).
License Agreement (except that you may choose to grant more extensive
warranty protection to some or all third parties, at your option).
c) You may charge a distribution fee for the physical act of
transferring a copy, and you may at your option offer warranty
protection in exchange for a fee.
3. You may copy and distribute this program or any portion of it in
compiled, executable or object code form under the terms of Paragraphs
1 and 2 above provided that you do the following:
Mere aggregation of another unrelated program with this program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other program under the scope of these terms.
a) cause each such copy to be accompanied by the
corresponding machine-readable source code, which must
be distributed under the terms of Paragraphs 1 and 2 above; or,
3. You may copy and distribute this program (or a portion or derivative
of it, under Paragraph 2) in object code or executable form under the terms
of Paragraphs 1 and 2 above provided that you also do one of the following:
b) cause each such copy to be accompanied by a
written offer, with no time limit, to give any third party
free (except for a nominal shipping charge) a machine readable
copy of the corresponding source code, to be distributed
under the terms of Paragraphs 1 and 2 above; or,
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) in the case of a recipient of this program in compiled, executable
or object code form (without the corresponding source code) you
shall cause copies you distribute to be accompanied by a copy
of the written offer of source code which you received along
with the copy you received.
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal
shipping charge) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
For an executable file, complete source code means all the source code for
all modules it contains; but, as a special exception, it need not include
source code for modules which are standard libraries that accompany the
operating system on which the executable file runs.
4. You may not copy, sublicense, distribute or transfer this program
except as expressly provided under this License Agreement. Any attempt

View File

@ -46,32 +46,40 @@ the terms of Paragraph 1 above, provided that you also do the following:
that in whole or in part contains or is a derivative of this
program or any part thereof, to be licensed at no charge to all
third parties on terms identical to those contained in this
License Agreement (except that you may choose to grant more
extensive warranty protection to third parties, at your option).
License Agreement (except that you may choose to grant more extensive
warranty protection to some or all third parties, at your option).
c) You may charge a distribution fee for the physical act of
transferring a copy, and you may at your option offer warranty
protection in exchange for a fee.
3. You may copy and distribute this program or any portion of it in
compiled, executable or object code form under the terms of Paragraphs
1 and 2 above provided that you do the following:
Mere aggregation of another unrelated program with this program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other program under the scope of these terms.
a) cause each such copy to be accompanied by the
corresponding machine-readable source code, which must
be distributed under the terms of Paragraphs 1 and 2 above; or,
3. You may copy and distribute this program (or a portion or derivative
of it, under Paragraph 2) in object code or executable form under the terms
of Paragraphs 1 and 2 above provided that you also do one of the following:
b) cause each such copy to be accompanied by a
written offer, with no time limit, to give any third party
free (except for a nominal shipping charge) a machine readable
copy of the corresponding source code, to be distributed
under the terms of Paragraphs 1 and 2 above; or,
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) in the case of a recipient of this program in compiled, executable
or object code form (without the corresponding source code) you
shall cause copies you distribute to be accompanied by a copy
of the written offer of source code which you received along
with the copy you received.
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal
shipping charge) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
For an executable file, complete source code means all the source code for
all modules it contains; but, as a special exception, it need not include
source code for modules which are standard libraries that accompany the
operating system on which the executable file runs.
4. You may not copy, sublicense, distribute or transfer this program
except as expressly provided under this License Agreement. Any attempt

View File

@ -24,7 +24,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include <a.out.h>
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/file.h>
@ -41,16 +41,8 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#ifdef UMAX_CORE
#include <sys/ptrace.h>
#else /* not UMAX_CORE */
#ifdef mac_aux
#include <sys/seg.h>
#include <sys/mmu.h>
#include <sys/signal.h>
#include <sys/time.h>
#include <sys/user.h>
#else
#include <sys/user.h>
#endif /* mac_aux */
#endif /* UMAX_CORE */
#endif
#endif /* NEW_SUN_CORE */
#ifndef N_TXTADDR
@ -72,6 +64,8 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define AOUTHDR struct exec
#endif
extern char *sys_siglist[];
START_FILE
/* Hook for `exec_file_command' command to call. */
@ -105,8 +99,9 @@ static CORE_ADDR stack_end;
/* Virtual addresses of bounds of two areas of memory in the exec file.
Note that the data area in the exec file is used only when there is no core file. */
static CORE_ADDR text_start;
static CORE_ADDR text_end;
CORE_ADDR text_start;
CORE_ADDR text_end;
static CORE_ADDR exec_data_start;
static CORE_ADDR exec_data_end;
@ -211,6 +206,12 @@ core_file_command (filename, from_tty)
bcopy (&corestr.c_aouthdr, &core_aouthdr, sizeof (struct exec));
printf ("Core file is from \"%s\".\n", corestr.c_cmdname);
if (corestr.c_signo > 0)
printf ("Program terminated with signal %d, %s.\n",
corestr.c_signo,
corestr.c_signo < NSIG
? sys_siglist[corestr.c_signo]
: "(undocumented)");
}
#else /* not NEW_SUN_CORE */
/* 4.2-style (and perhaps also sysV-style) core dump file. */
@ -235,18 +236,14 @@ core_file_command (filename, from_tty)
reg_offset = 0;
bcopy (&u.pt_aouthdr, &core_aouthdr, sizeof (AOUTHDR));
printf ("Core file is from \"%s\".\n", u.pt_comm);
if (u.pt_signal > 0)
printf ("Program terminated with signal %d, %s.\n",
u.pt_signal,
u.pt_signal < NSIG
? sys_siglist[u.pt_signal]
: "(undocumented)");
#else /* not UMAX_CORE */
#ifdef mac_aux
/* This may well not work for 0407 (nonshared text) a.out's */
data_end = data_start + u.u_dsize << PAGESHIFT;
stack_start = stack_end - u.u_ssize << PAGESHIFT;
data_offset = USIZE;
stack_offset = USIZE + u.u_dsize << PAGESHIFT;
reg_offset = (int) &u.u_ar0[0] - (int) &u;
core_aouthdr.a_magic = u.u_exdata.ux_mag;
#else
data_end = data_start + NBPG * u.u_dsize;
stack_start = stack_end - NBPG * u.u_ssize;
data_offset = NBPG * UPAGES;
@ -256,7 +253,6 @@ core_file_command (filename, from_tty)
/* I don't know where to find this info.
So, for now, mark it as not available. */
core_aouthdr.a_magic = 0;
#endif /* not mac_aux */
#endif /* not UMAX_CORE */
/* Read the register values out of the core file and store
@ -285,10 +281,7 @@ core_file_command (filename, from_tty)
corefile = savestring (filename, strlen (filename));
else
{
char dirname[MAXPATHLEN];
getwd (dirname);
corefile = concat (dirname, "/", filename);
corefile = concat (current_directory, "/", filename);
}
set_current_frame (read_register (FP_REGNUM));
@ -672,12 +665,6 @@ register_addr (regno, blockend)
if (regno < 0 || regno >= NUM_REGS)
error ("Invalid register number %d.", regno);
#ifdef mac_aux
/* FIXME, we don't know where the regs are. Maybe the test command
* that tests what parts of the upage are writeable will find 'em for us.
*/
#define REGISTER_U_ADDR(addr, foo, bar) addr = 0;
#endif
REGISTER_U_ADDR (addr, blockend, regno);
return addr;

File diff suppressed because it is too large Load Diff

View File

@ -73,3 +73,7 @@ struct command_line
};
struct command_line *read_command_lines ();
/* String containing the current directory (what getwd would return). */
char *current_directory;

View File

@ -46,32 +46,40 @@ the terms of Paragraph 1 above, provided that you also do the following:
that in whole or in part contains or is a derivative of this
program or any part thereof, to be licensed at no charge to all
third parties on terms identical to those contained in this
License Agreement (except that you may choose to grant more
extensive warranty protection to third parties, at your option).
License Agreement (except that you may choose to grant more extensive
warranty protection to some or all third parties, at your option).
c) You may charge a distribution fee for the physical act of
transferring a copy, and you may at your option offer warranty
protection in exchange for a fee.
3. You may copy and distribute this program or any portion of it in
compiled, executable or object code form under the terms of Paragraphs
1 and 2 above provided that you do the following:
Mere aggregation of another unrelated program with this program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other program under the scope of these terms.
a) cause each such copy to be accompanied by the
corresponding machine-readable source code, which must
be distributed under the terms of Paragraphs 1 and 2 above; or,
3. You may copy and distribute this program (or a portion or derivative
of it, under Paragraph 2) in object code or executable form under the terms
of Paragraphs 1 and 2 above provided that you also do one of the following:
b) cause each such copy to be accompanied by a
written offer, with no time limit, to give any third party
free (except for a nominal shipping charge) a machine readable
copy of the corresponding source code, to be distributed
under the terms of Paragraphs 1 and 2 above; or,
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) in the case of a recipient of this program in compiled, executable
or object code form (without the corresponding source code) you
shall cause copies you distribute to be accompanied by a copy
of the written offer of source code which you received along
with the copy you received.
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal
shipping charge) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
For an executable file, complete source code means all the source code for
all modules it contains; but, as a special exception, it need not include
source code for modules which are standard libraries that accompany the
operating system on which the executable file runs.
4. You may not copy, sublicense, distribute or transfer this program
except as expressly provided under this License Agreement. Any attempt

View File

@ -50,7 +50,7 @@ CORE_ADDR
parse_and_eval_address_1 (expptr)
char **expptr;
{
struct expression *expr = parse_c_1 (expptr, 0);
struct expression *expr = parse_c_1 (expptr, 0, 0);
register CORE_ADDR addr;
register struct cleanup *old_chain
= make_cleanup (free_current_contents, &expr);
@ -73,6 +73,24 @@ parse_and_eval (exp)
do_cleanups (old_chain);
return val;
}
/* Parse up to a comma (or to a closeparen)
in the string EXPP as an expression, evaluate it, and return the value.
EXPP is advanced to point to the comma. */
value
parse_to_comma_and_eval (expp)
char **expp;
{
struct expression *expr = parse_c_1 (expp, 0, 1);
register value val;
register struct cleanup *old_chain
= make_cleanup (free_current_contents, &expr);
val = evaluate_expression (expr);
do_cleanups (old_chain);
return val;
}
/* Evaluate an expression in internal prefix form
such as is constructed by expread.y.
@ -118,8 +136,8 @@ evaluate_subexp (exp, pos, noside)
{
enum exp_opcode op;
int tem;
register int pc;
register value arg1, arg2;
register int pc, pc2, *oldpos;
register value arg1, arg2, arg3;
int nargs;
value *argvec;
@ -128,6 +146,12 @@ evaluate_subexp (exp, pos, noside)
switch (op)
{
case OP_SCOPE:
tem = strlen (&exp->elts[pc + 2].string);
(*pos) += 3 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
return value_static_field (exp->elts[pc + 1].type,
&exp->elts[pc + 2].string, -1);
case OP_LONG:
(*pos) += 3;
return value_from_long (exp->elts[pc + 1].type,
@ -156,21 +180,6 @@ evaluate_subexp (exp, pos, noside)
(*pos) += 2;
return value_of_internalvar (exp->elts[pc + 1].internalvar);
case OP_FUNCALL:
(*pos) += 2;
nargs = exp->elts[pc + 1].longconst;
argvec = (value *) alloca (sizeof (value) * (nargs + 1));
for (tem = 0; tem <= nargs; tem++)
/* Ensure that array expressions are coerced into pointer objects. */
argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
if (noside == EVAL_AVOID_SIDE_EFFECTS)
return allocate_value (TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0])));
return call_function (argvec[0], nargs, argvec + 1);
case OP_STRING:
tem = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
@ -193,13 +202,146 @@ evaluate_subexp (exp, pos, noside)
return arg2;
}
case OP_FUNCALL:
(*pos) += 2;
op = exp->elts[*pos].opcode;
if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
{
int fnptr;
int tem2;
nargs = exp->elts[pc + 1].longconst + 1;
/* First, evaluate the structure into arg2 */
pc2 = (*pos)++;
if (noside == EVAL_SKIP)
goto nosideret;
if (op == STRUCTOP_MEMBER)
{
arg2 = evaluate_subexp_for_address (exp, pos, noside);
}
else
{
arg2 = evaluate_subexp (exp, pos, noside);
}
/* If the function is a virtual function, then the
aggregate value (providing the structure) plays
its part by providing the vtable. Otherwise,
it is just along for the ride: call the function
directly. */
arg1 = evaluate_subexp (exp, pos, noside);
fnptr = value_as_long (arg1);
if (fnptr < 128)
{
struct type *basetype;
int i, j;
basetype = TYPE_TARGET_TYPE (VALUE_TYPE (arg2));
basetype = TYPE_VPTR_BASETYPE (basetype);
for (i = TYPE_NFN_FIELDS (basetype) - 1; i >= 0; i--)
{
struct fn_field *f = TYPE_FN_FIELDLIST1 (basetype, i);
/* If one is virtual, then all are virtual. */
if (TYPE_FN_FIELD_VIRTUAL_P (f, 0))
for (j = TYPE_FN_FIELDLIST_LENGTH (basetype, i) - 1; j >= 0; --j)
if (TYPE_FN_FIELD_VOFFSET (f, j) == fnptr)
{
value vtbl;
value base = value_ind (arg2);
struct type *fntype = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
if (TYPE_VPTR_FIELDNO (basetype) < 0)
TYPE_VPTR_FIELDNO (basetype)
= fill_in_vptr_fieldno (basetype);
VALUE_TYPE (base) = basetype;
vtbl = value_field (base, TYPE_VPTR_FIELDNO (basetype));
VALUE_TYPE (vtbl) = lookup_pointer_type (fntype);
VALUE_TYPE (arg1) = builtin_type_int;
arg1 = value_subscript (vtbl, arg1);
VALUE_TYPE (arg1) = fntype;
goto got_it;
}
}
if (i < 0)
error ("virtual function at index %d not found", fnptr);
}
else
{
VALUE_TYPE (arg1) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)));
}
got_it:
/* Now, say which argument to start evaluating from */
tem = 2;
}
else if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
{
/* Hair for method invocations */
int tem2;
nargs = exp->elts[pc + 1].longconst + 1;
/* First, evaluate the structure into arg2 */
pc2 = (*pos)++;
tem2 = strlen (&exp->elts[pc2 + 1].string);
*pos += 2 + (tem2 + sizeof (union exp_element)) / sizeof (union exp_element);
if (noside == EVAL_SKIP)
goto nosideret;
if (op == STRUCTOP_STRUCT)
{
arg2 = evaluate_subexp_for_address (exp, pos, noside);
}
else
{
arg2 = evaluate_subexp (exp, pos, noside);
}
/* Now, say which argument to start evaluating from */
tem = 2;
}
else
{
nargs = exp->elts[pc + 1].longconst;
tem = 0;
}
argvec = (value *) alloca (sizeof (value) * (nargs + 2));
for (; tem <= nargs; tem++)
/* Ensure that array expressions are coerced into pointer objects. */
argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
/* signal end of arglist */
argvec[tem] = 0;
if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
{
argvec[1] = arg2;
argvec[0] =
value_struct_elt (arg2, argvec+1, &exp->elts[pc2 + 1].string,
op == STRUCTOP_STRUCT
? "structure" : "structure pointer");
}
else if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
{
argvec[1] = arg2;
argvec[0] = arg1;
}
if (noside == EVAL_SKIP)
goto nosideret;
if (noside == EVAL_AVOID_SIDE_EFFECTS)
return allocate_value (TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0])));
return call_function (argvec[0], nargs, argvec + 1);
case STRUCTOP_STRUCT:
tem = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
arg1 = evaluate_subexp (exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
return value_struct_elt (arg1, &exp->elts[pc + 1].string,
return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string,
"structure");
case STRUCTOP_PTR:
@ -208,9 +350,37 @@ evaluate_subexp (exp, pos, noside)
arg1 = evaluate_subexp (exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
return value_struct_elt (arg1, &exp->elts[pc + 1].string,
return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string,
"structure pointer");
case STRUCTOP_MEMBER:
arg1 = evaluate_subexp_for_address (exp, pos, noside);
arg2 = evaluate_subexp (exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
/* Now, convert these values to an address.
@@ We do not know what type we are looking for,
@@ so we must assume that the value requested is a
@@ member address (as opposed to a member function address). */
arg3 = value_from_long (builtin_type_long,
value_as_long (arg1) + value_as_long (arg2));
VALUE_TYPE (arg3) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)));
return value_ind (arg3);
case STRUCTOP_MPTR:
arg1 = evaluate_subexp (exp, pos, noside);
arg2 = evaluate_subexp (exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
/* Now, convert these values to an address.
@@ We do not know what type we are looking for,
@@ so we must assume that the value requested is a
@@ member address (as opposed to a member function address). */
arg3 = value_from_long (builtin_type_long,
value_as_long (arg1) + value_as_long (arg2));
VALUE_TYPE (arg3) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)));
return value_ind (arg3);
case BINOP_ASSIGN:
arg1 = evaluate_subexp (exp, pos, noside);
arg2 = evaluate_subexp (exp, pos, noside);
@ -373,7 +543,22 @@ evaluate_subexp (exp, pos, noside)
evaluate_subexp (exp, pos, EVAL_SKIP);
goto nosideret;
}
return evaluate_subexp_for_address (exp, pos, noside);
/* C++: check for and handle pointer to members. */
op = exp->elts[*pos].opcode;
if (op == OP_SCOPE)
{
char *name = &exp->elts[pc+3].string;
int tem = strlen (name);
struct type *domain = exp->elts[pc+2].type;
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
arg1 = value_struct_elt_for_address (domain, 0, name);
if (arg1)
return arg1;
error ("no field `%s' in structure", name);
}
else
return evaluate_subexp_for_address (exp, pos, noside);
case UNOP_SIZEOF:
if (noside == EVAL_SKIP)
@ -426,6 +611,13 @@ evaluate_subexp (exp, pos, noside)
return arg1;
value_assign (arg1, arg2);
return arg1;
case OP_THIS:
(*pos) += 1;
return value_of_this (1);
default:
error ("internal error: I dont know how to evaluation what you gave me");
}
nosideret:

View File

@ -79,7 +79,9 @@ static struct op_print op_print_tab[] =
{"&", UNOP_ADDR, PREC_PREFIX, 0},
{"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
{"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
{"--", UNOP_PREDECREMENT, PREC_PREFIX, 0}
{"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
/* C++ */
{"::", BINOP_SCOPE, PREC_PREFIX, 0},
};
static void print_subexp ();
@ -119,6 +121,18 @@ print_subexp (exp, pos, stream, prec)
opcode = exp->elts[pc].opcode;
switch (opcode)
{
case OP_SCOPE:
myprec = PREC_PREFIX;
assoc = 0;
(*pos) += 2;
print_subexp (exp, pos, stream, (int) myprec + assoc);
fprintf (stream, " :: ");
nargs = strlen (&exp->elts[pc + 2].string);
(*pos) += 1 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
fprintf (stream, &exp->elts[pc + 2].string);
return;
case OP_LONG:
(*pos) += 3;
value_print (value_from_long (exp->elts[pc + 1].type,

2114
gdb/expread.tab.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -93,10 +93,14 @@ struct stoken
struct block *bval;
enum exp_opcode opcode;
struct internalvar *ivar;
struct type **tvec;
int *ivec;
}
%type <voidval> exp exp1 start variable
%type <tval> type typebase
%type <tvec> nonempty_typelist
%type <bval> block
%token <lval> INT CHAR
@ -122,6 +126,9 @@ struct stoken
%token <opcode> ASSIGN_MODIFY
/* C++ */
%token THIS
%left ','
%left ABOVE_COMMA
%right '=' ASSIGN_MODIFY
@ -196,12 +203,20 @@ exp : exp ARROW name
write_exp_elt (STRUCTOP_PTR); }
;
exp : exp ARROW '*' exp
{ write_exp_elt (STRUCTOP_MPTR); }
;
exp : exp '.' name
{ write_exp_elt (STRUCTOP_STRUCT);
write_exp_string ($3);
write_exp_elt (STRUCTOP_STRUCT); }
;
exp : exp '.' '*' exp
{ write_exp_elt (STRUCTOP_MEMBER); }
;
exp : exp '[' exp1 ']'
{ write_exp_elt (BINOP_SUBSCRIPT); }
;
@ -390,8 +405,17 @@ exp : STRING
write_exp_elt (OP_STRING); }
;
/* C++. */
exp : THIS
{ write_exp_elt (OP_THIS);
write_exp_elt (OP_THIS); }
;
/* end of C++. */
block : name
{ struct symtab *tem = lookup_symtab (copy_name ($1));
{
struct symtab *tem = lookup_symtab (copy_name ($1));
struct symbol *sym;
if (tem)
@ -406,34 +430,88 @@ block : name
else
error ("No file or function \"%s\".",
copy_name ($1));
}}
}
}
;
block : block COLONCOLON name
{ struct symbol *tem
{
struct symbol *tem
= lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE);
if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
error ("No function \"%s\" in specified context.",
copy_name ($3));
$$ = SYMBOL_BLOCK_VALUE (tem); }
copy_name ($1));
$$ = SYMBOL_BLOCK_VALUE (tem);
}
;
variable: block COLONCOLON name
{ struct symbol *sym;
sym = lookup_symbol ($3, copy_name ($1), VAR_NAMESPACE);
{
struct symbol *sym;
sym = lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE);
if (sym == 0)
error ("No symbol \"%s\" in specified context.",
copy_name ($3));
write_exp_elt (OP_VAR_VALUE);
write_exp_elt (sym);
write_exp_elt (OP_VAR_VALUE); }
write_exp_elt (OP_VAR_VALUE);
}
;
variable: typebase COLONCOLON name
{
struct type *type = $1;
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
&& TYPE_CODE (type) != TYPE_CODE_UNION)
error ("`%s' is not defined as an aggregate type.",
TYPE_NAME (type));
write_exp_elt (OP_SCOPE);
write_exp_elt (type);
write_exp_string ($3);
write_exp_elt (OP_SCOPE);
}
| COLONCOLON name
{
char *name = copy_name ($2);
struct symbol *sym;
int i;
sym = lookup_symbol_2 (name, 0, VAR_NAMESPACE);
if (sym)
{
write_exp_elt (OP_VAR_VALUE);
write_exp_elt (sym);
write_exp_elt (OP_VAR_VALUE);
break;
}
for (i = 0; i < misc_function_count; i++)
if (!strcmp (misc_function_vector[i].name, name))
break;
if (i < misc_function_count)
{
write_exp_elt (OP_LONG);
write_exp_elt (builtin_type_int);
write_exp_elt (misc_function_vector[i].address);
write_exp_elt (OP_LONG);
write_exp_elt (UNOP_MEMVAL);
write_exp_elt (builtin_type_char);
write_exp_elt (UNOP_MEMVAL);
}
else
if (symtab_list == 0)
error ("No symbol table is loaded. Use the \"symbol-file\" command.");
else
error ("No symbol \"%s\" in current context.", name);
}
;
variable: NAME
{ struct symbol *sym;
sym = lookup_symbol (copy_name ($1),
expression_context_block,
VAR_NAMESPACE);
sym = lookup_symbol_1 (copy_name ($1),
expression_context_block,
VAR_NAMESPACE);
if (sym)
{
write_exp_elt (OP_VAR_VALUE);
@ -444,6 +522,32 @@ variable: NAME
{
register char *arg = copy_name ($1);
register int i;
int v, val;
/* C++: see if it hangs off of `this'. Must
not inadvertently convert from a method call
to data ref. */
v = (int)value_of_this (0);
if (v)
{
val = check_field (v, arg);
if (val)
{
write_exp_elt (OP_THIS);
write_exp_elt (OP_THIS);
write_exp_elt (STRUCTOP_PTR);
write_exp_string ($1);
write_exp_elt (STRUCTOP_PTR);
break;
}
}
sym = lookup_symbol_2 (arg, 0, VAR_NAMESPACE);
if (sym)
{
write_exp_elt (OP_VAR_VALUE);
write_exp_elt (sym);
write_exp_elt (OP_VAR_VALUE);
break; /* YACC-dependent */
}
for (i = 0; i < misc_function_count; i++)
if (!strcmp (misc_function_vector[i].name, arg))
break;
@ -471,6 +575,17 @@ variable: NAME
type : typebase
| type '*'
{ $$ = lookup_pointer_type ($1); }
| type '&'
{ $$ = lookup_reference_type ($1); }
| typebase COLONCOLON '*'
{ $$ = lookup_member_pointer_type (builtin_type_int, $1); }
| type '(' typebase COLONCOLON '*' ')'
{ $$ = lookup_member_pointer_type ($1, $3); }
| type '(' typebase COLONCOLON '*' ')' '(' ')'
{ $$ = lookup_member_pointer_type (lookup_function_type ($1, 0), $3); }
| type '(' typebase COLONCOLON '*' ')' '(' nonempty_typelist ')'
{ $$ = lookup_member_pointer_type (lookup_function_type ($1, $8), $3);
free ($8); }
;
typebase
@ -490,6 +605,19 @@ typebase
{ $$ = lookup_unsigned_typename (copy_name ($2)); }
;
nonempty_typelist
: type
{ $$ = (struct type **)xmalloc (sizeof (struct type *) * 2);
$$[0] = (struct type *)0;
$$[1] = $1;
}
| nonempty_typelist ',' type
{ int len = sizeof (struct type *) * ++($<ivec>1[0]);
$$ = (struct type **)xrealloc ($1, len);
$$[$<ivec>$[0]] = $3;
}
;
name : NAME
| TYPENAME
;
@ -598,6 +726,14 @@ static char *lexptr;
static char *namecopy;
/* Current depth in parentheses within the expression. */
static int paren_depth;
/* Nonzero means stop parsing on first comma (if not within parentheses). */
static int comma_terminates;
/* Take care of parsing a number (anything that starts with a digit).
Set yylval and return the token type; update lexptr.
LEN is the number of characters in it. */
@ -753,6 +889,24 @@ yylex ()
error ("Invalid character constant.");
return CHAR;
case '(':
paren_depth++;
lexptr++;
return c;
case ')':
if (paren_depth == 0)
return 0;
paren_depth--;
lexptr++;
return c;
case ',':
if (comma_terminates && paren_depth == 0)
return 0;
lexptr++;
return c;
case '+':
case '-':
case '*':
@ -766,8 +920,6 @@ yylex ()
case '@':
case '<':
case '>':
case '(':
case ')':
case '[':
case ']':
case '.':
@ -776,7 +928,6 @@ yylex ()
case '=':
case '{':
case '}':
case ',':
lexptr++;
return c;
@ -881,13 +1032,23 @@ yylex ()
{
return STRUCT;
}
if (namelen == 5 && !strncmp (tokstart, "union", 5))
if (namelen == 5)
{
return UNION;
if (!strncmp (tokstart, "union", 5))
{
return UNION;
}
}
if (namelen == 4 && !strncmp (tokstart, "enum", 4))
if (namelen == 4)
{
return ENUM;
if (!strncmp (tokstart, "enum", 4))
{
return ENUM;
}
if (!strncmp (tokstart, "this", 4))
{
return THIS;
}
}
if (namelen == 6 && !strncmp (tokstart, "sizeof", 6))
{
@ -968,10 +1129,20 @@ length_of_subexp (expr, endpos)
register int args = 0;
register int i;
if (endpos < 0)
error ("?error in length_of_subexp");
i = (int) expr->elts[endpos - 1].opcode;
switch (i)
{
/* C++ */
case OP_SCOPE:
oplen = 4 + ((expr->elts[endpos - 2].longconst
+ sizeof (union exp_element))
/ sizeof (union exp_element));
break;
case OP_LONG:
case OP_DOUBLE:
oplen = 4;
@ -1002,7 +1173,6 @@ length_of_subexp (expr, endpos)
oplen = 3 + ((expr->elts[endpos - 2].longconst
+ sizeof (union exp_element))
/ sizeof (union exp_element));
break;
case TERNOP_COND:
@ -1014,6 +1184,11 @@ length_of_subexp (expr, endpos)
args = 2;
break;
/* C++ */
case OP_THIS:
oplen = 2;
break;
default:
args = 1 + (i < (int) BINOP_END);
}
@ -1051,6 +1226,13 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg)
opcode = inexpr->elts[inend - 1].opcode;
switch (opcode)
{
/* C++ */
case OP_SCOPE:
oplen = 4 + ((inexpr->elts[inend - 2].longconst
+ sizeof (union exp_element))
/ sizeof (union exp_element));
break;
case OP_LONG:
case OP_DOUBLE:
oplen = 4;
@ -1093,6 +1275,11 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg)
args = 2;
break;
/* C++ */
case OP_THIS:
oplen = 2;
break;
default:
args = 1 + ((int) opcode < (int) BINOP_END);
}
@ -1136,10 +1323,12 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg)
if BLOCK is zero, use the block of the selected stack frame.
Meanwhile, advance *STRINGPTR to point after the expression,
at the first nonwhite character that is not part of the expression
(possibly a null character). */
(possibly a null character).
If COMMA is nonzero, stop if a comma is reached. */
struct expression *
parse_c_1 (stringptr, block)
parse_c_1 (stringptr, block, comma)
char **stringptr;
struct block *block;
{
@ -1147,6 +1336,8 @@ parse_c_1 (stringptr, block)
lexptr = *stringptr;
comma_terminates = comma;
if (lexptr == 0 || *lexptr == 0)
error_no_arg ("expression to compute");
@ -1182,7 +1373,7 @@ parse_c_expression (string)
char *string;
{
register struct expression *exp;
exp = parse_c_1 (&string, 0);
exp = parse_c_1 (&string, 0, 0);
if (*string)
error ("Junk after end of expression.");
return exp;

View File

@ -60,6 +60,18 @@ enum exp_opcode
BINOP_COMMA, /* , */
BINOP_SUBSCRIPT, /* x[y] */
BINOP_EXP, /* Exponentiation */
/* C++. */
BINOP_SCOPE, /* :: */
/* STRUCTOP_MEMBER is used for pointer-to-member constructs.
X . * Y translates into X STRUCTOP_MEMBER Y. */
STRUCTOP_MEMBER,
/* STRUCTOP_MPTR is used for pointer-to-member constructs
when X is a pointer instead of an aggregate. */
STRUCTOP_MPTR,
/* end of C++. */
BINOP_END,
BINOP_ASSIGN_MODIFY, /* +=, -=, *=, and so on.
@ -144,6 +156,17 @@ enum exp_opcode
(after the string), followed by another STRUCTOP_... code. */
STRUCTOP_STRUCT,
STRUCTOP_PTR,
/* C++ */
/* OP_THIS is just a placeholder for the class instance variable.
It just comes in a tight (OP_THIS, OP_THIS) pair. */
OP_THIS,
/* OP_SCOPE surrounds a type name and a field name. The type
name is encoded as one element, but the field name stays as
a string, which, of course, is variable length. */
OP_SCOPE,
};
union exp_element

View File

@ -213,7 +213,7 @@ read_var_value (var, frame)
register int len;
if (SYMBOL_CLASS (var) == LOC_BLOCK)
type = lookup_function_type (type);
type = lookup_function_type (type, 0);
v = allocate_value (type);
VALUE_LVAL (v) = lval_memory; /* The most likely possibility. */
@ -368,7 +368,7 @@ locate_var_value (var, frame)
test.i = 1;
if (test.c != 1 && len < REGISTER_RAW_SIZE (val))
/* Big-endian, and we want less than full size. */
addr+ = REGISTER_RAW_SIZE (val) - len;
addr += REGISTER_RAW_SIZE (val) - len;
break;
}
error ("Address requested for identifier \"%s\" which is in a register.",

View File

@ -48,32 +48,40 @@ the terms of Paragraph 1 above, provided that you also do the following:
that in whole or in part contains or is a derivative of this
program or any part thereof, to be licensed at no charge to all
third parties on terms identical to those contained in this
License Agreement (except that you may choose to grant more
extensive warranty protection to third parties, at your option).
License Agreement (except that you may choose to grant more extensive
warranty protection to some or all third parties, at your option).
c) You may charge a distribution fee for the physical act of
transferring a copy, and you may at your option offer warranty
protection in exchange for a fee.
3. You may copy and distribute this program or any portion of it in
compiled, executable or object code form under the terms of Paragraphs
1 and 2 above provided that you do the following:
Mere aggregation of another unrelated program with this program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other program under the scope of these terms.
a) cause each such copy to be accompanied by the
corresponding machine-readable source code, which must
be distributed under the terms of Paragraphs 1 and 2 above; or,
3. You may copy and distribute this program (or a portion or derivative
of it, under Paragraph 2) in object code or executable form under the terms
of Paragraphs 1 and 2 above provided that you also do one of the following:
b) cause each such copy to be accompanied by a
written offer, with no time limit, to give any third party
free (except for a nominal shipping charge) a machine readable
copy of the corresponding source code, to be distributed
under the terms of Paragraphs 1 and 2 above; or,
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) in the case of a recipient of this program in compiled, executable
or object code form (without the corresponding source code) you
shall cause copies you distribute to be accompanied by a copy
of the written offer of source code which you received along
with the copy you received.
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal
shipping charge) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
For an executable file, complete source code means all the source code for
all modules it contains; but, as a special exception, it need not include
source code for modules which are standard libraries that accompany the
operating system on which the executable file runs.
4. You may not copy, sublicense, distribute or transfer this program
except as expressly provided under this License Agreement. Any attempt

View File

@ -1,13 +0,0 @@
main() {
int i;
for (i = 0; i >= 0; i++)
bar();
}
bar()
{
int i;
i = 10;
}

View File

@ -1,39 +0,0 @@
Symbols from foo:
Name Value Class Type Size Line Section
crt0.s | | file | | | |
foo.c | | file | | | |
main | 228|extern| int( )| 66| |.text
.bf | 228|fcn | | | 1|.text
i | -4|auto | int| | |
.ef | 274|fcn | | | 6|.text
bar | 294|extern| int( )| 50| |.text
.bf | 294|fcn | | | 9|.text
i | -4|auto | int| | |
.ef | 324|fcn | | | 5|.text
dbxxx.s | | file | | | |
initfpu.s | | file | | | |
cuexit.s | | file | | | |
fakcu.c | | file | | | |
_cleanup | 404|extern| ( )| 42| |.text
.bf | 404|fcn | | | 23|.text
.ef | 426|fcn | | | 2|.text
_ac_r | 4194760|static| *char| | |.data
copyright.c | | file | | | |
_ac_r | 4194764|static| *char| | |.data
_start | 168|extern| | | |.text
_dbargs | 4195016|extern| | | |.bss
exit | 388|extern| | | |.text
initfpu | 380|extern| | | |.text
environ | 4194756|extern| | | |.data
splimit% | 4194752|extern| | | |.data
_dbsubc | 344|extern| | | |.text
_dbsubn | 376|extern| | | |.text
_ac_s | 4194768|extern| char[0]| | |.data
etext | 448|extern| | | |
edata | 4195016|extern| | | |
end | 4195528|extern| | | |
_sorigin | 4195528|extern| | | |

View File

@ -1,213 +0,0 @@
0000000 0150 0003 21fc 7629 0000 0310 0000 0032
001 P \0 003 ! 374 v ) \0 \0 003 020 \0 \0 \0 2
0000020 001c 0103 010b 0000 0000 0118 0000 0108
\0 034 001 003 001 013 \0 \0 \0 \0 001 030 \0 \0 001 \b
0000040 0000 0200 0000 00a8 0000 00a8 0040 01c0
\0 \0 002 \0 \0 \0 \0 250 \0 \0 \0 250 \0 @ 001 300
0000060 2e74 6578 7400 0000 0000 00a8 0000 00a8
. t e x t \0 \0 \0 \0 \0 \0 250 \0 \0 \0 250
0000100 0000 0118 0000 00a8 0000 0000 0000 02c8
\0 \0 001 030 \0 \0 \0 250 \0 \0 \0 \0 \0 \0 002 310
0000120 0000 000c 0000 0020 2e64 6174 6100 0000
\0 \0 \0 \f \0 \0 \0 . d a t a \0 \0 \0
0000140 0040 01c0 0040 01c0 0000 0108 0000 01c0
\0 @ 001 300 \0 @ 001 300 \0 \0 001 \b \0 \0 001 300
0000160 0000 0000 0000 0000 0000 0000 0000 0040
\0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 @
0000200 2e62 7373 0000 0000 0040 02c8 0040 02c8
. b s s \0 \0 \0 \0 \0 @ 002 310 \0 @ 002 310
0000220 0000 0200 0000 0000 0000 0000 0000 0000
\0 \0 002 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000240 0000 0000 0000 0080 23c0 0040 01c0 518f
\0 \0 \0 \0 \0 \0 \0 200 # 300 \0 @ 001 300 Q 217
0000260 2eaf 0008 41ef 000c 2f48 0004 2248 4a98
. 257 \0 \b A 357 \0 \f / H \0 004 " H J 230
0000300 66fc 2f48 0008 23c8 0040 01c4 4eb9 0000
f 374 / H \0 \b # 310 \0 @ 001 304 N 271 \0 \0
0000320 017c 4eb9 0000 00e4 2e80 4eb9 0000 0184
001 | N 271 \0 \0 \0 344 . 200 N 271 \0 \0 001 204
0000340 7001 4e40 480e ffff fff8 48ef 0000 0004
p 001 N @ H 016 377 377 377 370 H 357 \0 \0 \0 004
0000360 f237 f000 0170 0000 0004 42ae fffc 4aae
362 7 360 \0 001 p \0 \0 \0 004 B 256 377 374 J 256
0000400 fffc 6d00 000e 4eba 001e 52ae fffc 6000
377 374 m \0 \0 016 N 272 \0 036 R 256 377 374 ` \0
0000420 ffee 4cef 0000 0004 f237 d000 0170 0000
377 356 L 357 \0 \0 \0 004 362 7 320 \0 001 p \0 \0
0000440 0004 4e5e 4e75 480e ffff fff8 48ef 0000
\0 004 N ^ N u H 016 377 377 377 370 H 357 \0 \0
0000460 0004 f237 f000 0170 0000 0004 2d7c 0000
\0 004 362 7 360 \0 001 p \0 \0 \0 004 - | \0 \0
0000500 000a fffc 4cef 0000 0004 f237 d000 0170
\0 \n 377 374 L 357 \0 \0 \0 004 362 7 320 \0 001 p
0000520 0000 0004 4e5e 4e75 4e56 0000 207c 0040
\0 \0 \0 004 N ^ N u N V \0 \0 | \0 @
0000540 02c8 2258 2018 2200 e581 d1c1 6002 2f20
002 310 " X 030 " \0 345 201 321 301 ` 002 /
0000560 51c8 fffc 4e91 4e5e 4e41 4e71 4e56 fffc
Q 310 377 374 N 221 N ^ N A N q N V 377 374
0000600 4e5e 4e75 4eb9 0000 0194 7001 4e40 4e72
N ^ N u N 271 \0 \0 001 224 p 001 N @ N r
0000620 0000 4e71 480e ffff fffc 48ef 0000 0004
\0 \0 N q H 016 377 377 377 374 H 357 \0 \0 \0 004
0000640 f237 f000 0170 0000 0004 4cef 0000 0004
362 7 360 \0 001 p \0 \0 \0 004 L 357 \0 \0 \0 004
0000660 f237 d000 0170 0000 0004 4e5e 4e75 4e71
362 7 320 \0 001 p \0 \0 \0 004 N ^ N u N q
0000700 0000 0000 0000 0000 0040 01d0 0040 01d0
\0 \0 \0 \0 \0 \0 \0 \0 \0 @ 001 320 \0 @ 001 320
0000720 436f 7079 7269 6768 7420 2863 2920 3139
C o p y r i g h t ( c ) 1 9
0000740 3837 2041 7070 6c65 2043 6f6d 7075 7465
8 7 A p p l e C o m p u t e
0000760 722c 2049 6e63 2e2c 2031 3938 3520 4164
r , I n c . , 1 9 8 5 A d
0001000 6f62 6520 5379 7374 656d 7320 496e 636f
o b e S y s t e m s I n c o
0001020 7270 6f72 6174 6564 2c20 3139 3833 2d38
r p o r a t e d , 1 9 8 3 - 8
0001040 3720 4154 2654 2d49 532c 2031 3938 352d
7 A T & T - I S , 1 9 8 5 -
0001060 3837 204d 6f74 6f72 6f6c 6120 496e 632e
8 7 M o t o r o l a I n c .
0001100 2c20 3139 3830 2d38 3720 5375 6e20 4d69
, 1 9 8 0 - 8 7 S u n M i
0001120 6372 6f73 7973 7465 6d73 2049 6e63 2e2c
c r o s y s t e m s I n c . ,
0001140 2031 3938 302d 3837 2054 6865 2052 6567
1 9 8 0 - 8 7 T h e R e g
0001160 656e 7473 206f 6620 7468 6520 556e 6976
e n t s o f t h e U n i v
0001200 6572 7369 7479 206f 6620 4361 6c69 666f
e r s i t y o f C a l i f o
0001220 726e 6961 2c20 3139 3835 2d38 3720 556e
r n i a , 1 9 8 5 - 8 7 U n
0001240 6973 6f66 7420 436f 7270 6f72 6174 696f
i s o f t C o r p o r a t i o
0001260 6e2c 2041 6c6c 2052 6967 6874 7320 5265
n , A l l R i g h t s R e
0001300 7365 7276 6564 2e00 0000 0004 0000 0000
s e r v e d . \0 \0 \0 \0 004 \0 \0 \0 \0
0001320 00e4 0001 0000 00fa 0004 0000 0106 0005
\0 344 \0 001 \0 \0 \0 372 \0 004 \0 \0 001 006 \0 005
0001340 0000 0112 0006 0000 000b 0000 0000 0126
\0 \0 001 022 \0 006 \0 \0 \0 013 \0 \0 \0 \0 001 &
0001360 0001 0000 013c 0004 0000 0144 0005 0000
\0 001 \0 \0 001 < \0 004 \0 \0 001 D \0 005 \0 \0
0001400 001a 0000 0000 0194 0001 0000 01aa 0002
\0 032 \0 \0 \0 \0 001 224 \0 001 \0 \0 001 252 \0 002
0001420 2e66 696c 6500 0000 0000 0002 fffe 0000
. f i l e \0 \0 \0 \0 \0 \0 002 377 376 \0 \0
0001440 6701 6372 7430 2e73 0000 0000 0000 0000
g 001 c r t 0 . s \0 \0 \0 \0 \0 \0 \0 \0
0001460 0000 0000 2e66 696c 6500 0000 0000 0012
\0 \0 \0 \0 . f i l e \0 \0 \0 \0 \0 \0 022
0001500 fffe 0000 6701 666f 6f2e 6300 0000 0000
377 376 \0 \0 g 001 f o o . c \0 \0 \0 \0 \0
0001520 0000 0000 0000 0000 6d61 696e 0000 0000
\0 \0 \0 \0 \0 \0 \0 \0 m a i n \0 \0 \0 \0
0001540 0000 00e4 0001 0024 0201 0000 0000 0000
\0 \0 \0 344 \0 001 \0 $ 002 001 \0 \0 \0 \0 \0 \0
0001560 0042 0000 02c8 0000 000b 0000 2e62 6600
\0 B \0 \0 002 310 \0 \0 \0 013 \0 \0 . b f \0
0001600 0000 0000 0000 00e4 0001 0000 6501 0000
\0 \0 \0 \0 \0 \0 \0 344 \0 001 \0 \0 e 001 \0 \0
0001620 0000 0001 0000 0000 0000 0000 0000 0000
\0 \0 \0 001 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0001640 6900 0000 0000 0000 ffff fffc ffff 0004
i \0 \0 \0 \0 \0 \0 \0 377 377 377 374 377 377 \0 004
0001660 0100 2e65 6600 0000 0000 0000 0112 0001
001 \0 . e f \0 \0 \0 \0 \0 \0 \0 001 022 \0 001
0001700 0000 6501 0000 0000 0006 0000 0000 0000
\0 \0 e 001 \0 \0 \0 \0 \0 006 \0 \0 \0 \0 \0 \0
0001720 0000 0000 0000 6261 7200 0000 0000 0000
\0 \0 \0 \0 \0 \0 b a r \0 \0 \0 \0 \0 \0 \0
0001740 0126 0001 0024 0201 0000 0000 0000 0032
001 & \0 001 \0 $ 002 001 \0 \0 \0 \0 \0 \0 \0 2
0001760 0000 02e6 0000 0012 0000 2e62 6600 0000
\0 \0 002 346 \0 \0 \0 022 \0 \0 . b f \0 \0 \0
0002000 0000 0000 0126 0001 0000 6501 0000 0000
\0 \0 \0 \0 001 & \0 001 \0 \0 e 001 \0 \0 \0 \0
0002020 0009 0000 0000 0000 0000 0000 0000 6900
\0 \t \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 i \0
0002040 0000 0000 0000 ffff fffc ffff 0004 0100
\0 \0 \0 \0 \0 \0 377 377 377 374 377 377 \0 004 001 \0
0002060 2e65 6600 0000 0000 0000 0144 0001 0000
. e f \0 \0 \0 \0 \0 \0 \0 001 D \0 001 \0 \0
0002100 6501 0000 0000 0005 0000 0000 0000 0000
e 001 \0 \0 \0 \0 \0 005 \0 \0 \0 \0 \0 \0 \0 \0
0002120 0000 0000 2e66 696c 6500 0000 0000 0014
\0 \0 \0 \0 . f i l e \0 \0 \0 \0 \0 \0 024
0002140 fffe 0000 6701 6462 7878 782e 7300 0000
377 376 \0 \0 g 001 d b x x x . s \0 \0 \0
0002160 0000 0000 0000 0000 2e66 696c 6500 0000
\0 \0 \0 \0 \0 \0 \0 \0 . f i l e \0 \0 \0
0002200 0000 0016 fffe 0000 6701 696e 6974 6670
\0 \0 \0 026 377 376 \0 \0 g 001 i n i t f p
0002220 752e 7300 0000 0000 0000 0000 2e66 696c
u . s \0 \0 \0 \0 \0 \0 \0 \0 \0 . f i l
0002240 6500 0000 0000 0018 fffe 0000 6701 6375
e \0 \0 \0 \0 \0 \0 030 377 376 \0 \0 g 001 c u
0002260 6578 6974 2e73 0000 0000 0000 0000 0000
e x i t . s \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0002300 2e66 696c 6500 0000 0000 0021 fffe 0000
. f i l e \0 \0 \0 \0 \0 \0 ! 377 376 \0 \0
0002320 6701 6661 6b63 752e 6300 0000 0000 0000
g 001 f a k c u . c \0 \0 \0 \0 \0 \0 \0
0002340 0000 0000 5f63 6c65 616e 7570 0000 0194
\0 \0 \0 \0 _ c l e a n u p \0 \0 001 224
0002360 0001 0020 0201 0000 0000 0000 002a 0000
\0 001 \0 002 001 \0 \0 \0 \0 \0 \0 \0 * \0 \0
0002400 02fe 0000 0020 0000 2e62 6600 0000 0000
002 376 \0 \0 \0 \0 \0 . b f \0 \0 \0 \0 \0
0002420 0000 0194 0001 0000 6501 0000 0000 0017
\0 \0 001 224 \0 001 \0 \0 e 001 \0 \0 \0 \0 \0 027
0002440 0000 0000 0000 0000 0000 0000 2e65 6600
\0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 . e f \0
0002460 0000 0000 0000 01aa 0001 0000 6501 0000
\0 \0 \0 \0 \0 \0 001 252 \0 001 \0 \0 e 001 \0 \0
0002500 0000 0002 0000 0000 0000 0000 0000 0000
\0 \0 \0 002 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0002520 5f61 635f 7200 0000 0040 01c8 0002 0012
_ a c _ r \0 \0 \0 \0 @ 001 310 \0 002 \0 022
0002540 0300 2e66 696c 6500 0000 0000 0024 fffe
003 \0 . f i l e \0 \0 \0 \0 \0 \0 $ 377 376
0002560 0000 6701 636f 7079 7269 6768 742e 6300
\0 \0 g 001 c o p y r i g h t . c \0
0002600 0000 0000 0000 5f61 635f 7200 0000 0040
\0 \0 \0 \0 \0 \0 _ a c _ r \0 \0 \0 \0 @
0002620 01cc 0002 0012 0300 5f73 7461 7274 0000
001 314 \0 002 \0 022 003 \0 _ s t a r t \0 \0
0002640 0000 00a8 0001 0000 0200 5f64 6261 7267
\0 \0 \0 250 \0 001 \0 \0 002 \0 _ d b a r g
0002660 7300 0040 02c8 0003 0000 0200 6578 6974
s \0 \0 @ 002 310 \0 003 \0 \0 002 \0 e x i t
0002700 0000 0000 0000 0184 0001 0000 0200 696e
\0 \0 \0 \0 \0 \0 001 204 \0 001 \0 \0 002 \0 i n
0002720 6974 6670 7500 0000 017c 0001 0000 0200
i t f p u \0 \0 \0 001 | \0 001 \0 \0 002 \0
0002740 656e 7669 726f 6e00 0040 01c4 0002 0000
e n v i r o n \0 \0 @ 001 304 \0 002 \0 \0
0002760 0200 7370 6c69 6d69 7425 0040 01c0 0002
002 \0 s p l i m i t % \0 @ 001 300 \0 002
0003000 0000 0200 5f64 6273 7562 6300 0000 0158
\0 \0 002 \0 _ d b s u b c \0 \0 \0 001 X
0003020 0001 0000 0200 5f64 6273 7562 6e00 0000
\0 001 \0 \0 002 \0 _ d b s u b n \0 \0 \0
0003040 0178 0001 0000 0200 5f61 635f 7300 0000
001 x \0 001 \0 \0 002 \0 _ a c _ s \0 \0 \0
0003060 0040 01d0 0002 0032 0201 0000 0000 0000
\0 @ 001 320 \0 002 \0 2 002 001 \0 \0 \0 \0 \0 \0
0003100 0000 0000 0000 0000 0000 0000 6574 6578
\0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 e t e x
0003120 7400 0000 0000 01c0 ffff 0000 0200 6564
t \0 \0 \0 \0 \0 001 300 377 377 \0 \0 002 \0 e d
0003140 6174 6100 0000 0040 02c8 ffff 0000 0200
a t a \0 \0 \0 \0 @ 002 310 377 377 \0 \0 002 \0
0003160 656e 6400 0000 0000 0040 04c8 ffff 0000
e n d \0 \0 \0 \0 \0 \0 @ 004 310 377 377 \0 \0
0003200 0200 5f73 6f72 6967 696e 0040 04c8 ffff
002 \0 _ s o r i g i n \0 @ 004 310 377 377
0003220 0000 0200
\0 \0 002 \0
0003224

View File

@ -1,65 +0,0 @@
file "foo.c"
data 1
text
def main; val main; scl 2; type 044; endef
global main
main:
ln 1
def ~bf; val ~; scl 101; line 1; endef
link.l %fp,&F%1
movm.l &M%1,(4,%sp)
fmovm &FPM%1,(FPO%1,%sp)
def i; val -4+S%1; scl 1; type 04; endef
ln 4
clr.l ((S%1-4).w,%fp)
L%15:
tst.l ((S%1-4).w,%fp)
blt L%14
ln 5
jsr bar
L%13:
add.l &1,((S%1-4).w,%fp)
bra L%15
L%14:
L%12:
def ~ef; val ~; scl 101; line 6; endef
ln 6
movm.l (4,%sp),&M%1
fmovm (FPO%1,%sp),&FPM%1
unlk %fp
rts
def main; val ~; scl -1; endef
set S%1,0
set T%1,0
set F%1,-8
set FPO%1,4
set FPM%1,0x0000
set M%1,0x0000
data 1
text
def bar; val bar; scl 2; type 044; endef
global bar
bar:
ln 1
def ~bf; val ~; scl 101; line 9; endef
link.l %fp,&F%2
movm.l &M%2,(4,%sp)
fmovm &FPM%2,(FPO%2,%sp)
def i; val -4+S%2; scl 1; type 04; endef
ln 4
mov.l &10,((S%2-4).w,%fp)
L%17:
def ~ef; val ~; scl 101; line 5; endef
ln 5
movm.l (4,%sp),&M%2
fmovm (FPO%2,%sp),&FPM%2
unlk %fp
rts
def bar; val ~; scl -1; endef
set S%2,0
set T%2,0
set F%2,-8
set FPO%2,4
set FPM%2,0x0000
set M%2,0x0000
data 1

View File

@ -1,114 +0,0 @@
Symtab for file _globals_
Line table:
Blockvector:
block #000 (object 0x41a5cc) [0x0..0x0]
char _ac_s[0]; static at 0x4001d0,
int _dbargs; static at 0x4002c8,
int environ; static at 0x4001c4,
int splimit%; static at 0x4001c0,
block #001 (object 0x41a5a8) [0x0..0x0] (under 0x41a5cc)
Symtab for file copyright.c
Line table:
Blockvector:
block #000 (object 0x41a460) [0x0..0x0]
block #001 (object 0x41a444) [0x0..0x0] (under 0x41a460)
char *_ac_r; static at 0x4001cc,
Symtab for file fakcu.c
Line table:
line 23 at 194
line 24 at 1aa
Blockvector:
block #000 (object 0x41a3f0) [0x0..0x0]
void _cleanup; block (object 0x41a380) starting at 0x194,
block #001 (object 0x41a3d4) [0x0..0x0] (under 0x41a3f0)
char *_ac_r; static at 0x4001c8,
block #002 (object 0x41a380) [0x194..0x1b0] (under 0x41a3d4) _cleanup
Symtab for file cuexit.s
Line table:
Blockvector:
block #000 (object 0x41f210) [0x0..0x0]
block #001 (object 0x41f1ec) [0x0..0x0] (under 0x41f210)
Symtab for file initfpu.s
Line table:
Blockvector:
block #000 (object 0x41e1c4) [0x0..0x0]
block #001 (object 0x41e1a0) [0x0..0x0] (under 0x41e1c4)
Symtab for file dbxxx.s
Line table:
Blockvector:
block #000 (object 0x41d178) [0x0..0x0]
block #001 (object 0x41d154) [0x0..0x0] (under 0x41d178)
Symtab for file foo.c
Line table:
line 1 at e4
line 2 at fa
line 4 at fa
line 5 at 106
line 6 at 112
line 7 at 126
line 9 at 126
line 10 at 13c
line 12 at 13c
line 13 at 144
Blockvector:
block #000 (object 0x41a2d8) [0x0..0x0]
int bar; block (object 0x41a2b0) starting at 0x126,
int main; block (object 0x41a220) starting at 0xe4,
block #001 (object 0x41a23c) [0x0..0x0] (under 0x41a2d8)
block #002 (object 0x41a220) [0xe4..0x120] (under 0x41a23c) main
int i; local at 0xfffffffc,
block #003 (object 0x41a2b0) [0x126..0x150] (under 0x41a23c) bar
int i; local at 0xfffffffc,
Symtab for file crt0.s
Line table:
Blockvector:
block #000 (object 0x41b178) [0x0..0x0]
block #001 (object 0x41b154) [0x0..0x0] (under 0x41b178)

2788
gdb/gdb+.texinfo Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,91 +0,0 @@
.TH GDB 1 "13 April 1987"
.UC 4
.SH NAME
gdb \- Project GNU's DeBugger
.SH SYNOPSIS
\fBgdb\fP [ \fBoptions\fP ] See documentation mentioned below.
.SH DESCRIPTION
\fIgdb\fP is a source level symbolic debugger for C programs, created by
Richard M. Stallman (rms) for the GNU Project, and distributed by the
Free Software Foundation. Eventually GNU (Gnu's Not Unix) will be a
complete replacement for Berkeley Unix, all of which everyone will be
able to use freely. See the \fIGNU Emacs\fP man page for pointers to more
information.
.PP
\fIgdb\fP has something of the flavor of \fIdbx\fP,
but has more features and power. It can also be used to debug o/s
kernels, but needs to be configured differently for that task.
.PP
Project GNU isn't using Unix man pages. Its style of complete
documentation can be found by:
.PP
The help and info commands inside \fIgdb\fP.
.PP
In the Info system in \fIGNU Emacs\fP. Type C-h i, and follow the
directions. This is equivalent to the reference manual for
\fIgdb\fP, and has about 55 pages of text.
.PP
\fIgdb\fP could be extended to work with other languages (e.g. Pascal) and
machines (e.g. encores). If you like, copy the sources and give it a
try. When you have it working send \fIdiff -c\fP's of the changed files to
bug-gdb@prep.ai.mit.edu (fuller details below), so they can benefit everyone.
.SH DISTRIBUTION
\fIgdb\fP is free; anyone may redistribute copies of
\fIgdb\fP to anyone under the terms stated in the
\fIgdb\fP General Public License, a copy of which accompanies each copy of
\fIgdb\fP, is readable with the info command inside \fIgdb\fP,
and which also appears in the \fIgdb\fP reference manual.
.PP
Copies of \fIgdb\fP may sometimes be received packaged with
distributions of Unix systems, but it is never included in the scope
of any license covering those systems. Such inclusion would violate
the terms on which distribution is permitted. In fact, the primary
purpose of the General Public License is to prohibit anyone from
attaching any other restrictions to redistribution of \fIgdb\fP.
.PP
You can order printed copies of the \fIgdb\fP reference manual for $10.00/copy
postpaid from the Free Software Foundation, which develops GNU software
(contact them for quantity prices on the manual). Their address is:
.nf
Free Software Foundation
1000 Mass Ave.
Cambridge, MA 02138
.fi
As with all software and publications from FSF, everyone is permitted to
make and distribute copies of the \fIgdb\fP reference manual.
The TeX source to the \fIgdb\fP reference
manual is also included in the \fIGNU Emacs\fP source distribution.
.PP
.SH OPTIONS
See documentation.
.SH EXAMPLES
See documentation.
.SH "SEE ALSO"
adb(1), sdb(1), dbx(1)
.SH BUGS
There is a mailing list, bug-gdb@prep.ai.mit.edu on the internet
(ucbvax!prep.ai.mit.edu!bug-gdb on UUCPnet), for reporting \fIgdb\fP
bugs and fixes. But before reporting something as a bug, please try
to be sure that it really is a bug, not a misunderstanding or a
deliberate feature. We ask you to read the section ``Reporting Emacs
Bugs'' near the end of the \fIGNU Emacs\fP reference manual
(or Info system) for hints
on how and when to report bugs. Also, include the version number of
the \fIgdb\fP you are running in \fIevery\fR bug report that you send in.
.PP
Do not expect a personal answer to a bug report. The purpose of reporting
bugs is to get them fixed for everyone in the next release, if possible.
For personal assistance, look in the SERVICE file
(see the \fIGNU Emacs\fP man page) for
a list of people who offer it.
.PP
Please do not send anything but bug reports to this mailing list.
Send other stuff to gnu@prep.ai.mit.edu (or the
corresponding UUCP address). For more information about GNU mailing
lists, see the file MAILINGLISTS (see the \fIGNU Emacs\fP man page). Bugs tend
actually to be fixed if they can be isolated, so it is in your
interest to report them in such a way that they can be easily
reproduced.
.PP
No bugs are known at this time.

View File

@ -1,694 +0,0 @@
BABYL OPTIONS:
Version: 5
Labels:
Note: This is the header of an rmail file.
Note: If you are seeing it in rmail,
Note: it means the file has no messages in it.

From: mly@MICHAEL.AI.MIT.EDU (Richard Mlynarik)
To: rms@prep.ai.mit.edu
Subject: gdb suggestions (from hpux cdb)
Reply-To: mly-prep@prep.ai.mit.edu
"find-bug" command says "I can see the problem, but it will do you
good to find it yourself"
The gdb manual should explicitly state that gdb has no control over
forked (or execed or whatever) subprocesses.
I'd still like it if "delete" said what it had done.
Date: Tuesday, 13 May 1986, 00:40-EDT
From: <rms@LMI-ANGEL>
Sender: JC@LMI-ANGEL
Subject: interesting sdb features
To: rms@angel
output format p = pointer to procedure.
foo/x or foo/4x uses size of foo as size to print.
foo[1;4] to get elements 1 thru 4.
Continue to specified line number.
Interactively delete all breakpoints (asking about each one).
Command to write backtrace into a file, or even better to duplicate all
output to a file. This could work by playing with descriptor 1,
making it a pipe to `tee'. The original descriptor 1 is saved and
this mode can be turned off by putting it back.
Date: Wed, 18 Feb 87 15:37:14 EST
From: rms (Richard M. Stallman)
Message-Id: <8702182037.AA16492@prep.ai.mit.edu>
To: mly-prep@prep.ai.mit.edu
In-Reply-To: <8702181913.AA16118@prep.ai.mit.edu>
Subject: gdb "photo" command
I don't think all this is worth the trouble to do now,
because the right way to do it on TRIX is totally different
and much easier.
Commands to enable and disable the autodisplays. Associate
autodisplays with breakpoints perhaps, so they only display
at those breakpoints; this is easier than using breakpoint commands.
Remember how each breakpoint's position was specified.
Have command to reread symbol table and respecify each
breakpoint using same args (line number or function name) as before.
Have way to proceed process in background so that can then suspend
gdb but have subprocess continue
Date: Fri, 24 Jul 87 21:30:25 EDT
From: phr@PREP.AI.MIT.EDU (Paul Rubin)
To: bug-gdb@PREP.AI.MIT.EDU
After rereading the symbol table when user runs the "symbol-file"
command, when GDB notices that some of the source files are newer
it should reload them rather than just printing a message saying
they are newer.
Message-Id: <8704171941.AA05045@orville.arpa>
To: mly@prep.ai.mit.edu
Cc: raible@orville.arpa, fouts@orville.arpa, creon@orville.arpa
Subject: gdb hack/questions, etc
Date: 17 Apr 87 11:41:42 PST (Fri)
From: raible@orville.arpa
A couple of things:
1) Will gdb ever get dbx-sytly tracing? Wouldn't it be fairly easy to add?
2) How about an xemacs gdb mode which has various windows, perhaps using
terminal.el for generality?
3) Any word about that stupid IRIS SIGIOT problem? Do you know of anyone
else who has gotten IRIS subprocesses to work more reliably?
4) Below is a hack adapted from ramsdell@linus.uucp which can be pretty
useful in gdb. Instead of using gdb to patch extensive changes to a
particular function, you can do the following (assuming the 50 lines
of code below is part of your executable):
1) create a new file (foo.c) containing the new function
2) run cc -c foo.c
3) in gdb, and patch in the new function as follows:
(gdb) info breakpoints
/* Load in the new object code... */
#1 y 0x00000125 in main (dyn.c line 46)
break only if $function = funload ("foo"), 1
silent
echo new code for func ($function) initialized\n
cont
/* ...and use it instead of the old code. */
#2 y 0x000001c2 in func (dyn.c line 59)
break only if $ret = $function (a), 1
silent
set a = $ret
j 60 /* func has a return on line 60 */
This is more complicated than it has to be because of 2 bugs in v2.1:
1) function calls in a breakpoint command list seem to abort
the execution of the rest of the command list. This is
why all function calls are in the conditional part.
(gdb reference manual section 5.5).
2) A 'return' in a command list also aborts the execution, and
in addition, prompts you for a y/n.
(gdb reference manual section 11.1).
On the other hand, after doing 'cc -c foo.c' (which is pretty fast),
you can simply rerun your program to check out the changes.
This can be a big win!
The code for this is included below (compile with cc -g):
========================================================
#include <stdio.h>
#include <a.out.h>
typedef int (*intfun)();
char *myname;
intfun funload (filename) /* Dynamically load 1st function from a .o */
char *filename;
{
int fd, size;
struct exec hdr;
char buf[100];
intfun fun;
/* -A => incremental loading - use dyn as the base symbol table
-T => set the text segment origin to the following hex address
-N => magic number 407 (text not read-only)
*/
sprintf (buf, "ld -A %s -T %x -N %s.o -o %s -lc",
myname, sbrk (0), filename, filename);
/* NOTE: if anything mallocs space between here and below, this will fail */
system (buf);
fd = open (filename, 0);
read (fd, &hdr, sizeof(hdr));
size = hdr.a_text + hdr.a_data + hdr.a_bss;
if ((fun = (intfun) sbrk (size)) < 0)
printf ("Couldn't find the space"), exit();
read (fd, fun, size); /* Load code. */
/* NOTE: if anything mallocs space between here and above, this will fail */
close (fd);
return ((intfun) fun);
}
main (argc, argv)
char **argv;
{
intfun fun1, fun2;
myname = *argv;
fun1 = funload("fun1");
printf ("The answer is %d.\n", (*fun1)(11) );
fun2 = funload("fun2");
printf ("The answer is %d.\n", (*fun2)() );
}
1,edited,,
Received: by PREP.AI.MIT.EDU; Tue, 16 Jun 87 03:12:54 EDT
Date: Tue, 16 Jun 87 03:12:54 EDT
From: rms (Richard M. Stallman)
Message-Id: <8706160712.AA07910@prep.ai.mit.edu>
To: rms
Subject: GDB ideas
*** EOOH ***
Date: Tue, 16 Jun 87 03:12:54 EDT
From: rms (Richard M. Stallman)
To: rms
Subject: GDB ideas
* Within a user-defined command, have local convenience variables,
local functions, local defined commands.
** Optionally echo commands within a user-defined command.
** Optionally record all user-typed commands in a log file.
Optionally record GDB output there too, marked as output so it
will not be executed if replayed.
* Execution commands
** Step until next branch, or next call.
(finish is step until next return).
step branch
or should it be
continue branch
** Stop on any branch, call or return
affecting ordinary step and continue commands.
stop branch
** Trace all branches, calls, returns.
This could be done by stopping on those events
and having a continue command to be executed after.
stop branch
commands branch
continue
end
** Commands to continue or step without any display after stop.
These may be useful in user-defined commands.
Have one prefix command that does this, modifying whatever other
command you might use. For example,
silent step 5
silent cont
** Clear all breakpoint ignore-counts when inferior exits or is killed.
** Trace changes to a location (watchpoint).
Enable and disable them.
** Info command to show command-line for running the program.
* Auto-display
** Enable and disable display expressions.
Allow syntax 1d, 2d, etc. in enable, disable and delete commands.
Then there is no more need for an undisplay command.
** Displaying an auto variable should not do it in the wrong stack frame.
Either it should search for the proper stack frame to apply to
or it should deactivate itself when in the wrong frame.
* Printing
** Print an address as <file:line>+offset.
** Abbreviate initial whitespace modulo 16.
** p/x of an array should print each element with /x.
** Change the stack scan so that it has a more general idea
of what info is needed to describe a frame fully.
* Expressions
** Array slices. Can replace @.
** %name for use of symbol names containing funny characters.
** User-defined convenience functions that can appear in expressions.
** Expression syntax to convert line number to address.
** Expression syntax to specify a name scope with an address, line number
or frame number.
Use the line number by itself, or an address with *, just as in b or l cmd:
38:foo or *0x40a:foo. No good; the latter would be parsed as
*(0x40a:foo).
** Expression syntax to convert a frame number to its pc.
Perhaps unary %.
* Possible bugs
** Does set $pc= cause the current scope to be recalculated?
It should.

1,,
Received: by PREP.AI.MIT.EDU; Wed, 17 Jun 87 09:59:37 EDT
From: phr@ATHENA.MIT.EDU
Received: by ATHENA (5.45/4.7)
id AA09084; Wed, 17 Jun 87 08:54:36 EDT
Received: by ORPHEUS.MIT.EDU (5.45/4.7) id AA02565; Wed, 17 Jun 87 08:54:29 EDT
Date: Wed, 17 Jun 87 08:54:29 EDT
Message-Id: <8706171254.AA02565@ORPHEUS.MIT.EDU>
To: rms@prep.ai.mit.edu
Subject: gdb suggestion
Status: RO
*** EOOH ***
From: phr@ATHENA.MIT.EDU
Date: Wed, 17 Jun 87 08:54:29 EDT
To: rms@prep.ai.mit.edu
Subject: gdb suggestion
Completion of file and function names; e.g. typing
break XWriteBi
prints
No such symbol: XWriteBi.
Setting default command to "break XWriteBitmapFile"
so you can set a break at XWriteBitmapFile by hitting return a second
time. Other interfaces ("complete to XWriteBitmapFile? (y/n)")
are also possible.

1,edited,,
Received: by PREP.AI.MIT.EDU; Wed, 24 Sep 86 16:33:11 EDT
Date: Wed, 24 Sep 86 16:33:11 EDT
From: mly (Richard Mlynarik)
Message-Id: <8609242033.AA11520@prep.ai.mit.edu>
To: rms
Cc: mly-prep
Subject: gdb gripes/suggestions/requests
*** EOOH ***
Date: Wed, 24 Sep 86 16:33:11 EDT
From: mly (Richard Mlynarik)
To: rms
Cc: mly-prep
Subject: gdb gripes/suggestions/requests
If would be really nice to have some way to do conditionals in user
commands -- though this is really stretching the functionality of
gdb a little too much, perhaps. (see ~mly/e/.gdbint for some of
the contortions I go through with || to get conditional
evaluation...)
A -real- win wuold be some way to execute until he next function-call
(like c-d in the cadr debugger) This would even be useful if it
were rather slow -- it would probably be faster than setting
temporary breakpoints in all the functions which might be called,
and would certainly be faster than "step"ping one's way until a
funcall happened.
"info source" should mention what the directory search-path is (ie
what "info dir" says) and in which directory it found each of the
source files (and which source files it cannot locate in the
search-path)

1,,
Received: by xcssun.Berkeley.EDU (5.57/1.25)
id AA22869; Thu, 22 Oct 87 09:50:30 PDT
Received: from prep.ai.mit.edu by wheaties.ai.mit.edu; Thu, 22 Oct 87 12:17:59 EDT
Received: by PREP.AI.MIT.EDU; Thu, 22 Oct 87 12:21:00 EDT
Received: from pp.mcc.com by MCC.COM with TCP; Thu 22 Oct 87 10:54:41-CDT
Posted-Date: Thu, 22 Oct 87 10:55:13 CDT
Received: from big-d.aca.mcc.com by pp.mcc.com (4.12/KA70822)
id AA16571; Thu, 22 Oct 87 10:55:19 cdt
Return-Path: <tiemann@big-d.aca.mcc.com>
Received: by big-d.aca.mcc.com (3.2/KA70106)
id AA04247; Thu, 22 Oct 87 10:55:13 CDT
Date: Thu, 22 Oct 87 10:55:13 CDT
From: tiemann%pp.mcc.com@mcc.com (Michael Tiemann)
Message-Id: <8710221555.AA04247@big-d.aca.mcc.com>
To: bug-gdb@prep.ai.mit.edu
Subject: expanding file names
*** EOOH ***
Posted-Date: Thu, 22 Oct 87 10:55:13 CDT
Return-Path: <tiemann@big-d.aca.mcc.com>
Date: Thu, 22 Oct 87 10:55:13 CDT
From: tiemann%pp.mcc.com@mcc.com (Michael Tiemann)
To: bug-gdb@prep.ai.mit.edu
Subject: expanding file names
When running a program, gdb thoughtfully passes the argument list
through the shell, expanding files and environment variables as
needed. It would be nice if the same facility were added to the
command which adds directories to search paths. For example, it would
be nice to say "dir ~/foo" .
Michael

1,,
Received: by xcssun.Berkeley.EDU (5.57/1.25)
id AA25075; Fri, 23 Oct 87 10:42:52 PDT
Received: from prep.ai.mit.edu by wheaties.ai.mit.edu; Fri, 23 Oct 87 13:39:37 EDT
Received: by PREP.AI.MIT.EDU; Fri, 23 Oct 87 13:42:53 EDT
Received: from relay2.cs.net by RELAY.CS.NET id ac11193; 23 Oct 87 13:03 EDT
Received: from umb.edu by RELAY.CS.NET id ac05949; 23 Oct 87 13:01 EDT
Received: by umb.umb.edu; Fri, 23 Oct 87 10:18:40 EDT
Received: by ileaf.uucp (1.1/SMI-3.0DEV3)
id AA00599; Wed, 21 Oct 87 10:56:52 EDT
Received: from marvin.io.uucp by io.uucp (1.1/SMI-3.0DEV3)
id AA01359; Wed, 21 Oct 87 10:58:45 EDT
Received: by marvin.io.uucp (3.2/SMI-3.2)
id AA00334; Wed, 21 Oct 87 11:02:20 EDT
Date: Wed, 21 Oct 87 11:02:20 EDT
From: Mark Dionne <io!marvin!md%ileaf.uucp%umb.umb.edu@relay.cs.net>
Message-Id: <8710211502.AA00334@marvin.io.uucp>
To: ileaf!umb!bug-gdb@prep.ai.mit.edu
Subject: gdb bug
*** EOOH ***
Date: Wed, 21 Oct 87 11:02:20 EDT
From: Mark Dionne <io!marvin!md%ileaf.uucp%umb.umb.edu@relay.cs.net>
To: ileaf!umb!bug-gdb@prep.ai.mit.edu
Subject: gdb bug
The /FMT and @ options of the "print" command seem to interact
in GDB 2.1. For example:
(gdb) p ($cmpn.buf[-1])@($cmpn.gapb - $cmpn.buf + 1)
$17 = {-16383, -24285, 55, 27944, -24285, -24285, 55, 28010, -24285,
-24285, 55, 28076, -24285, -24285, 55, 28142, -24285}
(gdb) p/x ($cmpn.buf[-1])@($cmpn.gapb - $cmpn.buf + 1)
$18 = 0xc001
I guess I see what's happening: the /x is applying to the whole
array rather than to the individual elements. Feature or bug?
...!harvard!umb!ileaf!md Mark Dionne, Interleaf
...!sun!sunne!ileaf!md Ten Canal Park, Cambridge, MA 02141
(617) 577-9813 x5551

1,,
Received: by PREP.AI.MIT.EDU; Sun, 6 Sep 87 14:27:19 EDT
Message-Id: <8709061827.AA18170@prep.ai.mit.edu>
Received: from relay2.cs.net by RELAY.CS.NET id af03990; 6 Sep 87 14:22 EDT
Received: from umb.edu by RELAY.CS.NET id ab03029; 6 Sep 87 14:16 EDT
Received: by umb.umb.edu; Sun, 6 Sep 87 12:10:34 EDT
Date: Sun, 6 Sep 87 12:10:34 EDT
Received: by typo.umb.edu; Sun, 6 Sep 87 12:04:21 EDT
From: Robert Morris <ram%typo.umb.edu@RELAY.CS.NET>
To: bug-gdb@PREP.AI.MIT.EDU
Subject: convenient script
*** EOOH ***
Date: Sun, 6 Sep 87 12:10:34 EDT
From: Robert Morris <ram%typo.umb.edu@RELAY.CS.NET>
To: bug-gdb@PREP.AI.MIT.EDU
Subject: convenient script
I find it easier to maintain binaries on our heterogenous
network if I keep this trivial script in gdb source directory. Use it
if you want.
------------
#! /bin/csh -f
# SETUP
# setup gdb files for presently known machines
# ram@umb.edu
# (ram%umb.edu@relay.cs.net if you have an incomplete mailer)
# or ...!harvard!umb!ram
#
# e.g. SETUP sun3
# note that sunX means major release X of sun software, generally
# sun3 at this writing (gnu 18.41)
#
# note GDB with gnuemacs 18.41 is already configured for vaxen
# Bob Morris, UMASS-Boston 9/6/87
switch ($1)
case "sun2":
;
case "sun3" :
set cputype="m68k";
set inittype="suninit";
breaksw;
default :
set cputype=$1;
set inittype=$1init;
breaksw;
endsw
echo \#include \"m-$1.h\" > param.h
echo \#include \"$cputype-pinsn.c\" > pinsn.c
ed initialize.h <<! >& /dev/null
/init.h/
c
#include "m-$inittype.h"
.
w
q
!

1,answered,,
Received: from prep.ai.mit.edu by wheaties.ai.mit.edu; Sat, 19 Dec 87 18:18:50 EST
Received: by PREP.AI.MIT.EDU; Sat, 19 Dec 87 18:24:38 EST
Received: from big-d.aca.mcc.com by MCC.COM with TCP; Sat 19 Dec 87 17:19:48-CST
Date: Sat, 19 Dec 87 17:19:41 CST
From: tiemann@mcc.com (Michael Tiemann)
Posted-Date: Sat, 19 Dec 87 17:19:41 CST
Message-Id: <8712192319.AA26775@big-d.aca.mcc.com>
Received: by big-d.aca.mcc.com (3.2/ACA-V2.1)
id AA26775; Sat, 19 Dec 87 17:19:41 CST
To: rms@prep.ai.mit.edu
Subject: gdb
*** EOOH ***
Date: Sat, 19 Dec 87 17:19:41 CST
From: tiemann@mcc.com (Michael Tiemann)
Posted-Date: Sat, 19 Dec 87 17:19:41 CST
To: rms@prep.ai.mit.edu
Subject: gdb
file values.c, function unpack_field_as_long:
val &= (1 << bitsize) - 1;
This is not as machine independent as it could be. If you feel like
fixing this potential problem, there are many other instances to worry
about.
Michael

1,,
Received: by xcssun.Berkeley.EDU (5.57/1.25)
id AA04771; Thu, 20 Aug 87 22:33:25 PDT
Received: from [128.52.22.14] by ucbvax.Berkeley.EDU (5.58/1.27)
id AA07119; Thu, 20 Aug 87 00:37:04 PDT
Received: by PREP.AI.MIT.EDU; Thu, 20 Aug 87 03:37:35 EDT
Date: Thu, 20 Aug 87 03:37:35 EDT
From: rms@prep.ai.mit.edu (Richard M. Stallman)
Message-Id: <8708200737.AA15589@prep.ai.mit.edu>
To: rms@prep.ai.mit.edu
Subject: GDB changes for next version
*** EOOH ***
Date: Thu, 20 Aug 87 03:37:35 EDT
From: rms@prep.ai.mit.edu (Richard M. Stallman)
To: rms@prep.ai.mit.edu
Subject: GDB changes for next version
1. Use links, rather than editing some files, to configure it.
2. Can misc functions eval as their addresses rather than as
a char in that address? Is this reasonable in all cases
given that non-functions cannot be distinguished
and that you might use the result in various ways (arithmetic, etc.).

1,,
Received: by xcssun.Berkeley.EDU (5.57/1.25)
id AA09136; Sat, 29 Aug 87 02:20:15 PDT
Received: from PREP.AI.MIT.EDU by ucbvax.Berkeley.EDU (5.58/1.27)
id AA26072; Sat, 29 Aug 87 02:21:51 PDT
Received: by PREP.AI.MIT.EDU; Sat, 29 Aug 87 05:22:30 EDT
Received: by RUTGERS.EDU (5.54/1.14) with UUCP
id AA22247; Sat, 29 Aug 87 05:21:13 EDT
Received: from sequent.UUCP by spool.wisc.edu; Sat, 29 Aug 87 04:18:41 CDT
Received: from reed.UUCP by ogcvax.OGC.EDU (5.51/OGC_4.8)
id AA08044; Fri, 28 Aug 87 20:06:41 PDT
Received: by reed.UUCP (5.51/5.17)
id AA05059; Fri, 28 Aug 87 19:19:15 PDT
From: uwvax!sequent!ogcvax!reed!keith@rutgers.edu (Keith Packard)
Message-Id: <8708290219.AA05059@reed.UUCP>
To: rms@prep.ai.mit.edu
Subject: Re: GDB
In-Reply-To: Your message of Thu, 20 Aug 87 03:39:37 EDT.
<8708200735.AA26546@EDDIE.MIT.EDU>
Date: Fri, 28 Aug 87 19:19:13 PDT
*** EOOH ***
From: uwvax!sequent!ogcvax!reed!keith@rutgers.edu (Keith Packard)
To: rms@prep.ai.mit.edu
Subject: Re: GDB
In-Reply-To: Your message of Thu, 20 Aug 87 03:39:37 EDT.
<8708200735.AA26546@EDDIE.MIT.EDU>
Date: Fri, 28 Aug 87 19:19:13 PDT
Here is a simple test program for exibiting the trouble with signals:
-----
# include <signal.h>
main ()
{
int handle ();
int i;
signal (SIGALRM, handle);
alarm (5);
for (i = 0; i < 100000; i++)
printf ("%d\n", i);
}
handle ()
{
printf ("signal!\n");
alarm (5);
}
-----
To demonstrate the problem, simply place a breakpoint before the call to
alarm and then start stepping through the program:
(gdb) break 7
(gdb) step
...
...
Eventually, the alarm call occurs and the program ends up in some
signal handling code -- unfortuantely a machine dependent location. At this
point, because the fp has moved out of the current function (in fact on
many machines the frame is not in a consistent state at this point) gdb
assumes that a new function has started and suspends execution with another
prompt.
A reasonable solution would be to have gdb insert a breakpoint at the
expected signal return address and continue to that breakpoint -- I've
implemented this and found that it works. There is, however, one nasty
problem -- longjmp around the suspended frame and the breakpoint is not hit
at the expected time.
Have fun...
keith packard
tektronix!reed!keith

1,,
Received: by xcssun.Berkeley.EDU (5.57/1.25)
id AA09143; Sat, 29 Aug 87 02:24:58 PDT
Received: by neptune.Berkeley.EDU (5.57/1.25)
id AA03738; Sat, 29 Aug 87 02:24:50 PDT
Date: Sat, 29 Aug 87 02:24:50 PDT
From: rms@neptune.berkeley.edu (Richard Stallman)
Message-Id: <8708290924.AA03738@neptune.Berkeley.EDU>
To: rms@neptune.Berkeley.EDU
Subject: GDB bug
Reply-To: rms@prep.ai.mit.edu
*** EOOH ***
Date: Sat, 29 Aug 87 02:24:50 PDT
From: rms@neptune.berkeley.edu (Richard Stallman)
To: rms@neptune.Berkeley.EDU
Subject: GDB bug
Reply-To: rms@prep.ai.mit.edu
Is there any way to make GDB, when stepping across a function call,
notice any attempt to longjump out of that call?
Perhaps an implicit breakpoint at longjump.
If longjump is called, find the pc in the jmp_buf and put
a self-deleting breakpoint there.

1,,
Received: by xcssun.Berkeley.EDU (5.57/1.25)
id AA07976; Fri, 28 Aug 87 09:26:12 PDT
Received: from PREP.AI.MIT.EDU by ucbvax.Berkeley.EDU (5.58/1.27)
id AA03230; Fri, 28 Aug 87 09:28:04 PDT
Received: by PREP.AI.MIT.EDU; Fri, 28 Aug 87 12:28:43 EDT
Date: Fri, 28 Aug 87 12:28:43 EDT
From: phr@prep.ai.mit.edu (Paul Rubin)
Message-Id: <8708281628.AA09926@prep.ai.mit.edu>
To: rms@prep.ai.mit.edu
Subject: gdb suggestions
*** EOOH ***
Date: Fri, 28 Aug 87 12:28:43 EDT
From: phr@prep.ai.mit.edu (Paul Rubin)
To: rms@prep.ai.mit.edu
Subject: gdb suggestions
1. I wish gdb had a command to re-read the sources so that I can edit
the program and recompile it without having to kill and restart gdb.
2. Would be nice if gdb could somehow connect the subprocess's tty channels
to a pty, so I can run gdb in an X window and the subprocess in a different
(xterm) window.
This might need hair to detect if the subprocess is running when you try
to examine variables, etc. and stop the subproc or report an error if it is.


View File

@ -1,5 +1,5 @@
/* Memory-access and commands for inferior process, for GDB.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
@ -31,47 +31,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include <signal.h>
#include <sys/param.h>
#ifdef mac_aux
/* Warning! This table is positional and highly dependent on the local
system. Check it closely against <sys/signal.h> when porting. */
char *sys_siglist[] = {
"Signal 0",
"Hangup",
"Interrupt",
"Quit",
"Invalid instruction",
"Trace/breakpoint trap",
"IOT trap",
"EMT trap",
"Floating point exception",
"Killed",
"Bus error",
"Segmentation fault",
"Bad system call",
"Broken pipe",
"Alarm clock",
"Terminated",
"User signal 1",
"User signal 2",
"Child exited",
"Power-fail restart",
"Stopped",
"Stopped (tty input)",
"Stopped (tty output)",
"Stopped (signal)",
"Cputime limit exceeded",
"File size limit exceeded",
"Virtual timer expired",
"Profiling timer expired",
"Window changed",
"Continued",
"Urgent I/O condition",
"I/O possible",
};
#else
/* More portable systems do it for you */
extern char *sys_siglist[];
#endif
#define ERROR_NO_INFERIOR \
if (inferior_pid == 0) error ("The program is not being run.");
@ -161,7 +121,7 @@ set_args_command (args)
if (!args) args = "";
inferior_args = concat (" ", args, "");
}
void
tty_command (file)
char *file;
@ -197,19 +157,32 @@ Start it from the beginning? "))
error ("Program already started.");
}
if (args)
set_args_command (args);
exec_file = (char *) get_exec_file ();
if (from_tty)
if (remote_debugging)
{
printf ("Starting program: %s%s\n",
exec_file, inferior_args);
fflush (stdout);
free (allargs);
if (from_tty)
{
printf ("Starting program: %s%s\n",
exec_file, inferior_args);
fflush (stdout);
}
}
else
{
if (args)
set_args_command (args);
allargs = concat ("exec ", exec_file, inferior_args);
inferior_pid = create_inferior (allargs, environ_vector (inferior_environ));
exec_file = (char *) get_exec_file ();
if (from_tty)
{
printf ("Starting program: %s%s\n",
exec_file, inferior_args);
fflush (stdout);
}
allargs = concat ("exec ", exec_file, inferior_args);
inferior_pid = create_inferior (allargs, environ_vector (inferior_environ));
}
clear_proceed_status ();
@ -326,6 +299,7 @@ jump_command (arg, from_tty)
int from_tty;
{
register CORE_ADDR addr;
struct symtabs_and_lines sals;
struct symtab_and_line sal;
ERROR_NO_INFERIOR;
@ -333,7 +307,14 @@ jump_command (arg, from_tty)
if (!arg)
error_no_arg ("starting address");
sal = decode_line_spec (arg, 1);
sals = decode_line_spec (arg, 1);
if (sals.nelts != 1)
{
error ("Unreasonable jump request");
}
sal = sals.sals[0];
free (sals.sals);
if (sal.symtab == 0 && sal.pc == 0)
error ("No source file has been specified.");
@ -751,8 +732,8 @@ registers_info (addr_exp)
/*
* attach_command --
* takes a program started up outside of gdb and ``attaches'' to it.
* This stops it cold in it's tracks and allows us to start tracing
* it. For this to work, we must be able to send the process a
* This stops it cold in its tracks and allows us to start tracing it.
* For this to work, we must be able to send the process a
* signal and we must have the same effective uid as the program.
*/
static void
@ -762,11 +743,17 @@ attach_command (args, from_tty)
{
char *exec_file;
int pid;
int remote;
dont_repeat();
if (!args)
error_no_arg ("process-id to attach");
while (*args == ' ' || *args == '\t') args++;
if (args[0] == '/')
remote = 1;
else
pid = atoi (args);
@ -782,12 +769,21 @@ attach_command (args, from_tty)
if (from_tty)
{
printf ("Attaching program: %s pid %d\n",
exec_file, pid);
if (remote)
printf ("Attaching remote machine\n");
else
printf ("Attaching program: %s pid %d\n",
exec_file, pid);
fflush (stdout);
}
attach_program (pid);
if (remote)
{
remote_open (args, from_tty);
start_remote ();
}
else
attach_program (pid);
}
/*

View File

@ -27,6 +27,10 @@ extern char *inferior_io_terminal;
extern int inferior_pid;
/* Nonzero if debugging a remote machine via a serial link or ethernet. */
extern int remote_debugging;
/* Last signal that the inferior received (why it stopped). */
extern int stop_signal;

View File

@ -25,25 +25,14 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include "inferior.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sgtty.h>
#include <fcntl.h>
#ifdef mac_aux
#include <sys/seg.h>
#include <sys/mmu.h>
#include <sys/signal.h>
#include <sys/time.h>
#include <sys/user.h>
#else
#include <sys/user.h>
#endif /* mac_aux */
#ifdef UMAX_PTRACE
#include <a.out.h>
#endif
@ -53,10 +42,6 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include <machine/reg.h>
#endif
#ifdef SYSV_TTYS
#include <termio.h>
#endif
extern int errno;
/* Nonzero if we are debugging an attached outside process
@ -64,31 +49,21 @@ extern int errno;
static int attach_flag;
#define UPAGE_MASK 0x00003FFF
START_FILE
/* Record terminal status separately for debugger and inferior. */
#ifdef SYSV_TTYS
static struct termio ti_inferior;
#else
static struct sgttyb sg_inferior;
static struct tchars tc_inferior;
static struct ltchars ltc_inferior;
static int lmode_inferior;
#endif
static int tflags_inferior;
static int pgrp_inferior;
#ifdef SYSV_TTYS
static struct termio ti_ours;
#else
static struct sgttyb sg_ours;
static struct tchars tc_ours;
static struct ltchars ltc_ours;
static int lmode_ours;
#endif
static int tflags_ours;
static int pgrp_ours;
@ -107,15 +82,13 @@ static int terminal_is_ours;
void
terminal_init_inferior ()
{
if (remote_debugging)
return;
#ifdef SYSV_TTYS
ti_inferior = ti_ours;
#else
sg_inferior = sg_ours;
tc_inferior = tc_ours;
ltc_inferior = ltc_ours;
lmode_inferior = lmode_ours;
#endif
tflags_inferior = tflags_ours;
pgrp_inferior = inferior_pid;
@ -128,18 +101,17 @@ terminal_init_inferior ()
void
terminal_inferior ()
{
if (remote_debugging)
return;
if (terminal_is_ours) /* && inferior_thisrun_terminal == 0) */
{
fcntl (0, F_SETFL, tflags_inferior);
fcntl (0, F_SETFL, tflags_inferior);
#ifdef SYSV_TTYS
ioctl (0, TCSETA, &ti_inferior);
#else
ioctl (0, TIOCSETN, &sg_inferior);
ioctl (0, TIOCSETC, &tc_inferior);
ioctl (0, TIOCSLTC, &ltc_inferior);
ioctl (0, TIOCLSET, &lmode_inferior);
#endif
ioctl (0, TIOCSPGRP, &pgrp_inferior);
}
terminal_is_ours = 0;
@ -156,6 +128,9 @@ terminal_inferior ()
void
terminal_ours_for_output ()
{
if (remote_debugging)
return;
terminal_ours_1 (1);
}
@ -166,6 +141,9 @@ terminal_ours_for_output ()
void
terminal_ours ()
{
if (remote_debugging)
return;
terminal_ours_1 (0);
}
@ -188,55 +166,37 @@ terminal_ours_1 (output_only)
signal (SIGTTOU, osigttou);
tflags_inferior = fcntl (0, F_GETFL, 0);
#ifdef SYSV_TTYS
ioctl (0, TCGETA, &ti_inferior);
#else
ioctl (0, TIOCGETP, &sg_inferior);
ioctl (0, TIOCGETC, &tc_inferior);
ioctl (0, TIOCGLTC, &ltc_inferior);
ioctl (0, TIOCLGET, &lmode_inferior);
#endif
}
fcntl (0, F_SETFL, tflags_ours);
fcntl (0, F_SETFL, tflags_ours);
#ifdef SYSV_TTYS
ti_ours.c_lflag |= ICANON | ISIG;
if (output_only)
ti_ours.c_lflag &= ~((ICANON|ISIG)&ti_inferior.c_lflag);
ioctl (0, TCSETA, &ti_ours);
ti_ours.c_lflag |= ICANON | ISIG;
#else
sg_ours.sg_flags &= ~RAW & ~CBREAK;
if (output_only)
sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags;
fcntl (0, F_SETFL, tflags_ours);
fcntl (0, F_SETFL, tflags_ours);
ioctl (0, TIOCSETN, &sg_ours);
ioctl (0, TIOCSETC, &tc_ours);
ioctl (0, TIOCSLTC, &ltc_ours);
ioctl (0, TIOCLSET, &lmode_ours);
sg_ours.sg_flags &= ~RAW & ~CBREAK;
#endif
}
static void
term_status_command ()
{
register int i;
if (remote_debugging)
{
printf ("No terminal status when remote debugging.\n");
return;
}
printf ("Inferior's terminal status (currently saved by GDB):\n");
#ifdef SYSV_TTYS
printf ("fcntl flags = 0x%x, owner pid = %d.\n",
tflags_inferior, pgrp_inferior);
printf ("iflag = 0x%04x, oflag = 0x%04x, cflag = 0x%04x, lflag = 0x%04x\n",
ti_inferior.c_iflag, ti_inferior.c_oflag,
ti_inferior.c_cflag, ti_inferior.c_lflag);
printf ("line discipline = %d\n", ti_inferior.c_line);
printf ("control chars: ");
for (i = 0; i < NCC; i++)
printf ("0x%x ", ti_inferior.c_cc[i]);
printf ("\n");
#else
printf ("fcntl flags = 0x%x, lmode = 0x%x,\nsgttyb.sg_flags = 0x%x, owner pid = %d.\n",
tflags_inferior, lmode_inferior,
sg_inferior.sg_flags, pgrp_inferior);
@ -248,7 +208,6 @@ term_status_command ()
for (i = 0; i < sizeof (struct ltchars); i++)
printf ("0x%x ", ((char *)&ltc_inferior)[i]);
printf ("\n");
#endif
}
static void
@ -334,6 +293,8 @@ create_inferior (allargs, env)
static void
kill_command ()
{
if (remote_debugging)
return;
if (inferior_pid == 0)
error ("The program is not being run.");
if (!query ("Kill the inferior process? "))
@ -343,6 +304,8 @@ kill_command ()
kill_inferior ()
{
if (remote_debugging)
return;
if (inferior_pid == 0)
return;
ptrace (8, inferior_pid, 0, 0);
@ -370,9 +333,14 @@ resume (step, signal)
int signal;
{
errno = 0;
ptrace (step ? 9 : 7, inferior_pid, 1, signal);
if (errno)
perror_with_name ("ptrace");
if (remote_debugging)
remote_resume (step, signal);
else
{
ptrace (step ? 9 : 7, inferior_pid, 1, signal);
if (errno)
perror_with_name ("ptrace");
}
}
#ifdef NEW_SUN_PTRACE
@ -415,17 +383,22 @@ fetch_inferior_registers ()
struct fp_status inferior_fp_registers;
extern char registers[];
ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers);
ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
if (remote_debugging)
remote_fetch_registers (registers);
else
{
ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers);
ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
bcopy (&inferior_registers, registers, 16 * 4);
bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
sizeof inferior_fp_registers.fps_regs);
*(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
*(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
bcopy (&inferior_fp_registers.fps_control,
&registers[REGISTER_BYTE (FPC_REGNUM)],
sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
bcopy (&inferior_registers, registers, 16 * 4);
bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
sizeof inferior_fp_registers.fps_regs);
*(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
*(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
bcopy (&inferior_fp_registers.fps_control,
&registers[REGISTER_BYTE (FPC_REGNUM)],
sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
}
}
/* Store our register values back into the inferior.
@ -439,17 +412,22 @@ store_inferior_registers (regno)
struct fp_status inferior_fp_registers;
extern char registers[];
bcopy (registers, &inferior_registers, 16 * 4);
bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
sizeof inferior_fp_registers.fps_regs);
inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
&inferior_fp_registers.fps_control,
sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
if (remote_debugging)
remote_store_registers (registers);
else
{
bcopy (registers, &inferior_registers, 16 * 4);
bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
sizeof inferior_fp_registers.fps_regs);
inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
&inferior_fp_registers.fps_control,
sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
}
}
#else
@ -467,7 +445,7 @@ fetch_inferior_registers ()
#else
struct user u;
unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
offset = ptrace (3, inferior_pid, offset, 0) & UPAGE_MASK;
offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
#endif
for (regno = 0; regno < NUM_REGS; regno++)
@ -497,7 +475,7 @@ store_inferior_registers (regno)
#else
struct user u;
unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
offset = ptrace (3, inferior_pid, offset, 0) & UPAGE_MASK;
offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
#endif
if (regno >= 0)
@ -551,13 +529,18 @@ read_inferior_memory (memaddr, myaddr, len)
/* Read all the longwords */
for (i = 0; i < count; i++, addr += sizeof (int))
buffer[i] = ptrace (1, inferior_pid, addr, 0);
{
if (remote_debugging)
buffer[i] = remote_fetch_word (addr);
else
buffer[i] = ptrace (1, inferior_pid, addr, 0);
}
/* Copy appropriate bytes out of the buffer. */
bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
}
/* Copy LEN bytes of data from debugger memnory at MYADDR
/* Copy LEN bytes of data from debugger memory at MYADDR
to inferior's memory at MEMADDR.
On failure (cannot write the inferior)
returns the value of errno. */
@ -580,11 +563,21 @@ write_inferior_memory (memaddr, myaddr, len)
/* Fill start and end extra bytes of buffer with existing memory data. */
buffer[0] = ptrace (1, inferior_pid, addr, 0);
if (remote_debugging)
buffer[0] = remote_fetch_word (addr);
else
buffer[0] = ptrace (1, inferior_pid, addr, 0);
if (count > 1)
buffer[count - 1]
= ptrace (1, inferior_pid,
addr + (count - 1) * sizeof (int), 0);
{
if (remote_debugging)
buffer[count - 1]
= remote_fetch_word (addr + (count - 1) * sizeof (int));
else
buffer[count - 1]
= ptrace (1, inferior_pid,
addr + (count - 1) * sizeof (int), 0);
}
/* Copy data to be written over corresponding part of buffer */
@ -595,7 +588,10 @@ write_inferior_memory (memaddr, myaddr, len)
for (i = 0; i < count; i++, addr += sizeof (int))
{
errno = 0;
ptrace (4, inferior_pid, addr, buffer[i]);
if (remote_debugging)
remote_store_word (addr, buffer[i]);
else
ptrace (4, inferior_pid, addr, buffer[i]);
if (errno)
return errno;
}
@ -611,7 +607,7 @@ try_writing_regs_command ()
extern int errno;
if (inferior_pid == 0)
error ("The program is not being run.");
error ("There is no inferior process now.");
for (i = 0; ; i += 2)
{
@ -644,14 +640,10 @@ Report which ones can be written.");
inferior_pid = 0;
#ifdef SYSV_TTYS
ioctl (0, TCGETA, &ti_ours);
#else
ioctl (0, TIOCGETP, &sg_ours);
ioctl (0, TIOCGETC, &tc_ours);
ioctl (0, TIOCGLTC, &ltc_ours);
ioctl (0, TIOCLGET, &lmode_ours);
#endif
fcntl (0, F_GETFL, tflags_ours);
ioctl (0, TIOCGPGRP, &pgrp_ours);

View File

@ -1,5 +1,5 @@
/* Start and stop the inferior process, for GDB.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
@ -90,6 +90,10 @@ static int stop_after_attach;
int pc_changed;
/* Nonzero if debugging a remote machine via a serial link or ethernet. */
int remote_debugging;
/* Save register contents here when about to pop a stack dummy frame. */
char stop_registers[REGISTER_BYTES];
@ -238,8 +242,38 @@ start_inferior ()
/* Install inferior's terminal modes. */
terminal_inferior ();
if (remote_debugging)
{
trap_expected = 0;
fetch_inferior_registers();
set_current_frame (read_register(FP_REGNUM));
stop_frame = get_current_frame();
inferior_pid = 3;
if (insert_breakpoints())
fatal("Can't insert breakpoints");
breakpoints_inserted = 1;
proceed(-1, -1, 0);
}
else
{
wait_for_inferior ();
normal_stop ();
}
}
/* Start remote-debugging of a machine over a serial link. */
void
start_remote ()
{
clear_proceed_status ();
running_in_shell = 0;
trap_expected = 0;
inferior_pid = 3;
breakpoints_inserted = 0;
mark_breakpoints_out ();
wait_for_inferior ();
normal_stop ();
normal_stop();
}
#ifdef ATTACH_DETACH
@ -290,7 +324,16 @@ wait_for_inferior ()
while (1)
{
prev_pc = read_pc ();
pid = wait (&w);
if (remote_debugging)
remote_wait (&w);
else
{
pid = wait (&w);
if (pid != inferior_pid)
continue;
}
pc_changed = 0;
fetch_inferior_registers ();
stop_pc = read_pc ();
@ -530,6 +573,7 @@ wait_for_inferior ()
else if (!random_signal && step_range_end)
{
newfun = find_pc_function (stop_pc);
newmisc = -1;
if (newfun)
{
newfun_pc = BLOCK_START (SYMBOL_BLOCK_VALUE (newfun))

View File

@ -49,32 +49,40 @@ the terms of Paragraph 1 above, provided that you also do the following:
that in whole or in part contains or is a derivative of this
program or any part thereof, to be licensed at no charge to all
third parties on terms identical to those contained in this
License Agreement (except that you may choose to grant more
extensive warranty protection to third parties, at your option).
License Agreement (except that you may choose to grant more extensive
warranty protection to some or all third parties, at your option).
c) You may charge a distribution fee for the physical act of
transferring a copy, and you may at your option offer warranty
protection in exchange for a fee.
3. You may copy and distribute this program or any portion of it in
compiled, executable or object code form under the terms of Paragraphs
1 and 2 above provided that you do the following:
Mere aggregation of another unrelated program with this program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other program under the scope of these terms.
a) cause each such copy to be accompanied by the
corresponding machine-readable source code, which must
be distributed under the terms of Paragraphs 1 and 2 above; or,
3. You may copy and distribute this program (or a portion or derivative
of it, under Paragraph 2) in object code or executable form under the terms
of Paragraphs 1 and 2 above provided that you also do one of the following:
b) cause each such copy to be accompanied by a
written offer, with no time limit, to give any third party
free (except for a nominal shipping charge) a machine readable
copy of the corresponding source code, to be distributed
under the terms of Paragraphs 1 and 2 above; or,
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) in the case of a recipient of this program in compiled, executable
or object code form (without the corresponding source code) you
shall cause copies you distribute to be accompanied by a copy
of the written offer of source code which you received along
with the copy you received.
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal
shipping charge) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
For an executable file, complete source code means all the source code for
all modules it contains; but, as a special exception, it need not include
source code for modules which are standard libraries that accompany the
operating system on which the executable file runs.
4. You may not copy, sublicense, distribute or transfer this program
except as expressly provided under this License Agreement. Any attempt

View File

@ -1,485 +0,0 @@
/* Parameters for execution on Macintosh under A/UX, for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#ifndef mac_aux
#define mac_aux
#endif
/* Get rid of any system-imposed stack limit if possible. */
#undef SET_STACK_LIMIT_HUGE
/* Define this if the C compiler puts an underscore at the front
of external names before giving them to the linker. */
#undef NAMES_HAVE_UNDERSCORE
/* COFF format object files */
#define COFF_FORMAT
/* System eVil ttys */
#define SYSV_TTYS
/* Debugger information will not be in DBX format. */
#undef READ_DBX_FORMAT
/* Offset from address of function to start of its code.
Zero on most machines. */
#define FUNCTION_START_OFFSET 0
/* Advance PC across any function entry prologue instructions
to reach some "real" code. */
#define SKIP_PROLOGUE(pc) \
{ register int op = read_memory_integer (pc, 2); \
if (op == 0047126) \
pc += 4; /* Skip link #word */ \
else if (op == 0044016) \
pc += 6; /* Skip link #long */ \
}
/* Immediately after a function call, return the saved pc.
Can't go through the frames for this because on some machines
the new frame is not set up until the new function executes
some instructions. */
#define SAVED_PC_AFTER_CALL(frame) \
read_memory_integer (read_register (SP_REGNUM), 4)
/* Address of end of stack space. */
#define STACK_END_ADDR 0x20000000
/* Stack grows downward. */
#define INNER_THAN <
/* Sequence of bytes for breakpoint instruction. */
#define BREAKPOINT {0x4e, 0x4f}
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
#define DECR_PC_AFTER_BREAK 2
/* Nonzero if instruction at PC is a return instruction. */
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e76)
/* Return 1 if P points to an invalid floating point value. */
#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */
/* Say how long (ordinary) registers are. */
#define REGISTER_TYPE long
/* Number of machine registers */
#define NUM_REGS 31
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
#define REGISTER_NAMES \
{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
"a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \
"ps", "pc", \
"fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \
"fpcontrol", "fpstatus", "fpiaddr", "fpcode", "fpflags" }
/* Register numbers of various important registers.
Note that some of these values are "real" register numbers,
and correspond to the general registers of the machine,
and some are "phony" register numbers which are too large
to be actual register numbers as far as the user is concerned
but do serve to get the desired values when passed to read_register. */
#define FP_REGNUM 14 /* Contains address of executing stack frame */
#define SP_REGNUM 15 /* Contains address of top of stack */
#define PS_REGNUM 16 /* Contains processor status */
#define PC_REGNUM 17 /* Contains program counter */
#define FP0_REGNUM 18 /* Floating point register 0 */
#define FPC_REGNUM 26 /* 68881 control register */
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (16*4+8*12+8+20)
/* Index within `registers' of the first byte of the space for
register N. */
#define REGISTER_BYTE(N) \
((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168 \
: (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \
: (N) * 4)
/* Number of bytes of storage in the actual machine representation
for register N. On the 68000, all regs are 4 bytes
except the floating point regs which are 12 bytes. */
#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4)
/* Number of bytes of storage in the program's representation
for register N. On the 68000, all regs are 4 bytes
except the floating point regs which are 8-byte doubles. */
#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4)
/* Largest value REGISTER_RAW_SIZE can have. */
#define MAX_REGISTER_RAW_SIZE 12
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
#define MAX_REGISTER_VIRTUAL_SIZE 8
/* Nonzero if register N requires conversion
from raw format to virtual format. */
#define REGISTER_CONVERTIBLE(N) (((unsigned)(N) - FP0_REGNUM) < 8)
/* Convert data from raw format for register REGNUM
to virtual format for register REGNUM. */
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
convert_from_68881 ((FROM), (TO)); \
else \
bcopy ((FROM), (TO), 4); }
/* Convert data from virtual format for register REGNUM
to raw format for register REGNUM. */
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
convert_to_68881 ((FROM), (TO)); \
else \
bcopy ((FROM), (TO), 4); }
/* Return the GDB type object for the "standard" data type
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) \
(((unsigned)(N) - FP0_REGNUM) < 8 ? builtin_type_double : builtin_type_int)
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
into VALBUF. */
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
/* Extract from an array REGBUF containing the (raw) register state
the address in which a function should return its structure value,
as a CORE_ADDR (or an expression that can be used as one). */
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
/* Enable use of alternate code to read and write registers. */
#undef NEW_SUN_PTRACE
/* Enable use of alternate code for Sun's format of core dump file. */
#undef NEW_SUN_CORE
/* Do implement the attach and detach commands. */
#undef ATTACH_DETACH
/* It is safe to look for symsegs on a Sun, because Sun's ld
does not screw up with random garbage at end of file. */
#define READ_GDB_SYMSEGS
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
/* FRAME_CHAIN takes a frame's nominal address
and produces the frame's chain-pointer.
FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
and produces the nominal address of the caller frame.
However, if FRAME_CHAIN_VALID returns zero,
it means the given frame is the outermost one and has no caller.
In that case, FRAME_CHAIN_COMBINE is not used. */
/* In the case of the Sun, the frame's nominal address
is the address of a 4-byte word containing the calling frame's address. */
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
#define FRAME_SAVED_PC(frame) (read_memory_integer (frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) (fi.frame)
#define FRAME_LOCALS_ADDRESS(fi) (fi.frame)
/* Set VAL to the number of args passed to frame described by FI.
Can set VAL to -1, meaning no way to tell. */
/* We can't tell how many args there are
now that the C compiler delays popping them. */
#define FRAME_NUM_ARGS(val,fi) (val = -1)
#if 0
#define FRAME_NUM_ARGS(val, fi) \
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame); \
register int insn = 0177777 & read_memory_integer (pc, 2); \
val = 0; \
if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \
val = read_memory_integer (pc + 2, 2); \
else if ((insn & 0170777) == 0050217 /* addql #N, sp */ \
|| (insn & 0170777) == 0050117) /* addqw */ \
{ val = (insn >> 9) & 7; if (val == 0) val = 8; } \
else if (insn == 0157774) /* addal #WW, sp */ \
val = read_memory_integer (pc + 2, 4); \
val >>= 2; }
#endif
/* Return number of bytes at start of arglist that are not really args. */
#define FRAME_ARGS_SKIP 8
/* Put here the code to store, into a struct frame_saved_regs,
the addresses of the saved registers of frame described by FRAME_INFO.
This includes special registers such as pc and fp saved in special
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame. */
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
{ register int regnum; \
register int regmask; \
register CORE_ADDR next_addr; \
register CORE_ADDR pc; \
int nextinsn; \
bzero (&frame_saved_regs, sizeof frame_saved_regs); \
if ((frame_info).pc >= (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \
&& (frame_info).pc <= (frame_info).frame) \
{ next_addr = (frame_info).frame; \
pc = (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\
else \
{ pc = get_pc_function_start ((frame_info).pc); \
/* Verify we have a link a6 instruction next; \
if not we lose. If we win, find the address above the saved \
regs using the amount of storage from the link instruction. */\
if (044016 == read_memory_integer (pc, 2)) \
next_addr = (frame_info).frame + read_memory_integer (pc += 2, 4), pc+=4; \
else if (047126 == read_memory_integer (pc, 2)) \
next_addr = (frame_info).frame + read_memory_integer (pc += 2, 2), pc+=2; \
else goto lose; \
/* If have an addal #-n, sp next, adjust next_addr. */ \
if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \
next_addr += read_memory_integer (pc += 2, 4), pc += 4; \
} \
/* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \
regmask = read_memory_integer (pc + 2, 2); \
/* But before that can come an fmovem. Check for it. */ \
nextinsn = 0xffff & read_memory_integer (pc, 2); \
if (0xf227 == nextinsn \
&& (regmask & 0xff00) == 0xe000) \
{ pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \
if (regmask & 1) \
(frame_saved_regs).regs[regnum] = (next_addr -= 12); \
regmask = read_memory_integer (pc + 2, 2); } \
if (0044327 == read_memory_integer (pc, 2)) \
{ pc += 4; /* Regmask's low bit is for register 0, the first written */ \
for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \
if (regmask & 1) \
(frame_saved_regs).regs[regnum] = (next_addr += 4) - 4; } \
else if (0044347 == read_memory_integer (pc, 2)) \
{ pc += 4; /* Regmask's low bit is for register 15, the first pushed */ \
for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \
if (regmask & 1) \
(frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
else if (0x2f00 == 0xfff0 & read_memory_integer (pc, 2)) \
{ regnum = 0xf & read_memory_integer (pc, 2); pc += 2; \
(frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
/* fmovemx to index of sp may follow. */ \
regmask = read_memory_integer (pc + 2, 2); \
nextinsn = 0xffff & read_memory_integer (pc, 2); \
if (0xf236 == nextinsn \
&& (regmask & 0xff00) == 0xf000) \
{ pc += 10; /* Regmask's low bit is for register fp0, the first written */ \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \
if (regmask & 1) \
(frame_saved_regs).regs[regnum] = (next_addr += 12) - 12; \
regmask = read_memory_integer (pc + 2, 2); } \
/* clrw -(sp); movw ccr,-(sp) may follow. */ \
if (0x426742e7 == read_memory_integer (pc, 4)) \
(frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \
lose: ; \
(frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 8; \
(frame_saved_regs).regs[FP_REGNUM] = (frame_info).frame; \
(frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4; \
}
/* Things needed for making the inferior call functions. */
/* Push an empty stack frame, to record the current PC, etc. */
#define PUSH_DUMMY_FRAME \
{ register CORE_ADDR sp = read_register (SP_REGNUM); \
register int regnum; \
char raw_buffer[12]; \
sp = push_word (sp, read_register (PC_REGNUM)); \
sp = push_word (sp, read_register (FP_REGNUM)); \
write_register (FP_REGNUM, sp); \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
{ read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \
sp = push_bytes (sp, raw_buffer, 12); } \
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
sp = push_word (sp, read_register (regnum)); \
sp = push_word (sp, read_register (PS_REGNUM)); \
write_register (SP_REGNUM, sp); }
/* Discard from the stack the innermost frame,
restoring all saved registers. */
#define POP_FRAME \
{ register CORE_ADDR fp = read_register (FP_REGNUM); \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info fi; \
char raw_buffer[12]; \
fi = get_frame_info (fp); \
get_frame_saved_regs (&fi, &fsr); \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
if (fsr.regs[regnum]) \
{ read_memory (fsr.regs[regnum], raw_buffer, 12); \
write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
if (fsr.regs[regnum]) \
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
if (fsr.regs[PS_REGNUM]) \
write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
write_register (SP_REGNUM, fp + 8); \
set_current_frame (read_register (FP_REGNUM)); }
/* This sequence of words is the instructions
fmovem 0xff,-(sp)
moveml 0xfffc,-(sp)
clrw -(sp)
movew ccr,-(sp)
/..* The arguments are pushed at this point by GDB;
no code is needed in the dummy for this.
The CALL_DUMMY_START_OFFSET gives the position of
the following jsr instruction. *../
jsr @#32323232
addl #69696969,sp
bpt
nop
Note this is 28 bytes.
We actually start executing at the jsr, since the pushing of the
registers is done by PUSH_DUMMY_FRAME. If this were real code,
the arguments for the function called by the jsr would be pushed
between the moveml and the jsr, and we could allow it to execute through.
But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
and we cannot allow the moveml to push the registers again lest they be
taken for the arguments. */
#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
#define CALL_DUMMY_LENGTH 28
#define CALL_DUMMY_START_OFFSET 12
/* Insert the specified number of args and function address
into a call sequence of the above form stored at DUMMYNAME. */
#define FIX_CALL_DUMMY(dummyname, fun, nargs) \
{ *(int *)((char *) dummyname + 20) = nargs * 4; \
*(int *)((char *) dummyname + 14) = fun; }
/* Interface definitions for kernel debugger KDB. */
/* Map machine fault codes into signal numbers.
First subtract 0, divide by 4, then index in a table.
Faults for which the entry in this table is 0
are not handled by KDB; the program's own trap handler
gets to handle then. */
#define FAULT_CODE_ORIGIN 0
#define FAULT_CODE_UNITS 4
#define FAULT_TABLE \
{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
0, 0, 0, 0, 0, 0, 0, 0, \
SIGILL }
/* Start running with a stack stretching from BEG to END.
BEG and END should be symbols meaningful to the assembler.
This is used only for kdb. */
#define INIT_STACK(beg, end) \
{ asm (".globl end"); \
asm ("movel #end, sp"); \
asm ("movel #0,a6"); }
/* Push the frame pointer register on the stack. */
#define PUSH_FRAME_PTR \
asm ("movel a6,sp@-");
/* Copy the top-of-stack to the frame pointer register. */
#define POP_FRAME_PTR \
asm ("movl sp@,a6");
/* After KDB is entered by a fault, push all registers
that GDB thinks about (all NUM_REGS of them),
so that they appear in order of ascending GDB register number.
The fault code will be on the stack beyond the last register. */
#define PUSH_REGISTERS \
{ asm ("clrw -(sp)"); \
asm ("pea sp@(10)"); \
asm ("movem #0xfffe,sp@-"); }
/* Assuming the registers (including processor status) have been
pushed on the stack in order of ascending GDB register number,
restore them and return to the address in the saved PC register. */
#define POP_REGISTERS \
{ asm ("subil #8,sp@(28)"); \
asm ("movem sp@,#0xffff"); \
asm ("rte"); }

View File

@ -1,5 +0,0 @@
/* This is how the size of an individual .o file's text segment
is rounded on a mac under a/ux. */
#define FILEADDR_ROUND(addr) (addr)

View File

@ -1,437 +0,0 @@
/* Definitions to make GDB run on a merlin under utek 2.1
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#ifndef ns16000
#define ns16000
#endif
# include <machine/reg.h>
/* Define this if the C compiler puts an underscore at the front
of external names before giving them to the linker. */
#define NAMES_HAVE_UNDERSCORE
/* Debugger information will be in DBX format. */
#define READ_DBX_FORMAT
/* Offset from address of function to start of its code.
Zero on most machines. */
#define FUNCTION_START_OFFSET 0
/* Advance PC across any function entry prologue instructions
to reach some "real" code. */
#define SKIP_PROLOGUE(pc) \
{ register int op = read_memory_integer (pc, 1); \
if (op == 0x82) \
{ op = read_memory_integer (pc+2,1); \
if ((op & 0x80) == 0) pc += 3; \
else if ((op & 0xc0) == 0x80) pc += 4; \
else pc += 6; \
}}
/* Immediately after a function call, return the saved pc.
Can't always go through the frames for this because on some machines
the new frame is not set up until the new function executes
some instructions. */
#define SAVED_PC_AFTER_CALL(frame) \
read_memory_integer (read_register (SP_REGNUM), 4)
/* This is the amount to subtract from u.u_ar0
to get the offset in the core file of the register values. */
#define KERNEL_U_ADDR (0xfef000)
/* Address of end of stack space. */
#define STACK_END_ADDR (0x800000)
/* Stack grows downward. */
#define INNER_THAN <
/* Sequence of bytes for breakpoint instruction. */
#define BREAKPOINT {0xf2}
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
#define DECR_PC_AFTER_BREAK 0
/* Nonzero if instruction at PC is a return instruction. */
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0x12)
/* Return 1 if P points to an invalid floating point value. */
#define INVALID_FLOAT(p, len) 0
/* Define this to say that the "svc" insn is followed by
codes in memory saying which kind of system call it is. */
#define NS32K_SVC_IMMED_OPERANDS
/* Say how long (ordinary) registers are. */
#define REGISTER_TYPE long
/* Number of machine registers */
#define NUM_REGS 25
#define NUM_GENERAL_REGS 8
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
"pc", "sp", "fp", "ps", \
"fsr", \
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
"l0", "l1", "l2", "l3", "l4", \
}
/* Register numbers of various important registers.
Note that some of these values are "real" register numbers,
and correspond to the general registers of the machine,
and some are "phony" register numbers which are too large
to be actual register numbers as far as the user is concerned
but do serve to get the desired values when passed to read_register. */
#define AP_REGNUM FP_REGNUM
#define FP_REGNUM 10 /* Contains address of executing stack frame */
#define SP_REGNUM 9 /* Contains address of top of stack */
#define PC_REGNUM 8 /* Contains program counter */
#define PS_REGNUM 11 /* Contains processor status */
#define FPS_REGNUM 12 /* Floating point status register */
#define FP0_REGNUM 13 /* Floating point register 0 */
#define LP0_REGNUM 21 /* Double register 0 (same as FP0) */
#define REGISTER_U_ADDR(addr, blockend, regno) \
{ \
switch (regno) { \
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: \
addr = blockend + (R0 - regno) * sizeof (int); break; \
case PC_REGNUM: \
addr = blockend + PC * sizeof (int); break; \
case SP_REGNUM: \
addr = blockend + SP * sizeof (int); break; \
case FP_REGNUM: \
addr = blockend + FP * sizeof (int); break; \
case PS_REGNUM: \
addr = blockend + 12 * sizeof (int); break; \
case FPS_REGNUM: \
addr = 108; break; \
case FP0_REGNUM + 0: case FP0_REGNUM + 1: \
case FP0_REGNUM + 2: case FP0_REGNUM + 3: \
case FP0_REGNUM + 4: case FP0_REGNUM + 5: \
case FP0_REGNUM + 6: case FP0_REGNUM + 7: \
addr = 76 + (regno - FP0_REGNUM) * sizeof (float); break; \
case LP0_REGNUM + 0: case LP0_REGNUM + 1: \
case LP0_REGNUM + 2: case LP0_REGNUM + 3: \
addr = 76 + (regno - LP0_REGNUM) * sizeof (double); break; \
default: \
printf ("bad argument to REGISTER_U_ADDR %d\n", regno); \
abort (); \
} \
}
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES ((NUM_REGS - 4) * sizeof (int) + 4 * sizeof (double))
/* Index within `registers' of the first byte of the space for
register N. */
#define REGISTER_BYTE(N) ((N) >= LP0_REGNUM ? \
LP0_REGNUM * 4 + ((N) - LP0_REGNUM) * 8 : (N) * 4)
/* Number of bytes of storage in the actual machine representation
for register N. On the 32000, all regs are 4 bytes
except for the doubled floating registers. */
#define REGISTER_RAW_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
/* Number of bytes of storage in the program's representation
for register N. On the 32000, all regs are 4 bytes
except for the doubled floating registers. */
#define REGISTER_VIRTUAL_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
/* Largest value REGISTER_RAW_SIZE can have. */
#define MAX_REGISTER_RAW_SIZE 8
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
#define MAX_REGISTER_VIRTUAL_SIZE 8
/* Nonzero if register N requires conversion
from raw format to virtual format. */
#define REGISTER_CONVERTIBLE(N) 0
/* Convert data from raw format for register REGNUM
to virtual format for register REGNUM. */
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
/* Convert data from virtual format for register REGNUM
to raw format for register REGNUM. */
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
/* Return the GDB type object for the "standard" data type
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) \
((N) >= FP0_REGNUM ? \
((N) >= LP0_REGNUM ? \
builtin_type_double \
: builtin_type_float) \
: builtin_type_int)
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
into VALBUF. */
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
/* Extract from an array REGBUF containing the (raw) register state
the address in which a function should return its structure value,
as a CORE_ADDR (or an expression that can be used as one). */
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
/* FRAME_CHAIN takes a frame's nominal address
and produces the frame's chain-pointer.
FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
and produces the nominal address of the caller frame.
However, if FRAME_CHAIN_VALID returns zero,
it means the given frame is the outermost one and has no caller.
In that case, FRAME_CHAIN_COMBINE is not used. */
/* In the case of the Merlin, the frame's nominal address is the FP value,
and at that address is saved previous FP value as a 4-byte word. */
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
#define FRAME_SAVED_PC(frame) (read_memory_integer (frame + 4, 4))
/* compute base of arguments */
#define FRAME_ARGS_ADDRESS(fi) ((fi).frame)
#define FRAME_LOCALS_ADDRESS(fi) ((fi).frame)
/* Return number of args passed to a frame.
Can return -1, meaning no way to tell. */
#define FRAME_NUM_ARGS(numargs, fi) \
{ CORE_ADDR pc; \
int insn; \
int addr_mode; \
int width; \
\
pc = FRAME_SAVED_PC (fi.frame); \
insn = read_memory_integer (pc,2); \
addr_mode = (insn >> 11) & 0x1f; \
insn = insn & 0x7ff; \
if ((insn & 0x7fc) == 0x57c \
&& addr_mode == 0x14) /* immediate */ \
{ if (insn == 0x57c) /* adjspb */ \
width = 1; \
else if (insn == 0x57d) /* adjspw */ \
width = 2; \
else if (insn == 0x57f) /* adjspd */ \
width = 4; \
numargs = read_memory_integer (pc+2,width); \
if (width > 1) \
flip_bytes (&numargs, width); \
numargs = - sign_extend (numargs, width*8) / 4; } \
else numargs = -1; \
}
/* Return number of bytes at start of arglist that are not really args. */
#define FRAME_ARGS_SKIP 8
/* Put here the code to store, into a struct frame_saved_regs,
the addresses of the saved registers of frame described by FRAME_INFO.
This includes special registers such as pc and fp saved in special
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame. */
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
{ int regmask,regnum; \
int localcount; \
CORE_ADDR enter_addr; \
CORE_ADDR next_addr; \
\
enter_addr = get_pc_function_start ((frame_info).pc); \
regmask = read_memory_integer (enter_addr+1, 1); \
localcount = ns32k_localcount (enter_addr); \
next_addr = (frame_info).frame + localcount; \
for (regnum = 0; regnum < 8; regnum++, regmask >>= 1) \
(frame_saved_regs).regs[regnum] \
= (regmask & 1) ? (next_addr -= 4) : 0; \
(frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 4; \
(frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4; \
(frame_saved_regs).regs[FP_REGNUM] \
= read_memory_integer ((frame_info).frame, 4); }
/* Things needed for making the inferior call functions. */
/* Push an empty stack frame, to record the current PC, etc. */
#define PUSH_DUMMY_FRAME \
{ register CORE_ADDR sp = read_register (SP_REGNUM); \
register int regnum; \
sp = push_word (sp, read_register (PC_REGNUM)); \
sp = push_word (sp, read_register (FP_REGNUM)); \
write_register (FP_REGNUM, sp); \
for (regnum = 0; regnum < 8; regnum++) \
sp = push_word (sp, read_register (regnum)); \
write_register (SP_REGNUM, sp); \
}
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME \
{ register CORE_ADDR fp = read_register (FP_REGNUM); \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info fi; \
fi = get_frame_info (fp); \
get_frame_saved_regs (&fi, &fsr); \
for (regnum = 0; regnum < 8; regnum++) \
if (fsr.regs[regnum]) \
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
write_register (SP_REGNUM, fp + 8); \
}
/* This sequence of words is the instructions
enter 0xff,0 82 ff 00
jsr @0x00010203 7f ae c0 01 02 03
adjspd 0x69696969 7f a5 01 02 03 04
bpt f2
Note this is 16 bytes. */
#define CALL_DUMMY { 0x7f00ff82, 0x0201c0ae, 0x01a57f03, 0xf2040302 }
#define CALL_DUMMY_START_OFFSET 3
#define CALL_DUMMY_LENGTH 16
#define CALL_DUMMY_ADDR 5
#define CALL_DUMMY_NARGS 11
/* Insert the specified number of args and function address
into a call sequence of the above form stored at DUMMYNAME. */
#define FIX_CALL_DUMMY(dummyname, fun, nargs) \
{ int flipped = fun | 0xc0000000; \
flip_bytes (&flipped, 4); \
*((int *) (((char *) dummyname)+CALL_DUMMY_ADDR)) = flipped; \
flipped = - nargs * 4; \
flip_bytes (&flipped, 4); \
*((int *) (((char *) dummyname)+CALL_DUMMY_NARGS)) = flipped; \
}
#ifdef notdef
/* Interface definitions for kernel debugger KDB. */
/* Map machine fault codes into signal numbers.
First subtract 0, divide by 4, then index in a table.
Faults for which the entry in this table is 0
are not handled by KDB; the program's own trap handler
gets to handle then. */
#define FAULT_CODE_ORIGIN 0
#define FAULT_CODE_UNITS 4
#define FAULT_TABLE \
{ 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \
0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0}
/* Start running with a stack stretching from BEG to END.
BEG and END should be symbols meaningful to the assembler.
This is used only for kdb. */
#define INIT_STACK(beg, end) \
{ asm (".globl end"); \
asm ("movl $ end, sp"); \
asm ("clrl fp"); }
/* Push the frame pointer register on the stack. */
#define PUSH_FRAME_PTR \
asm ("pushl fp");
/* Copy the top-of-stack to the frame pointer register. */
#define POP_FRAME_PTR \
asm ("movl (sp), fp");
/* After KDB is entered by a fault, push all registers
that GDB thinks about (all NUM_REGS of them),
so that they appear in order of ascending GDB register number.
The fault code will be on the stack beyond the last register. */
#define PUSH_REGISTERS \
{ asm ("pushl 8(sp)"); \
asm ("pushl 8(sp)"); \
asm ("pushal 0x14(sp)"); \
asm ("pushr $037777"); }
/* Assuming the registers (including processor status) have been
pushed on the stack in order of ascending GDB register number,
restore them and return to the address in the saved PC register. */
#define POP_REGISTERS \
{ asm ("popr $037777"); \
asm ("subl2 $8,(sp)"); \
asm ("movl (sp),sp"); \
asm ("rei"); }
#endif

View File

@ -1,566 +0,0 @@
/* Parameters for execution on a Sony/NEWS, for GDB, the GNU debugger.
Here is an m-news800.h file for gdb version 2.1. It supports the 68881
registers.
Now(9/2 '87) NEWS's printf has a bug.
And support Sun assembly format instead of Motorola one.
Probably not well support floating registers from core file rarely that
I do not know detail.
(hikichi@srava.sra.junet or hikichi%srava.sra.junet%kddlabs%seismo.CSS.GOV)
Here is IEEE nan routine to use such bug fixed.
printf("%g\n", Nan);
> struct ieee { |* IEEE floating format *|
> unsigned int s:1;
> unsigned int e:11;
> unsigned int f1:20;
> unsigned int f2;
> };
>
> #define ZERO_F(x) ((x.f1 == 0) && (x.f2 == 0)) |* zero fraction ? *|
> #define ZERO_E(x) (x.e == 0) |* zero exponential ? *|
> #define MAX_E(x) (x.e == 0x7ff) |* max exponential ? *|
> #define MINUS_S(x) (x.s == 1) |* minus ? *|
>
> int
> is_nan(arg) |* Not a Number ? *|
> struct ieee arg;
> {
> if (MAX_E(arg) && !ZERO_F(arg))
> return (1);
> else
> return (0);
> }
>
> int
> is_plus_infinity(arg)
> struct ieee arg;
> {
> if (!MINUS_S(arg) && MAX_E(arg) && ZERO_F(arg))
> return (1);
> else
> return (0);
> }
>
> int
> is_minus_infinity(arg)
> struct ieee arg;
> {
> if (MINUS_S(arg) && MAX_E(arg) && ZERO_F(arg))
> return (1);
> else
> return (0);
> }
>
> int
> is_denormal(arg)
> struct ieee arg;
> {
> if (ZERO_E(arg))
> return (1);
> else
> return (0);
> }
Copyright (C) 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#ifdef 0 /* cannot use RCS id since initialize routine fails. */
static char *RCSid =
"$Header: m-news800.h,v 1.1 87/09/21 21:27:52 hikichi Exp $";
#endif lint
/*
* $Log: m-news800.h,v $
* Revision 1.1 87/09/21 21:27:52 hikichi
* Initial revision
*
*/
/* Identify this machine */
#ifndef news800
#define news800
#endif
/* #define USE_GAS */
/* Motorola assembly format */
#ifndef USE_GAS
#define MOTOROLA
#endif
/* bug when printf special number; NAN */
#define PRINTF_BUG
/* Define this if the C compiler puts an underscore at the front
of external names before giving them to the linker. */
#define NAMES_HAVE_UNDERSCORE
/* Offset from address of function to start of its code.
Zero on most machines. */
#define FUNCTION_START_OFFSET 0
/* Advance PC across any function entry prologue instructions
to reach some "real" code. */
#define SKIP_PROLOGUE(pc) \
{ register int op = read_memory_integer (pc, 2); \
if (op == 0047126) \
pc += 4; /* Skip link #word */ \
else if (op == 0044016) \
pc += 6; /* Skip link #long */ \
}
/* Immediately after a function call, return the saved pc.
Can't always go through the frames for this because on some machines
the new frame is not set up until the new function executes
some instructions. */
#define SAVED_PC_AFTER_CALL(frame) \
read_memory_integer (read_register (SP_REGNUM), 4)
/* THis is the amount to subtract from u.u_ar0
to get the offset in the core file of the register values. */
#define KERNEL_U_ADDR UADDR
/* Address of end of stack space. */
#define STACK_END_ADDR (0x80000000 - ctob(UPAGES + 1))
/* Stack grows downward. */
#define INNER_THAN <
/* Sequence of bytes for breakpoint instruction. */
#define BREAKPOINT {0x4e, 0x4f}
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
#define DECR_PC_AFTER_BREAK 2
/* Nonzero if instruction at PC is a return instruction. */
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e76)
/* Return 1 if P points to an invalid floating point value. */
#define INVALID_FLOAT(p) 0 /* Just a first guess; not checked */
/* Say how long registers are. */
#define REGISTER_TYPE long
/* Number of machine registers */
#define NUM_REGS 29
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
#define REGISTER_NAMES \
{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
"a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \
"pc", "ps", \
"fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \
"fpcontrol", "fpstatus", "fpiaddr" }
/* Register numbers of various important registers.
Note that some of these values are "real" register numbers,
and correspond to the general registers of the machine,
and some are "phony" register numbers which are too large
to be actual register numbers as far as the user is concerned
but do serve to get the desired values when passed to read_register. */
#define FP_REGNUM 14 /* Contains address of executing stack frame */
#define SP_REGNUM 15 /* Contains address of top of stack */
#define PC_REGNUM 16 /* Contains program counter */
#define PS_REGNUM 17 /* Contains processor status */
#define FP0_REGNUM 18 /* Floating point register 0 */
#define FPC_REGNUM 26 /* 68881 control register */
#define REGISTER_U_ADDR(addr, blockend, regno) \
{ if (regno <= FP_REGNUM) \
addr = blockend + 4 + regno * 4; \
else if (regno == SP_REGNUM) \
addr = blockend - 4 * 4; \
else if (regno <= PS_REGNUM) \
addr = blockend + (regno - PS_REGNUM) * 4; \
else if (regno < FPC_REGNUM) \
addr = blockend + 4 + 4 * 14 + 4 * 5 + (regno - FP0_REGNUM) * 12; \
else \
addr = blockend + 4 + 4 * 16 + (regno - FPC_REGNUM) * 4; \
}
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (16*4+8*12+8+12)
/* Index within `registers' of the first byte of the space for
register N. */
#define REGISTER_BYTE(N) \
((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168 \
: (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \
: (N) * 4)
/* Number of bytes of storage in the actual machine representation
for register N. On the 68000, all regs are 4 bytes
except the floating point regs which are 12 bytes. */
#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4)
/* Number of bytes of storage in the program's representation
for register N. On the 68000, all regs are 4 bytes
except the floating point regs which are 8-byte doubles. */
#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4)
/* Largest value REGISTER_RAW_SIZE can have. */
#define MAX_REGISTER_RAW_SIZE 12
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
#define MAX_REGISTER_VIRTUAL_SIZE 8
/* Nonzero if register N requires conversion
from raw format to virtual format. */
#define REGISTER_CONVERTIBLE(N) (((unsigned)(N) - FP0_REGNUM) < 8)
/* Convert data from raw format for register REGNUM
to virtual format for register REGNUM. */
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
convert_from_68881 ((FROM), (TO)); \
else \
bcopy ((FROM), (TO), 4); }
/* Convert data from virtual format for register REGNUM
to raw format for register REGNUM. */
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
convert_to_68881 ((FROM), (TO)); \
else \
bcopy ((FROM), (TO), 4); }
/* Return the GDB type object for the "standard" data type
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) \
(((unsigned)(N) - FP0_REGNUM) < 8 ? builtin_type_double : builtin_type_int)
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
/* FRAME_CHAIN takes a frame's nominal address
and produces the frame's chain-pointer.
FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
and produces the nominal address of the caller frame.
However, if FRAME_CHAIN_VALID returns zero,
it means the given frame is the outermost one and has no caller.
In that case, FRAME_CHAIN_COMBINE is not used. */
/* In the case of the NEWS, the frame's nominal address
is the address of a 4-byte word containing the calling frame's address. */
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
#define FRAME_SAVED_PC(frame) (read_memory_integer (frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) (fi.frame)
#define FRAME_LOCALS_ADDRESS(fi) (fi.frame)
/* Return number of args passed to a frame.
Can return -1, meaning no way to tell. */
#define FRAME_NUM_ARGS(val, fi) \
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame); \
register int insn = 0177777 & read_memory_integer (pc, 2); \
val = 0; \
if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \
val = read_memory_integer (pc + 2, 2); \
else if ((insn & 0170777) == 0050217 /* addql #N, sp */ \
|| (insn & 0170777) == 0050117) /* addqw */ \
{ val = (insn >> 9) & 7; if (val == 0) val = 8; } \
else if (insn == 0157774) /* addal #WW, sp */ \
val = read_memory_integer (pc + 2, 4); \
val >>= 2; }
/* Return number of bytes at start of arglist that are not really args. */
#define FRAME_ARGS_SKIP 8
/* Put here the code to store, into a struct frame_saved_regs,
the addresses of the saved registers of frame described by FRAME_INFO.
This includes special registers such as pc and fp saved in special
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame. */
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
{ register int regnum; \
register int regmask; \
register CORE_ADDR next_addr; \
register CORE_ADDR pc; \
register int insn; \
register int offset; \
bzero (&frame_saved_regs, sizeof frame_saved_regs); \
if ((frame_info).pc >= (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \
&& (frame_info).pc <= (frame_info).frame) \
{ next_addr = (frame_info).frame; \
pc = (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\
else \
{ pc = get_pc_function_start ((frame_info).pc); \
/* Verify we have a link a6 instruction next, \
or a branch followed by a link a6 instruction; \
if not we lose. If we win, find the address above the saved \
regs using the amount of storage from the link instruction. */\
retry: \
insn = read_memory_integer (pc, 2); \
if (insn == 044016) \
next_addr = (frame_info).frame - read_memory_integer (pc += 2, 4), pc+=4; \
else if (insn == 047126) \
next_addr = (frame_info).frame - read_memory_integer (pc += 2, 2), pc+=2; \
else if ((insn & 0177400) == 060000) /* bra insn */ \
{ offset = insn & 0377; \
pc += 2; /* advance past bra */ \
if (offset == 0) /* bra #word */ \
offset = read_memory_integer (pc, 2), pc += 2; \
else if (offset == 0377) /* bra #long */ \
offset = read_memory_integer (pc, 4), pc += 4; \
pc += offset; \
goto retry; \
} else goto lose; \
/* If have an addal #-n, sp next, adjust next_addr. */ \
if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \
next_addr += read_memory_integer (pc += 2, 4), pc += 4; \
} \
/* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \
insn = read_memory_integer (pc, 2), pc += 2; \
regmask = read_memory_integer (pc, 2); \
if ((insn & 0177760) == 022700) /* movl rn, (sp) */ \
(frame_saved_regs).regs[(insn&7) + ((insn&010)?8:0)] = next_addr; \
else if ((insn & 0177760) == 024700) /* movl rn, -(sp) */ \
(frame_saved_regs).regs[(insn&7) + ((insn&010)?8:0)] = next_addr-=4; \
else if (insn == 0044327) /* moveml mask, (sp) */ \
{ pc += 2; \
/* Regmask's low bit is for register 0, the first written */ \
next_addr -= 4; \
for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \
if (regmask & 1) \
(frame_saved_regs).regs[regnum] = (next_addr += 4); \
} else if (insn == 0044347) /* moveml mask, -(sp) */ \
{ pc += 2; \
/* Regmask's low bit is for register 15, the first pushed */ \
for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \
if (regmask & 1) \
(frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
/* clrw -(sp); movw ccr,-(sp) may follow. */ \
if (read_memory_integer (pc, 2) == 041147 \
&& read_memory_integer (pc+2, 2) == 042347) \
(frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \
lose: ; \
(frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 8; \
(frame_saved_regs).regs[FP_REGNUM] = (frame_info).frame; \
(frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4; \
}
/* Things needed for making the inferior call functions. */
/* Push an empty stack frame, to record the current PC, etc. */
#define PUSH_DUMMY_FRAME \
{ register CORE_ADDR sp = read_register (SP_REGNUM); \
register int regnum; \
char raw_buffer[12]; \
sp = push_word (sp, read_register (PC_REGNUM)); \
sp = push_word (sp, read_register (FP_REGNUM)); \
write_register (FP_REGNUM, sp); \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
{ read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \
sp = push_bytes (sp, raw_buffer, 12); } \
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
sp = push_word (sp, read_register (regnum)); \
sp = push_word (sp, read_register (PS_REGNUM)); \
write_register (SP_REGNUM, sp); }
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME \
{ register CORE_ADDR fp = read_register (FP_REGNUM); \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info fi; \
char raw_buffer[12]; \
fi = get_frame_info (fp); \
get_frame_saved_regs (&fi, &fsr); \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
if (fsr.regs[regnum]) \
{ read_memory (fsr.regs[regnum], raw_buffer, 12); \
write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
if (fsr.regs[regnum]) \
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
if (fsr.regs[PS_REGNUM]) \
write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
write_register (SP_REGNUM, fp + 8); \
}
/* This sequence of words is the instructions
fmove.m #<f0-f7>,-(sp)
movem.l 0xfffc,-(sp)
clr.w -(sp)
move.w ccr,-(sp)
/..* The arguments are pushed at this point by GDB;
no code is needed in the dummy for this.
The CALL_DUMMY_START_OFFSET gives the position of
the following jsr instruction. *../
jbsr (#32323232)
add.l #69696969,sp
bpt
nop
Note this is 24 bytes.
We actually start executing at the jsr, since the pushing of the
registers is done by PUSH_DUMMY_FRAME. If this were real code,
the arguments for the function called by the jsr would be pushed
between the moveml and the jsr, and we could allow it to execute through.
But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
and we cannot allow the moveml to push the registers again lest they be
taken for the arguments. */
#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
#define CALL_DUMMY_LENGTH 28
#define CALL_DUMMY_START_OFFSET 12
/* Insert the specified number of args and function address
into a call sequence of the above form stored at DUMMYNAME. */
#define FIX_CALL_DUMMY(dummyname, fun, nargs) \
{ *(int *)((char *) dummyname + 20) = nargs * 4; \
*(int *)((char *) dummyname + 14) = fun; }
/* Interface definitions for kernel debugger KDB. */
/* Map machine fault codes into signal numbers.
First subtract 0, divide by 4, then index in a table.
Faults for which the entry in this table is 0
are not handled by KDB; the program's own trap handler
gets to handle then. */
#define FAULT_CODE_ORIGIN 0
#define FAULT_CODE_UNITS 4
#define FAULT_TABLE \
{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
0, 0, 0, 0, 0, 0, 0, 0, \
SIGILL }
/* Start running with a stack stretching from BEG to END.
BEG and END should be symbols meaningful to the assembler.
This is used only for kdb. */
#ifdef MOTOROLA
#define INIT_STACK(beg, end) \
{ asm (".globl end"); \
asm ("move.l $ end, sp"); \
asm ("clr.l fp"); }
#else
#define INIT_STACK(beg, end) \
{ asm (".globl end"); \
asm ("movel $ end, sp"); \
asm ("clrl fp"); }
#endif
/* Push the frame pointer register on the stack. */
#ifdef MOTOROLA
#define PUSH_FRAME_PTR \
asm ("move.l fp, -(sp)");
#else
#define PUSH_FRAME_PTR \
asm ("movel fp, -(sp)");
#endif
/* Copy the top-of-stack to the frame pointer register. */
#ifdef MOTOROLA
#define POP_FRAME_PTR \
asm ("move.l (sp), fp");
#else
#define POP_FRAME_PTR \
asm ("movl (sp), fp");
#endif
/* After KDB is entered by a fault, push all registers
that GDB thinks about (all NUM_REGS of them),
so that they appear in order of ascending GDB register number.
The fault code will be on the stack beyond the last register. */
#ifdef MOTOROLA
#define PUSH_REGISTERS \
{ asm ("clr.w -(sp)"); \
asm ("pea (10,sp)"); \
asm ("movem $ 0xfffe,-(sp)"); }
#else
#define PUSH_REGISTERS \
{ asm ("clrw -(sp)"); \
asm ("pea 10(sp)"); \
asm ("movem $ 0xfffe,-(sp)"); }
#endif
/* Assuming the registers (including processor status) have been
pushed on the stack in order of ascending GDB register number,
restore them and return to the address in the saved PC register. */
#ifdef MOTOROLA
#define POP_REGISTERS \
{ asm ("subi.l $8,28(sp)"); \
asm ("movem (sp),$ 0xffff"); \
asm ("rte"); }
#else
#define POP_REGISTERS \
{ asm ("subil $8,28(sp)"); \
asm ("movem (sp),$ 0xffff"); \
asm ("rte"); }
#endif

View File

@ -1,4 +0,0 @@
/* This is how the size of an individual .o file's text segment
is rounded on a SONY NEWS. */
#define FILEADDR_ROUND(addr) ((addr + 3) & -4)

View File

@ -400,7 +400,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
the following jsr instruction. *../
jsr @#32323232
addl #69696969,sp
bpt
trap #15
nop
Note this is 28 bytes.
We actually start executing at the jsr, since the pushing of the

View File

@ -2,4 +2,4 @@
/* This is how the size of an individual .o file's text segment
is rounded on a sun. */
#define FILEADDR_ROUND(addr) (addr)
#define FILEADDR_ROUND(addr) ((addr + 3) & -4)

View File

@ -1,425 +0,0 @@
/* Definitions to make GDB run on an encore under umax 4.2
Copyright (C) 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#ifndef ns16000
#define ns16000
#endif
#define HAVE_WAIT_STRUCT
/* Encore's modifications to ptrace format */
#define UMAX_PTRACE
/* Encore's modifications to core-file format */
#define UMAX_CORE
/* Define this if the C compiler puts an underscore at the front
of external names before giving them to the linker. */
#define NAMES_HAVE_UNDERSCORE
/* Exec files and symbol tables are in COFF format */
#define COFF_FORMAT
/* Offset from address of function to start of its code.
Zero on most machines. */
#define FUNCTION_START_OFFSET 0
/* Advance PC across any function entry prologue instructions
to reach some "real" code. */
#define SKIP_PROLOGUE(pc) \
{ register unsigned char op = read_memory_integer (pc, 1); \
if (op == 0x82) { op = read_memory_integer (pc+2,1); \
if ((op & 0x80) == 0) pc += 3; \
else if ((op & 0xc0) == 0x80) pc += 4; \
else pc += 6; \
} \
}
/* Immediately after a function call, return the saved pc.
Can't always go through the frames for this because on some machines
the new frame is not set up until the new function executes
some instructions. */
#define SAVED_PC_AFTER_CALL(frame) \
read_memory_integer (read_register (SP_REGNUM), 4)
/* Address of end of stack space. */
#define STACK_END_ADDR (0xfffff000)
/* Stack grows downward. */
#define INNER_THAN <
/* Sequence of bytes for breakpoint instruction. */
#define BREAKPOINT {0xf2}
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
#define DECR_PC_AFTER_BREAK 0
/* Nonzero if instruction at PC is a return instruction. */
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0x12)
#ifndef NaN
#include <nan.h>
#endif NaN
/* Return 1 if P points to an invalid floating point value. */
#define INVALID_FLOAT(p, s) \
((s == sizeof (float))? \
NaF (*(float *) p) : \
NaD (*(double *) p))
/* Say how long (ordinary) registers are. */
#define REGISTER_TYPE long
/* Number of machine registers */
#define NUM_REGS 25
#define NUM_GENERAL_REGS 8
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
"sp", "fp", "pc", "ps", \
"fsr", \
"l0", "l1", "l2", "l3", "xx", \
}
/* Register numbers of various important registers.
Note that some of these values are "real" register numbers,
and correspond to the general registers of the machine,
and some are "phony" register numbers which are too large
to be actual register numbers as far as the user is concerned
but do serve to get the desired values when passed to read_register. */
#define FP0_REGNUM 8 /* Floating point register 0 */
#define SP_REGNUM 16 /* Contains address of top of stack */
#define AP_REGNUM FP_REGNUM
#define FP_REGNUM 17 /* Contains address of executing stack frame */
#define PC_REGNUM 18 /* Contains program counter */
#define PS_REGNUM 19 /* Contains processor status */
#define FPS_REGNUM 20 /* Floating point status register */
#define LP0_REGNUM 21 /* Double register 0 (same as FP0) */
/* called from register_addr() -- blockend not used for now */
#define REGISTER_U_ADDR(addr, blockend, regno) \
{ \
switch (regno) { \
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: \
addr = PU_R0 - (regno * sizeof (int)); break; \
case SP_REGNUM: \
addr = PU_SP; break; \
case PC_REGNUM: \
addr = PU_PC; break; \
case FP_REGNUM: \
addr = PU_FP; break; \
case PS_REGNUM: \
addr = PU_PSL; break; \
case FPS_REGNUM: \
addr = PU_FSR; break; \
case FP0_REGNUM + 0: case FP0_REGNUM + 1: \
case FP0_REGNUM + 2: case FP0_REGNUM + 3: \
case FP0_REGNUM + 4: case FP0_REGNUM + 5: \
case FP0_REGNUM + 6: case FP0_REGNUM + 7: \
addr = PU_F0 + (regno - FP0_REGNUM) * sizeof (float); break; \
case LP0_REGNUM + 0: case LP0_REGNUM + 1: \
case LP0_REGNUM + 2: case LP0_REGNUM + 3: \
addr = PU_F0 + (regno - LP0_REGNUM) * sizeof (double); break; \
default: \
printf ("bad argument to REGISTER_U_ADDR %d\n", regno); \
abort (); \
} \
}
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES ((NUM_REGS - 4) * sizeof (int) + 4 * sizeof (double))
/* Index within `registers' of the first byte of the space for
register N. */
#define REGISTER_BYTE(N) ((N) >= LP0_REGNUM ? \
LP0_REGNUM * 4 + ((N) - LP0_REGNUM) * 8 : (N) * 4)
/* Number of bytes of storage in the actual machine representation
for register N. On the 32000, all regs are 4 bytes
except for the doubled floating registers. */
#define REGISTER_RAW_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
/* Number of bytes of storage in the program's representation
for register N. On the 32000, all regs are 4 bytes
except for the doubled floating registers. */
#define REGISTER_VIRTUAL_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
/* Largest value REGISTER_RAW_SIZE can have. */
#define MAX_REGISTER_RAW_SIZE 8
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
#define MAX_REGISTER_VIRTUAL_SIZE 8
/* Nonzero if register N requires conversion
from raw format to virtual format. */
#define REGISTER_CONVERTIBLE(N) 0
/* Convert data from raw format for register REGNUM
to virtual format for register REGNUM. */
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
/* Convert data from virtual format for register REGNUM
to raw format for register REGNUM. */
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
/* Return the GDB type object for the "standard" data type
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) \
(((N) < FP0_REGNUM) ? \
builtin_type_int : \
((N) < FP0_REGNUM + 8) ? \
builtin_type_float : \
((N) < LP0_REGNUM) ? \
builtin_type_int : \
builtin_type_double)
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
into VALBUF. */
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
bcopy (REGBUF+REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 0), VALBUF, TYPE_LENGTH (TYPE))
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
write_register_bytes (REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 0), VALBUF, TYPE_LENGTH (TYPE))
/* Extract from an array REGBUF containing the (raw) register state
the address in which a function should return its structure value,
as a CORE_ADDR (or an expression that can be used as one). */
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
/* FRAME_CHAIN takes a frame's nominal address
and produces the frame's chain-pointer.
FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
and produces the nominal address of the caller frame.
However, if FRAME_CHAIN_VALID returns zero,
it means the given frame is the outermost one and has no caller.
In that case, FRAME_CHAIN_COMBINE is not used. */
/* In the case of the ns32000 series, the frame's nominal address is the FP
value, and at that address is saved previous FP value as a 4-byte word. */
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
#define FRAME_SAVED_PC(frame) (read_memory_integer (frame + 4, 4))
/* Compute base of arguments. */
#define FRAME_ARGS_ADDRESS(fi) \
((n32k_get_enter_addr (fi.pc) > 1) ? \
((fi).frame) : (read_register (SP_REGNUM) - 4))
#define FRAME_LOCALS_ADDRESS(fi) ((fi).frame)
/* Get the address of the enter opcode for this function, if it is active.
Returns positive address > 1 if pc is between enter/exit,
1 if pc before enter or after exit, 0 otherwise. */
extern CORE_ADDR n32k_get_enter_addr ();
/* Return number of args passed to a frame.
Can return -1, meaning no way to tell.
Encore's C compiler often reuses same area on stack for args,
so this will often not work properly. If the arg names
are known, it's likely most of them will be printed. */
#define FRAME_NUM_ARGS(numargs, fi) \
{ CORE_ADDR pc; \
CORE_ADDR enter_addr; \
unsigned int insn; \
unsigned int addr_mode; \
int width; \
\
numargs = -1; \
enter_addr = n32k_get_enter_addr (fi.pc); \
if (enter_addr > 0) \
{ \
pc = (enter_addr == 1) ? \
SAVED_PC_AFTER_CALL () : \
FRAME_SAVED_PC (fi.frame); \
insn = read_memory_integer (pc,2); \
addr_mode = (insn >> 11) & 0x1f; \
insn = insn & 0x7ff; \
if ((insn & 0x7fc) == 0x57c && \
addr_mode == 0x14) /* immediate */ \
{ \
if (insn == 0x57c) /* adjspb */ \
width = 1; \
else if (insn == 0x57d) /* adjspw */ \
width = 2; \
else if (insn == 0x57f) /* adjspd */ \
width = 4; \
numargs = read_memory_integer (pc+2,width); \
if (width > 1) \
flip_bytes (&numargs, width); \
numargs = - sign_extend (numargs, width*8) / 4;\
} \
} \
}
/* Return number of bytes at start of arglist that are not really args. */
#define FRAME_ARGS_SKIP 8
/* Put here the code to store, into a struct frame_saved_regs,
the addresses of the saved registers of frame described by FRAME_INFO.
This includes special registers such as pc and fp saved in special
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame. */
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
{ \
register int regmask, regnum; \
int localcount; \
register CORE_ADDR enter_addr; \
register CORE_ADDR next_addr; \
\
bzero (&(frame_saved_regs), sizeof (frame_saved_regs)); \
enter_addr = n32k_get_enter_addr ((frame_info).pc); \
if (enter_addr > 1) \
{ \
regmask = read_memory_integer (enter_addr+1, 1) & 0xff; \
localcount = n32k_localcount (enter_addr); \
next_addr = (frame_info).frame + localcount; \
for (regnum = 0; regnum < 8; regnum++, regmask >>= 1) \
(frame_saved_regs).regs[regnum] = (regmask & 1) ? \
(next_addr -= 4) : 0; \
(frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 4;\
(frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4;\
(frame_saved_regs).regs[FP_REGNUM] = \
(read_memory_integer ((frame_info).frame, 4));\
} \
else if (enter_addr == 1) \
{ \
CORE_ADDR sp = read_register (SP_REGNUM); \
(frame_saved_regs).regs[PC_REGNUM] = sp; \
(frame_saved_regs).regs[SP_REGNUM] = sp + 4; \
} \
}
/* Things needed for making the inferior call functions. */
/* Push an empty stack frame, to record the current PC, etc. */
#define PUSH_DUMMY_FRAME \
{ register CORE_ADDR sp = read_register (SP_REGNUM);\
register int regnum; \
sp = push_word (sp, read_register (PC_REGNUM)); \
sp = push_word (sp, read_register (FP_REGNUM)); \
write_register (FP_REGNUM, sp); \
for (regnum = 0; regnum < 8; regnum++) \
sp = push_word (sp, read_register (regnum)); \
write_register (SP_REGNUM, sp); \
}
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME \
{ register CORE_ADDR fp = read_register (FP_REGNUM); \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info fi; \
fi = get_frame_info (fp); \
get_frame_saved_regs (&fi, &fsr); \
for (regnum = 0; regnum < 8; regnum++) \
if (fsr.regs[regnum]) \
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
write_register (SP_REGNUM, fp + 8); \
}
/* This sequence of words is the instructions
enter 0xff,0 82 ff 00
jsr @0x00010203 7f ae c0 01 02 03
adjspd 0x69696969 7f a5 01 02 03 04
bpt f2
Note this is 16 bytes. */
#define CALL_DUMMY { 0x7f00ff82, 0x0201c0ae, 0x01a57f03, 0xf2040302 }
#define CALL_DUMMY_START_OFFSET 3
#define CALL_DUMMY_LENGTH 16
#define CALL_DUMMY_ADDR 5
#define CALL_DUMMY_NARGS 11
/* Insert the specified number of args and function address
into a call sequence of the above form stored at DUMMYNAME. */
#define FIX_CALL_DUMMY(dummyname, fun, nargs) \
{ \
int flipped; \
flipped = fun | 0xc0000000; \
flip_bytes (&flipped, 4); \
*((int *) (((char *) dummyname)+CALL_DUMMY_ADDR)) = flipped; \
flipped = - nargs * 4; \
flip_bytes (&flipped, 4); \
*((int *) (((char *) dummyname)+CALL_DUMMY_NARGS)) = flipped; \
}

View File

@ -345,7 +345,7 @@ print_insn_arg (d, buffer, p, addr, stream)
case 'd':
val = NEXTWORD (p);
fprintf (stream, "%d(%s)", val, fetch_arg (buffer, place, 3));
fprintf (stream, "%d(%s)", val, reg_names[fetch_arg (buffer, place, 3)]);
break;
case 's':
@ -710,20 +710,6 @@ print_base (regno, disp, stream)
FROM is the address of the extended float.
Store the double in *TO. */
#ifdef mac_aux
#ifdef __STDC__
#define asm16(str) asm ("short " str#)
#else
#define asm16(str) asm ("short str")
#endif
#else
#ifdef __STDC__
#define asm16(str) asm (".word " str#)
#else
#define asm16(str) asm (".word str")
#endif
#endif
convert_from_68881 (from, to)
char *from;
double *to;
@ -736,14 +722,12 @@ convert_from_68881 (from, to)
#else
/* Hand-assemble those insns since some assemblers lose
and some have different syntax. */
asm16 (020156);
asm16 (8);
asm16 (021156);
asm16 (12);
asm16 (0xf210);
asm16 (0x4800);
asm16 (0xf211);
asm16 (0x7400);
asm (".word 020156");
asm (".word 8");
asm (".word 021156");
asm (".word 12");
asm (".long 0xf2104800");
asm (".long 0xf2117400");
#endif
}
@ -761,13 +745,11 @@ convert_to_68881 (from, to)
asm ("fmovex fp0,a1@");
#else
/* Hand-assemble those insns since some assemblers lose. */
asm16 (020156);
asm16 (8);
asm16 (021156);
asm16 (12);
asm16 (0xf210);
asm16 (0x5400);
asm16 (0xf211);
asm16 (0x6800);
asm (".word 020156");
asm (".word 8");
asm (".word 021156");
asm (".word 12");
asm (".long 0xf2105400");
asm (".long 0xf2116800");
#endif
}

View File

@ -18,7 +18,6 @@ In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include <sys/types.h>
#include <sys/file.h>
#include <stdio.h>
#include <setjmp.h>
@ -49,6 +48,13 @@ struct cmd_list_element *infolist;
FILE *instream;
/* Current working directory. */
char *current_directory;
/* The directory name is actually stored here. */
static char dirbuf[MAXPATHLEN];
/* Nonzero if we should refrain from using an X window. */
int inhibit_windows = 0;
@ -59,6 +65,8 @@ int inhibit_windows = 0;
void (*window_hook) ();
extern int frame_file_full_name;
void free_command_lines ();
char *read_line ();
static void initialize_main ();
@ -106,6 +114,9 @@ main (argc, argv, envp)
line = (char *) xmalloc (linesize);
instream = stdin;
getwd (dirbuf);
current_directory = dirbuf;
#ifdef SET_STACK_LIMIT_HUGE
{
struct rlimit rlim;
@ -118,6 +129,8 @@ main (argc, argv, envp)
}
#endif /* SET_STACK_LIMIT_HUGE */
/* Run the init function of each source file */
/* Look for flag arguments. */
for (i = 1; i < argc; i++)
@ -128,6 +141,8 @@ main (argc, argv, envp)
inhibit_gdbinit = 1;
else if (!strcmp (argv[i], "-nw"))
inhibit_windows = 1;
else if (!strcmp (argv[i], "-fullname"))
frame_file_full_name = 1;
else if (!strcmp (argv[i], "-batch"))
batch = 1, quiet = 1;
else if (argv[i][0] == '-')
@ -160,7 +175,8 @@ main (argc, argv, envp)
extern void tty_command ();
if (!strcmp (arg, "-q") || !strcmp (arg, "-nx")
|| !strcmp (arg, "quiet") || !strcmp (arg, "-batch"))
|| !strcmp (arg, "-quiet") || !strcmp (arg, "-batch")
|| !strcmp (arg, "-fullname"))
/* Already processed above */
continue;
@ -369,6 +385,10 @@ read_line (repeat)
c = fgetc (instream);
if (c == -1 || c == '\n')
break;
else if (c == '\\')
if ((c = fgetc (instream)) == '\n')
continue;
else ungetc (c, instream);
if (p - line == linesize - 1)
{
linesize *= 2;
@ -378,7 +398,6 @@ read_line (repeat)
}
*p++ = c;
}
signal (SIGTSTP, SIG_DFL);
immediate_quit--;
@ -649,10 +668,12 @@ copying_info ()
{
immediate_quit++;
printf (" GDB GENERAL PUBLIC LICENSE\n\
\n (Clarified 11 Feb 1988)\
\n\
Copyright (C) 1986 Richard M. Stallman\n\
Copyright (C) 1988 Richard M. Stallman\n\
Everyone is permitted to copy and distribute verbatim copies\n\
of this license, but changing it is not allowed.\n\
You can also use this wording to make the terms for other programs.\n\
\n\
The license agreements of most software companies keep you at the\n\
mercy of those companies. By contrast, our general public license is\n\
@ -695,8 +716,8 @@ allowed to distribute or change GDB.\n\
1. You may copy and distribute verbatim copies of GDB source code as\n\
you receive it, in any medium, provided that you conspicuously and\n\
appropriately publish on each copy a valid copyright notice \"Copyright\n\
\(C) 1987 Free Software Foundation, Inc.\" (or with the year updated if\n\
that is appropriate); keep intact the notices on all files that refer\n\
\(C) 1988 Free Software Foundation, Inc.\" (or with whatever year is\n\
appropriate); keep intact the notices on all files that refer\n\
to this License Agreement and to the absence of any warranty; and give\n\
any other recipients of the GDB program a copy of this License\n\
Agreement along with the program. You may charge a distribution fee\n\
@ -717,48 +738,55 @@ Paragraph 1 above, provided that you also do the following:\n\
that in whole or in part contains or is a derivative of GDB\n\
or any part thereof, to be licensed to all third parties on terms\n\
identical to those contained in this License Agreement (except that\n\
you may choose to grant more extensive warranty protection to third\n\
parties, at your option).\n\
you may choose to grant more extensive warranty protection to some\n\
or all third parties, at your option).\n\
\n");
printf ("\
c) if the modified program serves as a debugger, cause it\n\
when started running in the simplest and usual way, to print\n\
an announcement including a valid copyright notice\n\
\"Copyright (C) 1987 Free Software Foundation, Inc.\" (or with\n\
the year updated if appropriate), saying that there\n\
is no warranty (or else, saying that you provide\n\
a warranty) and that users may redistribute the program under\n\
these conditions, and telling the user how to view a copy of\n\
this License Agreement.\n\
\"Copyright (C) 1988 Free Software Foundation, Inc.\" (or with\n\
the year that is appropriate), saying that there is no warranty\n\
(or else, saying that you provide a warranty) and that users may\n\
redistribute the program under these conditions, and telling the user\n\
how to view a copy of this License Agreement.\n\
\n\
d) You may charge a distribution fee for the physical act of\n\
transferring a copy, and you may at your option offer warranty\n\
protection in exchange for a fee.\n\
\n\
Mere aggregation of another unrelated program with this program (or its\n\
derivative) on a volume of a storage or distribution medium does not bring\n\
the other program under the scope of these terms.\n\
--Type Return to print more--");
fflush (stdout);
read_line ();
printf ("\
3. You may copy and distribute GDB or any portion of it in\n\
compiled, executable or object code form under the terms of Paragraphs\n\
1 and 2 above provided that you do the following:\n\
3. You may copy and distribute GDB (or a portion or derivative of it,\n\
under Paragraph 2) in object code or executable form under the terms of\n\
Paragraphs 1 and 2 above provided that you also do one of the following:\n\
\n\
a) cause each such copy to be accompanied by the\n\
corresponding machine-readable source code, which must\n\
be distributed under the terms of Paragraphs 1 and 2 above; or,\n\
a) accompany it with the complete corresponding machine-readable\n\
source code, which must be distributed under the terms of\n\
Paragraphs 1 and 2 above; or,\n\
\n\
b) cause each such copy to be accompanied by a\n\
written offer, with no time limit, to give any third party\n\
free (except for a nominal shipping charge) a machine readable\n\
copy of the corresponding source code, to be distributed\n\
under the terms of Paragraphs 1 and 2 above; or,\n\n");
b) accompany it with a written offer, valid for at least three\n\
years, to give any third party free (except for a nominal\n\
shipping charge) a complete machine-readable copy of the\n\
corresponding source code, to be distributed under the terms of\n\
Paragraphs 1 and 2 above; or,\n\n");
printf ("\
c) in the case of a recipient of GDB in compiled, executable\n\
or object code form (without the corresponding source code) you\n\
shall cause copies you distribute to be accompanied by a copy\n\
of the written offer of source code which you received along\n\
with the copy you received.\n\
c) accompany it with the information you received as to where the\n\
corresponding source code may be obtained. (This alternative is\n\
allowed only for noncommercial distribution and only if you\n\
received the program in object code or executable form alone.)\n\
\n\
For an executable file, complete source code means all the source code for\n\
all modules it contains; but, as a special exception, it need not include\n\
source code for modules which are standard libraries that accompany the\n\
operating system on which the executable file runs.\n\
--Type Return to print more--");
fflush (stdout);
read_line ();
@ -819,7 +847,7 @@ ANY CLAIM BY ANY OTHER PARTY.\n");
static void
print_gdb_version ()
{
printf ("GDB %s, Copyright (C) 1987 Free Software Foundation, Inc.\n\
printf ("GDB %s, Copyright (C) 1988 Free Software Foundation, Inc.\n\
There is ABSOLUTELY NO WARRANTY for GDB; type \"info warranty\" for details.\n\
GDB is free software and you are welcome to distribute copies of it\n\
under certain conditions; type \"info copying\" to see the conditions.\n",
@ -901,9 +929,8 @@ pwd_command (arg, from_tty)
char *arg;
int from_tty;
{
char buf[MAXPATHLEN];
if (arg) error ("The \"pwd\" command does not take an argument: %s", arg);
printf ("Working directory %s.\n", getwd (buf));
printf ("Working directory %s.\n", dirbuf);
}
static void
@ -916,6 +943,7 @@ cd_command (dir, from_tty)
if (chdir (dir) < 0)
perror_with_name (dir);
getwd (dirbuf);
if (from_tty)
pwd_command ((char *) 0, 1);
}
@ -996,7 +1024,7 @@ dump_me_command ()
static void
initialize_main ()
{
prompt = savestring ("(gdb) ", 6);
prompt = savestring ("(gdb+) ", 7);
/* Define the classes of commands.
They will appear in the help list in the reverse of this order. */

View File

@ -1,307 +0,0 @@
/* ns32k-opcode.h */
#ifndef ns32k_opcodeT
#define ns32k_opcodeT int
#endif /* no ns32k_opcodeT */
struct not_wot /* ns32k opcode table: wot to do with this */
/* particular opcode */
{
int obits; /* number of opcode bits */
int ibits; /* number of instruction bits */
ns32k_opcodeT code; /* op-code (may be > 8 bits!) */
char *args; /* how to compile said opcode */
};
struct not /* ns32k opcode text */
{
char * name; /* opcode name: lowercase string [key] */
struct not_wot detail; /* rest of opcode table [datum] */
};
/* F : 32 bit float
* L : 64 bit float
* B : byte
* W : word
* D : double-word
* Q : quad-word
* d : displacement
* q : quick
* i : immediate (8 bits)
* r : register number (3 bits)
* p : displacement - pc relative addressing
*/
static struct not
notstrs[] =
{
{ "absf", 14,24, 0x35be, "1F2F" },
{ "absl", 14,24, 0x34be, "1L2L" },
{ "absb", 14,24, 0x304e, "1B2B" },
{ "absw", 14,24, 0x314e, "1W2W" },
{ "absd", 14,24, 0x334e, "1D2D" },
{ "acbb", 7,16, 0x4c, "2B1q3p" },
{ "addf", 14,24, 0x01be, "1F2F" },
{ "addl", 14,24, 0x00be, "1L2L" },
{ "addb", 6,16, 0x00, "1B2B" },
{ "addw", 6,16, 0x01, "1W2W" },
{ "addd", 6,16, 0x03, "1D2D" },
{ "addcb", 6,16, 0x10, "1B2B" },
{ "addcw", 6,16, 0x11, "1W2W" },
{ "addcd", 6,16, 0x13, "1D2D" },
{ "addpb", 14,24, 0x3c4e, "1B2B" },
{ "addpw", 14,24, 0x3d4e, "1W2W" },
{ "addpd", 14,24, 0x3f4e, "1D2D" },
{ "addqb", 7,16, 0x0c, "2B1q" },
{ "addqw", 7,16, 0x0d, "2W1q" },
{ "addqd", 7,16, 0x0f, "2D1q" },
{ "addr", 6,16, 0x27, "1D2D" },
{ "adjspb", 11,16, 0x057c, "1B" },
{ "adjspw", 11,16, 0x057d, "1W" },
{ "adjspd", 11,16, 0x057f, "1D" },
{ "andb", 6,16, 0x28, "1B2B" },
{ "andw", 6,16, 0x29, "1W2W" },
{ "andd", 6,16, 0x2b, "1D2D" },
{ "ashb", 14,24, 0x044e, "1B2B" },
{ "ashw", 14,24, 0x054e, "1B2W" },
{ "ashd", 14,24, 0x074e, "1B2D" },
{ "beq", 8,8, 0x0a, "1p" },
{ "bne", 8,8, 0x1a, "1p" },
{ "bcs", 8,8, 0x2a, "1p" },
{ "bcc", 8,8, 0x3a, "1p" },
{ "bhi", 8,8, 0x4a, "1p" },
{ "bls", 8,8, 0x5a, "1p" },
{ "bgt", 8,8, 0x6a, "1p" },
{ "ble", 8,8, 0x7a, "1p" },
{ "bfs", 8,8, 0x8a, "1p" },
{ "bfc", 8,8, 0x9a, "1p" },
{ "blo", 8,8, 0xaa, "1p" },
{ "bhs", 8,8, 0xba, "1p" },
{ "blt", 8,8, 0xca, "1p" },
{ "bge", 8,8, 0xda, "1p" },
{ "bicb", 6,16, 0x08, "1B2B" },
{ "bicw", 6,16, 0x09, "1W2W" },
{ "bicd", 6,16, 0x0b, "1D2D" },
{ "bicpsrb", 11,16, 0x17c, "1B" },
{ "bicpsrw", 11,16, 0x17d, "1W" },
{ "bispsrb", 11,16, 0x37c, "1B" },
{ "bispsrw", 11,16, 0x37d, "1W" },
{ "bpt", 8,8, 0xf2, "" },
{ "br", 8,8, 0xea, "1p" },
{ "bsr", 8,8, 0x02, "1p" },
{ "caseb", 11,16, 0x77c, "1B" },
{ "casew", 11,16, 0x77d, "1W" },
{ "cased", 11,16, 0x77f, "1D" },
{ "cbitb", 14,24, 0x084e, "1B2D" },
{ "cbitw", 14,24, 0x094e, "1W2D" },
{ "cbitd", 14,24, 0x0b4e, "1D2D" },
{ "cbitib", 14,24, 0x0c4e, "1B2D" },
{ "cbitiw", 14,24, 0x0d4e, "1W2D" },
{ "cbitid", 14,24, 0x0f4e, "1D2D" },
{ "checkb", 11,24, 0x0ee, "2A3B1r" },
{ "checkw", 11,24, 0x1ee, "2A3B1r" },
{ "checkd", 11,24, 0x3ee, "2A3D1r" },
{ "cmpf", 14,24, 0x09be, "1F2F" },
{ "cmpl", 14,24, 0x08be, "1L2L" },
{ "cmpb", 6,16, 0x04, "1B2B" },
{ "cmpw", 6,16, 0x05, "1W2W" },
{ "cmpd", 6,16, 0x07, "1D2D" },
{ "cmpmb", 14,24, 0x04ce, "1D2D3d" },
{ "cmpmw", 14,24, 0x05ce, "1D2D3d" },
{ "cmpmd", 14,24, 0x07ce, "1D2D3d" },
{ "cmpqb", 7,16, 0x1c, "2B1q" },
{ "cmpqw", 7,16, 0x1d, "2W1q" },
{ "cmpqd", 7,16, 0x1f, "2D1q" },
{ "cmpsb", 16,16, 0x040e, "1i" },
{ "cmpsw", 16,16, 0x050e, "1i" },
{ "cmpsd", 16,16, 0x070e, "1i" },
{ "cmpst", 16,16, 0x840e, "1i" },
{ "comb", 14,24, 0x344e, "1B2B" },
{ "comw", 14,24, 0x354e, "1W2W" },
{ "comd", 14,24, 0x374e, "1D2D" },
{ "cvtp", 11,24, 0x036e, "2D3D1r" },
{ "cxp", 8,8, 0x22, "1p" },
{ "cxpd", 11,16, 0x07f, "1D" },
{ "deib", 14,24, 0x2cce, "1B2W" },
{ "deiw", 14,24, 0x2cce, "1W2D" },
{ "deid", 14,24, 0x2cce, "1D2Q" },
{ "dia", 8,8, 0xc2, "" },
{ "divf", 14,24, 0x21be, "1F2F" },
{ "divl", 14,24, 0x20be, "1L2L" },
{ "divb", 14,24, 0x3cce, "1B2B" },
{ "divw", 14,24, 0x3dce, "1W2W" },
{ "divd", 14,24, 0x3fce, "1D2D" },
{ "enter", 8,8, 0x82, "1i2d" },
{ "exit", 8,8, 0x92, "1i" },
{ "extb", 11,24, 0x02e, "2D3B1r4d" },
{ "extw", 11,24, 0x12e, "2D3W1r4d" },
{ "extd", 11,24, 0x32e, "2D3D1r4d" },
{ "extsb", 14,24, 0x0cce, "1D2B3i" },
{ "extsw", 14,24, 0x0dce, "1D2W3i" },
{ "extsd", 14,24, 0x0fce, "1D2D3i" },
{ "ffsb", 14,24, 0x046e, "1B2B" },
{ "ffsw", 14,24, 0x056e, "1W2B" },
{ "ffsd", 14,24, 0x076e, "1D2B" },
{ "flag", 8,8, 0xd2, "" },
{ "floorfb", 14,24, 0x3c3e, "1F2B" },
{ "floorfw", 14,24, 0x3d3e, "1F2W" },
{ "floorfd", 14,24, 0x3f3e, "1F2D" },
{ "floorlb", 14,24, 0x383e, "1L2B" },
{ "floorlw", 14,24, 0x393e, "1L2W" },
{ "floorld", 14,24, 0x3b3e, "1L2D" },
{ "ibitb", 14,24, 0x384e, "1B2D" },
{ "ibitw", 14,24, 0x394e, "1W2D" },
{ "ibitd", 14,24, 0x3b4e, "1D2D" },
{ "indexb", 11,24, 0x42e, "2B3B1r" },
{ "indexw", 11,24, 0x52e, "2W3W1r" },
{ "indexd", 11,24, 0x72e, "2D3D1r" },
{ "insb", 11,24, 0x0ae, "2B3B1r4d" },
{ "insw", 11,24, 0x1ae, "2W3W1r4d" },
{ "insd", 11,24, 0x3ae, "2D3D1r4d" },
{ "inssb", 14,24, 0x08ce, "1B2D3i" },
{ "inssw", 14,24, 0x09ce, "1W2D3i" },
{ "inssd", 14,24, 0x0bce, "1D2D3i" },
{ "jsr", 11,16, 0x67f, "1A" },
{ "jump", 11,16, 0x27f, "1A" },
{ "lfsr", 19,24, 0x00f3e,"1D" },
{ "lmr", 15,24, 0x0b1e, "2D1q" },
{ "lprb", 7,16, 0x6c, "2B1q" },
{ "lprw", 7,16, 0x6d, "2W1q" },
{ "lprd", 7,16, 0x6f, "2D1q" },
{ "lshb", 14,24, 0x144e, "1B2B" },
{ "lshw", 14,24, 0x154e, "1B2W" },
{ "lshd", 14,24, 0x174e, "1B2D" },
{ "meib", 14,24, 0x24ce, "1B2W" },
{ "meiw", 14,24, 0x25ce, "1W2D" },
{ "meid", 14,24, 0x27ce, "1D2Q" },
{ "modb", 14,24, 0x38ce, "1B2B" },
{ "modw", 14,24, 0x39ce, "1W2W" },
{ "modd", 14,24, 0x3bce, "1D2D" },
{ "movf", 14,24, 0x05be, "1F2F" },
{ "movl", 14,24, 0x04be, "1L2L" },
{ "movb", 6,16, 0x14, "1B2B" },
{ "movw", 6,16, 0x15, "1W2W" },
{ "movd", 6,16, 0x17, "1D2D" },
{ "movbf", 14,24, 0x043e, "1B2F" },
{ "movwf", 14,24, 0x053e, "1W2F" },
{ "movdf", 14,24, 0x073e, "1D2F" },
{ "movbl", 14,24, 0x003e, "1B2L" },
{ "movwl", 14,24, 0x013e, "1W2L" },
{ "movdl", 14,24, 0x033e, "1D2L" },
{ "movfl", 14,24, 0x1b3e, "1F2L" },
{ "movlf", 14,24, 0x163e, "1L2F" },
{ "movmb", 14,24, 0x00ce, "1D2D3d" },
{ "movmw", 14,24, 0x00de, "1D2D3d" },
{ "movmd", 14,24, 0x00fe, "1D2D3d" },
{ "movqb", 7,16, 0x5c, "2B1q" },
{ "movqw", 7,16, 0x5d, "2B1q" },
{ "movqd", 7,16, 0x5f, "2B1q" },
{ "movsb", 16,16, 0x000e, "1i" },
{ "movsw", 16,16, 0x010e, "1i" },
{ "movsd", 16,16, 0x030e, "1i" },
{ "movst", 16,16, 0x800e, "1i" },
{ "movsub", 14,24, 0x0cae, "1A1A" },
{ "movsuw", 14,24, 0x0dae, "1A1A" },
{ "movsud", 14,24, 0x0fae, "1A1A" },
{ "movusb", 14,24, 0x1cae, "1A1A" },
{ "movusw", 14,24, 0x1dae, "1A1A" },
{ "movusd", 14,24, 0x1fae, "1A1A" },
{ "movxbd", 14,24, 0x1cce, "1B2D" },
{ "movxwd", 14,24, 0x1dce, "1W2D" },
{ "movxbw", 14,24, 0x10ce, "1B2W" },
{ "movzbd", 14,24, 0x18ce, "1B2D" },
{ "movzwd", 14,24, 0x19ce, "1W2D" },
{ "movzbw", 14,24, 0x14ce, "1B2W" },
{ "mulf", 14,24, 0x31be, "1F2F" },
{ "mull", 14,24, 0x30be, "1L2L" },
{ "mulb", 14,24, 0x20ce, "1B2B" },
{ "mulw", 14,24, 0x21ce, "1W2W" },
{ "muld", 14,24, 0x23ce, "1D2D" },
{ "negf", 14,24, 0x15be, "1F2F" },
{ "negl", 14,24, 0x14be, "1L2L" },
{ "negb", 14,24, 0x204e, "1B2B" },
{ "negw", 14,24, 0x214e, "1W2W" },
{ "negd", 14,24, 0x234e, "1D2D" },
{ "nop", 8,8, 0xa2, "" },
{ "notb", 14,24, 0x244e, "1B2B" },
{ "notw", 14,24, 0x254e, "1W2W" },
{ "notd", 14,24, 0x274e, "1D2D" },
{ "orb", 6,16, 0x18, "1B1B" },
{ "orw", 6,16, 0x19, "1W1W" },
{ "ord", 6,16, 0x1b, "1D1D" },
{ "quob", 14,24, 0x30ce, "1B2B" },
{ "quow", 14,24, 0x31ce, "1W2W" },
{ "quod", 14,24, 0x33ce, "1D2D" },
{ "rdval", 19,24, 0x0031e,"1A" },
{ "remb", 14,24, 0x34ce, "1B2B" },
{ "remw", 14,24, 0x35ce, "1W2W" },
{ "remd", 14,24, 0x37ce, "1D2D" },
{ "restore", 8,8, 0x72, "1i" },
{ "ret", 8,8, 0x12, "1d" },
{ "reti", 8,8, 0x52, "" },
{ "rett", 8,8, 0x42, "" },
{ "rotb", 14,24, 0x004e, "1B2B" },
{ "rotw", 14,24, 0x014e, "1B2W" },
{ "rotd", 14,24, 0x034e, "1B2D" },
{ "roundfb", 14,24, 0x243e, "1F2B" },
{ "roundfw", 14,24, 0x253e, "1F2W" },
{ "roundfd", 14,24, 0x273e, "1F2D" },
{ "roundlb", 14,24, 0x203e, "1L2B" },
{ "roundlw", 14,24, 0x213e, "1L2W" },
{ "roundld", 14,24, 0x233e, "1L2D" },
{ "rxp", 8,8, 0x32, "1d" },
{ "sCONDb", 7,16, 0x3c, "2B1q" },
{ "sCONDw", 7,16, 0x3d, "2D1q" },
{ "sCONDd", 7,16, 0x3f, "2D1q" },
{ "save", 8,8, 0x62, "1i" },
{ "sbitb", 14,24, 0x184e, "1B2A" },
{ "sbitw", 14,24, 0x194e, "1W2A" },
{ "sbitd", 14,24, 0x1b4e, "1D2A" },
{ "sbitib", 14,24, 0x1c4e, "1B2A" },
{ "sbitiw", 14,24, 0x1d4e, "1W2A" },
{ "sbitid", 14,24, 0x1f4e, "1D2A" },
{ "setcfg", 15,24, 0x0b0e, "5D1q" },
{ "sfsr", 14,24, 0x673e, "5D1D" },
{ "skpsb", 16,16, 0x0c0e, "1i" },
{ "skpsw", 16,16, 0x0d0e, "1i" },
{ "skpsd", 16,16, 0x0f0e, "1i" },
{ "skpst", 16,16, 0x8c0e, "1i" },
{ "smr", 15,24, 0x0f1e, "2D1q" },
{ "sprb", 7,16, 0x2c, "2B1q" },
{ "sprw", 7,16, 0x2d, "2W1q" },
{ "sprd", 7,16, 0x2f, "2D1q" },
{ "subf", 14,24, 0x11be, "1F2F" },
{ "subl", 14,24, 0x10be, "1L2L" },
{ "subb", 6,16, 0x20, "1B2B" },
{ "subw", 6,16, 0x21, "1W2W" },
{ "subd", 6,16, 0x23, "1D2D" },
{ "subcb", 6,16, 0x30, "1B2B" },
{ "subcw", 6,16, 0x31, "1W2W" },
{ "subcd", 6,16, 0x33, "1D2D" },
{ "subpb", 14,24, 0x2c4e, "1B2B" },
{ "subpw", 14,24, 0x2d4e, "1W2W" },
{ "subpd", 14,24, 0x2f4e, "1D2D" },
#ifndef NS32K_SVC_IMMED_OPERANDS
{ "svc", 8,8, 0xe2, "2i1i" }, /* not really, but unix uses it */
#else
{ "svc", 8,8, 0xe2, "" }, /* not really, but unix uses it */
#endif
{ "tbitb", 6,16, 0x34, "1B2A" },
{ "tbitw", 6,16, 0x35, "1W2A" },
{ "tbitd", 6,16, 0x37, "1D2A" },
{ "truncfb", 14,24, 0x2c3e, "1F2B" },
{ "truncfw", 14,24, 0x2d3e, "1F2W" },
{ "truncfd", 14,24, 0x2f3e, "1F2D" },
{ "trunclb", 14,24, 0x283e, "1L2B" },
{ "trunclw", 14,24, 0x293e, "1L2W" },
{ "truncld", 14,24, 0x2b3e, "1L2D" },
{ "wait", 8,8, 0xb2, "" },
{ "wrval", 19,24, 0x0071e,"1A" },
{ "xorb", 6,16, 0x38, "1B2B" },
{ "xorw", 6,16, 0x39, "1W2W" },
{ "xord", 6,16, 0x3b, "1D2D" },
}; /* notstrs */
/* end: ns32k.opcode.h */
#define MAX_ARGS 4
#define ARG_LEN 50

View File

@ -1,437 +0,0 @@
/* Print 32000 instructions for GDB, the GNU debugger.
Copyright (C) 1986 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include <stdio.h>
#include "defs.h"
#include "param.h"
#include "symtab.h"
#include "ns32k-opcode.h"
/* 32000 instructions are never longer than this. */
#define MAXLEN 62
/* Number of elements in the opcode table. */
#define NOPCODES (sizeof notstrs / sizeof notstrs[0])
extern char *reg_names[];
#define NEXT_IS_ADDR '|'
/*
* extract "count" bits starting "offset" bits
* into buffer
*/
int
bit_extract (buffer, offset, count)
char *buffer;
int offset;
int count;
{
int result;
int mask;
int bit;
buffer += offset >> 3;
offset &= 7;
bit = 1;
result = 0;
while (count--)
{
if ((*buffer & (1 << offset)))
result |= bit;
if (++offset == 8)
{
offset = 0;
buffer++;
}
bit <<= 1;
}
return result;
}
double
dbit_extract (buffer, offset, count)
{
union {
struct {int low, high; } ival;
double dval;
} foo;
foo.ival.low = bit_extract (buffer, offset, 32);
foo.ival.high = bit_extract (buffer, offset+32, 32);
return foo.dval;
}
sign_extend (value, bits)
{
value = value & ((1 << bits) - 1);
return (value & (1 << (bits-1))
? value | (~((1 << bits) - 1))
: value);
}
flip_bytes (ptr, count)
char *ptr;
int count;
{
char tmp;
while (count > 0)
{
tmp = *ptr;
ptr[0] = ptr[count-1];
ptr[count-1] = tmp;
ptr++;
count -= 2;
}
}
/* Print the 32000 instruction at address MEMADDR in debugged memory,
on STREAM. Returns length of the instruction, in bytes. */
int
print_insn (memaddr, stream)
CORE_ADDR memaddr;
FILE *stream;
{
unsigned char buffer[MAXLEN];
register int i;
register unsigned char *p;
register char *d;
unsigned short first_word;
int gen, disp;
int ioffset; /* bits into instruction */
int aoffset; /* bits into arguments */
char arg_bufs[MAX_ARGS+1][ARG_LEN];
int argnum;
int maxarg;
read_memory (memaddr, buffer, MAXLEN);
first_word = *(unsigned short *) buffer;
for (i = 0; i < NOPCODES; i++)
if ((first_word & ((1 << notstrs[i].detail.obits) - 1))
== notstrs[i].detail.code)
break;
/* Handle undefined instructions. */
if (i == NOPCODES)
{
fprintf (stream, "0%o", buffer[0]);
return 1;
}
fprintf (stream, "%s", notstrs[i].name);
ioffset = notstrs[i].detail.ibits;
aoffset = notstrs[i].detail.ibits;
d = notstrs[i].detail.args;
if (*d)
{
fputc ('\t', stream);
maxarg = 0;
while (*d)
{
argnum = *d - '1';
d++;
if (argnum > maxarg && argnum < MAX_ARGS)
maxarg = argnum;
ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
memaddr, arg_bufs[argnum]);
d++;
}
for (argnum = 0; argnum <= maxarg; argnum++)
{
CORE_ADDR addr;
char *ch, *index ();
for (ch = arg_bufs[argnum]; *ch;)
{
if (*ch == NEXT_IS_ADDR)
{
++ch;
addr = atoi (ch);
print_address (addr, stream);
while (*ch && *ch != NEXT_IS_ADDR)
++ch;
if (*ch)
++ch;
}
else
putc (*ch++, stream);
}
if (argnum < maxarg)
fprintf (stream, ", ");
}
}
return aoffset / 8;
}
print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result)
char d;
int ioffset, *aoffsetp;
char *buffer;
CORE_ADDR addr;
char *result;
{
int addr_mode;
float Fvalue;
double Lvalue;
int Ivalue;
int disp1, disp2;
int index;
switch (d)
{
case 'F':
case 'L':
case 'B':
case 'W':
case 'D':
case 'A':
addr_mode = bit_extract (buffer, ioffset-5, 5);
ioffset -= 5;
switch (addr_mode)
{
case 0x0: case 0x1: case 0x2: case 0x3:
case 0x4: case 0x5: case 0x6: case 0x7:
sprintf (result, "r%d", addr_mode);
break;
case 0x8: case 0x9: case 0xa: case 0xb:
case 0xc: case 0xd: case 0xe: case 0xf:
disp1 = get_displacement (buffer, aoffsetp);
sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
break;
case 0x10:
case 0x11:
case 0x12:
disp1 = get_displacement (buffer, aoffsetp);
disp2 = get_displacement (buffer, aoffsetp);
sprintf (result, "%d(%d(%s))", disp2, disp1,
addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
break;
case 0x13:
sprintf (result, "reserved");
break;
case 0x14:
switch (d)
{
case 'B':
Ivalue = bit_extract (buffer, *aoffsetp, 8);
Ivalue = sign_extend (Ivalue, 8);
*aoffsetp += 8;
sprintf (result, "$%d", Ivalue);
break;
case 'W':
Ivalue = bit_extract (buffer, *aoffsetp, 16);
flip_bytes (&Ivalue, 2);
*aoffsetp += 16;
Ivalue = sign_extend (Ivalue, 16);
sprintf (result, "$%d", Ivalue);
break;
case 'D':
Ivalue = bit_extract (buffer, *aoffsetp, 32);
flip_bytes (&Ivalue, 4);
*aoffsetp += 32;
sprintf (result, "$%d", Ivalue);
break;
case 'A':
Ivalue = bit_extract (buffer, *aoffsetp, 32);
flip_bytes (&Ivalue, 4);
*aoffsetp += 32;
sprintf (result, "$|%d|", Ivalue);
break;
case 'F':
Fvalue = (float) bit_extract (buffer, *aoffsetp, 32);
flip_bytes (&Fvalue, 4);
*aoffsetp += 32;
sprintf (result, "$%g", Fvalue);
break;
case 'L':
Lvalue = dbit_extract (buffer, *aoffsetp, 64);
flip_bytes (&Lvalue, 8);
*aoffsetp += 64;
sprintf (result, "$%g", Lvalue);
break;
}
break;
case 0x15:
disp1 = get_displacement (buffer, aoffsetp);
sprintf (result, "@|%d|", disp1);
break;
case 0x16:
disp1 = get_displacement (buffer, aoffsetp);
disp2 = get_displacement (buffer, aoffsetp);
sprintf (result, "EXT(%d) + %d", disp1, disp2);
break;
case 0x17:
sprintf (result, "tos");
break;
case 0x18:
disp1 = get_displacement (buffer, aoffsetp);
sprintf (result, "%d(fp)", disp1);
break;
case 0x19:
disp1 = get_displacement (buffer, aoffsetp);
sprintf (result, "%d(sp)", disp1);
break;
case 0x1a:
disp1 = get_displacement (buffer, aoffsetp);
sprintf (result, "%d(sb)", disp1);
break;
case 0x1b:
disp1 = get_displacement (buffer, aoffsetp);
sprintf (result, "|%d|", addr + disp1);
break;
case 0x1c:
case 0x1d:
case 0x1e:
case 0x1f:
index = bit_extract (buffer, *aoffsetp, 8);
*aoffsetp += 8;
print_insn_arg (d, *aoffsetp, aoffsetp, buffer, addr,
result);
{
static char *ind[] = {"b", "w", "d", "q"};
char *off;
off = result + strlen (result);
sprintf (off, "[r%d:%s]", index & 7,
ind[addr_mode & 3]);
}
break;
}
break;
case 'q':
Ivalue = bit_extract (buffer, ioffset-4, 4);
Ivalue = sign_extend (Ivalue, 4);
sprintf (result, "%d", Ivalue);
ioffset -= 4;
break;
case 'r':
Ivalue = bit_extract (buffer, ioffset-3, 3);
sprintf (result, "r%d", Ivalue&7);
ioffset -= 3;
break;
case 'd':
sprintf (result, "%d", get_displacement (buffer, aoffsetp));
break;
case 'p':
sprintf (result, "%c%d%c", NEXT_IS_ADDR,
addr + get_displacement (buffer, aoffsetp),
NEXT_IS_ADDR);
break;
case 'i':
Ivalue = bit_extract (buffer, *aoffsetp, 8);
*aoffsetp += 8;
sprintf (result, "0x%x", Ivalue);
break;
}
return ioffset;
}
get_displacement (buffer, aoffsetp)
char *buffer;
int *aoffsetp;
{
int Ivalue;
Ivalue = bit_extract (buffer, *aoffsetp, 8);
switch (Ivalue & 0xc0)
{
case 0x00:
case 0x40:
Ivalue = sign_extend (Ivalue, 7);
*aoffsetp += 8;
break;
case 0x80:
Ivalue = bit_extract (buffer, *aoffsetp, 16);
flip_bytes (&Ivalue, 2);
Ivalue = sign_extend (Ivalue, 14);
*aoffsetp += 16;
break;
case 0xc0:
Ivalue = bit_extract (buffer, *aoffsetp, 32);
flip_bytes (&Ivalue, 4);
Ivalue = sign_extend (Ivalue, 30);
*aoffsetp += 32;
break;
}
return Ivalue;
}
/* Return the number of locals in the current frame given a pc
pointing to the enter instruction. This is used in the macro
FRAME_FIND_SAVED_REGS. */
ns32k_localcount (enter_pc)
CORE_ADDR enter_pc;
{
unsigned char localtype;
int localcount;
localtype = read_memory_integer (enter_pc+2, 1);
if ((localtype & 0x80) == 0)
localcount = localtype;
else if ((localtype & 0xc0) == 0x80)
localcount = (((localtype & 0x3f) << 8)
| (read_memory_integer (enter_pc+3, 1) & 0xff));
else
localcount = (((localtype & 0x3f) << 24)
| ((read_memory_integer (enter_pc+3, 1) & 0xff) << 16)
| ((read_memory_integer (enter_pc+4, 1) & 0xff) << 8 )
| (read_memory_integer (enter_pc+5, 1) & 0xff));
return localcount;
}
/*
* Get the address of the enter opcode for the function
* containing PC, if there is an enter for the function,
* and if the pc is between the enter and exit.
* Returns positive address if pc is between enter/exit,
* 1 if pc before enter or after exit, 0 otherwise.
*/
CORE_ADDR
n32k_get_enter_addr (pc)
CORE_ADDR pc;
{
CORE_ADDR enter_addr;
unsigned char op;
if (ABOUT_TO_RETURN (pc))
return 1; /* after exit */
enter_addr = get_pc_function_start (pc);
if (pc == enter_addr)
return 1; /* before enter */
op = read_memory_integer (enter_addr, 1);
if (op != 0x82)
return 0; /* function has no enter/exit */
return enter_addr; /* pc is between enter and exit */
}

View File

@ -1 +0,0 @@
../gcc/gcc-1.22/obstack.c

324
gdb/obstack.c Normal file
View File

@ -0,0 +1,324 @@
/* obstack.c - subroutines used implicitly by object stack macros
Copyright (C) 1988 Free Software Foundation, Inc.
NO WARRANTY
BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
GENERAL PUBLIC LICENSE TO COPY
1. You may copy and distribute verbatim copies of this source file
as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy a valid copyright notice "Copyright
(C) 1988 Free Software Foundation, Inc."; and include following the
copyright notice a verbatim copy of the above disclaimer of warranty
and of this License. You may charge a distribution fee for the
physical act of transferring a copy.
2. You may modify your copy or copies of this source file or
any portion of it, and copy and distribute such modifications under
the terms of Paragraph 1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating
that you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish,
that in whole or in part contains or is a derivative of this
program or any part thereof, to be licensed at no charge to all
third parties on terms identical to those contained in this
License Agreement (except that you may choose to grant more extensive
warranty protection to some or all third parties, at your option).
c) You may charge a distribution fee for the physical act of
transferring a copy, and you may at your option offer warranty
protection in exchange for a fee.
Mere aggregation of another unrelated program with this program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other program under the scope of these terms.
3. You may copy and distribute this program (or a portion or derivative
of it, under Paragraph 2) in object code or executable form under the terms
of Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal
shipping charge) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
For an executable file, complete source code means all the source code for
all modules it contains; but, as a special exception, it need not include
source code for modules which are standard libraries that accompany the
operating system on which the executable file runs.
4. You may not copy, sublicense, distribute or transfer this program
except as expressly provided under this License Agreement. Any attempt
otherwise to copy, sublicense, distribute or transfer this program is void and
your rights to use the program under this License agreement shall be
automatically terminated. However, parties who have received computer
software programs from you with this License Agreement will not have
their licenses terminated so long as such parties remain in full compliance.
5. If you wish to incorporate parts of this program into other free
programs whose distribution conditions are different, write to the Free
Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet
worked out a simple rule that can be stated here, but we will often permit
this. We will be guided by the two goals of preserving the free status of
all derivatives our free software and of promoting the sharing and reuse of
software.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding! */
#include "obstack.h"
#ifdef __STDC__
#define POINTER void *
#else
#define POINTER char *
#endif
/* The non-GNU-C macros copy the obstack into this global variable
to avoid multiple evaluation. */
struct obstack *_obstack;
/* Initialize an obstack H for use. Specify chunk size SIZE.
Objects start on multiples of ALIGNMENT.
CHUNKFUN is the function to use to allocate chunks,
and FREEFUN the function to free them. */
void
_obstack_begin (h, size, alignment, chunkfun, freefun)
struct obstack *h;
int size;
int alignment;
POINTER (*chunkfun) ();
void (*freefun) ();
{
register struct _obstack_chunk* chunk; /* points to new chunk */
h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
h->freefun = freefun;
h->chunk_size = size;
h->alignment_mask = alignment - 1;
chunk = h->chunk = (*h->chunkfun) (h->chunk_size);
h->next_free = h->object_base = chunk->contents;
h->chunk_limit = chunk->limit
= (char *) chunk + h->chunk_size;
chunk->prev = 0;
}
/* Allocate a new current chunk for the obstack *H
on the assumption that LENGTH bytes need to be added
to the current object, or a new object of length LENGTH allocated.
Copies any partial object from the end of the old chunk
to the beginning of the new one. */
void
_obstack_newchunk (h, length)
struct obstack *h;
int length;
{
register struct _obstack_chunk* old_chunk = h->chunk;
register struct _obstack_chunk* new_chunk;
register long new_size;
register int obj_size = h->next_free - h->object_base;
register int i;
/* Compute size for new chunk. */
new_size = (obj_size + length) << 1;
if (new_size < h->chunk_size)
new_size = h->chunk_size;
/* Allocate and initialize the new chunk. */
new_chunk = h->chunk = (*h->chunkfun) (new_size);
new_chunk->prev = old_chunk;
new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
/* Move the existing object to the new chunk.
Word at a time is fast and is safe because these
structures are aligned at least that much. */
for (i = (obj_size + sizeof (int) - 1) / sizeof (int); i >= 0; i--)
((int *)new_chunk->contents)[i] = ((int *)h->object_base)[i];
h->object_base = new_chunk->contents;
h->next_free = h->object_base + obj_size;
}
/* Free objects in obstack H, including OBJ and everything allocate
more recently than OBJ. If OBJ is zero, free everything in H. */
void
#ifdef __STDC__
#undef obstack_free
obstack_free (h, obj)
#else
_obstack_free (h, obj)
#endif
struct obstack *h;
POINTER obj;
{
register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
register struct _obstack_chunk* plp; /* point to previous chunk if any */
lp = (h)->chunk;
while (lp != 0 && ((POINTER)lp > obj || (POINTER)(lp)->limit < obj))
{
plp = lp -> prev;
(*h->freefun) (lp);
lp = plp;
}
if (lp)
{
(h)->object_base = (h)->next_free = (char *)(obj);
(h)->chunk_limit = lp->limit;
(h)->chunk = lp;
}
else if (obj != 0)
/* obj is not in any of the chunks! */
abort ();
}
/* Now define the functional versions of the obstack macros.
Define them to simply use the corresponding macros to do the job. */
#ifdef __STDC__
/* These function definitions do not work with non-ANSI preprocessors;
they won't pass through the macro names in parentheses. */
/* The function names appear in parentheses in order to prevent
the macro-definitions of the names from being expanded there. */
POINTER (obstack_base) (obstack)
struct obstack *obstack;
{
return obstack_base (obstack);
}
POINTER (obstack_next_free) (obstack)
struct obstack *obstack;
{
return obstack_next_free (obstack);
}
int (obstack_object_size) (obstack)
struct obstack *obstack;
{
return obstack_object_size (obstack);
}
int (obstack_room) (obstack)
struct obstack *obstack;
{
return obstack_room (obstack);
}
void (obstack_grow) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
int length;
{
obstack_grow (obstack, pointer, length);
}
void (obstack_grow0) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
int length;
{
obstack_grow0 (obstack, pointer, length);
}
void (obstack_1grow) (obstack, character)
struct obstack *obstack;
int character;
{
obstack_1grow (obstack, character);
}
void (obstack_blank) (obstack, length)
struct obstack *obstack;
int length;
{
obstack_blank (obstack, length);
}
void (obstack_1grow_fast) (obstack, character)
struct obstack *obstack;
int character;
{
obstack_1grow_fast (obstack, character);
}
void (obstack_blank_fast) (obstack, length)
struct obstack *obstack;
int length;
{
obstack_blank_fast (obstack, length);
}
POINTER (obstack_finish) (obstack)
struct obstack *obstack;
{
return obstack_finish (obstack);
}
POINTER (obstack_alloc) (obstack, length)
struct obstack *obstack;
int length;
{
return obstack_alloc (obstack, length);
}
POINTER (obstack_copy) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
int length;
{
return obstack_copy (obstack, pointer, length);
}
POINTER (obstack_copy0) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
int length;
{
return obstack_copy0 (obstack, pointer, length);
}
#endif /* __STDC__ */

View File

@ -1 +0,0 @@
../gcc/gcc-1.19/obstack.h

443
gdb/obstack.h Normal file
View File

@ -0,0 +1,443 @@
/* obstack.h - object stack macros
Copyright (C) 1986, 1988 Free Software Foundation, Inc.
NO WARRANTY
BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
GENERAL PUBLIC LICENSE TO COPY
1. You may copy and distribute verbatim copies of this source file
as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy a valid copyright notice "Copyright
(C) 1988 Free Software Foundation, Inc."; and include following the
copyright notice a verbatim copy of the above disclaimer of warranty
and of this License. You may charge a distribution fee for the
physical act of transferring a copy.
2. You may modify your copy or copies of this source file or
any portion of it, and copy and distribute such modifications under
the terms of Paragraph 1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating
that you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish,
that in whole or in part contains or is a derivative of this
program or any part thereof, to be licensed at no charge to all
third parties on terms identical to those contained in this
License Agreement (except that you may choose to grant more extensive
warranty protection to some or all third parties, at your option).
c) You may charge a distribution fee for the physical act of
transferring a copy, and you may at your option offer warranty
protection in exchange for a fee.
Mere aggregation of another unrelated program with this program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other program under the scope of these terms.
3. You may copy and distribute this program (or a portion or derivative
of it, under Paragraph 2) in object code or executable form under the terms
of Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal
shipping charge) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
For an executable file, complete source code means all the source code for
all modules it contains; but, as a special exception, it need not include
source code for modules which are standard libraries that accompany the
operating system on which the executable file runs.
4. You may not copy, sublicense, distribute or transfer this program
except as expressly provided under this License Agreement. Any attempt
otherwise to copy, sublicense, distribute or transfer this program is void and
your rights to use the program under this License agreement shall be
automatically terminated. However, parties who have received computer
software programs from you with this License Agreement will not have
their licenses terminated so long as such parties remain in full compliance.
5. If you wish to incorporate parts of this program into other free
programs whose distribution conditions are different, write to the Free
Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet
worked out a simple rule that can be stated here, but we will often permit
this. We will be guided by the two goals of preserving the free status of
all derivatives our free software and of promoting the sharing and reuse of
software.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding! */
/* Summary:
All the apparent functions defined here are macros. The idea
is that you would use these pre-tested macros to solve a
very specific set of problems, and they would run fast.
Caution: no side-effects in arguments please!! They may be
evaluated MANY times!!
These macros operate a stack of objects. Each object starts life
small, and may grow to maturity. (Consider building a word syllable
by syllable.) An object can move while it is growing. Once it has
been "finished" it never changes address again. So the "top of the
stack" is typically an immature growing object, while the rest of the
stack is of mature, fixed size and fixed address objects.
These routines grab large chunks of memory, using a function you
supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
by calling `obstack_chunk_free'. You must define them and declare
them before using any obstack macros.
Each independent stack is represented by a `struct obstack'.
Each of the obstack macros expects a pointer to such a structure
as the first argument.
One motivation for this package is the problem of growing char strings
in symbol tables. Unless you are "facist pig with a read-only mind"
[Gosper's immortal quote from HAKMEM item 154, out of context] you
would not like to put any arbitrary upper limit on the length of your
symbols.
In practice this often means you will build many short symbols and a
few long symbols. At the time you are reading a symbol you don't know
how long it is. One traditional method is to read a symbol into a
buffer, realloc()ating the buffer every time you try to read a symbol
that is longer than the buffer. This is beaut, but you still will
want to copy the symbol from the buffer to a more permanent
symbol-table entry say about half the time.
With obstacks, you can work differently. Use one obstack for all symbol
names. As you read a symbol, grow the name in the obstack gradually.
When the name is complete, finalize it. Then, if the symbol exists already,
free the newly read name.
The way we do this is to take a large chunk, allocating memory from
low addresses. When you want to build a aymbol in the chunk you just
add chars above the current "high water mark" in the chunk. When you
have finished adding chars, because you got to the end of the symbol,
you know how long the chars are, and you can create a new object.
Mostly the chars will not burst over the highest address of the chunk,
because you would typically expect a chunk to be (say) 100 times as
long as an average object.
In case that isn't clear, when we have enough chars to make up
the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
so we just point to it where it lies. No moving of chars is
needed and this is the second win: potentially long strings need
never be explicitly shuffled. Once an object is formed, it does not
change its address during its lifetime.
When the chars burst over a chunk boundary, we allocate a larger
chunk, and then copy the partly formed object from the end of the old
chunk to the beggining of the new larger chunk. We then carry on
accreting characters to the end of the object as we normaly would.
A special macro is provided to add a single char at a time to a
growing object. This allows the use of register variables, which
break the ordinary 'growth' macro.
Summary:
We allocate large chunks.
We carve out one object at a time from the current chunk.
Once carved, an object never moves.
We are free to append data of any size to the currently
growing object.
Exactly one object is growing in an obstack at any one time.
You can run one obstack per control block.
You may have as many control blocks as you dare.
Because of the way we do it, you can `unwind' a obstack
back to a previous state. (You may remove objects much
as you would with a stack.)
*/
/* Don't do the contents of this file more than once. */
#ifndef __OBSTACKS__
#define __OBSTACKS__
#ifdef __STDC__
/* Do the function-declarations before defining the macros. */
void obstack_init (struct obstack *obstack);
void * obstack_alloc (struct obstack *obstack, int size);
void * obstack_copy (struct obstack *obstack, void *address, int size);
void * obstack_copy0 (struct obstack *obstack, void *address, int size);
void obstack_free (struct obstack *obstack, void *block);
void obstack_blank (struct obstack *obstack, int size);
void obstack_grow (struct obstack *obstack, void *data, int size);
void obstack_grow0 (struct obstack *obstack, void *data, int size);
void obstack_1grow (struct obstack *obstack, int data_char);
void * obstack_finish (struct obstack *obstack);
int obstack_object_size (struct obstack *obstack);
int obstack_room (struct obstack *obstack);
void obstack_1grow_fast (struct obstack *obstack, int data_char);
void obstack_blank_fast (struct obstack *obstack, int size);
void * object_base (struct obstack *obstack);
void * object_next_free (struct obstack *obstack);
int obstack_alignment_mask (struct obstack *obstack);
int obstack_chunk_size (struct obstack *obstack);
#endif /* __STDC__ */
/* Non-ANSI C cannot really support alternative functions for these macros,
so we do not declare them. */
struct _obstack_chunk /* Lives at front of each chunk. */
{
char *limit; /* 1 past end of this chunk */
struct _obstack_chunk *prev; /* address of prior chunk or NULL */
char contents[4]; /* objects begin here */
};
struct obstack /* control current object in current chunk */
{
long chunk_size; /* preferred size to allocate chunks in */
struct _obstack_chunk* chunk; /* address of current struct obstack_chunk */
char *object_base; /* address of object we are building */
char *next_free; /* where to add next char to current object */
char *chunk_limit; /* address of char after current chunk */
int temp; /* Temporary for some macros. */
int alignment_mask; /* Mask of alignment for each object. */
struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */
void (*freefun) (); /* User's function to free a chunk. */
};
/* Pointer to beginning of object being allocated or to be allocated next.
Note that this might not be the final address of the object
because a new chunk might be needed to hold the final size. */
#define obstack_base(h) ((h)->object_base)
/* Size for allocating ordinary chunks. */
#define obstack_chunk_size(h) ((h)->chunk_size)
/* Pointer to next byte not yet allocated in current chunk. */
#define obstack_next_free(h) ((h)->next_free)
/* Mask specifying low bits that should be clear in address of an object. */
#define obstack_alignment_mask(h) ((h)->alignment_mask)
#define obstack_init(h) \
_obstack_begin ((h), 4096 - 4, 4, obstack_chunk_alloc, obstack_chunk_free)
#define obstack_begin(h, size) \
_obstack_begin ((h), (size), 4, obstack_chunk_alloc, obstack_chunk_free)
#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
#define obstack_blank_fast(h,n) ((h)->next_free += (n))
#if defined (__GNU__) && defined (__STDC__)
/* For GNU C we can define these macros to compute all args only once
without using a global variable.
Also, we can avoid using the `temp' slot, to make faster code.
By checking both __GNU__ and __STDC__, we can make sure
both GNU language extensions and ANSI preprocessing are available. */
#define obstack_object_size(OBSTACK) \
({ struct obstack *__o = (OBSTACK); \
(unsigned) (__o->next_free - __o->object_base); })
#define obstack_room(OBSTACK) \
({ struct obstack *__o = (OBSTACK); \
(unsigned) (__o->chunk_limit - __o->next_free); })
#define obstack_grow(OBSTACK,where,length) \
({ struct obstack *__o = (OBSTACK); \
int __len = (length); \
((__o->next_free + __len > __o->chunk_limit) \
? _obstack_newchunk (__o, __len) : 0); \
bcopy (where, __o->next_free, __len); \
__o->next_free += __len; \
(void) 0; })
#define obstack_grow0(OBSTACK,where,length) \
({ struct obstack *__o = (OBSTACK); \
int __len = (length); \
((__o->next_free + __len + 1 > __o->chunk_limit) \
? _obstack_newchunk (__o, __len + 1) : 0), \
bcopy (where, __o->next_free, __len), \
__o->next_free += __len, \
*(__o->next_free)++ = 0; \
(void) 0; })
#define obstack_1grow(OBSTACK,datum) \
({ struct obstack *__o = (OBSTACK); \
((__o->next_free + 1 > __o->chunk_limit) \
? _obstack_newchunk (__o, 1) : 0), \
*(__o->next_free)++ = (datum); \
(void) 0; })
#define obstack_blank(OBSTACK,length) \
({ struct obstack *__o = (OBSTACK); \
int __len = (length); \
((__o->next_free + __len > __o->chunk_limit) \
? _obstack_newchunk (__o, __len) : 0); \
__o->next_free += __len; \
(void) 0; })
#define obstack_alloc(OBSTACK,length) \
({ struct obstack *__h = (OBSTACK); \
obstack_blank (__h, (length)); \
obstack_finish (__h); })
#define obstack_copy(OBSTACK,where,length) \
({ struct obstack *__h = (OBSTACK); \
obstack_grow (__h, (where), (length)); \
obstack_finish (__h); })
#define obstack_copy0(OBSTACK,where,length) \
({ struct obstack *__h = (OBSTACK); \
obstack_grow0 (__h, (where), (length)); \
obstack_finish (__h); })
#define obstack_finish(OBSTACK) \
({ struct obstack *__o = (OBSTACK); \
void *value = (void *) __o->object_base; \
__o->next_free \
= (char*)((int)(__o->next_free+__o->alignment_mask) \
& ~ (__o->alignment_mask)); \
((__o->next_free - (char *)__o->chunk \
> __o->chunk_limit - (char *)__o->chunk) \
? __o->next_free = __o->chunk_limit : 0); \
__o->object_base = __o->next_free; \
value; })
#define obstack_free(OBSTACK, OBJ) \
({ struct obstack *__o = (OBSTACK); \
void *__obj = (OBJ); \
if (__obj >= (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
__o->next_free = __o->object_base = __obj; \
else (obstack_free) (__o, __obj); })
#else /* not __GNU__ */
/* The non-GNU macros copy the obstack-pointer into this global variable
to avoid multiple evaluation. */
extern struct obstack *_obstack;
#define obstack_object_size(h) \
(unsigned) (_obstack = (h), (h)->next_free - (h)->object_base)
#define obstack_room(h) \
(unsigned) (_obstack = (h), (h)->chunk_limit - (h)->next_free)
#define obstack_grow(h,where,length) \
( (h)->temp = (length), \
(((h)->next_free + (h)->temp > (h)->chunk_limit) \
? _obstack_newchunk ((h), (h)->temp) : 0), \
bcopy (where, (h)->next_free, (h)->temp), \
(h)->next_free += (h)->temp)
#define obstack_grow0(h,where,length) \
( (h)->temp = (length), \
(((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \
? _obstack_newchunk ((h), (h)->temp + 1) : 0), \
bcopy (where, (h)->next_free, (h)->temp), \
(h)->next_free += (h)->temp, \
*((h)->next_free)++ = 0)
#define obstack_1grow(h,datum) \
( (((h)->next_free + 1 > (h)->chunk_limit) \
? _obstack_newchunk ((h), 1) : 0), \
*((h)->next_free)++ = (datum))
#define obstack_blank(h,length) \
( (h)->temp = (length), \
(((h)->next_free + (h)->temp > (h)->chunk_limit) \
? _obstack_newchunk ((h), (h)->temp) : 0), \
(h)->next_free += (h)->temp)
#define obstack_alloc(h,length) \
(obstack_blank ((h), (length)), obstack_finish ((h)))
#define obstack_copy(h,where,length) \
(obstack_grow ((h), (where), (length)), obstack_finish ((h)))
#define obstack_copy0(h,where,length) \
(obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
#define obstack_finish(h) \
( (h)->temp = (int) (h)->object_base, \
(h)->next_free \
= (char*)((int)((h)->next_free+(h)->alignment_mask) \
& ~ ((h)->alignment_mask)), \
(((h)->next_free - (char *)(h)->chunk \
> (h)->chunk_limit - (char *)(h)->chunk) \
? (h)->next_free = (h)->chunk_limit : 0), \
(h)->object_base = (h)->next_free, \
(char *) (h)->temp)
#ifdef __STDC__
#define obstack_free(h,obj) \
( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
(((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
? (int) ((h)->next_free = (h)->object_base \
= (h)->temp + (char *) (h)->chunk) \
: (int) (obstack_free) ((h), (h)->temp + (char *) (h)->chunk)))
#else
#define obstack_free(h,obj) \
( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
(((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
? (int) ((h)->next_free = (h)->object_base \
= (h)->temp + (char *) (h)->chunk) \
: (int) _obstack_free ((h), (h)->temp + (char *) (h)->chunk)))
#endif
#endif /* not __GNU__ */
#endif /* not __OBSTACKS__ */

View File

@ -1 +1 @@
#include "m-mac-aux.h"
#include "m-sun3.h"

126
gdb/parent.c Normal file
View File

@ -0,0 +1,126 @@
#include <stdio.h>
class math_stuff
{
char name[40];
int value;
public:
void bla();
math_stuff(char*);
~math_stuff();
void add(int);
void print_value(char*);
};
void math_stuff::bla()
{
printf("bla\n");
}
math_stuff::math_stuff(char* new_name)
{
sprintf((char *)this->name,(char *)"MATH_STUFF_%s",new_name);
value = 0;
}
math_stuff::~math_stuff()
{
printf((char *)"Deleting MATH_STUFF instance '%s'\n",this->name);
}
void math_stuff::add(int x)
{
this->value += x;
}
void math_stuff::print_value(char *where)
{
printf((char *)"current value of '%s' at '%s' = %d\n", this->name, where, this->value);
}
class derived : public math_stuff
{
char *dname;
int val;
public:
math_stuff stuff;
derived(char*);
~derived();
void print_all(char*);
};
derived::derived(char *der_name)
: ((char *)"hello, world!"), stuff("derived stuff"), val(10)
{
printf((char *)"derived name = %s\n", der_name);
dname = der_name;
stuff.add(6);
stuff.print_value ((char *)"grind");
}
derived::~derived()
{
printf ((char *)"Good bye! \n");
}
derived::print_all(char *msg)
{
printf((char *)"Here's the lowdown:\n");
printf((char *)"My name is %s\n", dname);
printf((char *)"My value = %d\n", val);
stuff.print_value ((char *)"low");
this->print_value((char *)"down");
printf((char *)"That's all you get tonight.\n\n");
}
main()
{
int pid;
int i;
pid = vfork();
if (pid > 0)
printf(" the inferior pid of the child is %d\n",pid);
if (pid == 0)
{
/* execl ("/bin/sh", "sh", "-c",argv[1],0);*/
math_stuff* a;
derived* d;
math_stuff b $ (" no gnus are good gnus ");
int child;
child = getpid();
printf( " the child from parent.c is %d\n",child);
ptrace (0);
a = new math_stuff((char *)"a");
d = new derived((char *)"two words");
a->add(2);
a->add(4);
a->add(5);
a->print_value((char *)"here");
a->add(7);
a->print_value((char *)"there");
a->add(3);
a->add(1);
a->print_value((char *)"end");
d->print_all ((char *)"all");
delete a;
delete d;
exit(0);
}
i = 5;
i = 6;
i = 7;
}

View File

@ -1,5 +1,5 @@
/* Print values for GNU debugger gdb.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
@ -95,6 +95,10 @@ decode_format (string_ptr, oformat, osize)
break;
}
/* Make sure 'g' size is not used on integer types. */
if (val.size == 'g' && val.format != 'f')
val.size = 'w';
while (*p == ' ' || *p == '\t') p++;
*string_ptr = p;
@ -103,12 +107,15 @@ decode_format (string_ptr, oformat, osize)
/* Print value VAL on stdout according to FORMAT, a letter or 0.
Do not end with a newline.
0 means print VAL according to its own type. */
0 means print VAL according to its own type.
SIZE is the letter for the size of datum being printed.
This is used to pad hex numbers so they line up. */
static void
print_formatted (val, format)
print_formatted (val, format, size)
register value val;
register char format;
char size;
{
register CORE_ADDR val_long;
int len = TYPE_LENGTH (VALUE_TYPE (val));
@ -143,7 +150,24 @@ print_formatted (val, format)
break;
case 'x':
printf ("0x%x", val_long);
switch (size)
{
case 'b':
printf ("0x%02x", val_long);
break;
case 'h':
printf ("0x%04x", val_long);
break;
case 0: /* no size specified, like in print */
case 'w':
printf ("0x%08x", val_long);
break;
case 'g':
printf ("0x%16x", val_long);
break;
default:
error ("Undefined output size \"%c\".", size);
}
break;
case 'd':
@ -279,6 +303,7 @@ do_examine (fmt, addr)
while (count > 0)
{
print_address (next_address, stdout);
fputc (':', stdout);
for (i = maxelts;
i > 0 && count > 0;
i--, count--)
@ -287,7 +312,7 @@ do_examine (fmt, addr)
/* Note that this sets next_address for the next object. */
last_examine_address = next_address;
last_examine_value = value_at (val_type, next_address);
print_formatted (last_examine_value, format);
print_formatted (last_examine_value, format, size);
}
fputc ('\n', stdout);
fflush (stdout);
@ -339,10 +364,11 @@ print_command (exp)
else
val = access_value_history (0);
if (!val) return; /* C++ */
histindex = record_latest_value (val);
printf ("$%d = ", histindex);
print_formatted (val, format);
print_formatted (val, format, fmt.size);
printf ("\n");
if (cleanup)
@ -372,7 +398,7 @@ output_command (exp)
val = evaluate_expression (expr);
print_formatted (val, format);
print_formatted (val, format, fmt.size);
do_cleanups (old_chain);
}
@ -388,17 +414,41 @@ set_command (exp)
do_cleanups (old_chain);
}
/* C++: Modified to give useful information about variable which
hang off of `this'. */
static void
address_info (exp)
char *exp;
{
register struct symbol *sym;
register CORE_ADDR val;
struct block *block, *get_selected_block ();
if (exp == 0)
error ("Argument required.");
sym = lookup_symbol (exp, get_selected_block (), VAR_NAMESPACE);
block = get_selected_block ();
sym = lookup_symbol_1 (exp, block, VAR_NAMESPACE);
if (! sym)
{
value v;
/* C++: see if it hangs off of `this'. Must
not inadvertently convert from a method call
to data ref. */
v = value_of_this (0);
if (v)
{
val = check_field (v, exp);
if (val)
{
printf ("Symbol \"%s\" is a field of the local class variable `this'\n", exp);
return;
}
}
else
sym = lookup_symbol_2 (exp, 0, VAR_NAMESPACE);
}
if (sym == 0)
{
register int i;
@ -522,9 +572,12 @@ whatis_command (exp)
else
val = access_value_history (0);
printf ("type = ");
type_print (VALUE_TYPE (val), "", stdout, 1);
printf ("\n");
if (val != 0)
{
printf ("type = ");
type_print (VALUE_TYPE (val), "", stdout, 1);
printf ("\n");
}
if (exp)
do_cleanups (old_chain);
@ -586,6 +639,143 @@ ptype_command (typename)
type_print (type, "", stdout, 1);
printf ("\n");
}
/* Print all the methods that correspond to the name METHOD.
Can optionally qualify the method with a CLASSNAME, as
in CLASSNAME :: METHODNAME. This routine does not call
parse_c_expression, so the input must conform to one of
these two forms. */
static void
pmethod_command (exp)
char *exp;
{
# if 0
struct expression *expr;
register value val;
register struct cleanup *old_chain;
char *classname, *methodname;
methodname = exp;
while (*exp++ <= ' ') ; /* remove leading whitespace */
if (exp[-1] == ':')
if (*exp == ':')
classname = (char *)1;
else error ("Invalid syntax: \"%s\"", methodname);
else
{
classname = exp-1;
while (*exp++ != ':') ;
exp[-1] = '\0';
if (*exp == ':')
{
while (*exp++ <= ' ') ; /* remove leading 2nd whitespace */
methodname = exp-1;
while (((*exp | 0x20) >= 'a' && ((*exp | 0x20) <= 'z')) || *exp == '_')
exp++;
if (*exp)
{
*exp++ = '\0';
while (*exp)
if (*exp > ' ') error ("junk after method name");
}
}
else error ("Invalid syntax: \"%s\"", methodname);
}
if (classname)
{
if (classname != (char *)1)
classtype = lookup_typename (classname);
else
{
register struct symtab *s;
register struct blockvector *bv;
struct blockvector *prev_bv = 0;
register struct block *b;
register int i, j;
register struct symbol *sym;
char *val;
int found_in_file;
static char *classnames[]
= {"variable", "function", "type", "method"};
int print_count = 0;
if (regexp)
if (val = (char *) re_comp (regexp))
error ("Invalid regexp: %s", val);
printf (regexp
? "All %ss matching regular expression \"%s\":\n"
: "All defined %ss:\n",
classnames[class],
regexp);
for (s = symtab_list; s; s = s->next)
{
found_in_file = 0;
bv = BLOCKVECTOR (s);
/* Often many files share a blockvector.
Scan each blockvector only once so that
we don't get every symbol many times.
It happens that the first symtab in the list
for any given blockvector is the main file. */
if (bv != prev_bv)
for (i = 0; i < 2; i++)
{
b = BLOCKVECTOR_BLOCK (bv, i);
for (j = 0; j < BLOCK_NSYMS (b); j++)
{
QUIT;
sym = BLOCK_SYM (b, j);
if ((regexp == 0 || re_exec (SYMBOL_NAME (sym)))
&& ((class == 0 && SYMBOL_CLASS (sym) != LOC_TYPEDEF
&& SYMBOL_CLASS (sym) != LOC_BLOCK)
|| (class == 1 && SYMBOL_CLASS (sym) == LOC_BLOCK)
|| (class == 2 && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
|| (class == 3 && SYMBOL_CLASS (sym) == LOC_BLOCK)))
{
if (!found_in_file)
{
printf ("\nFile %s:\n", s->filename);
print_count += 2;
}
found_in_file = 1;
MORE;
if (i == 1)
printf ("static ");
type_print (SYMBOL_TYPE (sym),
(SYMBOL_CLASS (sym) == LOC_TYPEDEF
? "" : SYMBOL_NAME (sym)),
stdout, 0);
printf (";\n");
}
}
}
prev_bv = bv;
}
}
}
if (exp)
{
expr = parse_c_expression (exp);
old_chain = make_cleanup (free_current_contents, &expr);
val = evaluate_type (expr);
}
else
val = access_value_history (0);
if (val != 0)
{
printf ("type = ");
type_print (VALUE_TYPE (val), "", stdout, 1);
printf ("\n");
}
if (exp)
do_cleanups (old_chain);
# endif
}
struct display
{
@ -767,7 +957,8 @@ do_displays ()
printf ("/%c ", d->format.format);
print_expression (d->exp, stdout);
printf (" = ");
print_formatted (evaluate_expression (d->exp), d->format.format);
print_formatted (evaluate_expression (d->exp),
d->format.format, d->format.size);
printf ("\n");
}
fflush (stdout);
@ -896,6 +1087,171 @@ print_frame_nameless_args (argsaddr, start, end, stream)
}
}
static void
printf_command (arg)
char *arg;
{
register char *f;
register char *s = arg;
char *string;
value *val_args;
int nargs = 0;
int allocated_args = 20;
char *arg_bytes;
char *argclass;
int i;
int argindex;
int nargs_wanted;
val_args = (value *) xmalloc (allocated_args * sizeof (value));
if (s == 0)
error_no_arg ("format-control string and values to print");
/* Skip white space before format string */
while (*s == ' ' || *s == '\t') s++;
/* A format string should follow, enveloped in double quotes */
if (*s++ != '"')
error ("Bad format string, missing '\"'.");
/* Parse the format-control string and copy it into the string STRING,
processing some kinds of escape sequence. */
f = string = (char *) alloca (strlen (s) + 1);
while (*s != '"')
{
int c = *s++;
switch (c)
{
case '\0':
error ("Bad format string, non-terminated '\"'.");
/* doesn't return */
case '\\':
switch (c = *s++)
{
case '\\':
*f++ = '\\';
break;
case 'n':
*f++ = '\n';
break;
case 't':
*f++ = '\t';
break;
case 'r':
*f++ = '\r';
break;
case '"':
*f++ = '"';
break;
default:
/* ??? TODO: handle other escape sequences */
error ("Unrecognized \\ escape character in format string.");
}
break;
default:
*f++ = c;
}
}
/* Skip over " and following space and comma. */
s++;
*f++ = '\0';
while (*s == ' ' || *s == '\t') s++;
if (*s != ',' && *s != 0)
error ("Invalid argument syntax");
if (*s == ',') s++;
while (*s == ' ' || *s == '\t') s++;
/* Now scan the string for %-specs and see what kinds of args they want.
argclass[I] is set to 1 if the Ith arg should be a string. */
argclass = (char *) alloca (strlen (s));
nargs_wanted = 0;
f = string;
while (*f)
if (*f++ == '%')
{
while (index ("0123456789.hlL-+ #", *f)) f++;
if (*f == 's')
argclass[nargs_wanted++] = 1;
else if (*f != '%')
argclass[nargs_wanted++] = 0;
f++;
}
/* Now, parse all arguments and evaluate them.
Store the VALUEs in VAL_ARGS. */
while (*s != '\0')
{
char *s1;
if (nargs == allocated_args)
val_args = (value *) xrealloc (val_args,
(allocated_args *= 2)
* sizeof (value));
s1 = s;
val_args[nargs++] = parse_to_comma_and_eval (&s1);
s = s1;
if (*s == ',')
s++;
}
if (nargs != nargs_wanted)
error ("Wrong number of arguments for specified format-string");
/* Now lay out an argument-list containing the arguments
as doubles, integers and C pointers. */
arg_bytes = (char *) alloca (sizeof (double) * nargs);
argindex = 0;
for (i = 0; i < nargs; i++)
{
if (argclass[i])
{
char *str;
int tem, j;
tem = value_as_long (val_args[i]);
/* This is a %s argument. Find the length of the string. */
for (j = 0; ; j++)
{
char c;
QUIT;
read_memory (tem + j, &c, 1);
if (c == 0)
break;
}
/* Copy the string contents into a string inside GDB. */
str = (char *) alloca (j + 1);
read_memory (tem, str, j);
str[j] = 0;
/* Pass address of internal copy as the arg to vprintf. */
*((int *) &arg_bytes[argindex]) = (int) str;
argindex += sizeof (int);
}
else if (VALUE_TYPE (val_args[i])->code == TYPE_CODE_FLT)
{
*((double *) &arg_bytes[argindex]) = value_as_double (val_args[i]);
argindex += sizeof (double);
}
else
{
*((int *) &arg_bytes[argindex]) = value_as_long (val_args[i]);
argindex += sizeof (int);
}
}
vprintf (string, arg_bytes);
}
static
initialize ()
{
@ -925,6 +1281,11 @@ The selected stack frame's lexical context is used to look up the name.");
add_com ("whatis", class_vars, whatis_command,
"Print data type of expression EXP.");
add_com ("pmethod", class_vars, pmethod_command,
"Print definitions of method METHOD.\n\
Argument must resolve to a method name within the containing scope.\n\
All definitions found go into history array.");
add_info ("display", display_info,
"Expressions to display when program stops, with code numbers.");
add_com ("undisplay", class_vars, undisplay_command,
@ -941,6 +1302,9 @@ and examining is done as in the \"x\" command.\n\n\
With no argument, display all currently requested auto-display expressions.\n\
Use \"undisplay\" to cancel display requests previously made.");
add_com ("printf", class_vars, printf_command,
"printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\
This is useful for formatted output in user-defined commands.");
add_com ("output", class_vars, output_command,
"Like \"print\" but don't put in value history and don't print newline.\n\
This is useful in user-defined commands.");

607
gdb/remote.c Normal file
View File

@ -0,0 +1,607 @@
/* Memory-access and commands for inferior process, for GDB.
Copyright (C) 1988 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
/* Remote communication protocol.
All values are encoded in ascii hex digits.
Request Packet
read registers g
reply XX....X Each byte of register data
is described by two hex digits.
Registers are in the internal order
for GDB, and the bytes in a register
are in the same order the machine uses.
or ENN for an error.
write regs GXX..XX Each byte of register data
is described by two hex digits.
reply OK for success
ENN for an error
read mem mAA..AA,LLLL AA..AA is address, LLLL is length.
reply XX..XX XX..XX is mem contents
or ENN NN is errno
write mem MAA..AA,LLLL:XX..XX
AA..AA is address,
LLLL is number of bytes,
XX..XX is data
reply OK for success
ENN for an error
cont cAA..AA AA..AA is address to resume
If AA..AA is omitted,
resume at same address.
step sAA..AA AA..AA is address to resume
If AA..AA is omitted,
resume at same address.
There is no immediate reply to step or cont.
The reply comes when the machine stops.
It is SAA AA is the "signal number"
kill req k
*/
#include <stdio.h>
#include <signal.h>
#include "defs.h"
#include "initialize.h"
#include "param.h"
#include "frame.h"
#include "inferior.h"
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <a.out.h>
#include <sys/file.h>
#include <sgtty.h>
int kiodebug;
int icache;
/* Descriptor for I/O to remote machine. */
int remote_desc;
#define PBUFSIZ 300
static void remote_send ();
static void putpkt ();
static void getpkt ();
static void dcache_flush ();
START_FILE
/* Open a connection to a remote debugger.
NAME is the filename used for communication. */
void
remote_open (name, from_tty)
char *name;
int from_tty;
{
struct sgttyb sg;
remote_debugging = 0;
dcache_init ();
remote_desc = open (name, O_RDWR);
if (remote_desc < 0)
perror_with_name (name);
ioctl (remote_desc, TIOCGETP, &sg);
sg.sg_flags = RAW;
ioctl (remote_desc, TIOCSETP, &sg);
if (from_tty)
printf ("Remote debugging using %s\n", name);
remote_debugging = 1;
}
/* Convert hex digit A to a number. */
static int
fromhex (a)
int a;
{
if (a >= '0' && a <= '9')
return a - '0';
else if (a >= 'a' && a <= 'f')
return a - 'a' + 10;
else
error ("Reply contains invalid hex digit");
}
/* Convert number NIB to a hex digit. */
static int
tohex (nib)
int nib;
{
if (nib < 10)
return '0'+nib;
else
return 'a'+nib-10;
}
/* Tell the remote machine to resume. */
int
remote_resume (step, signal)
int step, signal;
{
char buf[PBUFSIZ];
dcache_flush ();
strcpy (buf, step ? "s": "c");
putpkt (buf);
}
/* Wait until the remote machine stops, then return,
storing status in STATUS just as `wait' would. */
int
remote_wait (status)
union wait *status;
{
char buf[PBUFSIZ];
status->w_status = 0;
getpkt (buf);
if (buf[0] == 'E')
error ("Remote failure reply: %s", buf);
if (buf[0] != 'S')
error ("Invalid remote reply: %s", buf);
status->w_stopval = WSTOPPED;
status->w_stopsig = (fromhex (buf[1]) << 4) + fromhex (buf[2]);
}
/* Read the remote registers into the block REGS. */
void
remote_fetch_registers (regs)
char *regs;
{
char buf[PBUFSIZ];
int i;
char *p;
sprintf (buf, "g");
remote_send (buf);
/* Reply describes registers byte by byte,
each byte encoded as two hex characters. */
p = buf;
for (i = 0; i < REGISTER_BYTES; i++)
{
if (p[0] == 0 || p[1] == 0)
error ("Remote reply is too short: %s", buf);
regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
p += 2;
}
}
/* Store the remote registers from the contents of the block REGS. */
void
remote_store_registers (regs)
char *regs;
{
char buf[PBUFSIZ];
int i;
char *p;
buf[0] = 'G';
/* Command describes registers byte by byte,
each byte encoded as two hex characters. */
p = buf + 1;
for (i = 0; i < REGISTER_BYTES; i++)
{
*p++ = (regs[i] > 4) & 0xf;
*p++ = regs[i] & 0xf;
}
remote_send (buf);
}
/* Read a word from remote address ADDR and return it.
This goes through the data cache. */
int
remote_fetch_word (addr)
CORE_ADDR addr;
{
if (icache)
{
extern CORE_ADDR text_start, text_end;
if (addr >= text_start && addr < text_end)
{
int buffer;
xfer_core_file (addr, &buffer, sizeof (int));
return buffer;
}
}
return dcache_fetch (addr);
}
/* Write a word WORD into remote address ADDR.
This goes through the data cache. */
void
remote_store_word (addr, word)
CORE_ADDR addr;
int word;
{
dcache_poke (addr, word);
}
/* Write memory data directly to the remote machine.
This does not inform the data cache; the data cache uses this.
MEMADDR is the address in the remote memory space.
MYADDR is the address of the buffer in our space.
LEN is the number of bytes. */
void
remote_write_bytes (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
char buf[PBUFSIZ];
int i;
char *p;
if (len > PBUFSIZ / 2 - 20)
abort ();
sprintf (buf, "M%x,%x:", memaddr, len);
/* Command describes registers byte by byte,
each byte encoded as two hex characters. */
p = buf + strlen (buf);
for (i = 0; i < len; i++)
{
*p++ = (myaddr[i] > 4) & 0xf;
*p++ = myaddr[i] & 0xf;
}
remote_send (buf);
}
/* Read memory data directly from the remote machine.
This does not use the data cache; the data cache uses this.
MEMADDR is the address in the remote memory space.
MYADDR is the address of the buffer in our space.
LEN is the number of bytes. */
void
remote_read_bytes (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
char buf[PBUFSIZ];
int i;
char *p;
if (len > PBUFSIZ / 2 - 1)
abort ();
sprintf (buf, "m%x,%x", memaddr, len);
remote_send (buf);
/* Reply describes registers byte by byte,
each byte encoded as two hex characters. */
p = buf;
for (i = 0; i < REGISTER_BYTES; i++)
{
if (p[0] == 0 || p[1] == 0)
error ("Remote reply is too short: %s", buf);
myaddr[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
p += 2;
}
}
/*
A debug packet whose contents are <data>
is encapsulated for transmission in the form:
$ <data> # CSUM1 CSUM2
<data> must be ASCII alphanumeric and cannot include characters
'$' or '#'
CSUM1 and CSUM2 are ascii hex representation of an 8-bit
checksum of <data>, the most significant nibble is sent first.
the hex digits 0-9,a-f are used.
Receiver responds with:
+ - if CSUM is correct and ready for next packet
- - if CSUM is incorrect
*/
/* Send the command in BUF to the remote machine,
and read the reply into BUF.
Report an error if we get an error reply. */
static void
remote_send (buf)
char *buf;
{
int i;
putpkt (buf);
getpkt (buf);
if (buf[0] == 'E')
error ("Remote failure reply: %s", buf);
}
/* Send a packet to the remote machine, with error checking.
The data of the packet is in BUF. */
static void
putpkt (buf)
char *buf;
{
int i;
char csum = 0;
char buf2[500];
char buf3[1];
int cnt = strlen (buf);
char *p;
if (kiodebug)
fprintf (stderr, "Sending packet: %s\n", buf);
/* Copy the packet into buffer BUF2, encapsulating it
and giving it a checksum. */
p = buf2;
*p++ = '$';
for (i = 0; i < cnt; i++)
{
csum += buf[i];
*p++ = buf[i];
}
*p++ = '#';
*p++ = tohex ((csum >> 4) & 0xf);
*p++ = tohex (csum & 0xf);
/* Send it over and over until we get a positive ack. */
do {
write (remote_desc, buf2, p - buf2);
read (remote_desc, buf3, 1);
} while (buf3[0] != '+');
}
static int
readchar ()
{
char buf[1];
while (read (remote_desc, buf, 1) != 1) ;
return buf[0] & 0x7f;
}
/* Read a packet from the remote machine, with error checking,
and store it in BUF. */
static void
getpkt (buf)
char *buf;
{
char *bp;
char csum = 0;
int c, c1, c2;
extern kiodebug;
while (1)
{
while ((c = readchar()) != '$');
bp = buf;
while (1)
{
c = readchar ();
if (c == '#')
break;
*bp++ = c;
csum += c;
}
*bp = 0;
c1 = fromhex (readchar ());
c2 = fromhex (readchar ());
if (csum == (c1 << 4) + c2)
break;
printf ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
(c1 << 4) + c2, csum, buf);
write (remote_desc, "-", 1);
}
write (remote_desc, "+", 1);
if (kiodebug)
fprintf (stderr,"Packet received :%s\n", buf);
}
/* The data cache records all the data read from the remote machine
since the last time it stopped.
Each cache block holds 16 bytes of data
starting at a multiple-of-16 address. */
#define DCACHE_SIZE 64 /* Number of cache blocks */
struct dcache_block {
struct dcache_block *next, *last;
unsigned int addr; /* Address for which data is recorded. */
int data[4];
};
struct dcache_block dcache_free, dcache_valid;
/* Free all the data cache blocks, thus discarding all cached data. */
static void
dcache_flush ()
{
register struct dcache_block *db;
while ((db = dcache_valid.next) != &dcache_valid)
{
remque (db);
insque (db, &dcache_free);
}
}
/*
* If addr is present in the dcache, return the address of the block
* containing it.
*/
struct dcache_block *
dcache_hit (addr)
{
register struct dcache_block *db;
if (addr & 3)
abort ();
/* Search all cache blocks for one that is at this address. */
db = dcache_valid.next;
while (db != &dcache_valid)
{
if ((addr & 0xfffffff0) == db->addr)
return db;
db = db->next;
}
return NULL;
}
/* Return the int data at address ADDR in dcache block DC. */
int
dcache_value (db, addr)
struct dcache_block *db;
unsigned int addr;
{
if (addr & 3)
abort ();
return (db->data[(addr>>2)&3]);
}
/* Get a free cache block, put it on the valid list,
and return its address. The caller should store into the block
the address and data that it describes. */
struct dcache_block *
dcache_alloc ()
{
register struct dcache_block *db;
if ((db = dcache_free.next) == &dcache_free)
/* If we can't get one from the free list, take last valid */
db = dcache_valid.last;
remque (db);
insque (db, &dcache_valid);
return (db);
}
/* Return the contents of the word at address ADDR in the remote machine,
using the data cache. */
int
dcache_fetch (addr)
CORE_ADDR addr;
{
register struct dcache_block *db;
db = dcache_hit (addr);
if (db == 0)
{
db = dcache_alloc ();
remote_read_bytes (addr & ~0xf, db->data, 16);
db->addr = addr & ~0xf;
}
return (dcache_value (db, addr));
}
/* Write the word at ADDR both in the data cache and in the remote machine. */
dcache_poke (addr, data)
CORE_ADDR addr;
int data;
{
register struct dcache_block *db;
/* First make sure the word is IN the cache. DB is its cache block. */
db = dcache_hit (addr);
if (db == 0)
{
db = dcache_alloc ();
remote_read_bytes (addr & ~0xf, db->data, 16);
db->addr = addr & ~0xf;
}
/* Modify the word in the cache. */
db->data[(addr>>2)&3] = data;
/* Send the changed word. */
remote_write_bytes (addr, &data, 4);
}
/* Initialize the data cache. */
dcache_init ()
{
register i;
register struct dcache_block *db;
db = (struct dcache_block *) xmalloc (sizeof (struct dcache_block) *
DCACHE_SIZE);
dcache_free.next = dcache_free.last = &dcache_free;
dcache_valid.next = dcache_valid.last = &dcache_valid;
for (i=0;i<DCACHE_SIZE;i++,db++)
insque (db, &dcache_free);
}
static initialize ()
{
}
END_FILE

View File

@ -1,44 +0,0 @@
Date: Tue, 6 Oct 87 08:52:07 PDT
To: bug-gnu-emacs@prep.ai.mit.edu
From: Lynn Slater <silvlis!wobegon!lrs@sun.com>
Sender: silvlis!wobegon!lrs@sun.com
Organization: Silvar-Lisco, 1080 Marsh Road, Menlo Park, CA 94025-1053
Phone.......: (415) 853-6336 (Office); (415) 796-4149 (Home)
Subject: GDB sing-along
Somebody asked us what was GDB. With apologies to Oscar Hemmerstein
II, Richard Rodgers, and Julie Andrews, we offered the following reply:
Let's start at the very beginning, a very good place to start,
When you're learning to sing, its Do, Re, Mi;
When you're learning to code, its G, D, B.
(background) G, D, B.
The first three letters just happen to be, G, D, B.
(background) G, D, B.
(Chorus)
G!, GNU!, it's Stallman's hope,
B, a break I set myself.
D, debug that rotten code,
Run, a far, far way to go.
Print, to see what you have done,
Set, a patch that follows print.
Quit, and recompile your code - - -
That will bring it back to G,
D,
B,
<link>
(Resume from the Chorus)
:-) Joel Bion, Mark Baushke, and Lynn Slater :-)

View File

@ -1,5 +1,5 @@
/* List lines of source files for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
@ -19,7 +19,6 @@ anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/file.h>
@ -40,9 +39,10 @@ struct symtab *current_source_symtab;
int current_source_line;
/* Line for "info line" to work on if no line specified. */
/* Line number of last line printed. Default for various commands.
current_source_line is usually, but not always, the same as this. */
static int line_info_default_line;
static int last_line_listed;
/* First line number listed by last listing command. */
@ -59,13 +59,16 @@ select_source_symtab (s)
{
if (s)
{
struct symtabs_and_lines sals;
struct symtab_and_line sal;
/* Make the default place to list be the function `main'
if one exists. */
if (lookup_symbol ("main", 0, VAR_NAMESPACE))
{
sal = decode_line_spec ("main", 1);
sals = decode_line_spec ("main", 1);
sal = sals.sals[0];
free (sals.sals);
current_source_symtab = sal.symtab;
current_source_line = sal.line - 9;
return;
@ -275,10 +278,7 @@ openp (path, try_cwd_first, string, mode, prot, filename_opened)
*filename_opened = savestring (filename, strlen (filename));
else
{
char dirname[MAXPATHLEN];
if (getwd (dirname) == NULL)
perror_with_name ("getwd");
*filename_opened = concat (dirname, "/", filename);
*filename_opened = concat (current_directory, "/", filename);
}
return fd;
@ -376,17 +376,40 @@ get_filename_and_charpos (s, line, fullname)
{
register int desc, linenums_changed = 0;
desc = openp (source_path, 0, s->filename, O_RDONLY, 0, fullname);
desc = openp (source_path, 0, s->filename, O_RDONLY, 0, &s->fullname);
if (desc < 0)
{
*fullname = NULL;
if (fullname)
*fullname = NULL;
return 0;
}
if (fullname)
*fullname = s->fullname;
if (s->line_charpos == 0) linenums_changed = 1;
if (linenums_changed) find_source_lines (s, desc);
close (desc);
return linenums_changed;
}
/* Print text describing the full name of the source file S
and the line number LINE and its corresponding character position.
The text starts with two Ctrl-z so that the Emacs-GDB interface
can easily find it.
Return 1 if successful, 0 if could not find the file. */
int
identify_source_line (s, line)
struct symtab *s;
int line;
{
if (s->line_charpos == 0)
get_filename_and_charpos (s, line, 0);
if (s->fullname == 0)
return 0;
printf ("\032\032%s:%d:%d\n", s->fullname, line, s->line_charpos[line - 1]);
return 1;
}
/* Print source lines from the file of symtab S,
starting with line number LINE and stopping before line number STOPLINE. */
@ -401,7 +424,7 @@ print_source_lines (s, line, stopline)
register FILE *stream;
int nlines = stopline - line;
desc = openp (source_path, 0, s->filename, O_RDONLY, 0, (char **) 0);
desc = openp (source_path, 0, s->filename, O_RDONLY, 0, &s->fullname);
if (desc < 0)
perror_with_name (s->filename);
@ -432,7 +455,7 @@ print_source_lines (s, line, stopline)
{
c = fgetc (stream);
if (c == EOF) break;
line_info_default_line = current_source_line;
last_line_listed = current_source_line;
printf ("%d\t", current_source_line++);
do
{
@ -456,6 +479,7 @@ list_command (arg, from_tty)
char *arg;
int from_tty;
{
struct symtabs_and_lines sals, sals_end;
struct symtab_and_line sal, sal_end;
struct symbol *sym;
char *arg1;
@ -500,7 +524,18 @@ list_command (arg, from_tty)
if (*arg1 == ',')
dummy_beg = 1;
else
sal = decode_line_1 (&arg1, 0, 0, 0);
{
sals = decode_line_1 (&arg1, 0, 0, 0);
if (! sals.nelts) return; /* C++ */
if (sals.nelts != 1)
{
error ("Unreasonable listing request");
}
sal = sals.sals[0];
free (sals.sals);
}
/* Record whether the BEG arg is all digits. */
@ -517,10 +552,16 @@ list_command (arg, from_tty)
arg1++;
if (*arg1 == 0)
dummy_end = 1;
else if (dummy_beg)
sal_end = decode_line_1 (&arg1, 0, 0, 0);
else
sal_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line);
{
if (dummy_beg)
sals_end = decode_line_1 (&arg1, 0, 0, 0);
else
sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line);
if (! sals_end.nelts) return; /* C++ */
sal_end = sals_end.sals[0];
free (sals_end.sals);
}
}
if (*arg1)
@ -583,18 +624,26 @@ line_info (arg, from_tty)
char *arg;
int from_tty;
{
struct symtabs_and_lines sals;
struct symtab_and_line sal;
int start_pc, end_pc;
if (arg == 0)
{
sal.symtab = current_source_symtab;
sal.line = line_info_default_line;
sal.line = last_line_listed;
}
else
{
sal = decode_line_spec (arg);
sals = decode_line_spec (arg);
if (sals.nelts == 0)
return; /* C++ */
if (sals.nelts != 1)
error ("unreasonable line info request");
sal = sals.sals[0];
free (sals.sals);
/* If this command is repeated with RET,
turn it into the no-arg variant. */
@ -616,13 +665,162 @@ line_info (arg, from_tty)
/* x/i should display this line's code. */
set_next_address (start_pc);
/* Repeating "info line" should do the following line. */
line_info_default_line = sal.line + 1;
last_line_listed = sal.line + 1;
}
else
printf ("Line number %d is out of range for \"%s\".\n",
sal.line, sal.symtab->filename);
}
/* Commands to search the source file for a regexp. */
static void
forward_search_command (regex, from_tty)
char *regex;
{
register int c;
register int desc;
register FILE *stream;
int line = last_line_listed + 1;
char *msg;
msg = (char *) re_comp (regex);
if (msg)
error (msg);
if (current_source_symtab == 0)
error ("No default source file yet. Do \"help list\".");
/* Search from last_line_listed+1 in current_source_symtab */
desc = openp (source_path, 0, current_source_symtab->filename,
O_RDONLY, 0, &current_source_symtab->fullname);
if (desc < 0)
perror_with_name (current_source_symtab->filename);
if (current_source_symtab->line_charpos == 0)
find_source_lines (current_source_symtab, desc);
if (line < 1 || line >= current_source_symtab->nlines)
{
close (desc);
error ("Expression not found");
}
if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
{
close (desc);
perror_with_name (current_source_symtab->filename);
}
stream = fdopen (desc, "r");
clearerr (stream);
while (1) {
char buf[4096]; /* Should be reasonable??? */
register char *p = buf;
c = fgetc (stream);
if (c == EOF)
break;
do {
*p++ = c;
} while (c != '\n' && (c = fgetc (stream)) >= 0);
/* we now have a source line in buf, null terminate and match */
*p = 0;
if (re_exec (buf) > 0)
{
/* Match! */
fclose (stream);
print_source_lines (current_source_symtab,
line, line+1);
current_source_line = max (line - 5, 1);
return;
}
line++;
}
printf ("Expression not found\n");
fclose (stream);
}
static void
reverse_search_command (regex, from_tty)
char *regex;
{
register int c;
register int desc;
register FILE *stream;
int line = last_line_listed - 1;
char *msg;
msg = (char *) re_comp (regex);
if (msg)
error (msg);
if (current_source_symtab == 0)
error ("No default source file yet. Do \"help list\".");
/* Search from last_line_listed-1 in current_source_symtab */
desc = openp (source_path, 0, current_source_symtab->filename,
O_RDONLY, 0, &current_source_symtab->fullname);
if (desc < 0)
perror_with_name (current_source_symtab->filename);
if (current_source_symtab->line_charpos == 0)
find_source_lines (current_source_symtab, desc);
if (line < 1 || line >= current_source_symtab->nlines)
{
close (desc);
error ("Expression not found");
}
if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
{
close (desc);
perror_with_name (current_source_symtab->filename);
}
stream = fdopen (desc, "r");
clearerr (stream);
while (1)
{
char buf[4096]; /* Should be reasonable??? */
register char *p = buf;
c = fgetc (stream);
if (c == EOF)
break;
do {
*p++ = c;
} while (c != '\n' && (c = fgetc (stream)) >= 0);
/* We now have a source line in buf; null terminate and match. */
*p = 0;
if (re_exec (buf) > 0)
{
/* Match! */
fclose (stream);
print_source_lines (current_source_symtab,
line, line+1);
current_source_line = max (line - 5, 1);
return;
}
line--;
if (fseek (stream, current_source_symtab->line_charpos[line - 1], 0) < 0)
{
fclose (stream);
perror_with_name (current_source_symtab->filename);
}
}
printf ("Expression not found\n");
fclose (stream);
return;
}
static
initialize ()
{
@ -649,6 +847,13 @@ This sets the default address for \"x\" to the line's first instruction\n\
so that \"x/i\" suffices to start examining the machine code.\n\
The address is also stored as the value of \"$_\".");
add_com ("forward-search", class_files, forward_search_command,
"Search for regular expression (see regex(3)) from last line listed.");
add_com_alias ("search", "forward-search", class_files, 0);
add_com ("reverse-search", class_files, reverse_search_command,
"Search backward for regular expression (see regex(3)) from last line listed.");
add_com ("list", class_files, list_command,
"List specified function or line.\n\
With no argument, lists ten more lines after or around previous listing.\n\

View File

@ -39,6 +39,11 @@ FRAME selected_frame;
int selected_frame_level;
/* Nonzero means print the full filename and linenumber
when a frame is printed, and do so in a format programs can parse. */
int frame_file_full_name = 0;
static void select_calling_frame ();
void print_frame_info ();
@ -114,9 +119,13 @@ print_frame_info (fi, level, source, args)
if (source != 0 && sal.symtab)
{
int done = 0;
if (source < 0 && fi->pc != sal.pc)
printf ("0x%x\t", fi->pc);
print_source_lines (sal.symtab, sal.line, sal.line + 1);
if (frame_file_full_name)
done = identify_source_line (sal.symtab, sal.line);
if (!done)
print_source_lines (sal.symtab, sal.line, sal.line + 1);
current_source_line = max (sal.line - 5, 1);
}
if (source != 0)

View File

@ -105,11 +105,6 @@ free_symtab (s)
Therefore, do nothing. */
break;
case free_explicit:
/* All the contents are part of a big block of memory
and that is our `free_ptr' and will be freed below. */
break;
case free_contents:
/* Here all the contents were malloc'ed structure by structure
and must be freed that way. */
@ -122,8 +117,7 @@ free_symtab (s)
free (bv);
/* Free the type vector. */
tv = TYPEVECTOR (s);
if (tv) /* FIXME, should this happen? It does... */
free (tv);
free (tv);
/* Also free the linetable. */
case free_linetable:
@ -177,10 +171,11 @@ static void relocate_blockvector ();
static void relocate_type ();
static void relocate_block ();
static void relocate_symbol ();
static void relocate_source ();
/* Relocate a file symbol table so that all the pointers
are valid C pointers. Pass the struct symtab for the file
and the amount to relocate by. */
/* Relocate a file's symseg so that all the pointers are valid C pointers.
Value is a `struct symtab'; but it is not suitable for direct
insertion into the `symtab_list' because it describes several files. */
static struct symtab *
relocate_symtab (root)
@ -203,8 +198,6 @@ relocate_symtab (root)
sp->version = root->version;
sp->blockvector = root->blockvector;
sp->typevector = root->typevector;
sp->free_code = free_explicit;
sp->free_ptr = (char *) root;
RELOCATE (TYPEVECTOR (sp));
RELOCATE (BLOCKVECTOR (sp));
@ -218,19 +211,6 @@ relocate_symtab (root)
return sp;
}
static void
relocate_typevector (tv)
struct typevector *tv;
{
register int ntypes = TYPEVECTOR_NTYPES (tv);
register int i;
for (i = 0; i < ntypes; i++)
RELOCATE (TYPEVECTOR_TYPE (tv, i));
for (i = 0; i < ntypes; i++)
relocate_type (TYPEVECTOR_TYPE (tv, i));
}
static void
relocate_blockvector (blp)
register struct blockvector *blp;
@ -289,6 +269,19 @@ relocate_symbol (sp)
RELOCATE (SYMBOL_TYPE (sp));
}
static void
relocate_typevector (tv)
struct typevector *tv;
{
register int ntypes = TYPEVECTOR_NTYPES (tv);
register int i;
for (i = 0; i < ntypes; i++)
RELOCATE (TYPEVECTOR_TYPE (tv, i));
for (i = 0; i < ntypes; i++)
relocate_type (TYPEVECTOR_TYPE (tv, i));
}
/* We cannot come up with an a priori spanning tree
for the network of types, since types can be used
for many symbols and also as components of other types.
@ -314,10 +307,40 @@ relocate_type (tp)
RELOCATE (TYPE_FIELD_NAME (tp, i));
}
}
static void
relocate_sourcevector (svp)
register struct sourcevector *svp;
{
register int nfiles = svp->length;
register int i;
for (i = 0; i < nfiles; i++)
RELOCATE (svp->source[i]);
for (i = 0; i < nfiles; i++)
relocate_source (svp->source[i]);
}
static void
relocate_source (sp)
register struct source *sp;
{
register int nitems = sp->contents.nitems;
register int i;
RELOCATE (sp->name);
for (i = 0; i < nitems; i++)
if (sp->contents.item[i] > 0)
TEXT_RELOCATE (sp->contents.item[i]);
}
/* Read symsegs from file named NAME open on DESC,
make symtabs from them, and return a chain of them.
Assumes DESC is prepositioned at the end of the string table,
These symtabs are not suitable for direct use in `symtab_list'
because each one describes a single object file, perhaps many source files.
`symbol_file_command' takes each of these, makes many real symtabs
from it, and then frees it.
We assume DESC is prepositioned at the end of the string table,
just before the symsegs if there are any. */
struct symtab *
@ -327,7 +350,7 @@ read_symsegs (desc, name)
{
struct symbol_root root;
register char *data;
register struct symtab *sp, *chain = 0;
register struct symtab *sp, *sp1, *chain = 0;
register int len;
while (1)
@ -343,8 +366,11 @@ read_symsegs (desc, name)
len = myread (desc, data + sizeof root,
root.length - sizeof root);
sp = relocate_symtab (data);
RELOCATE (((struct symbol_root *)data)->sourcevector);
relocate_sourcevector (((struct symbol_root *)data)->sourcevector);
sp->next = chain;
chain = sp;
sp->linetable = (struct linetable *) ((struct symbol_root *)data)->sourcevector;
}
return chain;

View File

@ -1,5 +1,6 @@
/* GDB symbol table format definitions.
Copyright (C) 1986 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@mcc.com)
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
@ -77,15 +78,16 @@ struct symbol_root
int textrel; /* Relocation for text addresses */
int datarel; /* Relocation for data addresses */
int bssrel; /* Relocation for bss addresses */
char *filename; /* Name of source file compiled */
char *filename; /* Name of main source file compiled */
char *filedir; /* Name of directory it was reached from */
struct blockvector *blockvector; /* Vector of all symbol naming blocks */
struct blockvector *blockvector; /* Vector of all symbol-naming blocks */
struct typevector *typevector; /* Vector of all data types */
enum language language; /* Code identifying the language used */
char *version; /* Version info. Not fully specified */
char *compilation; /* Compilation info. Not fully specified */
int databeg; /* Address within the file of data start */
int bssbeg; /* Address within the file of bss start */
struct sourcevector *sourcevector; /* Vector of line-number info */
};
/* All data types of symbols in the compiled program
@ -95,7 +97,7 @@ struct symbol_root
struct typevector
{
int length;
int length; /* Number of types described */
struct type *type[1];
};
@ -116,6 +118,10 @@ enum type_code
TYPE_CODE_SET, /* Pascal sets */
TYPE_CODE_RANGE, /* Range (integers within spec'd bounds) */
TYPE_CODE_PASCAL_ARRAY, /* Array with explicit type of index */
/* C++ */
TYPE_CODE_MPTR, /* Member pointer type */
TYPE_CODE_REF, /* C++ Reference types */
};
/* This appears in a type's flags word for an unsigned integer type. */
@ -143,11 +149,22 @@ struct type
The debugger may add the address of such a type
if it has to construct one later. */
struct type *pointer_type;
/* C++: also need a reference type. */
struct type *reference_type;
/* Type that is a function returning this type.
Zero if no such function type is known here.
The debugger may add the address of such a type
if it has to construct one later. */
struct type *function_type;
/* Handling of pointers to members:
TYPE_MAIN_VARIANT is used for pointer and pointer
to member types. Normally it the value of the address of its
containing type. However, for pointers to members, we must be
able to allocate pointer to member types and look them up
from some place of reference. */
struct type *main_variant;
/* Flags about this type. */
short flags;
/* Number of fields described for this type */
@ -184,6 +201,75 @@ struct type
Zero for range bounds and array domains. */
char *name;
} *fields;
/* C++ */
int *private_field_bits;
int *protected_field_bits;
/* Some flags to make life easier. */
unsigned char has_constructor;
unsigned char has_destructor;
/* Number of methods described for this type */
short nfn_fields;
/* Number of methods described for this type plus all the
methods that it derives from. */
int nfn_fields_total;
/* For classes, structures, and unions, a description of each field,
which consists of an overloaded name, followed by the types of
arguments that the method expects, and then the name after it
has been renamed to make it distinct. */
struct fn_fieldlist
{
/* The overloaded name. */
char *name;
/* The number of methods with this name. */
int length;
/* The list of methods. */
struct fn_field
{
#if 0
/* The overloaded name */
char *name;
#endif
/* The type of the argument */
struct type *type;
/* The argument list */
struct type **args;
/* The name after it has been processed */
char *physname;
/* If this is a virtual function, the offset into the vtbl-1,
else 0. */
int voffset;
} *fn_fields;
int *private_fn_field_bits;
int *protected_fn_field_bits;
} *fn_fieldlists;
unsigned char via_protected;
unsigned char via_public;
/* For types with virtual functions, VPTR_BASETYPE is the base class which
defined the virtual function table pointer. VPTR_FIELDNO is
the field number of that pointer in the structure.
For types that are pointer to member types, VPTR_BASETYPE
ifs the type that this pointer is a member of.
Unused otherwise. */
struct type *vptr_basetype;
int vptr_fieldno;
/* If this type has a base class, put it here.
If this type is a pointer type, the chain of member pointer
types goes here.
Unused otherwise. */
struct type *baseclass;
};
/* All of the name-scope contours of the program
@ -321,3 +407,37 @@ struct symbol
}
value;
};
/* Source-file information.
This describes the relation between source files and line numbers
and addresses in the program text. */
struct sourcevector
{
int length; /* Number of source files described */
struct source *source[1]; /* Descriptions of the files */
};
/* Each item is either minus a line number, or a program counter.
If it represents a line number, that is the line described by the next
program counter value. If it is positive, it is the program
counter at which the code for the next line starts.
Consecutive lines can be recorded by program counter entries
with no line number entries between them. Line number entries
are used when there are lines to skip with no code on them.
This is to make the table shorter. */
struct linetable
{
int nitems;
int item[1];
};
/* All the information on one source file. */
struct source
{
char *name; /* Name of file */
struct linetable contents;
};

View File

@ -1,5 +1,5 @@
/* Symbol table lookup for the GNU debugger, GDB.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
@ -26,10 +26,6 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include <stdio.h>
#include <obstack.h>
#ifdef mac_aux
#define REGCMP
#endif
START_FILE
/* Allocate an obstack to hold objects that should be freed
@ -143,7 +139,7 @@ lookup_struct (name, block)
if (sym == 0)
error ("No struct type named %s.", name);
if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_STRUCT)
error ("This context has union or enum %s, not a struct.", name);
error ("This context has class, union or enum %s, not a struct.", name);
return SYMBOL_TYPE (sym);
}
@ -159,7 +155,7 @@ lookup_union (name, block)
if (sym == 0)
error ("No union type named %s.", name);
if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_UNION)
error ("This context has struct or enum %s, not a union.", name);
error ("This context has class, struct or enum %s, not a union.", name);
return SYMBOL_TYPE (sym);
}
@ -175,19 +171,22 @@ lookup_enum (name, block)
if (sym == 0)
error ("No enum type named %s.", name);
if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_ENUM)
error ("This context has struct or union %s, not an enum.", name);
error ("This context has class, struct or union %s, not an enum.", name);
return SYMBOL_TYPE (sym);
}
/* Given a type TYPE, return a type of pointers to that type.
May need to construct such a type if this is the first use. */
May need to construct such a type if this is the first use.
C++: use TYPE_MAIN_VARIANT and TYPE_CHAIN to keep pointer
to member types under control. */
struct type *
lookup_pointer_type (type)
struct type *type;
{
register struct type *ptype = TYPE_POINTER_TYPE (type);
if (ptype) return ptype;
if (ptype) return TYPE_MAIN_VARIANT (ptype);
/* This is the first time anyone wanted a pointer to a TYPE. */
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
@ -197,6 +196,7 @@ lookup_pointer_type (type)
sizeof (struct type));
bzero (ptype, sizeof (struct type));
TYPE_MAIN_VARIANT (ptype) = ptype;
TYPE_TARGET_TYPE (ptype) = type;
TYPE_POINTER_TYPE (type) = ptype;
/* New type is permanent if type pointed to is permanent. */
@ -208,12 +208,100 @@ lookup_pointer_type (type)
return ptype;
}
struct type *
lookup_reference_type (type)
struct type *type;
{
register struct type *rtype = TYPE_REFERENCE_TYPE (type);
if (rtype) return TYPE_MAIN_VARIANT (rtype);
/* This is the first time anyone wanted a pointer to a TYPE. */
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
rtype = (struct type *) xmalloc (sizeof (struct type));
else
rtype = (struct type *) obstack_alloc (symbol_obstack,
sizeof (struct type));
bzero (rtype, sizeof (struct type));
TYPE_MAIN_VARIANT (rtype) = rtype;
TYPE_TARGET_TYPE (rtype) = type;
TYPE_REFERENCE_TYPE (type) = rtype;
/* New type is permanent if type pointed to is permanent. */
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
TYPE_FLAGS (rtype) |= TYPE_FLAG_PERM;
/* We assume the machine has only one representation for pointers! */
TYPE_LENGTH (rtype) = sizeof (char *);
TYPE_CODE (rtype) = TYPE_CODE_REF;
return rtype;
}
/* Given a type TYPE, return a type of pointers to that type.
May need to construct such a type if this is the first use.
The TYPE is the type of the member. The DOMAIN is the type
of the aggregate that the member belongs to. */
struct type *
lookup_member_pointer_type (type, domain)
struct type *type, *domain;
{
register struct type *ptype = TYPE_POINTER_TYPE (type);
struct type *main_type;
if (ptype)
{
ptype = TYPE_MAIN_VARIANT (ptype);
main_type = ptype;
while (ptype)
{
if (TYPE_DOMAIN_TYPE (ptype) == domain)
return ptype;
ptype = TYPE_CHAIN (ptype);
}
}
else
{
main_type = lookup_pointer_type (type);
TYPE_POINTER_TYPE (type) = main_type;
}
/* This is the first time anyone wanted a pointer to a TYPE. */
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
ptype = (struct type *) xmalloc (sizeof (struct type));
else
ptype = (struct type *) obstack_alloc (symbol_obstack,
sizeof (struct type));
bzero (ptype, sizeof (struct type));
TYPE_MAIN_VARIANT (ptype) = main_type;
TYPE_TARGET_TYPE (ptype) = type;
TYPE_DOMAIN_TYPE (ptype) = domain;
TYPE_POINTER_TYPE (type) = ptype;
/* New type is permanent if type pointed to is permanent. */
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
TYPE_FLAGS (ptype) |= TYPE_FLAG_PERM;
/* We assume the machine has only one representation for pointers! */
TYPE_LENGTH (ptype) = sizeof (char *);
TYPE_CODE (ptype) = TYPE_CODE_MPTR;
/* Now splice in the new member pointer type. */
if (main_type)
{
/* This type was not "smashed". */
TYPE_CHAIN (ptype) = TYPE_CHAIN (main_type);
TYPE_CHAIN (main_type) = ptype;
}
return ptype;
}
/* Given a type TYPE, return a type of functions that return that type.
May need to construct such a type if this is the first use. */
struct type *
lookup_function_type (type)
lookup_function_type (type, argtypes)
struct type *type;
struct type **argtypes;
{
register struct type *ptype = TYPE_FUNCTION_TYPE (type);
if (ptype) return ptype;
@ -251,6 +339,8 @@ smash_to_pointer_type (type, to_type)
TYPE_LENGTH (type) = sizeof (char *);
TYPE_CODE (type) = TYPE_CODE_PTR;
TYPE_MAIN_VARIANT (type) = type;
if (TYPE_POINTER_TYPE (to_type) == 0
&& !(TYPE_FLAGS (type) & TYPE_FLAG_PERM))
{
@ -258,6 +348,56 @@ smash_to_pointer_type (type, to_type)
}
}
/* Smash TYPE to be a type of pointers to TO_TYPE.
If TO_TYPE is not permanent and has no pointer-type yet,
record TYPE as its pointer-type.
TYPE is the type of the member. DOMAIN is the type of
the aggregate that the member belongs to. */
void
smash_to_member_pointer_type (type, domain, to_type)
struct type *type, *domain, *to_type;
{
bzero (type, sizeof (struct type));
TYPE_TARGET_TYPE (type) = to_type;
TYPE_DOMAIN_TYPE (type) = domain;
/* We assume the machine has only one representation for pointers! */
TYPE_LENGTH (type) = sizeof (char *);
TYPE_CODE (type) = TYPE_CODE_MPTR;
TYPE_MAIN_VARIANT (type) = lookup_pointer_type (to_type);
if (TYPE_POINTER_TYPE (to_type) == 0
&& !(TYPE_FLAGS (type) & TYPE_FLAG_PERM))
{
TYPE_POINTER_TYPE (to_type) = type;
}
}
/* Smash TYPE to be a type of reference to TO_TYPE.
If TO_TYPE is not permanent and has no pointer-type yet,
record TYPE as its pointer-type. */
void
smash_to_reference_type (type, to_type)
struct type *type, *to_type;
{
bzero (type, sizeof (struct type));
TYPE_TARGET_TYPE (type) = to_type;
/* We assume the machine has only one representation for pointers! */
TYPE_LENGTH (type) = sizeof (char *);
TYPE_CODE (type) = TYPE_CODE_REF;
TYPE_MAIN_VARIANT (type) = type;
if (TYPE_REFERENCE_TYPE (to_type) == 0
&& !(TYPE_FLAGS (type) & TYPE_FLAG_PERM))
{
TYPE_REFERENCE_TYPE (to_type) = type;
}
}
/* Smash TYPE to be a type of functions returning TO_TYPE.
If TO_TYPE is not permanent and has no function-type yet,
record TYPE as its function-type. */
@ -285,6 +425,62 @@ static struct symbol *lookup_block_symbol ();
in namespace NAMESPACE, visible from lexical block BLOCK.
Returns the struct symbol pointer, or zero if no symbol is found. */
struct symbol *
lookup_symbol_1 (name, block, namespace)
char *name;
register struct block *block;
enum namespace namespace;
{
register int i, n;
register struct symbol *sym;
register struct symtab *s;
struct blockvector *bv;
/* Search specified block and its superiors. */
while (block != 0)
{
sym = lookup_block_symbol (block, name, namespace);
if (sym) return sym;
block = BLOCK_SUPERBLOCK (block);
}
return 0;
}
struct symbol *
lookup_symbol_2 (name, block, namespace)
char *name;
register struct block *block; /* ignored as parameter */
enum namespace namespace;
{
register int i, n;
register struct symbol *sym;
register struct symtab *s;
struct blockvector *bv;
/* Now search all symtabs' global blocks. */
for (s = symtab_list; s; s = s->next)
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, 0);
sym = lookup_block_symbol (block, name, namespace);
if (sym) return sym;
}
/* Now search all symtabs' per-file blocks.
Not strictly correct, but more useful than an error. */
for (s = symtab_list; s; s = s->next)
{
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, 1);
sym = lookup_block_symbol (block, name, namespace);
if (sym) return sym;
}
return 0;
}
struct symbol *
lookup_symbol (name, block, namespace)
char *name;
@ -558,6 +754,26 @@ find_pc_line (pc, notcurrent)
}
return value;
}
/* Find the PC value for a given source file and line number.
Returns zero for invalid line number.
The source file is specified with a struct symtab. */
CORE_ADDR
find_line_pc (symtab, line)
struct symtab *symtab;
int line;
{
register struct linetable *l;
register int index;
int dummy;
if (symtab == 0)
return 0;
l = LINETABLE (symtab);
index = find_line_common(l, line, &dummy);
return index ? l->item[index] : 0;
}
/* Find the range of pc values in a line.
Store the starting pc of the line into *STARTPTR
@ -572,8 +788,8 @@ find_line_pc_range (symtab, thisline, startptr, endptr)
CORE_ADDR *startptr, *endptr;
{
register struct linetable *l;
register int i, line, item;
int len;
register int index;
int exact_match; /* did we get an exact linenumber match */
register CORE_ADDR prev_pc;
CORE_ADDR last_pc;
@ -581,78 +797,82 @@ find_line_pc_range (symtab, thisline, startptr, endptr)
return 0;
l = LINETABLE (symtab);
len = l->nitems;
prev_pc = -1;
for (i = 0; i < len; i++)
index = find_line_common (l, thisline, &exact_match);
if (index)
{
item = l->item[i];
if (item < 0)
line = - item - 1;
*startptr = l->item[index];
/* If we have not seen an entry for the specified line,
assume that means the specified line has zero bytes. */
if (!exact_match || index == l->nitems-1)
*endptr = *startptr;
else
{
line++;
/* As soon as we find a line following the specified one
we know the end pc and can return. */
if (line > thisline)
{
/* If we have not seen an entry for the specified line,
assume that means the specified line has zero bytes. */
*startptr = prev_pc == -1 ? item : prev_pc;
*endptr = item;
return 1;
}
/* If we see an entry for the specified line,
it gives the beginning. */
if (line == thisline)
prev_pc = item;
last_pc = item;
}
}
if (prev_pc != -1)
{
/* If we found the specified line but no later line, it's file's last.
Its range is from line's pc to file's end pc. */
*startptr = last_pc;
*endptr = BLOCK_END (BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), 0));
/* Perhaps the following entry is for the following line.
It's worth a try. */
if (l->item[index+1] > 0)
*endptr = l->item[index+1];
else
*endptr = find_line_pc (symtab, thisline+1);
return 1;
}
return 0;
}
/* Find the PC value for a given source file and line number.
Returns zero for invalid line number.
The source file is specified with a struct symtab. */
/* Given a line table and a line number, return the index into the line
table for the pc of the nearest line whose number is >= the specified one.
Return 0 if none is found. The value is never zero is it is an index.
CORE_ADDR
find_line_pc (symtab, line)
struct symtab *symtab;
int line;
Set *EXACT_MATCH nonzero if the value returned is an exact match. */
static int
find_line_common (l, lineno, exact_match)
register struct linetable *l;
register int lineno;
int *exact_match;
{
register struct linetable *l;
register int len;
register int i;
register int item;
register int nextline = -1;
register int len;
if (line <= 0)
/* BEST is the smallest linenumber > LINENO so far seen,
or 0 if none has been seen so far.
BEST_INDEX identifies the item for it. */
int best_index = 0;
int best = 0;
int nextline = -1;
if (lineno <= 0)
return 0;
l = LINETABLE (symtab);
len = l->nitems;
for (i = 0; i < len; i++)
{
item = l->item[i];
register int item = l->item[i];
if (item < 0)
nextline = - item - 1;
else
{
nextline++;
if (line <= nextline)
return item;
if (nextline == lineno)
{
*exact_match = 1;
return i;
}
if (nextline > lineno && (best == 0 || nextline < best))
{
best = lineno;
best_index = i;
}
}
}
return 0;
/* If we got here, we didn't get an exact match. */
*exact_match = 0;
return best_index;
}
int
@ -694,13 +914,15 @@ find_pc_line_pc_range (pc, startptr, endptr)
if no file is validly specified. Callers must check that.
Also, the line number returned may be invalid. */
struct symtab_and_line
struct symtabs_and_lines
decode_line_1 (argptr, funfirstline, default_symtab, default_line)
char **argptr;
int funfirstline;
struct symtab *default_symtab;
int default_line;
{
struct symtabs_and_lines decode_line_2 ();
struct symtabs_and_lines values;
struct symtab_and_line value;
register char *p, *p1;
register struct symtab *s;
@ -708,7 +930,14 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line)
register CORE_ADDR pc;
register int i;
char *copy;
struct symbol *sym_class;
char *class_name, *method_name, *phys_name;
int method_counter;
int i1;
struct symbol **sym_arr;
struct type *t, *field;
char **physnames;
/* Defaults have defaults. */
if (default_symtab == 0)
@ -723,9 +952,11 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line)
{
(*argptr)++;
pc = parse_and_eval_address_1 (argptr);
value = find_pc_line (pc, 0);
value.pc = pc;
return value;
values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
values.nelts = 1;
values.sals[0] = find_pc_line (pc, 0);
values.sals[0].pc = pc;
return values;
}
/* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
@ -741,6 +972,125 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line)
if (p[0] == ':')
{
/* C++ */
if (p[1] ==':')
{
/* Extract the class name. */
p1 = p;
while (p != *argptr && p[-1] == ' ') --p;
copy = (char *) alloca (p - *argptr + 1);
bcopy (*argptr, copy, p - *argptr);
copy[p - *argptr] = 0;
/* Discard the class name from the arg. */
p = p1 + 2;
while (*p == ' ' || *p == '\t') p++;
*argptr = p;
sym_class = lookup_symbol (copy, 0, STRUCT_NAMESPACE);
if (sym_class &&
(TYPE_CODE (SYMBOL_TYPE (sym_class)) == TYPE_CODE_STRUCT
|| TYPE_CODE (SYMBOL_TYPE (sym_class)) == TYPE_CODE_UNION))
{
/* Arg token is not digits => try it as a function name
Find the next token (everything up to end or next whitespace). */
p = *argptr;
while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p !=':') p++;
copy = (char *) alloca (p - *argptr + 1);
bcopy (*argptr, copy, p - *argptr);
copy[p - *argptr] = '\0';
/* no line number may be specified */
while (*p == ' ' || *p == '\t') p++;
*argptr = p;
sym = 0;
i1 = 0; /* counter for the symbol array */
t = SYMBOL_TYPE (sym_class);
sym_arr = (struct symbol **) alloca(TYPE_NFN_FIELDS_TOTAL (t) * sizeof(struct symbol*));
physnames = (char **) alloca (TYPE_NFN_FIELDS_TOTAL (t) * sizeof(char*));
if (destructor_name_p (copy, t))
{
/* destructors are a special case. */
struct fn_field *f = TYPE_FN_FIELDLIST1 (t, 0);
int len = TYPE_FN_FIELDLIST_LENGTH (t, 0) - 1;
phys_name = TYPE_FN_FIELD_PHYSNAME (f, len);
physnames[i1] = (char *)alloca (strlen (phys_name) + 1);
strcpy (physnames[i1], phys_name);
sym_arr[i1] = lookup_symbol (phys_name, SYMBOL_BLOCK_VALUE (sym_class), VAR_NAMESPACE);
if (sym_arr[i1]) i1++;
}
else while (t)
{
int constructor_p;
class_name = TYPE_NAME (t);
while (*class_name++ != ' ');
constructor_p = ! strcmp (class_name, copy);
sym_class = lookup_symbol (class_name, 0, STRUCT_NAMESPACE);
for (method_counter = TYPE_NFN_FIELDS (SYMBOL_TYPE (sym_class)) - 1;
method_counter >= 0;
--method_counter)
{
int field_counter;
struct fn_field *f =
TYPE_FN_FIELDLIST1 (SYMBOL_TYPE (sym_class), method_counter);
method_name = TYPE_FN_FIELDLIST_NAME (SYMBOL_TYPE (sym_class), method_counter);
if (!strcmp (copy, method_name))
for (field_counter = TYPE_FN_FIELDLIST_LENGTH (SYMBOL_TYPE (sym_class), method_counter) - (1 + constructor_p);
field_counter >= 0;
--field_counter)
{
phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
physnames[i1] = (char*) alloca (strlen (phys_name) + 1);
strcpy (physnames[i1], phys_name);
sym_arr[i1] = lookup_symbol (phys_name, SYMBOL_BLOCK_VALUE (sym_class), VAR_NAMESPACE);
if (sym_arr[i1]) i1++;
}
}
t = TYPE_BASECLASS(t);
}
if (i1 == 1)
{
sym = sym_arr[0];
if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
{
/* Arg is the name of a function */
pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) + FUNCTION_START_OFFSET;
if (funfirstline)
SKIP_PROLOGUE (pc);
values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
values.nelts = 1;
values.sals[0] = find_pc_line (pc, 0);
values.sals[0].pc = (values.sals[0].end && values.sals[0].pc != pc) ? values.sals[0].end : pc;
}
else
{
values.nelts = 0;
}
return values;
}
if (i1 > 0)
{
return decode_line_2 (argptr, sym_arr, physnames, i1, funfirstline);
}
else
error ("that class does not have any method named %s",copy);
}
else
error("no class, struct, or union named %s", copy );
}
/* end of C++ */
/* Extract the file name. */
p1 = p;
while (p != *argptr && p[-1] == ' ') --p;
@ -807,7 +1157,10 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line)
s = default_symtab;
value.symtab = s;
value.pc = 0;
return value;
values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
values.sals[0] = value;
values.nelts = 1;
return values;
}
/* Arg token is not digits => try it as a function name
@ -834,41 +1187,157 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line)
SKIP_PROLOGUE (pc);
value = find_pc_line (pc, 0);
value.pc = (value.end && value.pc != pc) ? value.end : pc;
return value;
values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
values.sals[0] = value;
values.nelts = 1;
return values;
}
if (sym)
error ("%s is not a function.", copy);
for (i = 0; i < misc_function_count; i++)
if (!strcmp (misc_function_vector[i].name, copy))
{
value.symtab = 0;
value.line = 0;
value.pc = misc_function_vector[i].address + FUNCTION_START_OFFSET;
if (funfirstline)
SKIP_PROLOGUE (value.pc);
return value;
}
if ((i = lookup_misc_func (copy)) < 0)
error ("Function %s not defined.", copy);
else
{
value.symtab = 0;
value.line = 0;
value.pc = misc_function_vector[i].address + FUNCTION_START_OFFSET;
if (funfirstline)
SKIP_PROLOGUE (value.pc);
values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
values.sals[0] = value;
values.nelts = 1;
return values;
}
if (symtab_list == 0)
error ("No symbol table is loaded. Use the \"symbol-file\" command.");
error ("Function %s not defined.", copy);
}
struct symtab_and_line
struct symtabs_and_lines
decode_line_spec (string, funfirstline)
char *string;
int funfirstline;
{
struct symtab_and_line sal;
struct symtabs_and_lines sals;
if (string == 0)
error ("Empty line specification.");
sal = decode_line_1 (&string, funfirstline,
current_source_symtab, current_source_line);
sals = decode_line_1 (&string, funfirstline,
current_source_symtab, current_source_line);
if (*string)
error ("Junk at end of line specification: %s", string);
return sal;
return sals;
}
struct symtabs_and_lines
decode_line_2 (argptr, sym_arr, physnames, nelts, funfirstline)
char **argptr;
struct symbol *sym_arr[];
char *physnames[];
int nelts;
int funfirstline;
{
char *getenv();
struct symtabs_and_lines values, return_values;
register CORE_ADDR pc;
char *args, *arg1, *read_line ();
int i;
char *prompt;
values.sals = (struct symtab_and_line *) alloca (nelts * sizeof(struct symtab_and_line));
return_values.sals = (struct symtab_and_line *) malloc (nelts * sizeof(struct symtab_and_line));
i = 0;
printf("[0] cancel\n[1] all\n");
while (i < nelts)
{
if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
{
/* Arg is the name of a function */
pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym_arr[i]))
+ FUNCTION_START_OFFSET;
if (funfirstline)
SKIP_PROLOGUE (pc);
values.sals[i] = find_pc_line (pc, 0);
printf("[%d] file:%s; line number:%d\n",
(i+2), values.sals[i].symtab->filename, values.sals[i].line);
}
else printf ("?HERE\n");
i++;
}
if ((prompt = getenv ("PS2")) == NULL)
{
prompt = ">";
}
printf("%s ",prompt);
fflush(stdout);
args = read_line (0);
if (args == 0)
error_no_arg ("one or more choice numbers");
i = 0;
while (*args)
{
int num;
arg1 = args;
while (*arg1 >= '0' && *arg1 <= '9') arg1++;
if (*arg1 && *arg1 != ' ' && *arg1 != '\t')
error ("Arguments must be choice numbers.");
num = atoi (args);
if (num == 0)
error ("cancelled");
else if (num == 1)
{
bcopy (values.sals, return_values.sals, (nelts * sizeof(struct symtab_and_line)));
return_values.nelts = nelts;
return return_values;
}
if (num > nelts + 2)
{
printf ("No choice number %d.\n", num);
}
else
{
num -= 2;
if (values.sals[num].pc)
{
return_values.sals[i++] = values.sals[num];
values.sals[num].pc = 0;
}
else
{
printf ("duplicate request for %d ignored.\n", num);
}
}
args = arg1;
while (*args == ' ' || *args == '\t') args++;
}
return_values.nelts = i;
return return_values;
}
/* Return the index of misc function named NAME. */
static
lookup_misc_func (name)
register char *name;
{
register int i;
for (i = 0; i < misc_function_count; i++)
if (!strcmp (misc_function_vector[i].name, name))
return i;
return -1; /* not found */
}
static void
@ -930,25 +1399,15 @@ list_symbols (regexp, class)
register struct block *b;
register int i, j;
register struct symbol *sym;
char *val = 0;
char *val;
int found_in_file;
static char *classnames[]
= {"variable", "function", "type"};
= {"variable", "function", "type", "method"};
int print_count = 0;
#ifdef REGCMP
extern char *regcmp(), *regex(), *loc1;
#endif
if (regexp) {
#ifdef REGCMP
val = regcmp(regexp, (char *)0);
if (val == 0)
error ("Invalid regexp: %s", regexp);
#else
if (regexp)
if (val = (char *) re_comp (regexp))
error ("Invalid regexp: %s", val);
#endif
}
printf (regexp
? "All %ss matching regular expression \"%s\":\n"
@ -973,19 +1432,12 @@ list_symbols (regexp, class)
{
QUIT;
sym = BLOCK_SYM (b, j);
if (regexp) {
#ifdef REGCMP
if (!regex(val, SYMBOL_NAME (sym)))
continue;
#else
if (!re_exec (SYMBOL_NAME (sym)))
continue;
#endif
}
if ((class == 0 && SYMBOL_CLASS (sym) != LOC_TYPEDEF
if ((regexp == 0 || re_exec (SYMBOL_NAME (sym)))
&& ((class == 0 && SYMBOL_CLASS (sym) != LOC_TYPEDEF
&& SYMBOL_CLASS (sym) != LOC_BLOCK)
|| (class == 1 && SYMBOL_CLASS (sym) == LOC_BLOCK)
|| (class == 2 && SYMBOL_CLASS (sym) == LOC_TYPEDEF))
|| (class == 2 && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
|| (class == 3 && SYMBOL_CLASS (sym) == LOC_BLOCK)))
{
if (!found_in_file)
{
@ -1000,26 +1452,35 @@ list_symbols (regexp, class)
&& SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE)
printf ("typedef ");
type_print (SYMBOL_TYPE (sym),
(SYMBOL_CLASS (sym) == LOC_TYPEDEF
? "" : SYMBOL_NAME (sym)),
stdout, 0);
if (class < 3)
{
type_print (SYMBOL_TYPE (sym),
(SYMBOL_CLASS (sym) == LOC_TYPEDEF
? "" : SYMBOL_NAME (sym)),
stdout, 0);
printf (";\n");
}
else
{
char buf[1024];
# if 0
type_print_base (TYPE_FN_FIELD_TYPE(t, i), stdout, 0, 0);
type_print_varspec_prefix (TYPE_FN_FIELD_TYPE(t, i), stdout, 0);
sprintf (buf, " %s::", TYPE_NAME (t));
type_print_method_args (TYPE_FN_FIELD_ARGS (t, i), buf, name, stdout);
# endif
}
if (class == 2
&& SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE
&& (TYPE_NAME ((SYMBOL_TYPE (sym))) == 0
|| 0 != strcmp (TYPE_NAME ((SYMBOL_TYPE (sym))),
SYMBOL_NAME (sym))))
printf (" %s", SYMBOL_NAME (sym));
printf (";\n");
}
}
}
prev_bv = bv;
}
#ifdef REGCMP
if (val)
(void)free(val);
#endif
}
static void
@ -1042,6 +1503,13 @@ types_info (regexp)
{
list_symbols (regexp, 2);
}
static void
methods_info (regexp)
char *regexp;
{
list_symbols (regexp, 3);
}
/* Initialize the standard C scalar types. */
@ -1056,6 +1524,7 @@ init_type (code, length, uns, name)
type = (struct type *) xmalloc (sizeof (struct type));
bzero (type, sizeof *type);
TYPE_MAIN_VARIANT (type) = type;
TYPE_CODE (type) = code;
TYPE_LENGTH (type) = length;
TYPE_FLAGS (type) = uns ? TYPE_FLAG_UNSIGNED : 0;
@ -1063,6 +1532,9 @@ init_type (code, length, uns, name)
TYPE_NFIELDS (type) = 0;
TYPE_NAME (type) = name;
/* C++ fancies. */
TYPE_NFN_FIELDS (type) = 0;
TYPE_BASECLASS (type) = 0;
return type;
}
@ -1075,6 +1547,11 @@ initialize ()
"All function names, or those matching REGEXP.");
add_info ("types", types_info,
"All types names, or those matching REGEXP.");
add_info ("methods", methods_info,
"All method names, or those matching REGEXP::REGEXP.\n\
If the class qualifier is ommited, it is assumed to be the current scope.\n\
If the first REGEXP is ommited, then all methods matching the second REGEXP\n\
are listed.");
add_info ("sources", sources_info,
"Source files in the program.");

View File

@ -53,8 +53,8 @@ int misc_function_count;
#include "symseg.h"
/* Each source file is represented by a struct symtab.
These objects are chained through the `next' field. */
/* Each source file is represented by a struct symtab. */
/* These objects are chained through the `next' field. */
struct symtab
{
@ -70,13 +70,12 @@ struct symtab
char *filename;
/* This component says how to free the data we point to:
free_contents => do a tree walk and free each object.
free_explicit => free what free_ptr points at, and the linetable.
free_nothing => do nothing; some other symtab will free
the data this one uses.
free_linetable => free just the linetable. */
enum free_code {free_nothing, free_contents, free_explicit, free_linetable}
enum free_code {free_nothing, free_contents, free_linetable}
free_code;
/* Pointer to one block storage to be freed, if nonzero. */
/* Pointer to one block of storage to be freed, if nonzero. */
char *free_ptr;
/* Total number of lines found in source file. */
int nlines;
@ -91,6 +90,9 @@ struct symtab
/* Offset within loader symbol table
of first local symbol for this file. */
int ldsymoff;
/* Full name of file as found by searching the source path.
0 if not yet known. */
char *fullname;
};
/* This is the list of struct symtab's that gdb considers current. */
@ -113,24 +115,6 @@ int current_source_line;
#define LINELIST(symtab) (symtab)->linetable
#define LINETABLE(symtab) (symtab)->linetable
/* Recording the code addresses of source lines. */
struct linetable
{
int nitems;
int item[1];
};
/* Each item is either minus a line number, or a program counter.
If it represents a line number, that is the line described by the next
program counter value. If it is positive, it is the program
counter at which the code for the next line starts.
Consecutive lines can be recorded by program counter entries
with no line number entries between them. Line number entries
are used when there are lines to skip with no code on them.
This is to make the table shorter. */
/* Macros normally used to access components of symbol table structures. */
#define BLOCKLIST_NBLOCKS(blocklist) (blocklist)->nblocks
@ -161,16 +145,34 @@ struct linetable
These types are never freed. */
#define TYPE_FLAG_PERM 4
/* Some macros for bitfields. */
#define B_SET(a,x) (a[x>>5] |= (1 << (x&31)))
#define B_CLR(a,x) (a[x>>5] &= ~(1 << (x&31)))
#define B_TST(a,x) (a[x>>5] & (1 << (x&31)))
#define TYPE_NAME(thistype) (thistype)->name
#define TYPE_TARGET_TYPE(thistype) (thistype)->target_type
#define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type
#define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type
#define TYPE_FUNCTION_TYPE(thistype) (thistype)->function_type
#define TYPE_MAIN_VARIANT(thistype) (thistype)->main_variant
#define TYPE_LENGTH(thistype) (thistype)->length
#define TYPE_FLAGS(thistype) (thistype)->flags
#define TYPE_UNSIGNED(thistype) ((thistype)->flags & TYPE_FLAG_UNSIGNED)
#define TYPE_CODE(thistype) (thistype)->code
#define TYPE_NFIELDS(thistype) (thistype)->nfields
#define TYPE_FIELDS(thistype) (thistype)->fields
/* C++ */
#define TYPE_VPTR_BASETYPE(thistype) (thistype)->vptr_basetype
#define TYPE_DOMAIN_TYPE(thistype) (thistype)->vptr_basetype
#define TYPE_VPTR_FIELDNO(thistype) (thistype)->vptr_fieldno
#define TYPE_FN_FIELDS(thistype) (thistype)->fn_fields
#define TYPE_NFN_FIELDS(thistype) (thistype)->nfn_fields
#define TYPE_NFN_FIELDS_TOTAL(thistype) (thistype)->nfn_fields_total
#define TYPE_BASECLASS(thistype) (thistype)->baseclass
#define TYPE_VIA_PUBLIC(thistype) (thistype)->via_public
#define TYPE_VIA_PROTECTED(thistype) (thistype)->via_protected
#define TYPE_CHAIN(thistype) (thistype)->baseclass
#define TYPE_FIELD(thistype, n) (thistype)->fields[n]
#define TYPE_FIELD_TYPE(thistype, n) (thistype)->fields[n].type
@ -179,11 +181,46 @@ struct linetable
#define TYPE_FIELD_BITPOS(thistype, n) (thistype)->fields[n].bitpos
#define TYPE_FIELD_BITSIZE(thistype, n) (thistype)->fields[n].bitsize
#define TYPE_FIELD_PACKED(thistype, n) (thistype)->fields[n].bitsize
#define TYPE_FIELD_PRIVATE_BITS(thistype) (thistype)->private_field_bits
#define TYPE_FIELD_PROTECTED_BITS(thistype) (thistype)->protected_field_bits
#define SET_TYPE_FIELD_PRIVATE(thistype, n) B_SET ((thistype)->private_field_bits, (n))
#define SET_TYPE_FIELD_PROTECTED(thistype, n) B_SET ((thistype)->protected_field_bits, (n))
#define TYPE_FIELD_PRIVATE(thistype, n) B_TST((thistype)->private_field_bits, (n))
#define TYPE_FIELD_PROTECTED(thistype, n) B_TST((thistype)->protected_field_bits, (n))
#define TYPE_HAS_DESTRUCTOR(thistype) ((thistype)->has_destructor)
#define TYPE_HAS_CONSTRUCTOR(thistype) ((thistype)->has_constructor)
#define TYPE_FIELD_STATIC(thistype, n) ((thistype)->fields[n].bitpos == -1)
#define TYPE_FIELD_STATIC_PHYSNAME(thistype, n) ((char *)(thistype)->fields[n].bitsize)
#define TYPE_FN_FIELDLISTS(thistype) (thistype)->fn_fieldlists
#define TYPE_FN_FIELDLIST(thistype, n) (thistype)->fn_fieldlists[n]
#define TYPE_FN_FIELDLIST1(thistype, n) (thistype)->fn_fieldlists[n].fn_fields
#define TYPE_FN_FIELDLIST_NAME(thistype, n) (thistype)->fn_fieldlists[n].name
#define TYPE_FN_FIELDLIST_LENGTH(thistype, n) (thistype)->fn_fieldlists[n].length
#define TYPE_FN_FIELD(thistype) (thistype)[n]
#define TYPE_FN_FIELD_NAME(thistype, n) (thistype)[n].name
#define TYPE_FN_FIELD_TYPE(thistype, n) (thistype)[n].type
#define TYPE_FN_FIELD_ARGS(thistype, n) (thistype)[n].args
#define TYPE_FN_FIELD_PHYSNAME(thistype, n) (thistype)[n].physname
#define TYPE_FN_FIELD_VIRTUAL_P(thistype, n) (thistype)[n].voffset
#define TYPE_FN_FIELD_VOFFSET(thistype, n) ((thistype)[n].voffset-1)
#define TYPE_FN_PRIVATE_BITS(thistype) (thistype).private_fn_field_bits
#define TYPE_FN_PROTECTED_BITS(thistype) (thistype).protected_fn_field_bits
#define SET_TYPE_FN_PRIVATE(thistype, n) B_SET ((thistype).private_fn_field_bits, n)
#define SET_TYPE_FN_PROTECTED(thistype, n) B_SET ((thistype).protected_fn_field_bits, n)
#define TYPE_FN_PRIVATE(thistype, n) B_TST ((thistype).private_fn_field_bits, n)
#define TYPE_FN_PROTECTED(thistype, n) B_TST ((thistype).protected_fn_field_bits, n)
/* Functions that work on the objects described above */
extern struct symtab *lookup_symtab ();
extern struct symbol *lookup_symbol ();
extern struct symbol *lookup_symbol_1 (), *lookup_symbol_2 ();
extern struct type *lookup_typename ();
extern struct type *lookup_unsigned_typename ();
extern struct type *lookup_struct ();
@ -195,6 +232,12 @@ extern struct symbol *block_function ();
extern struct symbol *find_pc_function ();
extern int find_pc_misc_function ();
/* C++ stuff. */
extern struct type *lookup_reference_type ();
extern struct type *lookup_member_pointer_type ();
extern struct type *lookup_class ();
/* end of C++ stuff. */
extern struct type *builtin_type_void;
extern struct type *builtin_type_char;
extern struct type *builtin_type_short;
@ -215,6 +258,12 @@ struct symtab_and_line
CORE_ADDR end;
};
struct symtabs_and_lines
{
struct symtab_and_line *sals;
int nelts;
};
/* Given a pc value, return line number it is in.
Second arg nonzero means if pc is on the boundary
use the previous statement's line number. */
@ -224,5 +273,5 @@ struct symtab_and_line find_pc_line ();
/* Given a string, return the line specified by it.
For commands like "list" and "breakpoint". */
struct symtab_and_line decode_line_spec ();
struct symtab_and_line decode_line_1 ();
struct symtabs_and_lines decode_line_spec ();
struct symtabs_and_lines decode_line_1 ();

View File

@ -1,13 +0,0 @@
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <stdio.h>
main ()
{
struct user u;
printf ("&u.u_ar0 - &u = %d, 0%o\n", (int) &u.u_ar0 - (int) &u,
(int) &u.u_ar0 - (int) &u);
printf ("sizeof (struct pcb) = %d, 0%o\n",
sizeof (struct pcb), sizeof (struct pcb));
}

View File

@ -1,25 +0,0 @@
enum foo {foo1, foo2};
static double statdouble;
newfun (ac)
struct haha {int a; } ac;
{
}
struct temp {int a; };
bar (a)
enum foo a;
{
static int lose;
double happy;
typedef int myint;
{
union wow { int a; char b; } wowvar;
static union wow wowvar1;
typedef int yourint;
char *winner;
}
}

View File

@ -1,10 +0,0 @@
main ()
{
int x = 0;
while (1)
{
sleep (1);
x++;
}
}

View File

@ -1,13 +0,0 @@
struct foo
{
int a : 5, : 4, b : 5;
char c;
int : 3, d : 8, : 0, e : 5;
};
struct foo x;
main ()
{
printf (x);
}

View File

@ -1,25 +0,0 @@
/* Source file for showing ENUM lossage in GDB.
Compile with "cc -o foo -g foo.c". */
enum bar { value1, value2, value3 };
struct foo {
enum bar enum_value;
int int_value;
char *pointer_value;
};
struct foo foo_instance;
struct foo *foo_instance_pointer;
main ()
{
foo_instance_pointer = &foo_instance;
foo_instance.enum_value = value2;
foo_instance.int_value = 1;
foo_instance.pointer_value = "Text to make a char *";
/* In GDB, set a breakpoint at this line. Then try to change the
value of foo_instance.enum_value in any way. I can't do it. */
}

View File

@ -1,12 +0,0 @@
main ()
{
foo(2);
foo(3);
}
foo (i)
{
printf ("i is %d, ", i);
printf ("i*i is %d\n", i * i);
}

View File

@ -1,16 +0,0 @@
main ()
{
register int ntabs;
register short x;
short stops[30];
foo ();
}
foo ()
{
register int ntabs;
register short x;
printf (x, ntabs);
}

View File

@ -1,17 +0,0 @@
# include <signal.h>
main ()
{
int handle ();
int i;
signal (SIGALRM, handle);
alarm (5);
for (i = 0; i < 100000; i++)
printf ("%d\n", i);
}
handle ()
{
printf ("signal!\n");
alarm (5);
}

View File

@ -191,9 +191,7 @@ void
quit ()
{
fflush (stdout);
#ifdef TIOCFLUSH
ioctl (fileno (stdout), TIOCFLUSH, 0);
#endif
error ("Quit");
}

View File

@ -17,7 +17,7 @@ notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "stdio.h"
#include "defs.h"
#include "initialize.h"
#include "param.h"
@ -56,11 +56,19 @@ value_cast (type, arg2)
return value_from_long (type, value_as_long (arg2));
else if (TYPE_LENGTH (type) == TYPE_LENGTH (VALUE_TYPE (arg2)))
{
if ((code1 == TYPE_CODE_MPTR) ^ (code2 == TYPE_CODE_MPTR))
printf ("warning: assignment between pointer-to-member and non pointer-to-member types\n");
VALUE_TYPE (arg2) = type;
return arg2;
}
else if (VALUE_LVAL (arg2) == lval_memory)
return value_at (type, VALUE_ADDRESS (arg2) + VALUE_OFFSET (arg2));
{
if ((code1 == TYPE_CODE_MPTR) ^ (code2 == TYPE_CODE_MPTR))
printf ("warning: assignment between pointer-to-member and non pointer-to-member types\n");
return value_at (type, VALUE_ADDRESS (arg2) + VALUE_OFFSET (arg2));
}
else
error ("Invalid cast.");
}
@ -278,6 +286,9 @@ value_ind (arg1)
{
COERCE_ARRAY (arg1);
if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_MPTR)
error ("not implemented: member pointers in value_ind");
/* Allow * on an integer so we can cast it to whatever we want. */
if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT)
return value_at (builtin_type_long,
@ -285,6 +296,9 @@ value_ind (arg1)
else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR)
return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
(CORE_ADDR) value_as_long (arg1));
else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF)
return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
(CORE_ADDR) value_as_long (arg1));
error ("Attempt to take contents of a non-pointer value.");
}
@ -411,6 +425,9 @@ call_function (function, nargs, args)
register struct type *ftype = VALUE_TYPE (function);
register enum type_code code = TYPE_CODE (ftype);
if (code == TYPE_CODE_MPTR)
error ("not implemented: member pointer to call_function");
/* Determine address to call. */
if (code == TYPE_CODE_FUNC)
{
@ -552,16 +569,24 @@ value_string (ptr, len)
/* Given ARG1, a value of type (pointer to a)* structure/union,
extract the component named NAME from the ultimate target structure/union
and return it as a value with its appropriate type.
ERR is used in the error message if ARG1's type is wrong. */
ERR is used in the error message if ARG1's type is wrong.
C++: ARGS is a list of argument types to aid in the selection of
an appropriate method. Also, handle derived types.
ERR is an error message to be printed in case the field is not found. */
value
value_struct_elt (arg1, name, err)
register value arg1;
value_struct_elt (arg1, args, name, err)
register value arg1, *args;
char *name;
char *err;
{
register struct type *t;
register int i;
int found = 0;
struct type *baseclass;
COERCE_ARRAY (arg1);
@ -569,28 +594,427 @@ value_struct_elt (arg1, name, err)
/* Follow pointers until we get to a non-pointer. */
while (TYPE_CODE (t) == TYPE_CODE_PTR)
while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
{
arg1 = value_ind (arg1);
COERCE_ARRAY (arg1);
t = VALUE_TYPE (arg1);
}
if (TYPE_CODE (t) == TYPE_CODE_MPTR)
error ("not implemented: member pointers in value_struct_elt");
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
&&
TYPE_CODE (t) != TYPE_CODE_UNION)
&& TYPE_CODE (t) != TYPE_CODE_UNION)
error ("Attempt to extract a component of a value that is not a %s.", err);
for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
{
if (!strcmp (TYPE_FIELD_NAME (t, i), name))
break;
baseclass = t;
if (!args)
{
/* if there are no arguments ...do this... */
/* Try as a variable first, because if we succeed, there
is less work to be done. */
while (t)
{
for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
{
if (!strcmp (TYPE_FIELD_NAME (t, i), name))
{
found = 1;
break;
}
}
if (i >= 0)
return TYPE_FIELD_STATIC (t, i)
? value_static_field (t, name, i) : value_field (arg1, i);
t = TYPE_BASECLASS (t);
VALUE_TYPE (arg1) = t; /* side effect! */
}
/* C++: If it was not found as a data field, then try to
return it as a pointer to a method. */
t = baseclass;
VALUE_TYPE (arg1) = t; /* side effect! */
if (destructor_name_p (name, t))
error ("use `info method' command to print out value of destructor");
while (t)
{
for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i)
{
if (! strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
{
error ("use `info method' command to print value of method \"%s\"", name);
}
}
t = TYPE_BASECLASS (t);
}
if (found == 0)
error("there is no field named %s", name);
return 0;
}
if (i < 0)
error ("Structure has no component named %s.", name);
if (destructor_name_p (name, t))
{
if (!args[1])
{
/* destructors are a special case. */
return (value)value_fn_field (arg1, 0, TYPE_FN_FIELDLIST_LENGTH (t, 0));
}
else
{
error ("destructor should not have any argument");
}
}
return value_field (arg1, i);
/* This following loop is for methods with arguments. */
while (t)
{
/* Look up as method first, because that is where we
expect to find it first. */
for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; i--)
{
struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
{
int j;
struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
found = 1;
for (j = TYPE_FN_FIELDLIST_LENGTH (t, i) - 1; j >= 0; --j)
{
if (!typecmp (TYPE_FN_FIELD_ARGS (f, j), args))
{
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
{
/* First, get the virtual function table pointer.
That comes with a strange type, so cast
it to type `pointer to long' (which
should serve just fine as a function type).
Then, index into the table, and convert
final value to appropriate function type. */
value vfn, vtbl;
value vi = value_from_long (builtin_type_int,
TYPE_FN_FIELD_VOFFSET (f, j));
VALUE_TYPE (arg1) = TYPE_VPTR_BASETYPE (t);
if (TYPE_VPTR_FIELDNO (t) < 0)
TYPE_VPTR_FIELDNO (t)
= fill_in_vptr_fieldno (t);
vtbl = value_field (arg1, TYPE_VPTR_FIELDNO (t));
vfn = value_subscript (vtbl, vi);
VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
return vfn;
}
else
return (value)value_fn_field (arg1, i, j);
}
}
}
}
t = TYPE_BASECLASS (t);
VALUE_TYPE (arg1) = t; /* side effect! */
}
if (found)
{
error ("Structure method %s not defined for arglist.", name);
return 0;
}
else
{
/* See if user tried to invoke data as function */
t = baseclass;
while (t)
{
for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
{
if (!strcmp (TYPE_FIELD_NAME (t, i), name))
{
found = 1;
break;
}
}
if (i >= 0)
return TYPE_FIELD_STATIC (t, i)
? value_static_field (t, name, i) : value_field (arg1, i);
t = TYPE_BASECLASS (t);
VALUE_TYPE (arg1) = t; /* side effect! */
}
error ("Structure has no component named %s.", name);
}
}
/* C++: return 1 is NAME is a legitimate name for the destructor
of type TYPE. If TYPE does not have a destructor, or
if NAME is inappropriate for TYPE, an error is signaled. */
int
destructor_name_p (name, type)
char *name;
struct type *type;
{
/* destructors are a special case. */
char *dname = TYPE_NAME (type);
if (name[0] == '~')
{
if (! TYPE_HAS_DESTRUCTOR (type))
error ("type `%s' does not have destructor defined",
TYPE_NAME (type));
/* Skip past the "struct " at the front. */
while (*dname++ != ' ') ;
if (strcmp (dname, name+1))
error ("destructor specification error");
else
return 1;
}
return 0;
}
/* C++: Given ARG1, a value of type (pointer to a)* structure/union,
return 1 if the component named NAME from the ultimate
target structure/union is defined, otherwise, return 0. */
int
check_field (arg1, name)
register value arg1;
char *name;
{
register struct type *t;
register int i;
int found = 0;
struct type *baseclass;
COERCE_ARRAY (arg1);
t = VALUE_TYPE (arg1);
/* Follow pointers until we get to a non-pointer. */
while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
{
arg1 = value_ind (arg1);
COERCE_ARRAY (arg1);
t = VALUE_TYPE (arg1);
}
if (TYPE_CODE (t) == TYPE_CODE_MPTR)
error ("not implemented: member pointers in check_field");
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
&& TYPE_CODE (t) != TYPE_CODE_UNION)
error ("Internal error: `this' is not an aggregate");
baseclass = t;
while (t)
{
for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
{
if (!strcmp (TYPE_FIELD_NAME (t, i), name))
{
return 1;
}
}
t = TYPE_BASECLASS (t);
VALUE_TYPE (arg1) = t; /* side effect! */
}
/* C++: If it was not found as a data field, then try to
return it as a pointer to a method. */
t = baseclass;
VALUE_TYPE (arg1) = t; /* side effect! */
/* Destructors are a special case. */
if (destructor_name_p (name, t))
return 1;
while (t)
{
for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i)
{
if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
return 1;
}
t = TYPE_BASECLASS (t);
}
return 0;
}
/* C++: Given an aggregate type DOMAIN, and a member name NAME,
return the address of this member as a pointer to member
type. If INTYPE is non-null, then it will be the type
of the member we are looking for. This will help us resolve
pointers to member functions. */
value
value_struct_elt_for_address (domain, intype, name)
struct type *domain, *intype;
char *name;
{
register struct type *t = domain;
register int i;
int found = 0;
value v;
struct type *baseclass;
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
&& TYPE_CODE (t) != TYPE_CODE_UNION)
error ("Internal error: non-aggregate type to value_struct_elt_for_address");
baseclass = t;
while (t)
{
for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
{
if (!strcmp (TYPE_FIELD_NAME (t, i), name))
{
if (TYPE_FIELD_PACKED (t, i))
error ("pointers to bitfield members not allowed");
v = value_from_long (builtin_type_int, TYPE_FIELD_BITPOS (t, i) >> 3);
VALUE_TYPE (v) = lookup_member_pointer_type (TYPE_FIELD_TYPE (t, i), baseclass);
return v;
}
}
t = TYPE_BASECLASS (t);
}
/* C++: If it was not found as a data field, then try to
return it as a pointer to a method. */
t = baseclass;
/* Destructors are a special case. */
if (destructor_name_p (name, t))
{
error ("pointers to destructors not implemented yet");
}
while (t)
{
for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i)
{
if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
{
int j = TYPE_FN_FIELDLIST_LENGTH (t, i);
struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
if (intype == 0 && j > 1)
error ("non-unique member `%s' requires type instantiation", name);
if (intype)
{
while (j--)
if (TYPE_FN_FIELD_TYPE (f, j) == intype)
break;
if (j < 0)
error ("no member function matches that type instantiation");
}
else
j = 0;
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
{
v = value_from_long (builtin_type_long,
TYPE_FN_FIELD_VOFFSET (f, j));
}
else
{
struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
0, VAR_NAMESPACE);
v = locate_var_value (s, 0);
}
VALUE_TYPE (v) = lookup_member_pointer_type (TYPE_FN_FIELD_TYPE (f, j), baseclass);
return v;
}
}
t = TYPE_BASECLASS (t);
}
return 0;
}
/* Compare two argument lists and return the position in which they differ,
or zero if equal. Note that we ignore the first argument, which is
the type of the instance variable. This is because we want to handle
derived classes. This is not entirely correct: we should actually
check to make sure that a requested operation is type secure,
shouldn't we? */
int typecmp(t1, t2)
struct type *t1[];
value t2[];
{
int i;
if (t1[0]->code == TYPE_CODE_VOID) return 0;
if (!t1[1])return 0;
for (i = 1; t1[i]->code != TYPE_CODE_VOID; i++)
{
if (! t2[i]
|| t1[i]->code != t2[i]->type->code
|| t1[i]->target_type != t2[i]->type->target_type)
{
return i+1;
}
}
return t2[i] ? i+1 : 0;
}
#ifndef FRAME
#include "frame.h"
#endif
/* C++: return the value of the class instance variable, if one exists.
Flag COMPLAIN signals an error if the request is made in an
inappropriate context. */
value
value_of_this (complain)
int complain;
{
extern FRAME selected_frame;
struct symbol *func, *sym;
char *funname = 0;
struct block *b;
int i;
if (selected_frame == 0)
if (complain)
error ("no frame selected");
else return 0;
func = get_frame_function (selected_frame);
if (func)
funname = SYMBOL_NAME (func);
else
if (complain)
error ("no `this' in nameless context");
else return 0;
b = SYMBOL_BLOCK_VALUE (func);
i = BLOCK_NSYMS (b);
if (i <= 0)
if (complain)
error ("no args, no `this'");
else return 0;
sym = BLOCK_SYM (b, 0);
if (strncmp ("$this", SYMBOL_NAME (sym), 5))
if (complain)
error ("current stack frame not in method");
else return 0;
return read_var_value (sym, selected_frame);
}
static

View File

@ -32,6 +32,7 @@ static int print_max;
static void type_print_varspec_suffix ();
static void type_print_varspec_prefix ();
static void type_print_base ();
static void type_print_method_args ();
START_FILE
@ -88,8 +89,10 @@ value_print (val, stream)
}
else
{
/* A simple (nonrepeated) value */
/* If it is a pointer, indicate what it points to. */
/* If it is a pointer, indicate what it points to.
C++: if it is a member pointer, we will take care
of that when we print it. */
if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR)
{
fprintf (stream, "(");
@ -192,23 +195,172 @@ val_print (type, valaddr, address, stream)
}
break;
case TYPE_CODE_MPTR:
{
struct type *domain = TYPE_DOMAIN_TYPE (type);
struct type *target = TYPE_TARGET_TYPE (type);
struct fn_field *f;
int j, len2;
char *kind = "";
val = unpack_long (builtin_type_int, valaddr);
if (TYPE_CODE (target) == TYPE_CODE_FUNC)
{
if (val < 128)
{
len = TYPE_NFN_FIELDS (domain);
for (i = 0; i < len; i++)
{
f = TYPE_FN_FIELDLIST1 (domain, i);
len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
for (j = 0; j < len2; j++)
{
QUIT;
if (TYPE_FN_FIELD_VOFFSET (f, j) == val)
{
kind = " virtual";
goto common;
}
}
}
}
else
{
struct symbol *sym = find_pc_function (val);
if (sym == 0)
error ("invalid pointer to member function");
len = TYPE_NFN_FIELDS (domain);
for (i = 0; i < len; i++)
{
f = TYPE_FN_FIELDLIST1 (domain, i);
len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
for (j = 0; j < len2; j++)
{
QUIT;
if (!strcmp (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j)))
goto common;
}
}
}
common:
if (i < len)
{
fprintf (stream, "& ");
type_print_base (domain, stream, 0, 0);
fprintf (stream, "::%s", kind);
type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0);
if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
&& TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$')
type_print_method_args
(TYPE_FN_FIELD_ARGS (f, j) + 1, "~",
TYPE_FN_FIELDLIST_NAME (domain, i), stream);
else
type_print_method_args
(TYPE_FN_FIELD_ARGS (f, j), "",
TYPE_FN_FIELDLIST_NAME (domain, i), stream);
break;
}
}
else
{
/* VAL is a byte offset into the structure type DOMAIN.
Find the name of the field for that offset and
print it. */
int extra = 0;
int bits = 0;
len = TYPE_NFIELDS (domain);
val <<= 3; /* @@ Make VAL into bit offset */
for (i = 0; i < len; i++)
{
int bitpos = TYPE_FIELD_BITPOS (domain, i);
QUIT;
if (val == bitpos)
break;
if (val < bitpos && i > 0)
{
int ptrsize = (TYPE_LENGTH (builtin_type_char) * TYPE_LENGTH (target));
/* Somehow pointing into a field. */
i -= 1;
extra = (val - TYPE_FIELD_BITPOS (domain, i));
if (extra & 0x3)
bits = 1;
else
extra >>= 3;
break;
}
}
if (i < len)
{
fprintf (stream, "& ");
type_print_base (domain, stream, 0, 0);
fprintf (stream, "::");
fprintf (stream, "%s", TYPE_FIELD_NAME (domain, i));
if (extra)
fprintf (stream, " + %d bytes", extra);
if (bits)
fprintf (stream, " (offset in bits)");
break;
}
}
fputc ('(', stream);
type_print (type, "", stream, -1);
fprintf (stream, ") %d", val >> 3);
break;
}
case TYPE_CODE_REF:
fprintf (stream, "(0x%x &) = ", * (int *) valaddr);
/* De-reference the reference. */
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF)
{
value val = value_at (TYPE_TARGET_TYPE (type), * (int *)valaddr);
val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
VALUE_ADDRESS (val), stream);
}
else
fprintf (stream, "???");
break;
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
fprintf (stream, "{");
len = TYPE_NFIELDS (type);
for (i = 0; i < len; i++)
if (TYPE_BASECLASS (type))
{
i = 1;
fprintf (stream, "<%s> = ", TYPE_NAME (TYPE_BASECLASS (type)));
val_print (TYPE_FIELD_TYPE (type, 0),
valaddr + TYPE_FIELD_BITPOS (type, 0) / 8,
0, stream);
}
else i = 0;
for (; i < len; i++)
{
if (i) fprintf (stream, ", ");
fprintf (stream, "%s = ", TYPE_FIELD_NAME (type, i));
if (TYPE_FIELD_PACKED (type, i))
/* check if static field */
if (TYPE_FIELD_STATIC (type, i))
{
value v;
v = value_static_field (type, TYPE_FIELD_NAME (type, i), i);
val_print (TYPE_FIELD_TYPE (type, i),
VALUE_CONTENTS (v), 0, stream);
}
else if (TYPE_FIELD_PACKED (type, i))
{
val = unpack_field_as_long (type, valaddr, i);
val_print (TYPE_FIELD_TYPE (type, i), &val, 0, stream);
}
else
val_print (TYPE_FIELD_TYPE (type, i),
valaddr + TYPE_FIELD_BITPOS (type, i) / 8,
0, stream);
{
val_print (TYPE_FIELD_TYPE (type, i),
valaddr + TYPE_FIELD_BITPOS (type, i) / 8,
0, stream);
}
}
fprintf (stream, "}");
break;
@ -336,13 +488,41 @@ type_print_1 (type, varstring, stream, show, level)
((show > 0 || TYPE_NAME (type) == 0)
&&
(code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC
|| code == TYPE_CODE_ARRAY)))
|| code == TYPE_CODE_ARRAY
|| code == TYPE_CODE_MPTR
|| code == TYPE_CODE_REF)))
fprintf (stream, " ");
type_print_varspec_prefix (type, stream, show, 0);
fprintf (stream, "%s", varstring);
type_print_varspec_suffix (type, stream, show, 0);
}
/* Print the method arguments ARGS to the file STREAM. */
static void
type_print_method_args (args, prefix, varstring, stream)
struct type **args;
char *prefix, *varstring;
FILE *stream;
{
int i;
fprintf (stream, " %s%s (", prefix, varstring);
if (args[1] && args[1]->code != TYPE_CODE_VOID)
{
i = 1; /* skip the class variable */
while (1)
{
type_print (args[i++], "", stream, 0);
if (args[i]->code != TYPE_CODE_VOID)
{
fprintf (stream, ", ");
}
else break;
}
}
fprintf (stream, ")");
}
/* Print any asterisks or open-parentheses needed before the
variable name (to describe its type).
@ -370,12 +550,29 @@ type_print_varspec_prefix (type, stream, show, passed_a_ptr)
fputc ('*', stream);
break;
case TYPE_CODE_MPTR:
type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
if (passed_a_ptr)
fputc ('(', stream);
type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, 1);
fprintf (stream, "::*");
break;
case TYPE_CODE_REF:
type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
fputc ('&', stream);
break;
case TYPE_CODE_FUNC:
case TYPE_CODE_ARRAY:
type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
passed_a_ptr);
if (passed_a_ptr)
fputc ('(', stream);
break;
case TYPE_CODE_ARRAY:
type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
passed_a_ptr);
}
}
@ -398,9 +595,8 @@ type_print_varspec_suffix (type, stream, show, passed_a_ptr)
switch (TYPE_CODE (type))
{
case TYPE_CODE_ARRAY:
type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0);
if (passed_a_ptr)
fprintf (stream, ")");
type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
passed_a_ptr);
fprintf (stream, "[");
if (TYPE_LENGTH (type) >= 0)
fprintf (stream, "%d",
@ -408,12 +604,18 @@ type_print_varspec_suffix (type, stream, show, passed_a_ptr)
fprintf (stream, "]");
break;
case TYPE_CODE_MPTR:
if (passed_a_ptr)
fputc (')', stream);
/* Fall through. */
case TYPE_CODE_PTR:
case TYPE_CODE_REF:
type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1);
break;
case TYPE_CODE_FUNC:
type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0);
type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
passed_a_ptr);
if (passed_a_ptr)
fprintf (stream, ")");
fprintf (stream, "()");
@ -458,6 +660,8 @@ type_print_base (type, stream, show, level)
{
case TYPE_CODE_ARRAY:
case TYPE_CODE_PTR:
case TYPE_CODE_MPTR:
case TYPE_CODE_REF:
case TYPE_CODE_FUNC:
type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
break;
@ -478,46 +682,84 @@ type_print_base (type, stream, show, level)
fprintf (stream, "{...}");
else
{
struct type *basetype, *dtype;
dtype = type;
basetype = TYPE_BASECLASS (type);
while (basetype)
{
if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype)))
{
while (*name != ' ') name++;
fprintf (stream, ": %s %s ",
TYPE_VIA_PUBLIC (dtype) ? "public" : "private",
name + 1);
}
dtype = basetype;
basetype = TYPE_BASECLASS (basetype);
}
fprintf (stream, "{");
len = TYPE_NFIELDS (type);
fprintf (stream, "\n");
for (i = 0; i < len; i++)
if (len) fprintf (stream, "\n");
else fprintf (stream, "<no data fields>\n");
/* If there is a base class for this type,
do not print the field that it occupies. */
for (i = !! TYPE_BASECLASS (type); i < len; i++)
{
QUIT;
/* Don't print out virtual function table. */
if (! strncmp (TYPE_FIELD_NAME (type, i),
"_vptr$", 6))
continue;
print_spaces (level + 4, stream);
/* If this is a bit-field and there is a gap before it,
print a nameless field to account for the gap. */
if (TYPE_FIELD_PACKED (type, i))
if (TYPE_FIELD_STATIC (type, i))
{
int gap = (TYPE_FIELD_BITPOS (type, i)
- (i > 0
? (TYPE_FIELD_BITPOS (type, i - 1)
+ (TYPE_FIELD_PACKED (type, i - 1)
? TYPE_FIELD_BITSIZE (type, i - 1)
: TYPE_LENGTH (TYPE_FIELD_TYPE (type, i - 1)) * 8))
: 0));
if (gap != 0)
{
fprintf (stream, "int : %d;\n", gap);
print_spaces (level + 4, stream);
}
fprintf (stream, "static ");
}
/* Print the declaration of this field. */
type_print_1 (TYPE_FIELD_TYPE (type, i),
TYPE_FIELD_NAME (type, i),
stream, show - 1, level + 4);
/* Print the field width. */
if (TYPE_FIELD_PACKED (type, i))
fprintf (stream, " : %d", TYPE_FIELD_BITSIZE (type, i));
if (!TYPE_FIELD_STATIC (type, i)
&& TYPE_FIELD_PACKED (type, i))
{
/* ??? don't know what to put here ??? */;
}
fprintf (stream, ";\n");
}
/* C++: print out the methods */
len = TYPE_NFN_FIELDS (type);
if (len) fprintf (stream, "\n");
for (i = 0; i < len; i++)
{
struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i);
for (j = 0; j < len2; j++)
{
QUIT;
print_spaces (level + 4, stream);
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
fprintf (stream, "virtual ");
type_print_base (TYPE_FN_FIELD_TYPE (f, j), stream, 0, level);
type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0);
if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
&& TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$')
type_print_method_args
(TYPE_FN_FIELD_ARGS (f, j) + 1, "~",
TYPE_FN_FIELDLIST_NAME (type, i), stream);
else
type_print_method_args
(TYPE_FN_FIELD_ARGS (f, j), "",
TYPE_FN_FIELDLIST_NAME (type, i), stream);
fprintf (stream, ";\n");
}
if (len2) fprintf (stream, "\n");
}
print_spaces (level, stream);
fputc ('}', stream);
}

View File

@ -108,7 +108,7 @@ value value_addr ();
value value_assign ();
value value_neg ();
value value_lognot ();
value value_struct_elt ();
value value_struct_elt (), value_struct_elt_for_address ();
value value_field ();
value value_cast ();
value value_repeat ();
@ -120,6 +120,7 @@ value value_being_returned ();
value evaluate_expression ();
value evaluate_type ();
value parse_and_eval ();
value parse_to_comma_and_eval ();
value access_value_history ();
value value_of_internalvar ();
@ -128,3 +129,7 @@ struct internalvar *lookup_internalvar ();
int value_equal ();
int value_less ();
int value_zerop ();
/* C++ */
value value_of_this ();
value value_static_field ();

View File

@ -424,7 +424,12 @@ value_as_double (val)
/* Unpack raw data (copied from debugee) at VALADDR
as a long, or as a double, assuming the raw data is described
by type TYPE. Knows how to convert different sizes of values
and can convert between fixed and floating point. */
and can convert between fixed and floating point.
C++: It is assumed that the front-end has taken care of
all matters concerning pointers to members. A pointer
to member which reaches here is considered to be equivalent
to an INT (or some size). After all, it is only an offset. */
long
unpack_long (type, valaddr)
@ -459,7 +464,8 @@ unpack_long (type, valaddr)
if (len == sizeof (long))
return * (unsigned long *) valaddr;
}
else if (code == TYPE_CODE_INT)
else if (code == TYPE_CODE_INT
|| code == TYPE_CODE_MPTR)
{
if (len == sizeof (char))
return * (char *) valaddr;
@ -473,12 +479,12 @@ unpack_long (type, valaddr)
if (len == sizeof (long))
return * (long *) valaddr;
}
else if (code == TYPE_CODE_PTR)
else if (code == TYPE_CODE_PTR
|| code == TYPE_CODE_REF)
{
if (len == sizeof (char *))
return (CORE_ADDR) * (char **) valaddr;
}
error ("Value not integer or pointer.");
}
@ -536,7 +542,9 @@ unpack_double (type, valaddr)
/* Given a value ARG1 of a struct or union type,
extract and return the value of one of its fields.
FIELDNO says which field. */
FIELDNO says which field.
For C++, must also be able to return values from static fields */
value
value_field (arg1, fieldno)
@ -574,6 +582,96 @@ value_field (arg1, fieldno)
return v;
}
value
value_fn_field (arg1, fieldno, subfieldno)
register value arg1;
register int fieldno;
{
register value v;
struct fn_field *f = TYPE_FN_FIELDLIST1 (VALUE_TYPE (arg1), fieldno);
register struct type *type = TYPE_FN_FIELD_TYPE (f, subfieldno);
struct symbol *sym;
sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, subfieldno),
0, VAR_NAMESPACE);
if (! sym) error ("Internal error: could not find physical method named %s",
TYPE_FN_FIELD_PHYSNAME (f, subfieldno));
v = allocate_value (type);
VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
VALUE_TYPE (v) = type;
return v;
}
/* The value of a static class member does not depend
on its instance, only on its type. If FIELDNO >= 0,
then fieldno is a valid field number and is used directly.
Otherwise, FIELDNAME is the name of the field we are
searching for. If it is not a static field name, an
error is signaled. TYPE is the type in which we look for the
static field member. */
value
value_static_field (type, fieldname, fieldno)
register struct type *type;
char *fieldname;
register int fieldno;
{
register value v;
struct symbol *sym;
if (fieldno < 0)
{
register struct type *t = type;
/* Look for static field. */
while (t)
{
int i;
for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
if (! strcmp (TYPE_FIELD_NAME (t, i), fieldname))
{
if (TYPE_FIELD_STATIC (t, i))
{
fieldno = i;
goto found;
}
else
error ("field `%s' is not static");
}
t = TYPE_BASECLASS (t);
}
t = type;
if (destructor_name_p (fieldname, t))
error ("use `info method' command to print out value of destructor");
while (t)
{
int i, j;
for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; i--)
{
if (! strcmp (TYPE_FN_FIELDLIST_NAME (t, i), fieldname))
{
error ("use `info method' command to print value of method \"%s\"", fieldname);
}
}
t = TYPE_BASECLASS (t);
}
error("there is no field named %s", fieldname);
}
found:
sym = lookup_symbol (TYPE_FIELD_STATIC_PHYSNAME (type, fieldno),
0, VAR_NAMESPACE);
if (! sym) error ("Internal error: could not find physical static variable named %s", TYPE_FIELD_BITSIZE (type, fieldno));
type = TYPE_FIELD_TYPE (type, fieldno);
v = value_at (type, (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym));
return v;
}
long
unpack_field_as_long (type, valaddr, fieldno)
struct type *type;

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