Related articles |
---|
'.stabs' info requested bimandre@BLEKUL60.BITNET (Andre Marien) (1990-06-05) |
Re: '.stabs' info requested bothner@cs.wisc.edu (1990-06-06) |
Re: '.stabs' info requested title@Think.COM (1990-06-06) |
Re: '.stabs' info requested pardo@cs.washington.edu (1990-06-07) |
Re: '.stabs' info requested dupuy@hudson.cs.columbia.edu (1990-06-07) |
Re: '.stabs' info requested meissner@osf.org (1990-06-14) |
Newsgroups: | comp.compilers |
From: | meissner@osf.org |
Date: | Thu, 14 Jun 90 03:28:37 GMT |
Organization: | Compilers Central |
Keywords: | code, debug |
In article <1990Jun5.173819.2970@esegue.segue.boston.ma.us>
bimandre@BLEKUL60.BITNET (Andre Marien) writes:
| [the stabs format for the MIPS-based DECstation is severely undocumented]
I have spent some time adding debug support to GCC for MIPS based computers
(such as the DECstation). Some of this is documented in the MIPS Assembly
Language Programmer's Guide, but a lot is left out. I have two programs that
I developed to work on the object files. The symbol table format originally
comes from a company called Third Eye software.
The first program (mips-tdump) is an expanded object file dumper, that pays
particular attention to the symbol table, and also displays line number
entries correctly (unlike the MIPS odump program).
The second program (mips-tfile) is a rather gross hack. It reads in the
normal object file produced by the assembler, and the compiler generated
assembly language input file, strips off the current symbol table, and rights
a new symbol table with all of the debug information added. This is
necessary, since there is absolutely no way to specify local variables and
type information to the assembler. This reminds me of the old days when the
vendor knew best, and mere users were not to peek behind the curtain......
Anyway, back to symbol tables. The MIPS symbol table has the following
pieces:
Symbolic Header
|
+-- Auxiliary Symbols
|
+-- Dense number table
|
+-- Optimizer Symbols
|
+-- External Strings
|
+-- External Symbols
|
+-- Relative file descriptors
|
+-- File table
|
+-- Procedure table
|
+-- Line number table
|
+-- Local Strings
|
+-- Local Symbols
The symbolic header points to each of the other tables, and also contains the
number of entries. It also contains a magic number and compiler version
number (1.31, 2.00, 2.10, 2.11 are versions I've heard about).
The auxiliary table is a series of 32 bit integers, that are referenced as
needed from the local symbol table. Unlike standard COFF, the aux.
information does not follow the symbol that uses it, but rather is a separate
table. In theory, this would allow the MIPS compilers to collapse duplicate
aux. entries, but I've not noticed this happening with the 1.31 compiler
suite. The different types of aux. entries are:
1) dnLow: Low bound on array dimension.
2) dnHigh: High bound on array dimension.
3) isym: Index to the local symbol which is the start of the
function for the end of function first aux. entry.
4) width: Width of structures and bitfields.
5) count: Count of ranges for variant part.
6) rndx: A relative index into the symbol table. The relative
index field has two parts: rfd which is a pointer into the
relative file index table or ST_RFDESCAPE which says the next
aux. entry is the file number, and index: which is the pointer
into the local symbol within a given file table. This is for
things like references to types defined in another file.
7) Type information: This is like the COFF type bits, except it
is 32 bits instead of 16; they still have room to add new
basic types; and they can handle more than 6 levels of array,
pointer, function, etc. Each type information field contains
the following structure members:
a) fBitfield: a bit that says this is a bitfield, and the
size in bits follows as the next aux. entry.
b) continued: a bit that says the next aux. entry is a
continuation of the current type information (in case
there are more than 6 levels of array/ptr/function).
c) bt: an integer containing the base type before adding
array, pointer, function, etc. qualifiers. The
current base types that I have documentation for are:
btNil /* undefined */
btAdr /* address - integer same size as ptr*/
btChar /* character */
btUChar /* unsigned character */
btShort /* short */
btUShort /* unsigned short */
btInt /* int */
btUInt /* unsigned int */
btLong /* long */
btULong /* unsigned long */
btFloat /* float (real) */
btDouble /* Double (real) */
btStruct /* Structure (Record) */
btUnion /* Union (variant) */
btEnum /* Enumerated */
btTypedef /* defined via a typedef isymRef */
btRange /* subrange of int */
btSet /* pascal sets */
btComplex /* fortran complex */
btDComplex /* fortran double complex */
btIndirect /* forward or unnamed typedef */
btFixedDec /* Fixed Decimal */
btFloatDec /* Float Decimal */
btString /* Varying Length Character String */
btBit /* Aligned Bit String */
btPicture /* Picture */
d) tq0 - tq5: type qualifier fields as needed. The
current type qualifier fields I have documentation for
are:
tqNil /* no more qualifiers */
tqPtr /* pointer */
tqProc /* procedure */
tqArray /* array */
tqFar /* 8086 far pointers */
tqVol /* volatile */
The dense number table is used in the front ends, and disappears by the time
the .o is created.
With the 1.31 compiler suite, the optimization symbols don't seem to be used
as far as I can tell.
The linker is the first entity that creates the relative file descriptor
table, and I believe it is used so that the individual file table pointers
don't have to be rewritten when the objects are merged together into the
program file.
Unlike COFF, the basic symbol & string tables are split into external and
local symbols/strings. The relocation information only goes off of the
external symbol table, and the debug information only goes off of the
internal symbol table. The external symbols can have links to an appropriate
file index and symbol within the file to give it the appropriate type
information. Because of this, the external symbols are actually larger than
the internal symbols (to contain the link information), and contain the local
symbol structure as a member, though this member is not the first member of
the external symbol structure (!). I suspect this split is to make strip
easier to deal with.
Each file table has offsets for where the line numbers, local strings, local
symbols, and procedure table starts from within the global tables, and the
indexs are reset to 0 for each of those tables for the file.
The procedure table contains the binary equivalents of the .ent (start of the
function address), .frame (what register is the virtual frame pointer,
constant offset from the register to obtain the VFP, and what register holds
the return address), .mask/.fmask (bitmask of saved registers, and where the
first register is stored relative to the VFP) assembler directives. It also
contains the low and high bounds of the line numbers if debugging is turned
on.
The line number table is a compressed form of the normal COFF line table.
Each line number entry is either 1 or 3 bytes long, and contains a signed
delta from the previous line, and an unsigned count of the number of
instructions this statement takes.
The local symbol table contains the following fields:
1) iss: index to the local string table giving the name of the
symbol.
2) value: value of the symbol (address, register number, etc.).
3) st: symbol type. The current symbol types are:
stNil /* Nuthin' special */
stGlobal /* external symbol */
stStatic /* static */
stParam /* procedure argument */
stLocal /* local variable */
stLabel /* label */
stProc /* External Procedure */
stBlock /* beginnning of block */
stEnd /* end (of anything) */
stMember /* member (of anything) */
stTypedef /* type definition */
stFile /* file name */
stRegReloc /* register relocation */
stForward /* forwarding address */
stStaticProc /* Static procedure */
stConstant /* const */
4) sc: storage class. The current storage classes are:
scText /* text symbol */
scData /* initialized data symbol */
scBss /* un-initialized data symbol */
scRegister /* value of symbol is register number */
scAbs /* value of symbol is absolute */
scUndefined /* who knows? */
scCdbLocal /* variable's value is IN se->va.?? */
scBits /* this is a bit field */
scCdbSystem /* value is IN debugger's address space */
scRegImage /* register value saved on stack */
scInfo /* symbol contains debugger information */
scUserStruct /* addr in struct user for current process */
scSData /* load time only small data */
scSBss /* load time only small common */
scRData /* load time only read only data */
scVar /* Var parameter (fortranpascal) */
scCommon /* common variable */
scSCommon /* small common */
scVarRegister /* Var parameter in a register */
scVariant /* Variant record */
scSUndefined /* small undefined(external) data */
scInit /* .init section symbol */
5) index: pointer to a local symbol or aux. entry.
For the following program:
#include <stdio.h>
main(){
printf("Hello World!\n");
return 0;
}
Mips-tdump produces the following information:
Global file header:
magic number 0x162
# sections 2
timestamp 645311799, Wed Jun 13 17:16:39 1990
symbolic header offset 284
symbolic header size 96
optional header 56
flags 0x0
Symbolic header, magic number = 0x7009, vstamp = 1.31:
Info Offset Number Bytes
==== ====== ====== =====
Line numbers 380 4 4 [13]
Dense numbers 0 0 0
Procedures Tables 384 1 52
Local Symbols 436 16 192
Optimization Symbols 0 0 0
Auxilary Symbols 628 39 156
Local Strings 784 80 80
External Strings 864 144 144
File Tables 1008 2 144
Relative Files 0 0 0
External Symbols 1152 20 320
File #0, "hello2.c"
Name index = 1 Readin = No
Merge = No Endian = LITTLE
Debug level = G2 Language = C
Adr = 0x00000000
Info Start Number Size Offset
==== ===== ====== ==== ======
Local strings 0 15 15 784
Local symbols 0 6 72 436
Line numbers 0 13 13 380
Optimization symbols 0 0 0 0
Procedures 0 1 52 384
Auxiliary symbols 0 14 56 628
Relative Files 0 0 0 0
There are 6 local symbols, starting at 436
Symbol# 0: "hello2.c"
End+1 symbol = 6
String index = 1
Storage class = Text Index = 6
Symbol type = File Value = 0
Symbol# 1: "main"
End+1 symbol = 5
Type = int
String index = 10
Storage class = Text Index = 12
Symbol type = Proc Value = 0
Symbol# 2: ""
End+1 symbol = 4
String index = 0
Storage class = Text Index = 4
Symbol type = Block Value = 8
Symbol# 3: ""
First symbol = 2
String index = 0
Storage class = Text Index = 2
Symbol type = End Value = 28
Symbol# 4: "main"
First symbol = 1
String index = 10
Storage class = Text Index = 1
Symbol type = End Value = 52
Symbol# 5: "hello2.c"
First symbol = 0
String index = 1
Storage class = Text Index = 0
Symbol type = End Value = 0
There are 14 auxiliary table entries, starting at 628.
* #0 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
* #1 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0]
* #2 8, [ 8/ 0], [ 2 0:0 0:0:0:0:0:0]
* #3 16, [ 16/ 0], [ 4 0:0 0:0:0:0:0:0]
* #4 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0]
* #5 32, [ 32/ 0], [ 8 0:0 0:0:0:0:0:0]
* #6 40, [ 40/ 0], [10 0:0 0:0:0:0:0:0]
* #7 44, [ 44/ 0], [11 0:0 0:0:0:0:0:0]
* #8 12, [ 12/ 0], [ 3 0:0 0:0:0:0:0:0]
* #9 20, [ 20/ 0], [ 5 0:0 0:0:0:0:0:0]
* #10 28, [ 28/ 0], [ 7 0:0 0:0:0:0:0:0]
* #11 36, [ 36/ 0], [ 9 0:0 0:0:0:0:0:0]
#12 5, [ 5/ 0], [ 1 1:0 0:0:0:0:0:0]
#13 24, [ 24/ 0], [ 6 0:0 0:0:0:0:0:0]
There are 1 procedure descriptor entries, starting at 0.
Procedure descriptor 0:
Name index = 10 Name = "main"
.mask 0x80000000,-4 .fmask 0x00000000,0
.frame $29,24,$31
Opt. start = -1 Symbols start = 1
First line # = 3 Last line # = 6
Line Offset = 0 Address = 0x00000000
There are 4 bytes holding line numbers, starting at 380.
Line 3, delta 0, count 2
Line 4, delta 1, count 3
Line 5, delta 1, count 2
Line 6, delta 1, count 6
File #1, "/usr/include/stdio.h"
Name index = 1 Readin = No
Merge = Yes Endian = LITTLE
Debug level = G2 Language = C
Adr = 0x00000000
Info Start Number Size Offset
==== ===== ====== ==== ======
Local strings 15 65 65 799
Local symbols 6 10 120 508
Line numbers 0 0 0 380
Optimization symbols 0 0 0 0
Procedures 1 0 0 436
Auxiliary symbols 14 25 100 684
Relative Files 0 0 0 0
There are 10 local symbols, starting at 442
Symbol# 0: "/usr/include/stdio.h"
End+1 symbol = 10
String index = 1
Storage class = Text Index = 10
Symbol type = File Value = 0
Symbol# 1: "_iobuf"
End+1 symbol = 9
String index = 22
Storage class = Info Index = 9
Symbol type = Block Value = 20
Symbol# 2: "_cnt"
Type = int
String index = 29
Storage class = Info Index = 4
Symbol type = Member Value = 0
Symbol# 3: "_ptr"
Type = ptr to char
String index = 34
Storage class = Info Index = 15
Symbol type = Member Value = 32
Symbol# 4: "_base"
Type = ptr to char
String index = 39
Storage class = Info Index = 16
Symbol type = Member Value = 64
Symbol# 5: "_bufsiz"
Type = int
String index = 45
Storage class = Info Index = 4
Symbol type = Member Value = 96
Symbol# 6: "_flag"
Type = short
String index = 53
Storage class = Info Index = 3
Symbol type = Member Value = 128
Symbol# 7: "_file"
Type = char
String index = 59
Storage class = Info Index = 2
Symbol type = Member Value = 144
Symbol# 8: ""
First symbol = 1
String index = 0
Storage class = Info Index = 1
Symbol type = End Value = 0
Symbol# 9: "/usr/include/stdio.h"
First symbol = 0
String index = 1
Storage class = Text Index = 0
Symbol type = End Value = 0
There are 25 auxiliary table entries, starting at 642.
* #14 -1, [4095/1048575], [63 1:1 f:f:f:f:f:f]
#15 65544, [ 8/ 16], [ 2 0:0 1:0:0:0:0:0]
#16 65544, [ 8/ 16], [ 2 0:0 1:0:0:0:0:0]
* #17 196656, [ 48/ 48], [12 0:0 3:0:0:0:0:0]
* #18 8191, [4095/ 1], [63 1:1 0:0:0:0:f:1]
* #19 1, [ 1/ 0], [ 0 1:0 0:0:0:0:0:0]
* #20 20479, [4095/ 4], [63 1:1 0:0:0:0:f:4]
* #21 1, [ 1/ 0], [ 0 1:0 0:0:0:0:0:0]
* #22 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
* #23 2, [ 2/ 0], [ 0 0:1 0:0:0:0:0:0]
* #24 160, [ 160/ 0], [40 0:0 0:0:0:0:0:0]
* #25 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
* #26 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
* #27 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
* #28 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
* #29 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
* #30 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
* #31 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
* #32 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
* #33 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
* #34 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
* #35 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
* #36 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
* #37 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
* #38 0, [ 0/ 0], [ 0 0:0 0:0:0:0:0:0]
There are 0 procedure descriptor entries, starting at 1.
There are 20 external symbols, starting at 1152
Symbol# 0: "_iob"
Type = array [3 {160}] of struct _iobuf { ifd = 1, index = 1 }
String index = 0 Ifd = 1
Storage class = Nil Index = 17
Symbol type = Global Value = 60
Symbol# 1: "fopen"
String index = 5 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 2: "fdopen"
String index = 11 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 3: "freopen"
String index = 18 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 4: "popen"
String index = 26 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 5: "tmpfile"
String index = 32 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 6: "ftell"
String index = 40 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 7: "rewind"
String index = 46 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 8: "setbuf"
String index = 53 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 9: "setbuffer"
String index = 60 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 10: "setlinebuf"
String index = 70 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 11: "fgets"
String index = 81 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 12: "gets"
String index = 87 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 13: "ctermid"
String index = 92 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 14: "cuserid"
String index = 100 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 15: "tempnam"
String index = 108 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 16: "tmpnam"
String index = 116 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 17: "sprintf"
String index = 123 Ifd = 1
Storage class = Nil Index = 1048575
Symbol type = Proc Value = 0
Symbol# 18: "main"
Type = int
String index = 131 Ifd = 0
Storage class = Text Index = 1
Symbol type = Proc Value = 0
Symbol# 19: "printf"
String index = 136 Ifd = 0
Storage class = Undefined Index = 1048575
Symbol type = Proc Value = 0
The following auxiliary table entries were unused:
#0 0 0x00000000 void
#2 8 0x00000008 char
#3 16 0x00000010 short
#4 24 0x00000018 int
#5 32 0x00000020 long
#6 40 0x00000028 float
#7 44 0x0000002c double
#8 12 0x0000000c unsigned char
#9 20 0x00000014 unsigned short
#10 28 0x0000001c unsigned int
#11 36 0x00000024 unsigned long
#14 0 0x00000000 void
#15 24 0x00000018 int
#19 32 0x00000020 long
#20 40 0x00000028 float
#21 44 0x0000002c double
#22 12 0x0000000c unsigned char
#23 20 0x00000014 unsigned short
#24 28 0x0000001c unsigned int
#25 36 0x00000024 unsigned long
#26 48 0x00000030 struct /* no name */ { ifd = -1, index = 1048575 }
[From meissner@osf.org]
--
Return to the
comp.compilers page.
Search the
comp.compilers archives again.