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: email@example.com (Zalman Stern)
To: rms@PREP.AI.MIT.EDU (Richard M. Stallman)
Subject: Re: RT diffs for gdb version 2.1
Cc: firstname.lastname@example.org (Mike Kazar), email@example.com (Zalman Stern)
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
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
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
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
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.
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.