6aa83a798d
* stabs.texinfo: More array fixes inspired by Jim's.
3153 lines
94 KiB
Plaintext
3153 lines
94 KiB
Plaintext
\input texinfo
|
|
@setfilename stabs.info
|
|
|
|
@ifinfo
|
|
@format
|
|
START-INFO-DIR-ENTRY
|
|
* Stabs: (stabs). The "stabs" debugging information format.
|
|
END-INFO-DIR-ENTRY
|
|
@end format
|
|
@end ifinfo
|
|
|
|
@ifinfo
|
|
This document describes GNU stabs (debugging symbol tables) in a.out files.
|
|
|
|
Copyright 1992 Free Software Foundation, Inc.
|
|
Contributed by Cygnus Support. Written by Julia Menapace.
|
|
|
|
Permission is granted to make and distribute verbatim copies of
|
|
this manual provided the copyright notice and this permission notice
|
|
are preserved on all copies.
|
|
|
|
@ignore
|
|
Permission is granted to process this file through Tex and print the
|
|
results, provided the printed document carries copying permission
|
|
notice identical to this one except for the removal of this paragraph
|
|
(this paragraph not being relevant to the printed manual).
|
|
|
|
@end ignore
|
|
Permission is granted to copy or distribute modified versions of this
|
|
manual under the terms of the GPL (for which purpose this text may be
|
|
regarded as a program in the language TeX).
|
|
@end ifinfo
|
|
|
|
@setchapternewpage odd
|
|
@settitle STABS
|
|
@titlepage
|
|
@title The ``stabs'' debug format
|
|
@author Julia Menapace
|
|
@author Cygnus Support
|
|
@page
|
|
@tex
|
|
\def\$#1${{#1}} % Kluge: collect RCS revision info without $...$
|
|
\xdef\manvers{\$Revision$} % For use in headers, footers too
|
|
{\parskip=0pt
|
|
\hfill Cygnus Support\par
|
|
\hfill \manvers\par
|
|
\hfill \TeX{}info \texinfoversion\par
|
|
}
|
|
@end tex
|
|
|
|
@vskip 0pt plus 1filll
|
|
Copyright @copyright{} 1992 Free Software Foundation, Inc.
|
|
Contributed by Cygnus Support.
|
|
|
|
Permission is granted to make and distribute verbatim copies of
|
|
this manual provided the copyright notice and this permission notice
|
|
are preserved on all copies.
|
|
|
|
@end titlepage
|
|
|
|
@ifinfo
|
|
@node Top
|
|
@top The "stabs" representation of debugging information
|
|
|
|
This document describes the GNU stabs debugging format in a.out files.
|
|
|
|
@menu
|
|
* Overview:: Overview of stabs
|
|
* Program structure:: Encoding of the structure of the program
|
|
* Simple types::
|
|
* Example:: A comprehensive example in C
|
|
* Variables::
|
|
* Aggregate Types::
|
|
* Symbol tables:: Symbol information in symbol tables
|
|
* GNU Cplusplus stabs::
|
|
|
|
Appendixes:
|
|
* Example2.c:: Source code for extended example
|
|
* Example2.s:: Assembly code for extended example
|
|
* Quick reference:: Various refernce tables
|
|
* Expanded reference:: Reference information by stab type
|
|
* Questions:: Questions and anomolies
|
|
* xcoff-differences:: Differences between GNU stabs in a.out
|
|
and GNU stabs in xcoff
|
|
* Sun-differences:: Differences between GNU stabs and Sun
|
|
native stabs
|
|
@end menu
|
|
@end ifinfo
|
|
|
|
|
|
@node Overview
|
|
@chapter Overview of stabs
|
|
|
|
@dfn{Stabs} refers to a format for information that describes a program
|
|
to a debugger. This format was apparently invented by
|
|
@c FIXME! <<name of inventor>> at
|
|
the University of California at Berkeley, for the @code{pdx} Pascal
|
|
debugger; the format has spread widely since then.
|
|
|
|
@menu
|
|
* Flow:: Overview of debugging information flow
|
|
* Stabs format:: Overview of stab format
|
|
* C example:: A simple example in C source
|
|
* Assembly code:: The simple example at the assembly level
|
|
@end menu
|
|
|
|
@node Flow
|
|
@section Overview of debugging information flow
|
|
|
|
The GNU C compiler compiles C source in a @file{.c} file into assembly
|
|
language in a @file{.s} file, which is translated by the assembler into
|
|
a @file{.o} file, and then linked with other @file{.o} files and
|
|
libraries to produce an executable file.
|
|
|
|
With the @samp{-g} option, GCC puts additional debugging information in
|
|
the @file{.s} file, which is slightly transformed by the assembler and
|
|
linker, and carried through into the final executable. This debugging
|
|
information describes features of the source file like line numbers,
|
|
the types and scopes of variables, and functions, their parameters and
|
|
their scopes.
|
|
|
|
For some object file formats, the debugging information is
|
|
encapsulated in assembler directives known collectively as `stab' (symbol
|
|
table) directives, interspersed with the generated code. Stabs are
|
|
the native format for debugging information in the a.out and xcoff
|
|
object file formats. The GNU tools can also emit stabs in the coff
|
|
and ecoff object file formats.
|
|
|
|
The assembler adds the information from stabs to the symbol information
|
|
it places by default in the symbol table and the string table of the
|
|
@file{.o} file it is building. The linker consolidates the @file{.o}
|
|
files into one executable file, with one symbol table and one string
|
|
table. Debuggers use the symbol and string tables in the executable as
|
|
a source of debugging information about the program.
|
|
|
|
@node Stabs format
|
|
@section Overview of stab format
|
|
|
|
There are three overall formats for stab assembler directives
|
|
differentiated by the first word of the stab. The name of the directive
|
|
describes what combination of four possible data fields will follow. It
|
|
is either @code{.stabs} (string), @code{.stabn} (number), or
|
|
@code{.stabd} (dot).
|
|
|
|
The overall format of each class of stab is:
|
|
|
|
@example
|
|
.stabs "@var{string}",@var{type},0,@var{desc},@var{value}
|
|
.stabn @var{type},0,@var{desc},@var{value}
|
|
.stabd @var{type},0,@var{desc}
|
|
@end example
|
|
|
|
In general, in @code{.stabs} the @var{string} field contains name and type
|
|
information. For @code{.stabd} the value field is implicit and has the value
|
|
of the current file location. Otherwise the value field often
|
|
contains a relocatable address, frame pointer offset, or register
|
|
number, that maps to the source code element described by the stab.
|
|
|
|
The real key to decoding the meaning of a stab is the number in its type
|
|
field. Each possible type number defines a different stab type. The
|
|
stab type further defines the exact interpretation of, and possible
|
|
values for, any remaining @code{"@var{string}"}, @var{desc}, or
|
|
@var{value} fields present in the stab. Table A (@pxref{Stab
|
|
types,,Table A: Symbol types from stabs}) lists in numeric order
|
|
the possible type field values for stab directives. The reference
|
|
section that follows Table A describes the meaning of the fields for
|
|
each stab type in detail. The examples that follow this overview
|
|
introduce the stab types in terms of the source code elements they
|
|
describe.
|
|
|
|
For @code{.stabs} the @code{"@var{string}"} field holds the meat of the
|
|
debugging information. The generally unstructured nature of this field
|
|
is what makes stabs extensible. For some stab types the string field
|
|
contains only a name. For other stab types the contents can be a great
|
|
deal more complex.
|
|
|
|
The overall format is of the @code{"@var{string}"} field is:
|
|
|
|
@example
|
|
"@var{name}@r{[}:@var{symbol_descriptor}@r{]}
|
|
@r{[}@var{type_number}@r{[}=@var{type_descriptor} @r{@dots{}]]}"
|
|
@end example
|
|
|
|
@var{name} is the name of the symbol represented by the stab.
|
|
|
|
The @var{symbol_descriptor} following the @samp{:} is an alphabetic
|
|
character that tells more specifically what kind of symbol the stab
|
|
represents. If the @var{symbol_descriptor} is omitted, but type
|
|
information follows, then the stab represents a local variable. For a
|
|
list of symbol_descriptors, see @ref{Symbol descriptors,,Table C: Symbol
|
|
descriptors}.
|
|
|
|
Type information is either a @var{type_number}, or a
|
|
@samp{@var{type_number}=}. The @var{type_number} alone is a type
|
|
reference, referring directly to a type that has already been defined.
|
|
|
|
The @samp{@var{type_number}=} is a type definition, where the number
|
|
represents a new type which is about to be defined. The type definition
|
|
may refer to other types by number, and those type numbers may be
|
|
followed by @samp{=} and nested definitions.
|
|
|
|
In a type definition, if the character that follows the equals sign is
|
|
non-numeric then it is a @var{type_descriptor}, and tells what kind of
|
|
type is about to be defined. Any other values following the
|
|
@var{type_descriptor} vary, depending on the @var{type_descriptor}. If
|
|
a number follows the @samp{=} then the number is a @var{type_reference}.
|
|
This is described more thoroughly in the section on types. @xref{Type
|
|
Descriptors,,Table D: Type Descriptors}, for a list of
|
|
@var{type_descriptor} values.
|
|
|
|
All this can make the @code{"@var{string}"} field quite long. All
|
|
versions of GDB, and some versions of DBX, can handle arbitrarily long
|
|
strings. But many versions of DBX cretinously limit the strings to
|
|
about 80 characters, so compilers which must work with such DBX's need
|
|
to split the @code{.stabs} directive into several @code{.stabs}
|
|
directives. Each stab duplicates exactly all but the
|
|
@code{"@var{string}"} field. The @code{"@var{string}"} field of the
|
|
every stab except the last is marked as continued with a
|
|
double-backslash at the end. Removing the backslashes and concatenating
|
|
the @code{"@var{string}"} fields of each stab produces the original,
|
|
long string.
|
|
|
|
@node C example
|
|
@section A simple example in C source
|
|
|
|
To get the flavor of how stabs describe source information for a C
|
|
program, let's look at the simple program:
|
|
|
|
@example
|
|
main()
|
|
@{
|
|
printf("Hello world");
|
|
@}
|
|
@end example
|
|
|
|
When compiled with @samp{-g}, the program above yields the following
|
|
@file{.s} file. Line numbers have been added to make it easier to refer
|
|
to parts of the @file{.s} file in the description of the stabs that
|
|
follows.
|
|
|
|
@node Assembly code
|
|
@section The simple example at the assembly level
|
|
|
|
@example
|
|
1 gcc2_compiled.:
|
|
2 .stabs "/cygint/s1/users/jcm/play/",100,0,0,Ltext0
|
|
3 .stabs "hello.c",100,0,0,Ltext0
|
|
4 .text
|
|
5 Ltext0:
|
|
6 .stabs "int:t1=r1;-2147483648;2147483647;",128,0,0,0
|
|
7 .stabs "char:t2=r2;0;127;",128,0,0,0
|
|
8 .stabs "long int:t3=r1;-2147483648;2147483647;",128,0,0,0
|
|
9 .stabs "unsigned int:t4=r1;0;-1;",128,0,0,0
|
|
10 .stabs "long unsigned int:t5=r1;0;-1;",128,0,0,0
|
|
11 .stabs "short int:t6=r1;-32768;32767;",128,0,0,0
|
|
12 .stabs "long long int:t7=r1;0;-1;",128,0,0,0
|
|
13 .stabs "short unsigned int:t8=r1;0;65535;",128,0,0,0
|
|
14 .stabs "long long unsigned int:t9=r1;0;-1;",128,0,0,0
|
|
15 .stabs "signed char:t10=r1;-128;127;",128,0,0,0
|
|
16 .stabs "unsigned char:t11=r1;0;255;",128,0,0,0
|
|
17 .stabs "float:t12=r1;4;0;",128,0,0,0
|
|
18 .stabs "double:t13=r1;8;0;",128,0,0,0
|
|
19 .stabs "long double:t14=r1;8;0;",128,0,0,0
|
|
20 .stabs "void:t15=15",128,0,0,0
|
|
21 .align 4
|
|
22 LC0:
|
|
23 .ascii "Hello, world!\12\0"
|
|
24 .align 4
|
|
25 .global _main
|
|
26 .proc 1
|
|
27 _main:
|
|
28 .stabn 68,0,4,LM1
|
|
29 LM1:
|
|
30 !#PROLOGUE# 0
|
|
31 save %sp,-136,%sp
|
|
32 !#PROLOGUE# 1
|
|
33 call ___main,0
|
|
34 nop
|
|
35 .stabn 68,0,5,LM2
|
|
36 LM2:
|
|
37 LBB2:
|
|
38 sethi %hi(LC0),%o1
|
|
39 or %o1,%lo(LC0),%o0
|
|
40 call _printf,0
|
|
41 nop
|
|
42 .stabn 68,0,6,LM3
|
|
43 LM3:
|
|
44 LBE2:
|
|
45 .stabn 68,0,6,LM4
|
|
46 LM4:
|
|
47 L1:
|
|
48 ret
|
|
49 restore
|
|
50 .stabs "main:F1",36,0,0,_main
|
|
51 .stabn 192,0,0,LBB2
|
|
52 .stabn 224,0,0,LBE2
|
|
@end example
|
|
|
|
This simple ``hello world'' example demonstrates several of the stab
|
|
types used to describe C language source files.
|
|
|
|
@node Program structure
|
|
@chapter Encoding for the structure of the program
|
|
|
|
@menu
|
|
* Source file:: The path and name of the source file
|
|
* Line numbers::
|
|
* Procedures::
|
|
* Block Structure::
|
|
@end menu
|
|
|
|
@node Source file
|
|
@section The path and name of the source file
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabs}
|
|
@item Type:
|
|
@code{N_SO}
|
|
@end table
|
|
|
|
The first stabs in the .s file contain the name and path of the source
|
|
file that was compiled to produce the .s file. This information is
|
|
contained in two records of stab type N_SO (100).
|
|
|
|
@example
|
|
.stabs "path_name", N_SO, NIL, NIL, Code_address_of_program_start
|
|
.stabs "file_name:", N_SO, NIL, NIL, Code_address_of_program_start
|
|
@end example
|
|
|
|
@example
|
|
2 .stabs "/cygint/s1/users/jcm/play/",100,0,0,Ltext0
|
|
3 .stabs "hello.c",100,0,0,Ltext0
|
|
4 .text
|
|
5 Ltext0:
|
|
@end example
|
|
|
|
@node Line numbers
|
|
@section Line Numbers
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabn}
|
|
@item Type:
|
|
@code{N_SLINE}
|
|
@end table
|
|
|
|
The start of source lines is represented by the @code{N_SLINE} (68) stab
|
|
type.
|
|
|
|
@example
|
|
.stabn N_SLINE, NIL, @var{line}, @var{address}
|
|
@end example
|
|
|
|
@var{line} is a source line number; @var{address} represents the code
|
|
address for the start of that source line.
|
|
|
|
@example
|
|
27 _main:
|
|
28 .stabn 68,0,4,LM1
|
|
29 LM1:
|
|
30 !#PROLOGUE# 0
|
|
@end example
|
|
|
|
@node Procedures
|
|
@section Procedures
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabs}
|
|
@item Type:
|
|
@code{N_FUN}
|
|
@item Symbol Descriptors:
|
|
@code{f} (local), @code{F} (global)
|
|
@end table
|
|
|
|
Procedures are described by the @code{N_FUN} stab type. The symbol
|
|
descriptor for a procedure is @samp{F} if the procedure is globally
|
|
scoped and @samp{f} if the procedure is static (locally scoped).
|
|
|
|
The @code{N_FUN} stab representing a procedure is located immediately
|
|
following the code of the procedure. The @code{N_FUN} stab is in turn
|
|
directly followed by a group of other stabs describing elements of the
|
|
procedure. These other stabs describe the procedure's parameters, its
|
|
block local variables and its block structure.
|
|
|
|
@example
|
|
48 ret
|
|
49 restore
|
|
@end example
|
|
|
|
The @code{.stabs} entry after this code fragment shows the @var{name} of
|
|
the procedure (@code{main}); the type descriptor @var{desc} (@code{F},
|
|
for a global procedure); a reference to the predefined type @code{int}
|
|
for the return type; and the starting @var{address} of the procedure.
|
|
|
|
Here is an exploded summary (with whitespace introduced for clarity),
|
|
followed by line 50 of our sample assembly output, which has this form:
|
|
|
|
@example
|
|
.stabs "@var{name}:
|
|
@var{desc} @r{(global proc @samp{F})}
|
|
@var{return_type_ref} @r{(int)}
|
|
",N_FUN, NIL, NIL,
|
|
@var{address}
|
|
@end example
|
|
|
|
@example
|
|
50 .stabs "main:F1",36,0,0,_main
|
|
@end example
|
|
|
|
@node Block Structure
|
|
@section Block Structure
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabn}
|
|
@item Types:
|
|
@code{N_LBRAC}, @code{N_RBRAC}
|
|
@end table
|
|
|
|
The program's block structure is represented by the @code{N_LBRAC} (left
|
|
brace) and the @code{N_RBRAC} (right brace) stab types. The following code
|
|
range, which is the body of @code{main}, is labeled with @samp{LBB2:} at the
|
|
beginning and @samp{LBE2:} at the end.
|
|
|
|
@example
|
|
37 LBB2:
|
|
38 sethi %hi(LC0),%o1
|
|
39 or %o1,%lo(LC0),%o0
|
|
40 call _printf,0
|
|
41 nop
|
|
42 .stabn 68,0,6,LM3
|
|
43 LM3:
|
|
44 LBE2:
|
|
@end example
|
|
|
|
The @code{N_LBRAC} and @code{N_RBRAC} stabs that describe the block
|
|
scope of the procedure are located after the @code{N_FUNC} stab that
|
|
represents the procedure itself. The @code{N_LBRAC} uses the
|
|
@code{LBB2} label as the code address in its value field, and the
|
|
@code{N_RBRAC} uses @code{LBE2}.
|
|
|
|
@example
|
|
50 .stabs "main:F1",36,0,0,_main
|
|
@end example
|
|
|
|
@example
|
|
.stabn N_LBRAC, NIL, NIL, @var{left-brace-address}
|
|
.stabn N_RBRAC, NIL, NIL, @var{right-brace-address}
|
|
@end example
|
|
|
|
@example
|
|
51 .stabn 192,0,0,LBB2
|
|
52 .stabn 224,0,0,LBE2
|
|
@end example
|
|
|
|
@node Simple types
|
|
@chapter Simple types
|
|
|
|
@menu
|
|
* Basic types:: Basic type definitions
|
|
* Range types:: Range types defined by min and max value
|
|
* Float "range" types:: Range type defined by size in bytes
|
|
@end menu
|
|
|
|
@node Basic types
|
|
@section Basic type definitions
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabs}
|
|
@item Type:
|
|
@code{N_LSYM}
|
|
@item Symbol Descriptor:
|
|
@code{t}
|
|
@end table
|
|
|
|
The basic types for the language are described using the @code{N_LSYM} stab
|
|
type. They are boilerplate and are emited by the compiler for each
|
|
compilation unit. Basic type definitions are not always a complete
|
|
description of the type and are sometimes circular. The debugger
|
|
recognizes the type anyway, and knows how to read bits as that type.
|
|
|
|
Each language and compiler defines a slightly different set of basic
|
|
types. In this example we are looking at the basic types for C emited
|
|
by the GNU compiler targeting the Sun4. Here the basic types are
|
|
mostly defined as range types.
|
|
|
|
|
|
@node Range types
|
|
@section Range types defined by min and max value
|
|
|
|
@table @strong
|
|
@item Type Descriptor:
|
|
@code{r}
|
|
@end table
|
|
|
|
When defining a range type, if the number after the first semicolon is
|
|
smaller than the number after the second one, then the two numbers
|
|
represent the smallest and the largest values in the range.
|
|
|
|
@example
|
|
4 .text
|
|
5 Ltext0:
|
|
|
|
.stabs "@var{name}:
|
|
@var{descriptor} @r{(type)}
|
|
@var{type-def}=
|
|
@var{type-desc}
|
|
@var{type-ref};
|
|
@var{low-bound};
|
|
@var{high-bound};
|
|
",
|
|
N_LSYM, NIL, NIL, NIL
|
|
|
|
6 .stabs "int:t1=r1;-2147483648;2147483647;",128,0,0,0
|
|
7 .stabs "char:t2=r2;0;127;",128,0,0,0
|
|
@end example
|
|
|
|
Here the integer type (@code{1}) is defined as a range of the integer
|
|
type (@code{1}). Likewise @code{char} is a range of @code{char}. This
|
|
part of the definition is circular, but at least the high and low bound
|
|
values of the range hold more information about the type.
|
|
|
|
Here short unsigned int is defined as type number 8 and described as a
|
|
range of type @code{int}, with a minimum value of 0 and a maximum of 65535.
|
|
|
|
@example
|
|
13 .stabs "short unsigned int:t8=r1;0;65535;",128,0,0,0
|
|
@end example
|
|
|
|
@node Float "range" types
|
|
@section Range type defined by size in bytes
|
|
|
|
@table @strong
|
|
@item Type Descriptor:
|
|
@code{r}
|
|
@end table
|
|
|
|
In a range definition, if the first number after the semicolon is
|
|
positive and the second is zero, then the type being defined is a
|
|
floating point type, and the number after the first semicolon is the
|
|
number of bytes needed to represent the type. Note that this does not
|
|
provide a way to distinguish 8-byte real floating point types from
|
|
8-byte complex floating point types.
|
|
|
|
@example
|
|
.stabs "@var{name}:
|
|
@var{desc}
|
|
@var{type-def}=
|
|
@var{type-desc}
|
|
@var{type-ref};
|
|
@var{bit-count};
|
|
0;
|
|
",
|
|
N_LSYM, NIL, NIL, NIL
|
|
|
|
17 .stabs "float:t12=r1;4;0;",128,0,0,0
|
|
18 .stabs "double:t13=r1;8;0;",128,0,0,0
|
|
19 .stabs "long double:t14=r1;8;0;",128,0,0,0
|
|
@end example
|
|
|
|
Cosmically enough, the @code{void} type is defined directly in terms of
|
|
itself.
|
|
|
|
@example
|
|
.stabs "@var{name}:
|
|
@var{symbol-desc}
|
|
@var{type-def}=
|
|
@var{type-ref}
|
|
",N_LSYM,NIL,NIL,NIL
|
|
|
|
20 .stabs "void:t15=15",128,0,0,0
|
|
@end example
|
|
|
|
|
|
@node Example
|
|
@chapter A Comprehensive Example in C
|
|
|
|
Now we'll examine a second program, @code{example2}, which builds on the
|
|
first example to introduce the rest of the stab types, symbol
|
|
descriptors, and type descriptors used in C.
|
|
@xref{Example2.c} for the complete @file{.c} source,
|
|
and @pxref{Example2.s} for the @file{.s} assembly code.
|
|
This description includes parts of those files.
|
|
|
|
@section Flow of control and nested scopes
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabn}
|
|
@item Types:
|
|
@code{N_SLINE}, @code{N_LBRAC}, @code{N_RBRAC} (cont.)
|
|
@end table
|
|
|
|
Consider the body of @code{main}, from @file{example2.c}. It shows more
|
|
about how @code{N_SLINE}, @code{N_RBRAC}, and @code{N_LBRAC} stabs are used.
|
|
|
|
@example
|
|
20 @{
|
|
21 static float s_flap;
|
|
22 int times;
|
|
23 for (times=0; times < s_g_repeat; times++)@{
|
|
24 int inner;
|
|
25 printf ("Hello world\n");
|
|
26 @}
|
|
27 @};
|
|
@end example
|
|
|
|
Here we have a single source line, the @samp{for} line, that generates
|
|
non-linear flow of control, and non-contiguous code. In this case, an
|
|
@code{N_SLINE} stab with the same line number proceeds each block of
|
|
non-contiguous code generated from the same source line.
|
|
|
|
The example also shows nested scopes. The @code{N_LBRAC} and
|
|
@code{N_LBRAC} stabs that describe block structure are nested in the
|
|
same order as the corresponding code blocks, those of the for loop
|
|
inside those for the body of main.
|
|
|
|
@noindent
|
|
This is the label for the @code{N_LBRAC} (left brace) stab marking the
|
|
start of @code{main}.
|
|
|
|
@example
|
|
57 LBB2:
|
|
@end example
|
|
|
|
@noindent
|
|
In the first code range for C source line 23, the @code{for} loop
|
|
initialize and test, @code{N_SLINE} (68) records the line number:
|
|
|
|
@example
|
|
.stabn N_SLINE, NIL,
|
|
@var{line},
|
|
@var{address}
|
|
|
|
58 .stabn 68,0,23,LM2
|
|
59 LM2:
|
|
60 st %g0,[%fp-20]
|
|
61 L2:
|
|
62 sethi %hi(_s_g_repeat),%o0
|
|
63 ld [%fp-20],%o1
|
|
64 ld [%o0+%lo(_s_g_repeat)],%o0
|
|
65 cmp %o1,%o0
|
|
66 bge L3
|
|
67 nop
|
|
|
|
@exdent label for the @code{N_LBRAC} (start block) marking the start of @code{for} loop
|
|
|
|
68 LBB3:
|
|
69 .stabn 68,0,25,LM3
|
|
70 LM3:
|
|
71 sethi %hi(LC0),%o1
|
|
72 or %o1,%lo(LC0),%o0
|
|
73 call _printf,0
|
|
74 nop
|
|
75 .stabn 68,0,26,LM4
|
|
76 LM4:
|
|
|
|
@exdent label for the @code{N_RBRAC} (end block) stab marking the end of the @code{for} loop
|
|
|
|
77 LBE3:
|
|
@end example
|
|
|
|
@noindent
|
|
Now we come to the second code range for source line 23, the @code{for}
|
|
loop increment and return. Once again, @code{N_SLINE} (68) records the
|
|
source line number:
|
|
|
|
@example
|
|
.stabn, N_SLINE, NIL,
|
|
@var{line},
|
|
@var{address}
|
|
|
|
78 .stabn 68,0,23,LM5
|
|
79 LM5:
|
|
80 L4:
|
|
81 ld [%fp-20],%o0
|
|
82 add %o0,1,%o1
|
|
83 st %o1,[%fp-20]
|
|
84 b,a L2
|
|
85 L3:
|
|
86 .stabn 68,0,27,LM6
|
|
87 LM6:
|
|
|
|
@exdent label for the @code{N_RBRAC} (end block) stab marking the end of the @code{for} loop
|
|
|
|
88 LBE2:
|
|
89 .stabn 68,0,27,LM7
|
|
90 LM7:
|
|
91 L1:
|
|
92 ret
|
|
93 restore
|
|
94 .stabs "main:F1",36,0,0,_main
|
|
95 .stabs "argc:p1",160,0,0,68
|
|
96 .stabs "argv:p20=*21=*2",160,0,0,72
|
|
97 .stabs "s_flap:V12",40,0,0,_s_flap.0
|
|
98 .stabs "times:1",128,0,0,-20
|
|
@end example
|
|
|
|
@noindent
|
|
Here is an illustration of stabs describing nested scopes. The scope
|
|
nesting is reflected in the nested bracketing stabs (@code{N_LBRAC},
|
|
192, appears here).
|
|
|
|
@example
|
|
.stabn N_LBRAC,NIL,NIL,
|
|
@var{block-start-address}
|
|
|
|
99 .stabn 192,0,0,LBB2 ## begin proc label
|
|
100 .stabs "inner:1",128,0,0,-24
|
|
101 .stabn 192,0,0,LBB3 ## begin for label
|
|
@end example
|
|
|
|
@noindent
|
|
@code{N_RBRAC} (224), ``right brace'' ends a lexical block (scope).
|
|
|
|
@example
|
|
.stabn N_RBRAC,NIL,NIL,
|
|
@var{block-end-address}
|
|
|
|
102 .stabn 224,0,0,LBE3 ## end for label
|
|
103 .stabn 224,0,0,LBE2 ## end proc label
|
|
@end example
|
|
|
|
@node Variables
|
|
@chapter Variables
|
|
|
|
@menu
|
|
* Automatic variables:: locally scoped
|
|
* Global Variables::
|
|
* Register variables::
|
|
* Initialized statics::
|
|
* Un-initialized statics::
|
|
* Parameters::
|
|
@end menu
|
|
|
|
@node Automatic variables
|
|
@section Locally scoped automatic variables
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabs}
|
|
@item Type:
|
|
@code{N_LSYM}
|
|
@item Symbol Descriptor:
|
|
none
|
|
@end table
|
|
|
|
|
|
In addition to describing types, the @code{N_LSYM} stab type also
|
|
describes locally scoped automatic variables. Refer again to the body
|
|
of @code{main} in @file{example2.c}. It allocates two automatic
|
|
variables: @samp{times} is scoped to the body of @code{main}, and
|
|
@samp{inner} is scoped to the body of the @code{for} loop.
|
|
@samp{s_flap} is locally scoped but not automatic, and will be discussed
|
|
later.
|
|
|
|
@example
|
|
20 @{
|
|
21 static float s_flap;
|
|
22 int times;
|
|
23 for (times=0; times < s_g_repeat; times++)@{
|
|
24 int inner;
|
|
25 printf ("Hello world\n");
|
|
26 @}
|
|
27 @};
|
|
@end example
|
|
|
|
The @code{N_LSYM} stab for an automatic variable is located just before the
|
|
@code{N_LBRAC} stab describing the open brace of the block to which it is
|
|
scoped.
|
|
|
|
@example
|
|
@exdent @code{N_LSYM} (128): automatic variable, scoped locally to @code{main}
|
|
|
|
.stabs "@var{name}:
|
|
@var{type-ref}",
|
|
N_LSYM, NIL, NIL,
|
|
@var{frame-pointer-offset}
|
|
|
|
98 .stabs "times:1",128,0,0,-20
|
|
99 .stabn 192,0,0,LBB2 ## begin `main' N_LBRAC
|
|
|
|
@exdent @code{N_LSYM} (128): automatic variable, scoped locally to the @code{for} loop
|
|
|
|
.stabs "@var{name}:
|
|
@var{type-ref}",
|
|
N_LSYM, NIL, NIL,
|
|
@var{frame-pointer-offset}
|
|
|
|
100 .stabs "inner:1",128,0,0,-24
|
|
101 .stabn 192,0,0,LBB3 ## begin `for' loop N_LBRAC
|
|
@end example
|
|
|
|
Since the character in the string field following the colon is not a
|
|
letter, there is no symbol descriptor. This means that the stab
|
|
describes a local variable, and that the number after the colon is a
|
|
type reference. In this case it a a reference to the basic type @code{int}.
|
|
Notice also that the frame pointer offset is negative number for
|
|
automatic variables.
|
|
|
|
|
|
@node Global Variables
|
|
@section Global Variables
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabs}
|
|
@item Type:
|
|
@code{N_GSYM}
|
|
@item Symbol Descriptor:
|
|
@code{G}
|
|
@end table
|
|
|
|
Global variables are represented by the @code{N_GSYM} stab type. The symbol
|
|
descriptor, following the colon in the string field, is @samp{G}. Following
|
|
the @samp{G} is a type reference or type definition. In this example it is a
|
|
type reference to the basic C type, @code{char}. The first source line in
|
|
@file{example2.c},
|
|
|
|
@example
|
|
1 char g_foo = 'c';
|
|
@end example
|
|
|
|
@noindent
|
|
yields the following stab. The stab immediately precedes the code that
|
|
allocates storage for the variable it describes.
|
|
|
|
@example
|
|
@exdent @code{N_GSYM} (32): global symbol
|
|
|
|
.stabs "@var{name}:
|
|
@var{descriptor}
|
|
@var{type-ref}",
|
|
N_GSYM, NIL, NIL, NIL
|
|
|
|
21 .stabs "g_foo:G2",32,0,0,0
|
|
22 .global _g_foo
|
|
23 .data
|
|
24 _g_foo:
|
|
25 .byte 99
|
|
@end example
|
|
|
|
The address of the variable represented by the @code{N_GSYM} is not contained
|
|
in the @code{N_GSYM} stab. The debugger gets this information from the
|
|
external symbol for the global variable.
|
|
|
|
@node Register variables
|
|
@section Global register variables
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabs}
|
|
@item Type:
|
|
@code{N_RSYM}
|
|
@item Symbol Descriptor:
|
|
@code{r}
|
|
@end table
|
|
|
|
The following source line defines a global variable, @code{g_bar}, which is
|
|
explicitly allocated in global register @code{%g5}.
|
|
|
|
@example
|
|
2 register int g_bar asm ("%g5");
|
|
@end example
|
|
|
|
Register variables have their own stab type, @code{N_RSYM}, and their own
|
|
symbol descriptor, @code{r}. The stab's value field contains the number of
|
|
the register where the variable data will be stored. Since the
|
|
variable was not initialized in this compilation unit, the stab is
|
|
emited at the end of the object file, with the stabs for other
|
|
uninitialized globals (@code{bcc}).
|
|
|
|
@example
|
|
@exdent @code{N_RSYM} (64): register variable
|
|
|
|
.stabs "@var{name}:
|
|
@var{descriptor}
|
|
@var{type-ref}",
|
|
N_RSYM, NIL, NIL,
|
|
@var{register}
|
|
|
|
133 .stabs "g_bar:r1",64,0,0,5
|
|
@end example
|
|
|
|
|
|
@node Initialized statics
|
|
@section Initialized static variables
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabs}
|
|
@item Type:
|
|
@code{N_STSYM}
|
|
@item Symbol Descriptors:
|
|
@code{S} (file scope), @code{V} (procedure scope)
|
|
@end table
|
|
|
|
Initialized static variables are represented by the @code{N_STSYM} stab
|
|
type. The symbol descriptor part of the string field shows if the
|
|
variable is file scope static (@samp{S}) or procedure scope static
|
|
(@samp{V}). The source line
|
|
|
|
@example
|
|
3 static int s_g_repeat = 2;
|
|
@end example
|
|
|
|
@noindent
|
|
yields the following code. The stab is located immediately preceding
|
|
the storage for the variable it represents. Since the variable in
|
|
this example is file scope static the symbol descriptor is @samp{S}.
|
|
|
|
@example
|
|
@exdent @code{N_STSYM} (38): initialized static variable (data seg w/internal linkage)
|
|
|
|
.stabs "@var{name}:
|
|
@var{descriptor}
|
|
@var{type-ref}",
|
|
N_STSYM,NIL,NIL,
|
|
@var{address}
|
|
|
|
26 .stabs "s_g_repeat:S1",38,0,0,_s_g_repeat
|
|
27 .align 4
|
|
28 _s_g_repeat:
|
|
29 .word 2
|
|
@end example
|
|
|
|
|
|
@node Un-initialized statics
|
|
@section Un-initialized static variables
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabs}
|
|
@item Type:
|
|
@code{N_LCSYM}
|
|
@item Symbol Descriptors:
|
|
@code{S} (file scope), @code{V} (procedure scope)
|
|
@end table
|
|
|
|
Un-initialized static variables are represented by the @code{N_LCSYM}
|
|
stab type. The symbol descriptor part of the string shows if the
|
|
variable is file scope static (@samp{S}) or procedure scope static
|
|
(@samp{V}). In this example it is procedure scope static. The source
|
|
line allocating @code{s_flap} immediately follows the open brace for the
|
|
procedure @code{main}.
|
|
|
|
@example
|
|
20 @{
|
|
21 static float s_flap;
|
|
@end example
|
|
|
|
The code that reserves storage for the variable @code{s_flap} precedes the
|
|
body of body of @code{main}.
|
|
|
|
@example
|
|
39 .reserve _s_flap.0,4,"bss",4
|
|
@end example
|
|
|
|
But since @code{s_flap} is scoped locally to @code{main}, its stab is
|
|
located with the other stabs representing symbols local to @code{main}.
|
|
The stab for @code{s_flap} is located just before the @code{N_LBRAC} for
|
|
@code{main}.
|
|
|
|
@example
|
|
@exdent @code{N_LCSYM} (40): uninitialized static var (BSS seg w/internal linkage)
|
|
|
|
.stabs "@var{name}:
|
|
@var{descriptor}
|
|
@var{type-ref}",
|
|
N_LCSYM, NIL, NIL,
|
|
@var{address}
|
|
|
|
97 .stabs "s_flap:V12",40,0,0,_s_flap.0
|
|
98 .stabs "times:1",128,0,0,-20
|
|
99 .stabn 192,0,0,LBB2 # N_LBRAC for main.
|
|
@end example
|
|
|
|
@c ............................................................
|
|
|
|
@node Parameters
|
|
@section Parameters
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabs}
|
|
@item Type:
|
|
@code{N_PSYM}
|
|
@item Symbol Descriptor:
|
|
@code{p}
|
|
@end table
|
|
|
|
Procedure parameters are represented by the N_PSYM stab type. The
|
|
following source lines show the parameters of the main routine.
|
|
|
|
@example
|
|
17 main (argc, argv)
|
|
18 int argc;
|
|
19 char* argv[];
|
|
20 @{
|
|
@end example
|
|
|
|
The N_PSYM stabs describing parameters to a function directly follow
|
|
the N_FUN stab that represents the procedure itself. The N_FUN stab
|
|
immediately follows the code of the procedure it describes. Following
|
|
the N_PSYM parameter stabs are any N_LSYM stabs representing local
|
|
variables.
|
|
|
|
@example
|
|
@exdent <36> N_FUN - describing the procedure main
|
|
|
|
94 .stabs "main:F1",36,0,0,_main
|
|
|
|
@exdent <160> N_PSYM - parameters
|
|
@exdent .stabs "name:sym_desc(value_param)type_ref(int)", N_PSYM,
|
|
@exdent NIL, NIL, frame_ptr_offset
|
|
|
|
95 .stabs "argc:p1",160,0,0,68
|
|
|
|
@exdent <160> N_PSYM - parameter
|
|
@exdent .stabs "name:sym_desc(value_param)type_def(20)=ptr_to type_def(21)=
|
|
@exdent ptr_to type_ref(char)
|
|
|
|
96 .stabs "argv:p20=*21=*2",160,0,0,72
|
|
@end example
|
|
|
|
The type definition of argv is interesting because it defines two new
|
|
types in terms of an existing one. The ``array'' argv is really a
|
|
pointer, according to C language rules, since it is declared as a
|
|
parameter. Its element type is character pointers. Thus the type of
|
|
argv is ptr to ptr to char. The stab for argv contains nested
|
|
type_definitions. Type 21 is ptr to type 2 (char) and argv (type 20)
|
|
is ptr to type 21.
|
|
|
|
@node Aggregate Types
|
|
@chapter Aggregate Types
|
|
|
|
Now let's look at some variable definitions involving complex types.
|
|
This involves understanding better how types are described. In the
|
|
examples so far types have been described as references to previously
|
|
defined types or defined in terms of subranges of or pointers to
|
|
previously defined types. The section that follows will talk about
|
|
the various other type descriptors that may follow the = sign in a
|
|
type definition.
|
|
|
|
@menu
|
|
* Arrays::
|
|
* Enumerations::
|
|
* Structure tags::
|
|
* Typedefs::
|
|
* Unions::
|
|
* Function types::
|
|
@end menu
|
|
|
|
@node Arrays
|
|
@section Array types
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabs}
|
|
@item Types:
|
|
@code{N_GSYM}, @code{N_LSYM}
|
|
@item Symbol Descriptor:
|
|
@code{T}
|
|
@item Type Descriptor:
|
|
@code{a}
|
|
@end table
|
|
|
|
As an example of an array type consider the global variable below.
|
|
|
|
@example
|
|
15 char char_vec[3] = @{'a','b','c'@};
|
|
@end example
|
|
|
|
Since the array is a global variable, it is described by the N_GSYM
|
|
stab type. The symbol descriptor G, following the colon in stab's
|
|
string field, also says the array is a global variable. Following the
|
|
G is a definition for type (19) as shown by the equals sign after the
|
|
type number.
|
|
|
|
After the equals sign is a type descriptor, a, which says that the type
|
|
being defined is an array. Following the type descriptor for an array
|
|
is the type of the index, a semicolon, and the type of the array elements.
|
|
|
|
The type of the index is often a range type, expressed as the letter r
|
|
and some parameters. It defines the size of the array. In in the
|
|
example below, the range @code{r1;0;2;} defines an index type which is
|
|
a subrange of type 1 (integer), with a lower bound of 0 and an upper
|
|
bound of 2. This defines the valid range of subscripts of a
|
|
three-element C array.
|
|
|
|
The array definition above generates the assembly language that
|
|
follows.
|
|
|
|
@example
|
|
@exdent <32> N_GSYM - global variable
|
|
@exdent .stabs "name:sym_desc(global)type_def(19)=type_desc(array)
|
|
@exdent index_type_ref(range of int from 0 to 2);element_type_ref(char)";
|
|
@exdent N_GSYM, NIL, NIL, NIL
|
|
|
|
32 .stabs "char_vec:G19=ar1;0;2;2",32,0,0,0
|
|
33 .global _char_vec
|
|
34 .align 4
|
|
35 _char_vec:
|
|
36 .byte 97
|
|
37 .byte 98
|
|
38 .byte 99
|
|
@end example
|
|
|
|
@node Enumerations
|
|
@section Enumerations
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabs}
|
|
@item Type:
|
|
@code{N_LSYM}
|
|
@item Symbol Descriptor:
|
|
@code{T}
|
|
@item Type Descriptor:
|
|
@code{e}
|
|
@end table
|
|
|
|
The source line below declares an enumeration type. It is defined at
|
|
file scope between the bodies of main and s_proc in example2.c.
|
|
Because the N_LSYM is located after the N_RBRAC that marks the end of
|
|
the previous procedure's block scope, and before the N_FUN that marks
|
|
the beginning of the next procedure's block scope, the N_LSYM does not
|
|
describe a block local symbol, but a file local one. The source line:
|
|
|
|
@example
|
|
29 enum e_places @{first,second=3,last@};
|
|
@end example
|
|
|
|
@noindent
|
|
generates the following stab, located just after the N_RBRAC (close
|
|
brace stab) for main. The type definition is in an N_LSYM stab
|
|
because type definitions are file scope not global scope.
|
|
|
|
@display
|
|
<128> N_LSYM - local symbol
|
|
.stab "name:sym_dec(type)type_def(22)=sym_desc(enum)
|
|
enum_name:value(0),enum_name:value(3),enum_name:value(4),;",
|
|
N_LSYM, NIL, NIL, NIL
|
|
@end display
|
|
|
|
@example
|
|
104 .stabs "e_places:T22=efirst:0,second:3,last:4,;",128,0,0,0
|
|
@end example
|
|
|
|
The symbol descriptor (T) says that the stab describes a structure,
|
|
enumeration, or type tag. The type descriptor e, following the 22= of
|
|
the type definition narrows it down to an enumeration type. Following
|
|
the e is a list of the elements of the enumeration. The format is
|
|
name:value,. The list of elements ends with a ;.
|
|
|
|
@node Structure tags
|
|
@section Structure Tags
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabs}
|
|
@item Type:
|
|
@code{N_LSYM}
|
|
@item Symbol Descriptor:
|
|
@code{T}
|
|
@item Type Descriptor:
|
|
@code{s}
|
|
@end table
|
|
|
|
The following source code declares a structure tag and defines an
|
|
instance of the structure in global scope. Then a typedef equates the
|
|
structure tag with a new type. A seperate stab is generated for the
|
|
structure tag, the structure typedef, and the structure instance. The
|
|
stabs for the tag and the typedef are emited when the definitions are
|
|
encountered. Since the structure elements are not initialized, the
|
|
stab and code for the structure variable itself is located at the end
|
|
of the program in .common.
|
|
|
|
@example
|
|
6 struct s_tag @{
|
|
7 int s_int;
|
|
8 float s_float;
|
|
9 char s_char_vec[8];
|
|
10 struct s_tag* s_next;
|
|
11 @} g_an_s;
|
|
12
|
|
13 typedef struct s_tag s_typedef;
|
|
@end example
|
|
|
|
The structure tag is an N_LSYM stab type because, like the enum, the
|
|
symbol is file scope. Like the enum, the symbol descriptor is T, for
|
|
enumeration, struct or tag type. The symbol descriptor s following
|
|
the 16= of the type definition narrows the symbol type to struct.
|
|
|
|
Following the struct symbol descriptor is the number of bytes the
|
|
struct occupies, followed by a description of each structure element.
|
|
The structure element descriptions are of the form name:type, bit
|
|
offset from the start of the struct, and number of bits in the
|
|
element.
|
|
|
|
|
|
@example
|
|
<128> N_LSYM - type definition
|
|
.stabs "name:sym_desc(struct tag) Type_def(16)=type_desc(struct type)
|
|
struct_bytes
|
|
elem_name:type_ref(int),bit_offset,field_bits;
|
|
elem_name:type_ref(float),bit_offset,field_bits;
|
|
elem_name:type_def(17)=type_desc(array)
|
|
index_type(range of int from 0 to 7);
|
|
element_type(char),bit_offset,field_bits;;",
|
|
N_LSYM,NIL,NIL,NIL
|
|
|
|
30 .stabs "s_tag:T16=s20s_int:1,0,32;s_float:12,32,32;
|
|
s_char_vec:17=ar1;0;7;2,64,64;s_next:18=*16,128,32;;",128,0,0,0
|
|
@end example
|
|
|
|
In this example, two of the structure elements are previously defined
|
|
types. For these, the type following the name: part of the element
|
|
description is a simple type reference. The other two structure
|
|
elements are new types. In this case there is a type definition
|
|
embedded after the name:. The type definition for the array element
|
|
looks just like a type definition for a standalone array. The s_next
|
|
field is a pointer to the same kind of structure that the field is an
|
|
element of. So the definition of structure type 16 contains an type
|
|
definition for an element which is a pointer to type 16.
|
|
|
|
@node Typedefs
|
|
@section Typedefs
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabs}
|
|
@item Type:
|
|
@code{N_LSYM}
|
|
@item Symbol Descriptor:
|
|
@code{t}
|
|
@end table
|
|
|
|
Here is the stab for the typedef equating the structure tag with a
|
|
type.
|
|
|
|
@display
|
|
<128> N_LSYM - type definition
|
|
.stabs "name:sym_desc(type name)type_ref(struct_tag)",N_LSYM,NIL,NIL,NIL
|
|
@end display
|
|
|
|
@example
|
|
31 .stabs "s_typedef:t16",128,0,0,0
|
|
@end example
|
|
|
|
And here is the code generated for the structure variable.
|
|
|
|
@display
|
|
<32> N_GSYM - global symbol
|
|
.stabs "name:sym_desc(global)type_ref(struct_tag)",N_GSYM,NIL,NIL,NIL
|
|
@end display
|
|
|
|
@example
|
|
136 .stabs "g_an_s:G16",32,0,0,0
|
|
137 .common _g_an_s,20,"bss"
|
|
@end example
|
|
|
|
Notice that the structure tag has the same type number as the typedef
|
|
for the structure tag. It is impossible to distinguish between a
|
|
variable of the struct type and one of its typedef by looking at the
|
|
debugging information.
|
|
|
|
|
|
@node Unions
|
|
@section Unions
|
|
|
|
@table @strong
|
|
@item Directive:
|
|
@code{.stabs}
|
|
@item Type:
|
|
@code{N_LSYM}
|
|
@item Symbol Descriptor:
|
|
@code{T}
|
|
@item Type Descriptor:
|
|
@code{u}
|
|
@end table
|
|
|
|
Next let's look at unions. In example2 this union type is declared
|
|
locally to a procedure and an instance of the union is defined.
|
|
|
|
@example
|
|
36 union u_tag @{
|
|
37 int u_int;
|
|
38 float u_float;
|
|
39 char* u_char;
|
|
40 @} an_u;
|
|
@end example
|
|
|
|
This code generates a stab for the union tag and a stab for the union
|
|
variable. Both use the N_LSYM stab type. Since the union variable is
|
|
scoped locally to the procedure in which it is defined, its stab is
|
|
located immediately preceding the N_LBRAC for the procedure's block
|
|
start.
|
|
|
|
The stab for the union tag, however is located preceding the code for
|
|
the procedure in which it is defined. The stab type is N_LSYM. This
|
|
would seem to imply that the union type is file scope, like the struct
|
|
type s_tag. This is not true. The contents and position of the stab
|
|
for u_type do not convey any infomation about its procedure local
|
|
scope.
|
|
|
|
@display
|
|
<128> N_LSYM - type
|
|
.stabs "name:sym_desc(union tag)type_def(22)=type_desc(union)
|
|
byte_size(4)
|
|
elem_name:type_ref(int),bit_offset(0),bit_size(32);
|
|
elem_name:type_ref(float),bit_offset(0),bit_size(32);
|
|
elem_name:type_ref(ptr to char),bit_offset(0),bit_size(32);;"
|
|
N_LSYM, NIL, NIL, NIL
|
|
@end display
|
|
|
|
@smallexample
|
|
105 .stabs "u_tag:T23=u4u_int:1,0,32;u_float:12,0,32;u_char:21,0,32;;",
|
|
128,0,0,0
|
|
@end smallexample
|
|
|
|
The symbol descriptor, T, following the name: means that the stab
|
|
describes an enumeration struct or type tag. The type descriptor u,
|
|
following the 23= of the type definition, narrows it down to a union
|
|
type definition. Following the u is the number of bytes in the union.
|
|
After that is a list of union element descriptions. Their format is
|
|
name:type, bit offset into the union, and number of bytes for the
|
|
element;.
|
|
|
|
The stab for the union variable follows. Notice that the frame
|
|
pointer offset for local variables is negative.
|
|
|
|
@display
|
|
<128> N_LSYM - local variable (with no symbol descriptor)
|
|
.stabs "name:type_ref(u_tag)", N_LSYM, NIL, NIL, frame_ptr_offset
|
|
@end display
|
|
|
|
@example
|
|
130 .stabs "an_u:23",128,0,0,-20
|
|
@end example
|
|
|
|
@node Function types
|
|
@section Function types
|
|
|
|
@display
|
|
type descriptor f
|
|
@end display
|
|
|
|
The last type descriptor in C which remains to be described is used
|
|
for function types. Consider the following source line defining a
|
|
global function pointer.
|
|
|
|
@example
|
|
4 int (*g_pf)();
|
|
@end example
|
|
|
|
It generates the following code. Since the variable is not
|
|
initialized, the code is located in the common area at the end of the
|
|
file.
|
|
|
|
@display
|
|
<32> N_GSYM - global variable
|
|
.stabs "name:sym_desc(global)type_def(24)=ptr_to(25)=
|
|
type_def(func)type_ref(int)
|
|
@end display
|
|
|
|
@example
|
|
134 .stabs "g_pf:G24=*25=f1",32,0,0,0
|
|
135 .common _g_pf,4,"bss"
|
|
@end example
|
|
|
|
Since the variable is global, the stab type is N_GSYM and the symbol
|
|
descriptor is G. The variable defines a new type, 24, which is a
|
|
pointer to another new type, 25, which is defined as a function
|
|
returning int.
|
|
|
|
@node Symbol tables
|
|
@chapter Symbol information in symbol tables
|
|
|
|
This section examines more closely the format of symbol table entries
|
|
and how stab assembler directives map to them. It also describes what
|
|
transformations the assembler and linker make on data from stabs.
|
|
|
|
Each time the assembler encounters a stab in its input file it puts
|
|
each field of the stab into corresponding fields in a symbol table
|
|
entry of its output file. If the stab contains a string field, the
|
|
symbol table entry for that stab points to a string table entry
|
|
containing the string data from the stab. Assembler labels become
|
|
relocatable addresses. Symbol table entries in a.out have the format:
|
|
|
|
@example
|
|
struct internal_nlist @{
|
|
unsigned long n_strx; /* index into string table of name */
|
|
unsigned char n_type; /* type of symbol */
|
|
unsigned char n_other; /* misc info (usually empty) */
|
|
unsigned short n_desc; /* description field */
|
|
bfd_vma n_value; /* value of symbol */
|
|
@};
|
|
@end example
|
|
|
|
For .stabs directives, the n_strx field holds the character offset
|
|
from the start of the string table to the string table entry
|
|
containing the "string" field. For other classes of stabs (.stabn and
|
|
.stabd) this field is null.
|
|
|
|
Symbol table entries with n_type fields containing a value greater or
|
|
equal to 0x20 originated as stabs generated by the compiler (with one
|
|
random exception). Those with n_type values less than 0x20 were
|
|
placed in the symbol table of the executable by the assembler or the
|
|
linker.
|
|
|
|
The linker concatenates object files and does fixups of externally
|
|
defined symbols. You can see the transformations made on stab data by
|
|
the assembler and linker by examining the symbol table after each pass
|
|
of the build, first the assemble and then the link.
|
|
|
|
To do this use nm with the -ap options. This dumps the symbol table,
|
|
including debugging information, unsorted. For stab entries the
|
|
columns are: value, other, desc, type, string. For assembler and
|
|
linker symbols, the columns are: value, type, string.
|
|
|
|
There are a few important things to notice about symbol tables. Where
|
|
the value field of a stab contains a frame pointer offset, or a
|
|
register number, that value is unchanged by the rest of the build.
|
|
|
|
Where the value field of a stab contains an assembly language label,
|
|
it is transformed by each build step. The assembler turns it into a
|
|
relocatable address and the linker turns it into an absolute address.
|
|
This source line defines a static variable at file scope:
|
|
|
|
@example
|
|
3 static int s_g_repeat
|
|
@end example
|
|
|
|
@noindent
|
|
The following stab describes the symbol.
|
|
|
|
@example
|
|
26 .stabs "s_g_repeat:S1",38,0,0,_s_g_repeat
|
|
@end example
|
|
|
|
@noindent
|
|
The assembler transforms the stab into this symbol table entry in the
|
|
@file{.o} file. The location is expressed as a data segment offset.
|
|
|
|
@example
|
|
21 00000084 - 00 0000 STSYM s_g_repeat:S1
|
|
@end example
|
|
|
|
@noindent
|
|
in the symbol table entry from the executable, the linker has made the
|
|
relocatable address absolute.
|
|
|
|
@example
|
|
22 0000e00c - 00 0000 STSYM s_g_repeat:S1
|
|
@end example
|
|
|
|
Stabs for global variables do not contain location information. In
|
|
this case the debugger finds location information in the assembler or
|
|
linker symbol table entry describing the variable. The source line:
|
|
|
|
@example
|
|
1 char g_foo = 'c';
|
|
@end example
|
|
|
|
@noindent
|
|
generates the stab:
|
|
|
|
@example
|
|
21 .stabs "g_foo:G2",32,0,0,0
|
|
@end example
|
|
|
|
The variable is represented by the following two symbol table entries
|
|
in the object file. The first one originated as a stab. The second
|
|
one is an external symbol. The upper case D signifies that the n_type
|
|
field of the symbol table contains 7, N_DATA with local linkage (see
|
|
Table B). The value field following the file's line number is empty
|
|
for the stab entry. For the linker symbol it contains the
|
|
rellocatable address corresponding to the variable.
|
|
|
|
@example
|
|
19 00000000 - 00 0000 GSYM g_foo:G2
|
|
20 00000080 D _g_foo
|
|
@end example
|
|
|
|
@noindent
|
|
These entries as transformed by the linker. The linker symbol table
|
|
entry now holds an absolute address.
|
|
|
|
@example
|
|
21 00000000 - 00 0000 GSYM g_foo:G2
|
|
@dots{}
|
|
215 0000e008 D _g_foo
|
|
@end example
|
|
|
|
@node GNU Cplusplus stabs
|
|
@chapter GNU C++ stabs
|
|
|
|
@menu
|
|
* Basic Cplusplus types::
|
|
* Simple classes::
|
|
* Class instance::
|
|
* Methods:: Method definition
|
|
* Protections::
|
|
* Method Modifiers:: (const, volatile, const volatile)
|
|
* Virtual Methods::
|
|
* Inheritence::
|
|
* Virtual Base Classes::
|
|
* Static Members::
|
|
@end menu
|
|
|
|
|
|
@subsection Symbol descriptors added for C++ descriptions:
|
|
|
|
@display
|
|
P - register parameter.
|
|
@end display
|
|
|
|
@subsection type descriptors added for C++ descriptions
|
|
|
|
@table @code
|
|
@item #
|
|
method type (two ## if minimal debug)
|
|
|
|
@item xs
|
|
cross-reference
|
|
@end table
|
|
|
|
|
|
@node Basic Cplusplus types
|
|
@section Basic types for C++
|
|
|
|
<< the examples that follow are based on a01.C >>
|
|
|
|
|
|
C++ adds two more builtin types to the set defined for C. These are
|
|
the unknown type and the vtable record type. The unknown type, type
|
|
16, is defined in terms of itself like the void type.
|
|
|
|
The vtable record type, type 17, is defined as a structure type and
|
|
then as a structure tag. The structure has four fields, delta, index,
|
|
pfn, and delta2. pfn is the function pointer.
|
|
|
|
<< In boilerplate $vtbl_ptr_type, what are the fields delta,
|
|
index, and delta2 used for? >>
|
|
|
|
This basic type is present in all C++ programs even if there are no
|
|
virtual methods defined.
|
|
|
|
@display
|
|
.stabs "struct_name:sym_desc(type)type_def(17)=type_desc(struct)struct_bytes(8)
|
|
elem_name(delta):type_ref(short int),bit_offset(0),field_bits(16);
|
|
elem_name(index):type_ref(short int),bit_offset(16),field_bits(16);
|
|
elem_name(pfn):type_def(18)=type_desc(ptr to)type_ref(void),
|
|
bit_offset(32),field_bits(32);
|
|
elem_name(delta2):type_def(short int);bit_offset(32),field_bits(16);;"
|
|
N_LSYM, NIL, NIL
|
|
@end display
|
|
|
|
@smallexample
|
|
.stabs "$vtbl_ptr_type:t17=s8
|
|
delta:6,0,16;index:6,16,16;pfn:18=*15,32,32;delta2:6,32,16;;"
|
|
,128,0,0,0
|
|
@end smallexample
|
|
|
|
@display
|
|
.stabs "name:sym_dec(struct tag)type_ref($vtbl_ptr_type)",N_LSYM,NIL,NIL,NIL
|
|
@end display
|
|
|
|
@example
|
|
.stabs "$vtbl_ptr_type:T17",128,0,0,0
|
|
@end example
|
|
|
|
@node Simple classes
|
|
@section Simple class definition
|
|
|
|
The stabs describing C++ language features are an extension of the
|
|
stabs describing C. Stabs representing C++ class types elaborate
|
|
extensively on the stab format used to describe structure types in C.
|
|
Stabs representing class type variables look just like stabs
|
|
representing C language variables.
|
|
|
|
Consider the following very simple class definition.
|
|
|
|
@example
|
|
class baseA @{
|
|
public:
|
|
int Adat;
|
|
int Ameth(int in, char other);
|
|
@};
|
|
@end example
|
|
|
|
The class baseA is represented by two stabs. The first stab describes
|
|
the class as a structure type. The second stab describes a structure
|
|
tag of the class type. Both stabs are of stab type N_LSYM. Since the
|
|
stab is not located between an N_FUN and a N_LBRAC stab this indicates
|
|
that the class is defined at file scope. If it were, then the N_LSYM
|
|
would signify a local variable.
|
|
|
|
A stab describing a C++ class type is similar in format to a stab
|
|
describing a C struct, with each class member shown as a field in the
|
|
structure. The part of the struct format describing fields is
|
|
expanded to include extra information relevent to C++ class members.
|
|
In addition, if the class has multiple base classes or virtual
|
|
functions the struct format outside of the field parts is also
|
|
augmented.
|
|
|
|
In this simple example the field part of the C++ class stab
|
|
representing member data looks just like the field part of a C struct
|
|
stab. The section on protections describes how its format is
|
|
sometimes extended for member data.
|
|
|
|
The field part of a C++ class stab representing a member function
|
|
differs substantially from the field part of a C struct stab. It
|
|
still begins with `name:' but then goes on to define a new type number
|
|
for the member function, describe its return type, its argument types,
|
|
its protection level, any qualifiers applied to the method definition,
|
|
and whether the method is virtual or not. If the method is virtual
|
|
then the method description goes on to give the vtable index of the
|
|
method, and the type number of the first base class defining the
|
|
method.
|
|
|
|
When the field name is a method name it is followed by two colons
|
|
rather than one. This is followed by a new type definition for the
|
|
method. This is a number followed by an equal sign and then the
|
|
symbol descriptor `##', indicating a method type. This is followed by
|
|
a type reference showing the return type of the method and a
|
|
semi-colon.
|
|
|
|
The format of an overloaded operator method name differs from that
|
|
of other methods. It is "op$::XXXX." where XXXX is the operator name
|
|
such as + or +=. The name ends with a period, and any characters except
|
|
the period can occur in the XXXX string.
|
|
|
|
The next part of the method description represents the arguments to
|
|
the method, preceeded by a colon and ending with a semi-colon. The
|
|
types of the arguments are expressed in the same way argument types
|
|
are expressed in C++ name mangling. In this example an int and a char
|
|
map to `ic'.
|
|
|
|
This is followed by a number, a letter, and an asterisk or period,
|
|
followed by another semicolon. The number indicates the protections
|
|
that apply to the member function. Here the 2 means public. The
|
|
letter encodes any qualifier applied to the method definition. In
|
|
this case A means that it is a normal function definition. The dot
|
|
shows that the method is not virtual. The sections that follow
|
|
elaborate further on these fields and describe the additional
|
|
information present for virtual methods.
|
|
|
|
|
|
@display
|
|
.stabs "class_name:sym_desc(type)type_def(20)=type_desc(struct)struct_bytes(4)
|
|
field_name(Adat):type(int),bit_offset(0),field_bits(32);
|
|
|
|
method_name(Ameth)::type_def(21)=type_desc(method)return_type(int);
|
|
:arg_types(int char);
|
|
protection(public)qualifier(normal)virtual(no);;"
|
|
N_LSYM,NIL,NIL,NIL
|
|
@end display
|
|
|
|
@smallexample
|
|
.stabs "baseA:t20=s4Adat:1,0,32;Ameth::21=##1;:ic;2A.;;",128,0,0,0
|
|
|
|
.stabs "class_name:sym_desc(struct tag)",N_LSYM,NIL,NIL,NIL
|
|
|
|
.stabs "baseA:T20",128,0,0,0
|
|
@end smallexample
|
|
|
|
@node Class instance
|
|
@section Class instance
|
|
|
|
As shown above, describing even a simple C++ class definition is
|
|
accomplished by massively extending the stab format used in C to
|
|
describe structure types. However, once the class is defined, C stabs
|
|
with no modifications can be used to describe class instances. The
|
|
following source:
|
|
|
|
@example
|
|
main () @{
|
|
baseA AbaseA;
|
|
@}
|
|
@end example
|
|
|
|
@noindent
|
|
yields the following stab describing the class instance. It looks no
|
|
different from a standard C stab describing a local variable.
|
|
|
|
@display
|
|
.stabs "name:type_ref(baseA)", N_LSYM, NIL, NIL, frame_ptr_offset
|
|
@end display
|
|
|
|
@example
|
|
.stabs "AbaseA:20",128,0,0,-20
|
|
@end example
|
|
|
|
@node Methods
|
|
@section Method defintion
|
|
|
|
The class definition shown above declares Ameth. The C++ source below
|
|
defines Ameth:
|
|
|
|
@example
|
|
int
|
|
baseA::Ameth(int in, char other)
|
|
@{
|
|
return in;
|
|
@};
|
|
@end example
|
|
|
|
|
|
This method definition yields three stabs following the code of the
|
|
method. One stab describes the method itself and following two
|
|
describe its parameters. Although there is only one formal argument
|
|
all methods have an implicit argument which is the `this' pointer.
|
|
The `this' pointer is a pointer to the object on which the method was
|
|
called. Note that the method name is mangled to encode the class name
|
|
and argument types. << Name mangling is not described by this
|
|
document - Is there already such a doc? >>
|
|
|
|
@example
|
|
.stabs "name:symbol_desriptor(global function)return_type(int)",
|
|
N_FUN, NIL, NIL, code_addr_of_method_start
|
|
|
|
.stabs "Ameth__5baseAic:F1",36,0,0,_Ameth__5baseAic
|
|
@end example
|
|
|
|
Here is the stab for the `this' pointer implicit argument. The name
|
|
of the `this' pointer is always `this.' Type 19, the `this' pointer is
|
|
defined as a pointer to type 20, baseA, but a stab defining baseA has
|
|
not yet been emited. Since the compiler knows it will be emited
|
|
shortly, here it just outputs a cross reference to the undefined
|
|
symbol, by prefixing the symbol name with xs.
|
|
|
|
@example
|
|
.stabs "name:sym_desc(register param)type_def(19)=
|
|
type_desc(ptr to)type_ref(baseA)=
|
|
type_desc(cross-reference to)baseA:",N_RSYM,NIL,NIL,register_number
|
|
|
|
.stabs "this:P19=*20=xsbaseA:",64,0,0,8
|
|
@end example
|
|
|
|
The stab for the explicit integer argument looks just like a parameter
|
|
to a C function. The last field of the stab is the offset from the
|
|
argument pointer, which in most systems is the same as the frame
|
|
pointer.
|
|
|
|
@example
|
|
.stabs "name:sym_desc(value parameter)type_ref(int)",
|
|
N_PSYM,NIL,NIL,offset_from_arg_ptr
|
|
|
|
.stabs "in:p1",160,0,0,72
|
|
@end example
|
|
|
|
<< The examples that follow are based on A1.C >>
|
|
|
|
@node Protections
|
|
@section Protections
|
|
|
|
|
|
In the simple class definition shown above all member data and
|
|
functions were publicly accessable. The example that follows
|
|
contrasts public, protected and privately accessable fields and shows
|
|
how these protections are encoded in C++ stabs.
|
|
|
|
Protections for class member data are signified by two characters
|
|
embeded in the stab defining the class type. These characters are
|
|
located after the name: part of the string. /0 means private, /1
|
|
means protected, and /2 means public. If these characters are omited
|
|
this means that the member is public. The following C++ source:
|
|
|
|
@example
|
|
class all_data @{
|
|
private:
|
|
int priv_dat;
|
|
protected:
|
|
char prot_dat;
|
|
public:
|
|
float pub_dat;
|
|
@};
|
|
@end example
|
|
|
|
@noindent
|
|
generates the following stab to describe the class type all_data.
|
|
|
|
@display
|
|
.stabs "class_name:sym_desc(type)type_def(19)=type_desc(struct)struct_bytes
|
|
data_name:/protection(private)type_ref(int),bit_offset,num_bits;
|
|
data_name:/protection(protected)type_ref(char),bit_offset,num_bits;
|
|
data_name:(/num omited, private)type_ref(float),bit_offset,num_bits;;"
|
|
N_LSYM,NIL,NIL,NIL
|
|
@end display
|
|
|
|
@smallexample
|
|
.stabs "all_data:t19=s12
|
|
priv_dat:/01,0,32;prot_dat:/12,32,8;pub_dat:12,64,32;;",128,0,0,0
|
|
@end smallexample
|
|
|
|
Protections for member functions are signified by one digit embeded in
|
|
the field part of the stab describing the method. The digit is 0 if
|
|
private, 1 if protected and 2 if public. Consider the C++ class
|
|
definition below:
|
|
|
|
@example
|
|
class all_methods @{
|
|
private:
|
|
int priv_meth(int in)@{return in;@};
|
|
protected:
|
|
char protMeth(char in)@{return in;@};
|
|
public:
|
|
float pubMeth(float in)@{return in;@};
|
|
@};
|
|
@end example
|
|
|
|
It generates the following stab. The digit in question is to the left
|
|
of an `A' in each case. Notice also that in this case two symbol
|
|
descriptors apply to the class name struct tag and struct type.
|
|
|
|
@display
|
|
.stabs "class_name:sym_desc(struct tag&type)type_def(21)=
|
|
sym_desc(struct)struct_bytes(1)
|
|
meth_name::type_def(22)=sym_desc(method)returning(int);
|
|
:args(int);protection(private)modifier(normal)virtual(no);
|
|
meth_name::type_def(23)=sym_desc(method)returning(char);
|
|
:args(char);protection(protected)modifier(normal)virual(no);
|
|
meth_name::type_def(24)=sym_desc(method)returning(float);
|
|
:args(float);protection(public)modifier(normal)virtual(no);;",
|
|
N_LSYM,NIL,NIL,NIL
|
|
@end display
|
|
|
|
@smallexample
|
|
.stabs "all_methods:Tt21=s1priv_meth::22=##1;:i;0A.;protMeth::23=##2;:c;1A.;
|
|
pubMeth::24=##12;:f;2A.;;",128,0,0,0
|
|
@end smallexample
|
|
|
|
@node Method Modifiers
|
|
@section Method Modifiers (const, volatile, const volatile)
|
|
|
|
<< based on a6.C >>
|
|
|
|
In the class example described above all the methods have the normal
|
|
modifier. This method modifier information is located just after the
|
|
protection information for the method. This field has four possible
|
|
character values. Normal methods use A, const methods use B, volatile
|
|
methods use C, and const volatile methods use D. Consider the class
|
|
definition below:
|
|
|
|
@example
|
|
class A @{
|
|
public:
|
|
int ConstMeth (int arg) const @{ return arg; @};
|
|
char VolatileMeth (char arg) volatile @{ return arg; @};
|
|
float ConstVolMeth (float arg) const volatile @{return arg; @};
|
|
@};
|
|
@end example
|
|
|
|
This class is described by the following stab:
|
|
|
|
@display
|
|
.stabs "class(A):sym_desc(struct)type_def(20)=type_desc(struct)struct_bytes(1)
|
|
meth_name(ConstMeth)::type_def(21)sym_desc(method)
|
|
returning(int);:arg(int);protection(public)modifier(const)virtual(no);
|
|
meth_name(VolatileMeth)::type_def(22)=sym_desc(method)
|
|
returning(char);:arg(char);protection(public)modifier(volatile)virt(no)
|
|
meth_name(ConstVolMeth)::type_def(23)=sym_desc(method)
|
|
returning(float);:arg(float);protection(public)modifer(const volatile)
|
|
virtual(no);;", @dots{}
|
|
@end display
|
|
|
|
@example
|
|
.stabs "A:T20=s1ConstMeth::21=##1;:i;2B.;VolatileMeth::22=##2;:c;2C.;
|
|
ConstVolMeth::23=##12;:f;2D.;;",128,0,0,0
|
|
@end example
|
|
|
|
@node Virtual Methods
|
|
@section Virtual Methods
|
|
|
|
<< The following examples are based on a4.C >>
|
|
|
|
The presence of virtual methods in a class definition adds additional
|
|
data to the class description. The extra data is appended to the
|
|
description of the virtual method and to the end of the class
|
|
description. Consider the class definition below:
|
|
|
|
@example
|
|
class A @{
|
|
public:
|
|
int Adat;
|
|
virtual int A_virt (int arg) @{ return arg; @};
|
|
@};
|
|
@end example
|
|
|
|
This results in the stab below describing class A. It defines a new
|
|
type (20) which is an 8 byte structure. The first field of the class
|
|
struct is Adat, an integer, starting at structure offset 0 and
|
|
occupying 32 bits.
|
|
|
|
The second field in the class struct is not explicitly defined by the
|
|
C++ class definition but is implied by the fact that the class
|
|
contains a virtual method. This field is the vtable pointer. The
|
|
name of the vtable pointer field starts with $vf and continues with a
|
|
type reference to the class it is part of. In this example the type
|
|
reference for class A is 20 so the name of its vtable pointer field is
|
|
$vf20, followed by the usual colon.
|
|
|
|
Next there is a type definition for the vtable pointer type (21).
|
|
This is in turn defined as a pointer to another new type (22).
|
|
|
|
Type 22 is the vtable itself, which is defined as an array, indexed by
|
|
a range of integers between 0 and 1, and whose elements are of type
|
|
17. Type 17 was the vtable record type defined by the boilerplate C++
|
|
type definitions, as shown earlier.
|
|
|
|
The bit offset of the vtable pointer field is 32. The number of bits
|
|
in the field are not specified when the field is a vtable pointer.
|
|
|
|
Next is the method definition for the virtual member function A_virt.
|
|
Its description starts out using the same format as the non-virtual
|
|
member functions described above, except instead of a dot after the
|
|
`A' there is an asterisk, indicating that the function is virtual.
|
|
Since is is virtual some addition information is appended to the end
|
|
of the method description.
|
|
|
|
The first number represents the vtable index of the method. This is a
|
|
32 bit unsigned number with the high bit set, followed by a
|
|
semi-colon.
|
|
|
|
The second number is a type reference to the first base class in the
|
|
inheritence hierarchy defining the virtual member function. In this
|
|
case the class stab describes a base class so the virtual function is
|
|
not overriding any other definition of the method. Therefore the
|
|
reference is to the type number of the class that the stab is
|
|
describing (20).
|
|
|
|
This is followed by three semi-colons. One marks the end of the
|
|
current sub-section, one marks the end of the method field, and the
|
|
third marks the end of the struct definition.
|
|
|
|
For classes containing virtual functions the very last section of the
|
|
string part of the stab holds a type reference to the first base
|
|
class. This is preceeded by `~%' and followed by a final semi-colon.
|
|
|
|
@display
|
|
.stabs "class_name(A):type_def(20)=sym_desc(struct)struct_bytes(8)
|
|
field_name(Adat):type_ref(int),bit_offset(0),field_bits(32);
|
|
field_name(A virt func ptr):type_def(21)=type_desc(ptr to)type_def(22)=
|
|
sym_desc(array)index_type_ref(range of int from 0 to 1);
|
|
elem_type_ref(vtbl elem type),
|
|
bit_offset(32);
|
|
meth_name(A_virt)::typedef(23)=sym_desc(method)returning(int);
|
|
:arg_type(int),protection(public)normal(yes)virtual(yes)
|
|
vtable_index(1);class_first_defining(A);;;~%first_base(A);",
|
|
N_LSYM,NIL,NIL,NIL
|
|
@end display
|
|
|
|
@example
|
|
.stabs "A:t20=s8Adat:1,0,32;$vf20:21=*22=ar1;0;1;17,32;A_virt::23=##1;:i;2A*-2147483647;20;;;~%20;",128,0,0,0
|
|
@end example
|
|
|
|
@node Inheritence
|
|
@section Inheritence
|
|
|
|
Stabs describing C++ derived classes include additional sections that
|
|
describe the inheritence hierarchy of the class. A derived class stab
|
|
also encodes the number of base classes. For each base class it tells
|
|
if the base class is virtual or not, and if the inheritence is private
|
|
or public. It also gives the offset into the object of the portion of
|
|
the object corresponding to each base class.
|
|
|
|
This additional information is embeded in the class stab following the
|
|
number of bytes in the struct. First the number of base classes
|
|
appears bracketed by an exclamation point and a comma.
|
|
|
|
Then for each base type there repeats a series: two digits, a number,
|
|
a comma, another number, and a semi-colon.
|
|
|
|
The first of the two digits is 1 if the base class is virtual and 0 if
|
|
not. The second digit is 2 if the derivation is public and 0 if not.
|
|
|
|
The number following the first two digits is the offset from the start
|
|
of the object to the part of the object pertaining to the base class.
|
|
|
|
After the comma, the second number is a type_descriptor for the base
|
|
type. Finally a semi-colon ends the series, which repeats for each
|
|
base class.
|
|
|
|
The source below defines three base classes A, B, and C and the
|
|
derived class D.
|
|
|
|
|
|
@example
|
|
class A @{
|
|
public:
|
|
int Adat;
|
|
virtual int A_virt (int arg) @{ return arg; @};
|
|
@};
|
|
|
|
class B @{
|
|
public:
|
|
int B_dat;
|
|
virtual int B_virt (int arg) @{return arg; @};
|
|
@};
|
|
|
|
class C @{
|
|
public:
|
|
int Cdat;
|
|
virtual int C_virt (int arg) @{return arg; @};
|
|
@};
|
|
|
|
class D : A, virtual B, public C @{
|
|
public:
|
|
int Ddat;
|
|
virtual int A_virt (int arg ) @{ return arg+1; @};
|
|
virtual int B_virt (int arg) @{ return arg+2; @};
|
|
virtual int C_virt (int arg) @{ return arg+3; @};
|
|
virtual int D_virt (int arg) @{ return arg; @};
|
|
@};
|
|
@end example
|
|
|
|
Class stabs similar to the ones described earlier are generated for
|
|
each base class.
|
|
|
|
@c FIXME!!! the linebreaks in the following example probably make the
|
|
@c examples literally unusable, but I don't know any other way to get
|
|
@c them on the page.
|
|
@smallexample
|
|
.stabs "A:T20=s8Adat:1,0,32;$vf20:21=*22=ar1;0;1;17,32;
|
|
A_virt::23=##1;:i;2A*-2147483647;20;;;~%20;",128,0,0,0
|
|
|
|
.stabs "B:Tt25=s8Bdat:1,0,32;$vf25:21,32;B_virt::26=##1;
|
|
:i;2A*-2147483647;25;;;~%25;",128,0,0,0
|
|
|
|
.stabs "C:Tt28=s8Cdat:1,0,32;$vf28:21,32;C_virt::29=##1;
|
|
:i;2A*-2147483647;28;;;~%28;",128,0,0,0
|
|
@end smallexample
|
|
|
|
In the stab describing derived class D below, the information about
|
|
the derivation of this class is encoded as follows.
|
|
|
|
@display
|
|
.stabs "derived_class_name:symbol_descriptors(struct tag&type)=
|
|
type_descriptor(struct)struct_bytes(32)!num_bases(3),
|
|
base_virtual(no)inheritence_public(no)base_offset(0),
|
|
base_class_type_ref(A);
|
|
base_virtual(yes)inheritence_public(no)base_offset(NIL),
|
|
base_class_type_ref(B);
|
|
base_virtual(no)inheritence_public(yes)base_offset(64),
|
|
base_class_type_ref(C); @dots{}
|
|
@end display
|
|
|
|
@c FIXME! fake linebreaks.
|
|
@smallexample
|
|
.stabs "D:Tt31=s32!3,000,20;100,25;0264,28;$vb25:24,128;Ddat:
|
|
1,160,32;A_virt::32=##1;:i;2A*-2147483647;20;;B_virt:
|
|
:32:i;2A*-2147483647;25;;C_virt::32:i;2A*-2147483647;
|
|
28;;D_virt::32:i;2A*-2147483646;31;;;~%20;",128,0,0,0
|
|
@end smallexample
|
|
|
|
@node Virtual Base Classes
|
|
@section Virtual Base Classes
|
|
|
|
A derived class object consists of a concatination in memory of the
|
|
data areas defined by each base class, starting with the leftmost and
|
|
ending with the rightmost in the list of base classes. The exception
|
|
to this rule is for virtual inheritence. In the example above, class
|
|
D inherits virtually from base class B. This means that an instance
|
|
of a D object will not contain it's own B part but merely a pointer to
|
|
a B part, known as a virtual base pointer.
|
|
|
|
In a derived class stab, the base offset part of the derivation
|
|
information, described above, shows how the base class parts are
|
|
ordered. The base offset for a virtual base class is always given as
|
|
0. Notice that the base offset for B is given as 0 even though B is
|
|
not the first base class. The first base class A starts at offset 0.
|
|
|
|
The field information part of the stab for class D describes the field
|
|
which is the pointer to the virtual base class B. The vbase pointer
|
|
name is $vb followed by a type reference to the virtual base class.
|
|
Since the type id for B in this example is 25, the vbase pointer name
|
|
is $vb25.
|
|
|
|
@c FIXME!! fake linebreaks below
|
|
@smallexample
|
|
.stabs "D:Tt31=s32!3,000,20;100,25;0264,28;$vb25:24,128;Ddat:1,
|
|
160,32;A_virt::32=##1;:i;2A*-2147483647;20;;B_virt::32:i;
|
|
2A*-2147483647;25;;C_virt::32:i;2A*-2147483647;28;;D_virt:
|
|
:32:i;2A*-2147483646;31;;;~%20;",128,0,0,0
|
|
@end smallexample
|
|
|
|
Following the name and a semicolon is a type reference describing the
|
|
type of the virtual base class pointer, in this case 24. Type 24 was
|
|
defined earlier as the type of the B class `this` pointer. The
|
|
`this' pointer for a class is a pointer to the class type.
|
|
|
|
@example
|
|
.stabs "this:P24=*25=xsB:",64,0,0,8
|
|
@end example
|
|
|
|
Finally the field offset part of the vbase pointer field description
|
|
shows that the vbase pointer is the first field in the D object,
|
|
before any data fields defined by the class. The layout of a D class
|
|
object is a follows, Adat at 0, the vtable pointer for A at 32, Cdat
|
|
at 64, the vtable pointer for C at 96, the virtual ase pointer for B
|
|
at 128, and Ddat at 160.
|
|
|
|
|
|
@node Static Members
|
|
@section Static Members
|
|
|
|
The data area for a class is a concatenation of the space used by the
|
|
data members of the class. If the class has virtual methods, a vtable
|
|
pointer follows the class data. The field offset part of each field
|
|
description in the class stab shows this ordering.
|
|
|
|
<< How is this reflected in stabs? See Cygnus bug #677 for some info. >>
|
|
|
|
@node Example2.c
|
|
@appendix Example2.c - source code for extended example
|
|
|
|
@example
|
|
1 char g_foo = 'c';
|
|
2 register int g_bar asm ("%g5");
|
|
3 static int s_g_repeat = 2;
|
|
4 int (*g_pf)();
|
|
5
|
|
6 struct s_tag @{
|
|
7 int s_int;
|
|
8 float s_float;
|
|
9 char s_char_vec[8];
|
|
10 struct s_tag* s_next;
|
|
11 @} g_an_s;
|
|
12
|
|
13 typedef struct s_tag s_typedef;
|
|
14
|
|
15 char char_vec[3] = @{'a','b','c'@};
|
|
16
|
|
17 main (argc, argv)
|
|
18 int argc;
|
|
19 char* argv[];
|
|
20 @{
|
|
21 static float s_flap;
|
|
22 int times;
|
|
23 for (times=0; times < s_g_repeat; times++)@{
|
|
24 int inner;
|
|
25 printf ("Hello world\n");
|
|
26 @}
|
|
27 @};
|
|
28
|
|
29 enum e_places @{first,second=3,last@};
|
|
30
|
|
31 static s_proc (s_arg, s_ptr_arg, char_vec)
|
|
32 s_typedef s_arg;
|
|
33 s_typedef* s_ptr_arg;
|
|
34 char* char_vec;
|
|
35 @{
|
|
36 union u_tag @{
|
|
37 int u_int;
|
|
38 float u_float;
|
|
39 char* u_char;
|
|
40 @} an_u;
|
|
41 @}
|
|
42
|
|
43
|
|
@end example
|
|
|
|
@node Example2.s
|
|
@appendix Example2.s - assembly code for extended example
|
|
|
|
@example
|
|
1 gcc2_compiled.:
|
|
2 .stabs "/cygint/s1/users/jcm/play/",100,0,0,Ltext0
|
|
3 .stabs "example2.c",100,0,0,Ltext0
|
|
4 .text
|
|
5 Ltext0:
|
|
6 .stabs "int:t1=r1;-2147483648;2147483647;",128,0,0,0
|
|
7 .stabs "char:t2=r2;0;127;",128,0,0,0
|
|
8 .stabs "long int:t3=r1;-2147483648;2147483647;",128,0,0,0
|
|
9 .stabs "unsigned int:t4=r1;0;-1;",128,0,0,0
|
|
10 .stabs "long unsigned int:t5=r1;0;-1;",128,0,0,0
|
|
11 .stabs "short int:t6=r1;-32768;32767;",128,0,0,0
|
|
12 .stabs "long long int:t7=r1;0;-1;",128,0,0,0
|
|
13 .stabs "short unsigned int:t8=r1;0;65535;",128,0,0,0
|
|
14 .stabs "long long unsigned int:t9=r1;0;-1;",128,0,0,0
|
|
15 .stabs "signed char:t10=r1;-128;127;",128,0,0,0
|
|
16 .stabs "unsigned char:t11=r1;0;255;",128,0,0,0
|
|
17 .stabs "float:t12=r1;4;0;",128,0,0,0
|
|
18 .stabs "double:t13=r1;8;0;",128,0,0,0
|
|
19 .stabs "long double:t14=r1;8;0;",128,0,0,0
|
|
20 .stabs "void:t15=15",128,0,0,0
|
|
21 .stabs "g_foo:G2",32,0,0,0
|
|
22 .global _g_foo
|
|
23 .data
|
|
24 _g_foo:
|
|
25 .byte 99
|
|
26 .stabs "s_g_repeat:S1",38,0,0,_s_g_repeat
|
|
27 .align 4
|
|
28 _s_g_repeat:
|
|
29 .word 2
|
|
@c FIXME! fake linebreak in line 30
|
|
30 .stabs "s_tag:T16=s20s_int:1,0,32;s_float:12,32,32;s_char_vec:
|
|
17=ar1;0;7;2,64,64;s_next:18=*16,128,32;;",128,0,0,0
|
|
31 .stabs "s_typedef:t16",128,0,0,0
|
|
32 .stabs "char_vec:G19=ar1;0;2;2",32,0,0,0
|
|
33 .global _char_vec
|
|
34 .align 4
|
|
35 _char_vec:
|
|
36 .byte 97
|
|
37 .byte 98
|
|
38 .byte 99
|
|
39 .reserve _s_flap.0,4,"bss",4
|
|
40 .text
|
|
41 .align 4
|
|
42 LC0:
|
|
43 .ascii "Hello world\12\0"
|
|
44 .align 4
|
|
45 .global _main
|
|
46 .proc 1
|
|
47 _main:
|
|
48 .stabn 68,0,20,LM1
|
|
49 LM1:
|
|
50 !#PROLOGUE# 0
|
|
51 save %sp,-144,%sp
|
|
52 !#PROLOGUE# 1
|
|
53 st %i0,[%fp+68]
|
|
54 st %i1,[%fp+72]
|
|
55 call ___main,0
|
|
56 nop
|
|
57 LBB2:
|
|
58 .stabn 68,0,23,LM2
|
|
59 LM2:
|
|
60 st %g0,[%fp-20]
|
|
61 L2:
|
|
62 sethi %hi(_s_g_repeat),%o0
|
|
63 ld [%fp-20],%o1
|
|
64 ld [%o0+%lo(_s_g_repeat)],%o0
|
|
65 cmp %o1,%o0
|
|
66 bge L3
|
|
67 nop
|
|
68 LBB3:
|
|
69 .stabn 68,0,25,LM3
|
|
70 LM3:
|
|
71 sethi %hi(LC0),%o1
|
|
72 or %o1,%lo(LC0),%o0
|
|
73 call _printf,0
|
|
74 nop
|
|
75 .stabn 68,0,26,LM4
|
|
76 LM4:
|
|
77 LBE3:
|
|
78 .stabn 68,0,23,LM5
|
|
79 LM5:
|
|
80 L4:
|
|
81 ld [%fp-20],%o0
|
|
82 add %o0,1,%o1
|
|
83 st %o1,[%fp-20]
|
|
84 b,a L2
|
|
85 L3:
|
|
86 .stabn 68,0,27,LM6
|
|
87 LM6:
|
|
88 LBE2:
|
|
89 .stabn 68,0,27,LM7
|
|
90 LM7:
|
|
91 L1:
|
|
92 ret
|
|
93 restore
|
|
94 .stabs "main:F1",36,0,0,_main
|
|
95 .stabs "argc:p1",160,0,0,68
|
|
96 .stabs "argv:p20=*21=*2",160,0,0,72
|
|
97 .stabs "s_flap:V12",40,0,0,_s_flap.0
|
|
98 .stabs "times:1",128,0,0,-20
|
|
99 .stabn 192,0,0,LBB2
|
|
100 .stabs "inner:1",128,0,0,-24
|
|
101 .stabn 192,0,0,LBB3
|
|
102 .stabn 224,0,0,LBE3
|
|
103 .stabn 224,0,0,LBE2
|
|
104 .stabs "e_places:T22=efirst:0,second:3,last:4,;",128,0,0,0
|
|
@c FIXME: fake linebreak in line 105
|
|
105 .stabs "u_tag:T23=u4u_int:1,0,32;u_float:12,0,32;u_char:21,0,32;;",
|
|
128,0,0,0
|
|
106 .align 4
|
|
107 .proc 1
|
|
108 _s_proc:
|
|
109 .stabn 68,0,35,LM8
|
|
110 LM8:
|
|
111 !#PROLOGUE# 0
|
|
112 save %sp,-120,%sp
|
|
113 !#PROLOGUE# 1
|
|
114 mov %i0,%o0
|
|
115 st %i1,[%fp+72]
|
|
116 st %i2,[%fp+76]
|
|
117 LBB4:
|
|
118 .stabn 68,0,41,LM9
|
|
119 LM9:
|
|
120 LBE4:
|
|
121 .stabn 68,0,41,LM10
|
|
122 LM10:
|
|
123 L5:
|
|
124 ret
|
|
125 restore
|
|
126 .stabs "s_proc:f1",36,0,0,_s_proc
|
|
127 .stabs "s_arg:p16",160,0,0,0
|
|
128 .stabs "s_ptr_arg:p18",160,0,0,72
|
|
129 .stabs "char_vec:p21",160,0,0,76
|
|
130 .stabs "an_u:23",128,0,0,-20
|
|
131 .stabn 192,0,0,LBB4
|
|
132 .stabn 224,0,0,LBE4
|
|
133 .stabs "g_bar:r1",64,0,0,5
|
|
134 .stabs "g_pf:G24=*25=f1",32,0,0,0
|
|
135 .common _g_pf,4,"bss"
|
|
136 .stabs "g_an_s:G16",32,0,0,0
|
|
137 .common _g_an_s,20,"bss"
|
|
@end example
|
|
|
|
|
|
@node Quick reference
|
|
@appendix Quick reference
|
|
|
|
@menu
|
|
* Stab types:: Table A: Symbol types from stabs
|
|
* Assembler types:: Table B: Symbol types from assembler and linker
|
|
* Symbol descriptors:: Table C
|
|
* Type Descriptors:: Table D
|
|
@end menu
|
|
|
|
@node Stab types
|
|
@section Table A: Symbol types from stabs
|
|
|
|
Table A lists stab types sorted by type number. Stab type numbers are
|
|
32 and greater. This is the full list of stab numbers, including stab
|
|
types that are used in languages other than C.
|
|
|
|
The #define names for these stab types are defined in:
|
|
devo/include/aout/stab.def
|
|
|
|
@smallexample
|
|
type type #define used to describe
|
|
dec hex name source program feature
|
|
------------------------------------------------
|
|
32 0x20 N_GYSM global symbol
|
|
34 0X22 N_FNAME function name (for BSD Fortran)
|
|
36 0x24 N_FUN function name or text segment variable for C
|
|
38 0x26 N_STSYM static symbol (data segment w/internal linkage)
|
|
40 0x28 N_LCSYM .lcomm symbol(BSS-seg variable w/internal linkage)
|
|
42 0x2a N_MAIN Name of main routine (not used in C)
|
|
48 0x30 N_PC global symbol (for Pascal)
|
|
50 0x32 N_NSYMS number of symbols (according to Ultrix V4.0)
|
|
52 0x34 N_NOMAP no DST map for sym (according to Ultrix V4.0)
|
|
64 0x40 N_RSYM register variable
|
|
66 0x42 N_M2C Modula-2 compilation unit
|
|
68 0x44 N_SLINE line number in text segment
|
|
70 0x46 N_DSLINE line number in data segment
|
|
|
|
72 0x48 N_BSLINE line number in bss segment
|
|
72 0x48 N_BROWS Sun source code browser, path to .cb file
|
|
|
|
74 0x4a N_DEFD GNU Modula2 definition module dependency
|
|
|
|
80 0x50 N_EHDECL GNU C++ exception variable
|
|
80 0x50 N_MOD2 Modula2 info "for imc" (according to Ultrix V4.0)
|
|
|
|
84 0x54 N_CATCH GNU C++ "catch" clause
|
|
96 0x60 N_SSYM structure of union element
|
|
100 0x64 N_SO path and name of source file
|
|
128 0x80 N_LSYM automatic var in the stack
|
|
(also used for type desc.)
|
|
130 0x82 N_BINCL beginning of an include file (Sun only)
|
|
132 0x84 N_SOL Name of sub-source (#include) file.
|
|
160 0xa0 N_PSYM parameter variable
|
|
162 0xa2 N_EINCL end of an include file
|
|
164 0xa4 N_ENTRY alternate entry point
|
|
192 0xc0 N_LBRAC beginning of a lexical block
|
|
194 0xc2 N_EXCL place holder for a deleted include file
|
|
196 0xc4 N_SCOPE modula2 scope information (Sun linker)
|
|
224 0xe0 N_RBRAC end of a lexical block
|
|
226 0xe2 N_BCOMM begin named common block
|
|
228 0xe4 N_ECOMM end named common block
|
|
232 0xe8 N_ECOML end common (local name)
|
|
|
|
<< used on Gould systems for non-base registers syms >>
|
|
240 0xf0 N_NBTEXT ??
|
|
242 0xf2 N_NBDATA ??
|
|
244 0xf4 N_NBBSS ??
|
|
246 0xf6 N_NBSTS ??
|
|
248 0xf8 N_NBLCS ??
|
|
@end smallexample
|
|
|
|
@node Assembler types
|
|
@section Table B: Symbol types from assembler and linker
|
|
|
|
Table B shows the types of symbol table entries that hold assembler
|
|
and linker symbols.
|
|
|
|
The #define names for these n_types values are defined in
|
|
/include/aout/aout64.h
|
|
|
|
@smallexample
|
|
dec hex #define
|
|
n_type n_type name used to describe
|
|
------------------------------------------
|
|
1 0x0 N_UNDF undefined symbol
|
|
2 0x2 N_ABS absolute symbol -- defined at a particular address
|
|
3 0x3 extern " (vs. file scope)
|
|
4 0x4 N_TEXT text symbol -- defined at offset in text segment
|
|
5 0x5 extern " (vs. file scope)
|
|
6 0x6 N_DATA data symbol -- defined at offset in data segment
|
|
7 0x7 extern " (vs. file scope)
|
|
8 0x8 N_BSS BSS symbol -- defined at offset in zero'd segment
|
|
9 extern " (vs. file scope)
|
|
|
|
12 0x0C N_FN_SEQ func name for Sequent compilers (stab exception)
|
|
|
|
49 0x12 N_COMM common sym -- visable after shared lib dynamic link
|
|
31 0x1f N_FN file name of a .o file
|
|
@end smallexample
|
|
|
|
@node Symbol descriptors
|
|
@section Table C: Symbol descriptors
|
|
|
|
@example
|
|
descriptor meaning
|
|
-------------------------------------------------
|
|
(empty) local variable
|
|
f local function
|
|
F global function
|
|
G global variable
|
|
p value parameter
|
|
r register variable
|
|
S static global variable
|
|
t type name
|
|
T enumeration, struct or type tag
|
|
V static local variable
|
|
@end example
|
|
|
|
@node Type Descriptors
|
|
@section Table D: Type Descriptors
|
|
|
|
@example
|
|
descriptor meaning
|
|
-------------------------------------
|
|
(empty) type reference
|
|
a array type
|
|
e enumeration type
|
|
f function type
|
|
r range type
|
|
s structure type
|
|
u union specifications
|
|
* pointer type
|
|
@end example
|
|
|
|
|
|
@node Expanded reference
|
|
@appendix Expanded reference by stab type.
|
|
|
|
Format of an entry:
|
|
|
|
The first line is the symbol type expressed in decimal, hexadecimal,
|
|
and as a #define (see devo/include/aout/stab.def).
|
|
|
|
The second line describes the language constructs the symbol type
|
|
represents.
|
|
|
|
The third line is the stab format with the significant stab fields
|
|
named and the rest NIL.
|
|
|
|
Subsequent lines expand upon the meaning and possible values for each
|
|
significant stab field. # stands in for the type descriptor.
|
|
|
|
Finally, any further information.
|
|
|
|
@menu
|
|
* N_GSYM:: Global variable
|
|
* N_FNAME:: Function name (BSD Fortran)
|
|
* N_FUN:: C Function name or text segment variable
|
|
* N_STSYM:: Initialized static symbol
|
|
* N_LCSYM:: Uninitialized static symbol
|
|
* N_MAIN:: Name of main routine (not for C)
|
|
* N_PC:: Pascal global symbol
|
|
* N_NSYMS:: Number of symbols
|
|
* N_NOMAP:: No DST map
|
|
* N_RSYM:: Register variable
|
|
* N_M2C:: Modula-2 compilation unit
|
|
* N_SLINE:: Line number in text segment
|
|
* N_DSLINE:: Line number in data segment
|
|
* N_BSLINE:: Line number in bss segment
|
|
* N_BROWS:: Path to .cb file for Sun source code browser
|
|
* N_DEFD:: GNU Modula2 definition module dependency
|
|
* N_EHDECL:: GNU C++ exception variable
|
|
* N_MOD2:: Modula2 information "for imc"
|
|
* N_CATCH:: GNU C++ "catch" clause
|
|
* N_SSYM:: Structure or union element
|
|
* N_SO:: Source file containing main
|
|
* N_LSYM:: Automatic variable
|
|
* N_BINCL:: Beginning of include file (Sun only)
|
|
* N_SOL:: Name of include file
|
|
* N_PSYM:: Parameter variable
|
|
* N_EINCL:: End of include file
|
|
* N_ENTRY:: Alternate entry point
|
|
* N_LBRAC:: Beginning of lexical block
|
|
* N_EXCL:: Deleted include file
|
|
* N_SCOPE:: Modula2 scope information (Sun only)
|
|
* N_RBRAC:: End of lexical block
|
|
* N_BCOMM:: Begin named common block
|
|
* N_ECOMM:: End named common block
|
|
* N_ECOML:: End common
|
|
* Gould:: non-base register symbols used on Gould systems
|
|
* N_LENG:: Length of preceding entry
|
|
@end menu
|
|
|
|
@node N_GSYM
|
|
@section 32 - 0x20 - N_GYSM
|
|
|
|
@display
|
|
Global variable.
|
|
|
|
.stabs "name", N_GSYM, NIL, NIL, NIL
|
|
@end display
|
|
|
|
@example
|
|
"name" -> "symbol_name:#type"
|
|
# -> G
|
|
@end example
|
|
|
|
Only the "name" field is significant. the location of the variable is
|
|
obtained from the corresponding external symbol.
|
|
|
|
@node N_FNAME
|
|
@section 34 - 0x22 - N_FNAME
|
|
Function name (for BSD Fortran)
|
|
|
|
@display
|
|
.stabs "name", N_FNAME, NIL, NIL, NIL
|
|
@end display
|
|
|
|
@example
|
|
"name" -> "function_name"
|
|
@end example
|
|
|
|
Only the "name" field is significant. The location of the symbol is
|
|
obtained from the corresponding extern symbol.
|
|
|
|
@node N_FUN
|
|
@section 36 - 0x24 - N_FUN
|
|
Function name or text segment variable for C.
|
|
|
|
@display
|
|
.stabs "name", N_FUN, NIL, desc, value
|
|
@end display
|
|
|
|
@example
|
|
@exdent @emph{For functions:}
|
|
"name" -> "proc_name:#return_type"
|
|
# -> F (global function)
|
|
f (local function)
|
|
desc -> line num for proc start. (GCC doesn't set and DBX doesn't miss it.)
|
|
value -> Code address of proc start.
|
|
|
|
@exdent @emph{For text segment variables:}
|
|
<<How to create one?>>
|
|
@end example
|
|
|
|
@node N_STSYM
|
|
@section 38 - 0x26 - N_STSYM
|
|
Initialized static symbol (data segment w/internal linkage).
|
|
|
|
@display
|
|
.stabs "name", N_STSYM, NIL, NIL, value
|
|
@end display
|
|
|
|
@example
|
|
"name" -> "symbol_name#type"
|
|
# -> S (scope global to compilation unit)
|
|
-> V (scope local to a procedure)
|
|
value -> Data Address
|
|
@end example
|
|
|
|
@node N_LCSYM
|
|
@section 40 - 0x28 - N_LCSYM
|
|
Unitialized static (.lcomm) symbol(BSS segment w/internal linkage).
|
|
|
|
@display
|
|
.stabs "name", N_LCLSYM, NIL, NIL, value
|
|
@end display
|
|
|
|
@example
|
|
"name" -> "symbol_name#type"
|
|
# -> S (scope global to compilation unit)
|
|
-> V (scope local to procedure)
|
|
value -> BSS Address
|
|
@end example
|
|
|
|
@node N_MAIN
|
|
@section 42 - 0x2a - N_MAIN
|
|
Name of main routine (not used in C)
|
|
|
|
@display
|
|
.stabs "name", N_MAIN, NIL, NIL, NIL
|
|
@end display
|
|
|
|
@example
|
|
"name" -> "name_of_main_routine"
|
|
@end example
|
|
|
|
@node N_PC
|
|
@section 48 - 0x30 - N_PC
|
|
Global symbol (for Pascal)
|
|
|
|
@display
|
|
.stabs "name", N_PC, NIL, NIL, value
|
|
@end display
|
|
|
|
@example
|
|
"name" -> "symbol_name" <<?>>
|
|
value -> supposedly the line number (stab.def is skeptical)
|
|
@end example
|
|
|
|
@display
|
|
stabdump.c says:
|
|
|
|
global pascal symbol: name,,0,subtype,line
|
|
<< subtype? >>
|
|
@end display
|
|
|
|
@node N_NSYMS
|
|
@section 50 - 0x32 - N_NSYMS
|
|
Number of symbols (according to Ultrix V4.0)
|
|
|
|
@display
|
|
0, files,,funcs,lines (stab.def)
|
|
@end display
|
|
|
|
@node N_NOMAP
|
|
@section 52 - 0x34 - N_NOMAP
|
|
no DST map for sym (according to Ultrix V4.0)
|
|
|
|
@display
|
|
name, ,0,type,ignored (stab.def)
|
|
@end display
|
|
|
|
@node N_RSYM
|
|
@section 64 - 0x40 - N_RSYM
|
|
register variable
|
|
|
|
@display
|
|
.stabs "name:type",N_RSYM,0,RegSize,RegNumber (Sun doc)
|
|
@end display
|
|
|
|
@node N_M2C
|
|
@section 66 - 0x42 - N_M2C
|
|
Modula-2 compilation unit
|
|
|
|
@display
|
|
.stabs "name", N_M2C, 0, desc, value
|
|
@end display
|
|
|
|
@example
|
|
"name" -> "unit_name,unit_time_stamp[,code_time_stamp]
|
|
desc -> unit_number
|
|
value -> 0 (main unit)
|
|
1 (any other unit)
|
|
@end example
|
|
|
|
@node N_SLINE
|
|
@section 68 - 0x44 - N_SLINE
|
|
Line number in text segment
|
|
|
|
@display
|
|
.stabn N_SLINE, 0, desc, value
|
|
@end display
|
|
|
|
@example
|
|
desc -> line_number
|
|
value -> code_address (relocatable addr where the corresponding code starts)
|
|
@end example
|
|
|
|
For single source lines that generate discontiguous code, such as flow
|
|
of control statements, there may be more than one N_SLINE stab for the
|
|
same source line. In this case there is a stab at the start of each
|
|
code range, each with the same line number.
|
|
|
|
@node N_DSLINE
|
|
@section 70 - 0x46 - N_DSLINE
|
|
Line number in data segment
|
|
|
|
@display
|
|
.stabn N_DSLINE, 0, desc, value
|
|
@end display
|
|
|
|
@example
|
|
desc -> line_number
|
|
value -> data_address (relocatable addr where the corresponding code
|
|
starts)
|
|
@end example
|
|
|
|
See comment for N_SLINE above.
|
|
|
|
@node N_BSLINE
|
|
@section 72 - 0x48 - N_BSLINE
|
|
Line number in bss segment
|
|
|
|
@display
|
|
.stabn N_BSLINE, 0, desc, value
|
|
@end display
|
|
|
|
@example
|
|
desc -> line_number
|
|
value -> bss_address (relocatable addr where the corresponding code
|
|
starts)
|
|
@end example
|
|
|
|
See comment for N_SLINE above.
|
|
|
|
@node N_BROWS
|
|
@section 72 - 0x48 - N_BROWS
|
|
Sun source code browser, path to .cb file
|
|
|
|
<<?>>
|
|
"path to associated .cb file"
|
|
|
|
Note: type field value overlaps with N_BSLINE
|
|
|
|
@node N_DEFD
|
|
@section 74 - 0x4a - N_DEFD
|
|
GNU Modula2 definition module dependency
|
|
|
|
GNU Modula-2 definition module dependency. Value is the modification
|
|
time of the definition file. Other is non-zero if it is imported with
|
|
the GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there
|
|
are enough empty fields?
|
|
|
|
@node N_EHDECL
|
|
@section 80 - 0x50 - N_EHDECL
|
|
GNU C++ exception variable <<?>>
|
|
|
|
"name is variable name"
|
|
|
|
Note: conflicts with N_MOD2.
|
|
|
|
@node N_MOD2
|
|
@section 80 - 0x50 - N_MOD2
|
|
Modula2 info "for imc" (according to Ultrix V4.0)
|
|
|
|
Note: conflicts with N_EHDECL <<?>>
|
|
|
|
@node N_CATCH
|
|
@section 84 - 0x54 - N_CATCH
|
|
GNU C++ "catch" clause
|
|
|
|
GNU C++ `catch' clause. Value is its address. Desc is nonzero if
|
|
this entry is immediately followed by a CAUGHT stab saying what
|
|
exception was caught. Multiple CAUGHT stabs means that multiple
|
|
exceptions can be caught here. If Desc is 0, it means all exceptions
|
|
are caught here.
|
|
|
|
@node N_SSYM
|
|
@section 96 - 0x60 - N_SSYM
|
|
Structure or union element
|
|
|
|
Value is offset in the structure.
|
|
|
|
<<?looking at structs and unions in C I didn't see these>>
|
|
|
|
@node N_SO
|
|
@section 100 - 0x64 - N_SO
|
|
Path and name of source file containing main routine
|
|
|
|
@display
|
|
.stabs "name", N_SO, NIL, NIL, value
|
|
@end display
|
|
|
|
@example
|
|
"name" -> /path/to/source/file
|
|
-> source_file_terminal_name
|
|
|
|
value -> the starting text address of the compilation.
|
|
@end example
|
|
|
|
These are found two in a row. The name field of the first N_SO
|
|
contains the path to the source file. The name field of the second
|
|
N_SO contains the terminal name of the source file itself.
|
|
|
|
@node N_LSYM
|
|
@section 128 - 0x80 - N_LSYM
|
|
Automatic var in the stack (also used for type descriptors.)
|
|
|
|
@display
|
|
.stabs "name" N_LSYM, NIL, NIL, value
|
|
@end display
|
|
|
|
@example
|
|
@exdent @emph{For stack based local variables:}
|
|
|
|
"name" -> name of the variable
|
|
value -> offset from frame pointer (negative)
|
|
|
|
@exdent @emph{For type descriptors:}
|
|
|
|
"name" -> "name_of_the_type:#type"
|
|
# -> t
|
|
|
|
type -> type_ref (or) type_def
|
|
|
|
type_ref -> type_number
|
|
type_def -> type_number=type_desc etc.
|
|
@end example
|
|
|
|
Type may be either a type reference or a type definition. A type
|
|
reference is a number that refers to a previously defined type. A
|
|
type definition is the number that will refer to this type, followed
|
|
by an equals sign, a type descriptor and the additional data that
|
|
defines the type. See the Table D for type descriptors and the
|
|
section on types for what data follows each type descriptor.
|
|
|
|
@node N_BINCL
|
|
@section 130 - 0x82 - N_BINCL
|
|
|
|
Beginning of an include file (Sun only)
|
|
|
|
Beginning of an include file. Only Sun uses this. In an object file,
|
|
only the name is significant. The Sun linker puts data into some of
|
|
the other fields.
|
|
|
|
@node N_SOL
|
|
@section 132 - 0x84 - N_SOL
|
|
|
|
Name of a sub-source file (#include file). Value is starting address
|
|
of the compilation.
|
|
<<?>>
|
|
|
|
@node N_PSYM
|
|
@section 160 - 0xa0 - N_PSYM
|
|
|
|
Parameter variable
|
|
|
|
@display
|
|
stabs. "name", N_PSYM, NIL, NIL, value
|
|
@end display
|
|
|
|
@example
|
|
"name" -> "param_name:#type"
|
|
# -> p (value parameter)
|
|
-> i (value parameter by reference, indirect access)
|
|
-> v (variable parameter by reference)
|
|
-> C (read-only parameter, conformant array bound)
|
|
-> x (conformant array value parameter)
|
|
-> pP (<<??>>)
|
|
-> pF (<<??>>)
|
|
-> X (function result variable)
|
|
-> b (based variable)
|
|
|
|
value -> offset from the argument pointer (positive).
|
|
@end example
|
|
|
|
On most machines the argument pointer is the same as the frame
|
|
pointer.
|
|
|
|
@node N_EINCL
|
|
@section 162 - 0xa2 - N_EINCL
|
|
|
|
End of an include file. This and N_BINCL act as brackets around the
|
|
file's output. In an ojbect file, there is no significant data in
|
|
this entry. The Sun linker puts data into some of the fields.
|
|
<<?>>
|
|
|
|
@node N_ENTRY
|
|
@section 164 - 0xa4 - N_ENTRY
|
|
|
|
Alternate entry point.
|
|
Value is its address.
|
|
<<?>>
|
|
|
|
@node N_LBRAC
|
|
@section 192 - 0xc0 - N_LBRAC
|
|
|
|
Beginning of a lexical block (left brace). The variable defined
|
|
inside the block precede the N_LBRAC symbol. Or can they follow as
|
|
well as long as a new N_FUNC was not encountered. <<?>>
|
|
|
|
@display
|
|
.stabn N_LBRAC, NIL, NIL, value
|
|
@end display
|
|
|
|
@example
|
|
value -> code address of block start.
|
|
@end example
|
|
|
|
@node N_EXCL
|
|
@section 194 - 0xc2 - N_EXCL
|
|
|
|
Place holder for a deleted include file. Replaces a N_BINCL and
|
|
everything up to the corresponding N_EINCL. The Sun linker generates
|
|
these when it finds multiple indentical copies of the symbols from an
|
|
included file. This appears only in output from the Sun linker.
|
|
<<?>>
|
|
|
|
@node N_SCOPE
|
|
@section 196 - 0xc4 - N_SCOPE
|
|
|
|
Modula2 scope information (Sun linker)
|
|
<<?>>
|
|
|
|
@node N_RBRAC
|
|
@section 224 - 0xe0 - N_RBRAC
|
|
|
|
End of a lexical block (right brace)
|
|
|
|
@display
|
|
.stabn N_RBRAC, NIL, NIL, value
|
|
@end display
|
|
|
|
@example
|
|
value -> code address of the end of the block.
|
|
@end example
|
|
|
|
@node N_BCOMM
|
|
@section 226 - 0xe2 - N_BCOMM
|
|
|
|
Begin named common block.
|
|
|
|
Only the name is significant.
|
|
<<?>>
|
|
|
|
@node N_ECOMM
|
|
@section 228 - 0xe4 - N_ECOMM
|
|
|
|
End named common block.
|
|
|
|
Only the name is significant and it should match the N_BCOMM
|
|
<<?>>
|
|
|
|
@node N_ECOML
|
|
@section 232 - 0xe8 - N_ECOML
|
|
|
|
End common (local name)
|
|
|
|
value is address.
|
|
<<?>>
|
|
|
|
@node Gould
|
|
@section Non-base registers on Gould systems
|
|
<< used on Gould systems for non-base registers syms, values assigned
|
|
at random, need real info from Gould. >>
|
|
<<?>>
|
|
|
|
@example
|
|
240 0xf0 N_NBTEXT ??
|
|
242 0xf2 N_NBDATA ??
|
|
244 0xf4 N_NBBSS ??
|
|
246 0xf6 N_NBSTS ??
|
|
248 0xf8 N_NBLCS ??
|
|
@end example
|
|
|
|
@node N_LENG
|
|
@section - 0xfe - N_LENG
|
|
|
|
Second symbol entry containing a length-value for the preceding entry.
|
|
The value is the length.
|
|
|
|
@node Questions
|
|
@appendix Questions and anomalies
|
|
|
|
@itemize @bullet
|
|
@item
|
|
For GNU C stabs defining local and global variables (N_LSYM and
|
|
N_GSYM), the desc field is supposed to contain the source line number
|
|
on which the variable is defined. In reality the desc field is always
|
|
0. (This behavour is defined in dbxout.c and putting a line number in
|
|
desc is controlled by #ifdef WINNING_GDB which defaults to false). Gdb
|
|
supposedly uses this information if you say 'list var'. In reality
|
|
var can be a variable defined in the program and gdb says `function
|
|
var not defined'
|
|
|
|
@item
|
|
In GNU C stabs there seems to be no way to differentiate tag types:
|
|
structures, unions, and enums (symbol descriptor T) and typedefs
|
|
(symbol descriptor t) defined at file scope from types defined locally
|
|
to a procedure or other more local scope. They all use the N_LSYM
|
|
stab type. Types defined at procedure scope are emited after the
|
|
N_RBRAC of the preceding function and before the code of the
|
|
procedure in which they are defined. This is exactly the same as
|
|
types defined in the source file between the two procedure bodies.
|
|
GDB overcompensates by placing all types in block #1 the block for
|
|
symbols of file scope. This is true for default, -ansi and
|
|
-traditional compiler options. (p0001063-gcc, p0001066-gdb)
|
|
|
|
@item
|
|
What ends the procedure scope? Is it the proc block's N_RBRAC or the
|
|
next N_FUN? (I believe its the first.)
|
|
|
|
@item
|
|
The comment in xcoff.h says DBX_STATIC_CONST_VAR_CODE is used for
|
|
static const variables. DBX_STATIC_CONST_VAR_CODE is set to N_FUN by
|
|
default, in dbxout.c. If included, xcoff.h redefines it to N_STSYM.
|
|
But testing the default behaviour, my Sun4 native example shows
|
|
N_STSYM not N_FUN is used to describe file static initialized
|
|
variables. (the code tests for TREE_READONLY(decl) &&
|
|
!TREE_THIS_VOLATILE(decl) and if true uses DBX_STATIC_CONST_VAR_CODE).
|
|
|
|
@item
|
|
Global variable stabs don't have location information. This comes
|
|
from the external symbol for the same variable. The external symbol
|
|
has a leading underbar on the _name of the variable and the stab does
|
|
not. How do we know these two symbol table entries are talking about
|
|
the same symbol when their names are different?
|
|
|
|
@item
|
|
Can gcc be configured to output stabs the way the Sun compiler
|
|
does, so that their native debugging tools work? <NO?> It doesn't by
|
|
default. GDB reads either format of stab. (gcc or SunC). How about
|
|
dbx?
|
|
@end itemize
|
|
|
|
@node xcoff-differences
|
|
@appendix Differences between GNU stabs in a.out and GNU stabs in xcoff
|
|
|
|
(The AIX/RS6000 native object file format is xcoff with stabs)
|
|
|
|
@itemize @bullet
|
|
@item
|
|
Instead of .stabs, xcoff uses .stabx.
|
|
|
|
@item
|
|
The data fields of an xcoff .stabx are in a different order than an
|
|
a.out .stabs. The order is: string, value, type. The desc and null
|
|
fields present in a.out stabs are missing in xcoff stabs. For N_GSYM
|
|
the value field is the name of the symbol.
|
|
|
|
@item
|
|
BSD a.out stab types correspond to AIX xcoff storage classes. In general the
|
|
mapping is N_STABTYPE becomes C_STABTYPE. Some stab types in a.out
|
|
are not supported in xcoff. See Table E. for full mappings.
|
|
|
|
exception:
|
|
initialised static N_STSYM and un-initialized static N_LCSYM both map
|
|
to the C_STSYM storage class. But the destinction is preserved
|
|
because in xcoff N_STSYM and N_LCSYM must be emited in a named static
|
|
block. Begin the block with .bs s[RW] data_section_name for N_STSYM
|
|
or .bs s bss_section_name for N_LCSYM. End the block with .es
|
|
|
|
@item
|
|
xcoff stabs describing tags and typedefs use the N_DECL (0x8c)instead
|
|
of N_LSYM stab type.
|
|
|
|
@item
|
|
xcoff uses N_RPSYM (0x8e) instead of the N_RSYM stab type for register
|
|
variables. If the register variable is also a value parameter, then
|
|
use R instead of P for the symbol descriptor.
|
|
|
|
6.
|
|
xcoff uses negative numbers as type references to the basic types.
|
|
There are no boilerplate type definitions emited for these basic
|
|
types. << make table of basic types and type numbers for C >>
|
|
|
|
@item
|
|
xcoff .stabx sometimes don't have the name part of the string field.
|
|
|
|
@item
|
|
xcoff uses a .file stab type to represent the source file name. There
|
|
is no stab for the path to the source file.
|
|
|
|
@item
|
|
xcoff uses a .line stab type to represent source lines. The format
|
|
is: .line line_number.
|
|
|
|
@item
|
|
xcoff emits line numbers relative to the start of the current
|
|
function. The start of a function is marked by .bf. If a function
|
|
includes lines from a seperate file, then those line numbers are
|
|
absolute line numbers in the <<sub-?>> file being compiled.
|
|
|
|
@item
|
|
The start of current include file is marked with: .bi "filename" and
|
|
the end marked with .ei "filename"
|
|
|
|
@item
|
|
If the xcoff stab is a N_FUN (C_FUN) then follow the string field with
|
|
,. instead of just ,
|
|
|
|
@item
|
|
The symbol descriptor for register parameters is P for a.out and R for
|
|
xcoff.
|
|
@end itemize
|
|
|
|
|
|
(I think that's it for .s file differences. They could stand to be
|
|
better presented. This is just a list of what I have noticed so far.
|
|
There are a *lot* of differences in the information in the symbol
|
|
tables of the executable and object files.)
|
|
|
|
Table E: mapping a.out stab types to xcoff storage classes
|
|
|
|
@example
|
|
stab type storage class
|
|
-------------------------------
|
|
N_GSYM C_GSYM
|
|
N_FNAME unknown
|
|
N_FUN C_FUN
|
|
N_STSYM C_STSYM
|
|
N_LCSYM C_STSYM
|
|
N_MAIN unkown
|
|
N_PC unknown
|
|
N_RSYM C_RSYM
|
|
N_RPSYM (0x8e) C_RPSYM
|
|
N_M2C unknown
|
|
N_SLINE unknown
|
|
N_DSLINE unknown
|
|
N_BSLINE unknown
|
|
N_BROWSE unchanged
|
|
N_CATCH unknown
|
|
N_SSYM unknown
|
|
N_SO unknown
|
|
N_LSYM C_LSYM
|
|
N_DECL (0x8c) C_DECL
|
|
N_BINCL unknown
|
|
N_SOL unknown
|
|
N_PSYM C_PSYM
|
|
N_EINCL unknown
|
|
N_ENTRY C_ENTRY
|
|
N_LBRAC unknown
|
|
N_EXCL unknown
|
|
N_SCOPE unknown
|
|
N_RBRAC unknown
|
|
N_BCOMM C_BCOMM
|
|
N_ECOMM C_ECOMM
|
|
N_ECOML C_ECOML
|
|
|
|
N_LENG unknown
|
|
@end example
|
|
|
|
@node Sun-differences
|
|
@appendix Differences between GNU stabs and Sun native stabs.
|
|
|
|
@itemize @bullet
|
|
@item
|
|
GNU C stabs define *all* types, file or procedure scope, as
|
|
N_LSYM. Sun doc talks about using N_GSYM too.
|
|
|
|
@item
|
|
Stabs describing block scopes, N_LBRAC and N_RBRAC are supposed to
|
|
contain the nesting level of the block in the desc field, re Sun doc.
|
|
GNU stabs always have 0 in that field.
|
|
|
|
@item
|
|
Sun C stabs use type number pairs in the format (a,b) where a is a
|
|
number starting with 1 and incremented for each sub-source file in the
|
|
compilation. b is a number starting with 1 and incremented for each
|
|
new type defined in the compilation. GNU C stabs use the type number
|
|
alone, with no source file number.
|
|
@end itemize
|
|
|
|
@contents
|
|
@bye
|