From: rocky@watson.ibm.com (Rocky Bernstein)
Newsgroups: gnu.gcc.bug
Subject: romp-ibm-aos debug table offset info
Date: 9 Sep 92 11:14:43 GMT
Reply-To: rocky@watson.ibm.com
Distribution: gnu
Organization: GNUs Not Usenet

I've been trying to get dbx on the RT/PC AOS to understand gcc 2.2.1's
output. The call trace back seems to be wrong often, unless one is in
the prolog code. gcc 2.2.1's romp.c code is slightly simplistic about
the offset information that it encodes in the debug table at the end
of a procedure.

Here is the line from output_epilog in romp.c used
to write this information when there is a frame:
	fprintf (file, "\t.byte 0x%xd, 53\n", nargs);

>From my understanding of the how the debug offset info is encoded,
this is interpreted as follows:
   There are nargs passed to the routine; THE FRAME POINTER IS R13;
   THE DISTANCE BETWEEN THE CURRENT AND PREVIOUS FRAME POINTERS
   IS 53*4 BYTES.

The last of two pieces of information I think are (often, probably)
wrong: the frame pointer for gcc on romp is r1, although r13 could
conceivably be used as well. The problem with using r13 is that dbx
(and perhaps other debuggers) check to see if the program is in a
subroutine prolog; if so, they use r1 for addressing the stack.
Thus, a scheme that is to work the same in the subroutine prolog or
not, must use r1.

The other problem with the romp code is the fact that
the distance between frame pointers is not always 212
bytes. (In fact, it rarely is). Better would be to consult the
variable total_size in output_epilog for the number of bytes between
the current and previous frame pointers.

At the end the diffs that I made to correct this. The comments give
my understanding of the funny way that the offset information is
encoded.

There is one problem with the below code. It requires that stabs
entries for local variables be changed by a constant value. (But from
what I've seen, as things stand the stabs entries are probably wrong
too.)  In the scheme below, the first local would have offest -4
rather than something like 60 as is now the case.

I'd like to make this change and test it out, but I don't see how to
do it in the right way.

1) Is anyone any using debuggers with gcc 2.2.1 on romp-ibm-aos?
Do they work?

2) How do I tell gcc what value to start with for a local offset in
the stabs entry?

Thanks,

R. Bernstein

diff romp.c romp.c.orig
1078a1079
>   rtx insn;
1126,1183d1126
< /* output offset information used by debuggers.
<
<    This is the exactly the total_size value of output_epilog
<    which is added to the frame pointer. However the value in the debug
<    table is encoded in a funny, space-saving way as follows:
<
<    The first byte contains two fields: a 2-bit size field and the first
<    6 bits of an offset value. The 2-bit size field is in the
<    high-order position and specifies how many subsequent bytes follow after
<    this one. An offset value is at most 4-bytes long.
<
<    The last 6 bits of the first byte start the offset value. In many cases,
<    where procedures have small local storage this is enough. Note that in
<    this case the high-order size field is zero so the byte can (almost) be
<    used as is (see below). Thus, the byte value of 0x0d is encodes a offset
<    size of 13 words, or 52 bytes.
<
<    For procedures with a local space larger than 60 bytes, the 6 bits
<    is the high-order 6 bits. The remaining bytes follow in Big Endian order
<    as necessary. Thus, the short value of 16907 (= 16384+523) encodes an
<    offset of 2092 bytes (523 words).
< 	
<    The total offset value is in words (not bytes), so the end value
<    has to be multiplied by 4 before it can be used in address
<    computations by a debugger. I suppose that using by word units rather
<    than bytes the space taken up by 2-bit length field
<    at the beginning is compensated for.
< */
<
< void output_encoded_offset(file, reg_offset)
<      FILE *file;
<      int reg_offset;
< {
<   /* Convert the offset value to 4-byte words rather than bytes. */
<   reg_offset >>= 2;
<
<   /* Now output 1-4 bytes in encoded form. */
<   if (reg_offset < (1<<6)) {
<     /* Fits into one byte */
<     fprintf(file, "\t.byte %d\n", reg_offset);
<     }
<   else if (reg_offset < (1<<(6+8))) {
<     /* Fits into two bytes */
<     fprintf(file, "\t.short %d\n", (1<<(6+8)) + reg_offset);
<   }
<   else if (reg_offset < (1<<(6+8+8))) {
<     /* Fits in three bytes */
<     fprintf(file, "\t.byte %d\n", (2<<6) + (reg_offset >> (6+8)));
<     fprintf(file, "\t.short %d\n", reg_offset % (1<<(6+8)));
<   }
<   else {
<     /* Better fit in 4 bytes */
<     fprintf(file, "\t.short %d", (3<<(6+8)) + (reg_offset >> (6+8)));
<     fprintf(file, "\t.short %d\n", reg_offset % (1<<(6+8)));
<   }
< }
<
<
1247,1249d1189
<
<       /* debug table info:
< 	 table header, usual-type stack frame, and first register saved. */
1253,1259c1193,1194
<
<       /* debug table info: the number of parameter words
< 	 and the register used as the frame pointer (r1). */
<       if (frame_pointer_needed) {
< 	fprintf (file, "\t.byte 0x%x1\n", nargs);
< 	output_encoded_offset(file, total_size);
<       }
---
>       if (frame_pointer_needed)
> 	fprintf (file, "\t.byte 0x%xd, 53\n", nargs);
1267,1268d1201
<       /* debug table info:
< 	 table header, no stack frame, and no parameters saved. */
Newsgroups: gnu.gcc.bug