gdb-2.5.1
This commit is contained in:
parent
7b4ac7e1ed
commit
632ea0ccc5
108
gdb/=emacs
108
gdb/=emacs
|
@ -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
136
gdb/=news
|
@ -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
|
||||
|
1182
gdb/=ns32k.msg
1182
gdb/=ns32k.msg
File diff suppressed because it is too large
Load Diff
103
gdb/=rt-ans2
103
gdb/=rt-ans2
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
147
gdb/=rt-answers
147
gdb/=rt-answers
|
@ -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-
|
||||
|
||||
|
||||
|
3338
gdb/=rt-changes
3338
gdb/=rt-changes
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
||||
|
997
gdb/=xgdb.msg
997
gdb/=xgdb.msg
|
@ -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.
|
||||
|
138
gdb/COPYING
138
gdb/COPYING
|
@ -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.
|
1025
gdb/ChangeLog
1025
gdb/ChangeLog
File diff suppressed because it is too large
Load Diff
28
gdb/Makefile
28
gdb/Makefile
|
@ -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
|
||||
|
|
|
@ -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
|
||||
@
|
|
@ -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
|
763
gdb/RCS/core.c,v
763
gdb/RCS/core.c,v
|
@ -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 *)®isters[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps;
|
||||
*(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc;
|
||||
bcopy (corestr.c_fpstatus.fps_regs,
|
||||
®isters[REGISTER_BYTE (FP0_REGNUM)],
|
||||
sizeof corestr.c_fpstatus.fps_regs);
|
||||
bcopy (&corestr.c_fpstatus.fps_control,
|
||||
®isters[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
|
||||
@
|
|
@ -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
|
||||
@
|
|
@ -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, <c_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, <c_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, <c_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 *)<c_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, ®isters[REGISTER_BYTE (FP0_REGNUM)],
|
||||
sizeof inferior_fp_registers.fps_regs);
|
||||
*(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
|
||||
*(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
|
||||
bcopy (&inferior_fp_registers.fps_control,
|
||||
®isters[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 (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
|
||||
sizeof inferior_fp_registers.fps_regs);
|
||||
inferior_registers.r_ps = *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
|
||||
inferior_registers.r_pc = *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
|
||||
bcopy (®isters[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, <c_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
|
||||
@
|
|
@ -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
|
||||
@
|
|
@ -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
|
||||
@
|
|
@ -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");
|
||||
@
|
1110
gdb/RCS/main.c,v
1110
gdb/RCS/main.c,v
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
@
|
|
@ -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);
|
||||
@
|
1153
gdb/RCS/symtab.c,v
1153
gdb/RCS/symtab.c,v
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
@
|
29
gdb/README
29
gdb/README
|
@ -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
852
gdb/TAGS
|
@ -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
|
191
gdb/alloca.c
191
gdb/alloca.c
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
13
gdb/bar.c
13
gdb/bar.c
|
@ -1,13 +0,0 @@
|
|||
main() {
|
||||
int i;
|
||||
|
||||
for (i = 0; i >= 0; i++)
|
||||
bar();
|
||||
}
|
||||
|
||||
bar()
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 10;
|
||||
}
|
65
gdb/bar.nm
65
gdb/bar.nm
|
@ -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)
|
93
gdb/bar.s
93
gdb/bar.s
|
@ -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
|
51
gdb/bar.sym
51
gdb/bar.sym
|
@ -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,
|
||||
|
||||
|
|
@ -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,
|
||||
|
|
191
gdb/breakpoint.c
191
gdb/breakpoint.c
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
55
gdb/core.c
55
gdb/core.c
|
@ -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;
|
||||
|
|
817
gdb/dbxread.c
817
gdb/dbxread.c
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
234
gdb/eval.c
234
gdb/eval.c
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
235
gdb/expread.y
235
gdb/expread.y
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.",
|
||||
|
|
|
@ -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
|
||||
|
|
13
gdb/foo.c
13
gdb/foo.c
|
@ -1,13 +0,0 @@
|
|||
main() {
|
||||
int i;
|
||||
|
||||
for (i = 0; i >= 0; i++)
|
||||
bar();
|
||||
}
|
||||
|
||||
bar()
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 10;
|
||||
}
|
39
gdb/foo.nm
39
gdb/foo.nm
|
@ -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| | | |
|
213
gdb/foo.od
213
gdb/foo.od
|
@ -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
|
65
gdb/foo.s
65
gdb/foo.s
|
@ -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
|
114
gdb/foo.sym
114
gdb/foo.sym
|
@ -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)
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
91
gdb/gdb.1
91
gdb/gdb.1
|
@ -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.
|
||||
|
694
gdb/gdb.ideas
694
gdb/gdb.ideas
|
@ -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.
|
||||
|
||||
|
112
gdb/infcmd.c
112
gdb/infcmd.c
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
192
gdb/inflow.c
192
gdb/inflow.c
|
@ -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, <c_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, <c_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, <c_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 *)<c_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, ®isters[REGISTER_BYTE (FP0_REGNUM)],
|
||||
sizeof inferior_fp_registers.fps_regs);
|
||||
*(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
|
||||
*(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
|
||||
bcopy (&inferior_fp_registers.fps_control,
|
||||
®isters[REGISTER_BYTE (FPC_REGNUM)],
|
||||
sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
|
||||
bcopy (&inferior_registers, registers, 16 * 4);
|
||||
bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)],
|
||||
sizeof inferior_fp_registers.fps_regs);
|
||||
*(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
|
||||
*(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
|
||||
bcopy (&inferior_fp_registers.fps_control,
|
||||
®isters[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 (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
|
||||
sizeof inferior_fp_registers.fps_regs);
|
||||
inferior_registers.r_ps = *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
|
||||
inferior_registers.r_pc = *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
|
||||
bcopy (®isters[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 (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
|
||||
sizeof inferior_fp_registers.fps_regs);
|
||||
inferior_registers.r_ps = *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
|
||||
inferior_registers.r_pc = *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
|
||||
bcopy (®isters[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, <c_ours);
|
||||
ioctl (0, TIOCLGET, &lmode_ours);
|
||||
#endif
|
||||
fcntl (0, F_GETFL, tflags_ours);
|
||||
ioctl (0, TIOCGPGRP, &pgrp_ours);
|
||||
|
||||
|
|
50
gdb/infrun.c
50
gdb/infrun.c
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
485
gdb/m-mac-aux.h
485
gdb/m-mac-aux.h
|
@ -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"); }
|
|
@ -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)
|
437
gdb/m-merlin.h
437
gdb/m-merlin.h
|
@ -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
|
566
gdb/m-news800.h
566
gdb/m-news800.h
|
@ -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
|
||||
|
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
425
gdb/m-umax.h
425
gdb/m-umax.h
|
@ -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; \
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
96
gdb/main.c
96
gdb/main.c
|
@ -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. */
|
||||
|
|
|
@ -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
|
|
@ -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 */
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
../gcc/gcc-1.22/obstack.c
|
|
@ -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__ */
|
|
@ -1 +0,0 @@
|
|||
../gcc/gcc-1.19/obstack.h
|
|
@ -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__ */
|
||||
|
|
@ -1 +1 @@
|
|||
#include "m-mac-aux.h"
|
||||
#include "m-sun3.h"
|
||||
|
|
|
@ -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;
|
||||
}
|
388
gdb/printcmd.c
388
gdb/printcmd.c
|
@ -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.");
|
||||
|
|
|
@ -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
|
44
gdb/song
44
gdb/song
|
@ -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 :-)
|
||||
|
245
gdb/source.c
245
gdb/source.c
|
@ -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, ¤t_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, ¤t_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\
|
||||
|
|
11
gdb/stack.c
11
gdb/stack.c
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
126
gdb/symseg.h
126
gdb/symseg.h
|
@ -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;
|
||||
};
|
||||
|
|
709
gdb/symtab.c
709
gdb/symtab.c
|
@ -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.");
|
||||
|
||||
|
|
99
gdb/symtab.h
99
gdb/symtab.h
|
@ -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 ();
|
||||
|
|
13
gdb/test2.c
13
gdb/test2.c
|
@ -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));
|
||||
}
|
25
gdb/test3.c
25
gdb/test3.c
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
main ()
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
sleep (1);
|
||||
x++;
|
||||
}
|
||||
}
|
13
gdb/testbf.c
13
gdb/testbf.c
|
@ -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);
|
||||
}
|
|
@ -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. */
|
||||
}
|
||||
|
12
gdb/testfb.c
12
gdb/testfb.c
|
@ -1,12 +0,0 @@
|
|||
|
||||
main ()
|
||||
{
|
||||
foo(2);
|
||||
foo(3);
|
||||
}
|
||||
|
||||
foo (i)
|
||||
{
|
||||
printf ("i is %d, ", i);
|
||||
printf ("i*i is %d\n", i * i);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -191,9 +191,7 @@ void
|
|||
quit ()
|
||||
{
|
||||
fflush (stdout);
|
||||
#ifdef TIOCFLUSH
|
||||
ioctl (fileno (stdout), TIOCFLUSH, 0);
|
||||
#endif
|
||||
error ("Quit");
|
||||
}
|
||||
|
454
gdb/valops.c
454
gdb/valops.c
|
@ -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
|
||||
|
|
326
gdb/valprint.c
326
gdb/valprint.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
|
|
108
gdb/values.c
108
gdb/values.c
|
@ -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
Loading…
Reference in New Issue