home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Education Sampler 1992 [NeXTSTEP]
/
Education_1992_Sampler.iso
/
NeXT
/
GnuSource
/
cc-61.0.1
/
cc
/
README.DWARF
< prev
next >
Wrap
Text File
|
1991-05-13
|
21KB
|
425 lines
Notes on GNU DWARF
------------------
This file accompanies a set of patches (i.e. a patch kit) to the Data General
1.37.27 version of the GNU C compiler (GCC). When applied to the DG
1.37.27 version of GCC, the result should be a version of GCC which
is able to generate DWARF debugging information for systems based on the
Motorola 88000 processor.
Note that as of DG version 1.37.27 of GCC, all patches necessary for
generating DWARF debugging information have been completely pre-integrated
into DG versions of GCC.
No attempt has been made to insure that the code which implements the
support for DWARF generation is either useful or correct when used with
other versions of GCC or when used for target processors other that 88k's.
In short, if it don't work for non-88k systems, or for GCC releases other
than the one specified here, don't blame me.
The DWARF patches have been generously donated by Network Computing Devices
to the Free Software Foundation, and are covered under the GNU General Public
Licence (aka `copyleft').
If you have questions or comments about these DWARF patches to GCC, please
send mail to me <rfg@ncd.com>. I will be happy to investigate any bugs
reported and I may even provide fixes (but of course, I can make no promises).
The DWARF debugging information produced by GCC deviates in a few minor
(but perhaps significant) respects from the DWARF debugging information
which may be produced by other C compilers. (Herein, the DWARF produced
to date by other C compilers shall be referred to as `Traditional DWARF'.)
The following paragraphs describe known differences between GNU DWARF and
traditional DWARF.
Note that a significant effort has been made to get the GNU compilers to
produce DWARF which, although different in some small respects from
traditional DWARF, is still close enough to traditional DWARF that it
should cause little or no problems for existing tools (i.e. linkers,
debuggers, etc.) which expect their input files to contain traditional
DWARF code.
(Footnote: Within this file, the term `Debugging Information Entry' will
be abbreviated as `DIE'.)
Known Differences Between GNU DWARF and Traditional DWARF
---------------------------------------------------------
In traditional DWARF, each DIE which represents a function definition
has a sequences of direct `child' DIEs (immediately following it) which
represent not only the function's formal parameters, but also all
of those things (i.e. types, functions, and objects) which are
declared directly within the outermost block of the function (but
not within any more deeply nested blocks).
In effect, traditional DWARF fails to even recognize the existence of
the outermost lexical blocks of function definitions.
In GNU DWARF, each function definition has a set of direct child DIEs
which represent the function's formal parameters, and the last actual
child DIE for each function definition is a lexical block DIE which
represents the outermost lexical block of the given function. This
block in turn has a set of it own child DIEs which represent the things
which are declared directly within the block which it represents.
The primary advantage of this approach is that it allows the compiler
to communicate (to the debugger) the addresses of the true beginning and
ending of the *body* of the function (excluding any prologue or epilogue
code necessary to properly initialize formal parameter variables or to
allocate or deallocate space for local variables). This information
can be used by the debugger to prevent invalid informational requests
(e.g. printing the value of a formal or a local) from being honored when
the current execution point is somewhere within either the prologue or
the epilogue of the current function.
Another advantage to this approach is that it makes it very easy for the
debugger to find the true beginning of a function body. This information
may be useful when setting a breakpoint at the `start' of a given function.
--------------------------------
In traditional DWARF, all DIEs representing labels and variables have
`low_pc' attributes and `location' attributes (respectively).
In GNU DWARF, when compiler optimization is enabled (via -O) it is possible
that some labels and local variables will be optimized out of existance.
In such cases, the DIEs produced for these entities will *not* contain
the normal `low_pc' and `location' attributes. When confronted with
such (perhaps non-standard) DIEs, debuggers should infer that the given
entities have been optimized out of existance and that (for all practical
purposes) they do not actually exist in the executable program.
--------------------------------
In traditional DWARF, a DIE for a statement label is generated at whatever
point (within the hierarchy of lexical block DIEs) that the given label is
first mentioned (either by being defined, or by being referred to in a goto
statement).
In GNU DWARF, all label DIEs for a given function are generated such
that they are direct children of the outermost lexical block DIE for
the function in which they appear. This placement more accurately
reflects the true `function scope' of labels. Furthermore, all label
DIEs for a given function precede all other types of DIEs which are
direct children of the outermost lexical block of the containing function.
--------------------------------
Some compilers producing traditional DWARF may fail to produce type
attributes within DIEs which describe functions. (This probably represents
a bug in these DWARF implementations.)
In GNU DWARF, these `function return type' attributes *are* produced.
--------------------------------
In traditional DWARF, visibility attributes are generated only for function
definitions which are explicitly declared as `static'. (Actually, some
C compilers producing `traditional DWARF' may *never* produce any visibility
attributes, even for static function definitions. This is probably just a
bug in these compilers however.)
In GNU DWARF, visibility attributes are produced for all file-scope
declarations (of both functions and data objects) which have `internal
linkage' (as described in the ANSI C standard, section 3.1.2.2).
Entities which have internal linkage are those entities which are
declared at file-scope with the `static' storage class specifier.
Note that all such entities get visibility attributes in which the
visibility is set to `VIS_local'.
The generation of visibility attributes (with VIS_local) for all entities
with internal linkage allows for the proper `commonizing' of debugging
information (i.e. DIEs) within linked (i.e. linker output) object files
produced by linking multiple original object files together. Specifically,
the generation of these visibility attributes is required in order to
prevent the unwarranted commonizing of DIEs representing external linkage
entities with DIEs for similarly named entities (from other compilation
units) which have internal linkage.
--------------------------------
Traditional DWARF was defined with the (incorrect) belief in mind that an
integral type which is explicitly declared as `signed' and an (otherwise
identical) `plain' integral are somehow different. In fact, ANSI C and
GCC believe that any such pair of types are *not* different types, but
rather are exactly the same type. (Note that there is an exception in
case of `char' types; i.e. `char' and `signed char' are in fact different
types.)
In GNU DWARF, no attempt is made to reinforce this incorrect notion.
Thus, GNU compilers do not produce any of the three (bogus) fundamental
type codes FT_signed_long, FT_signed_integer, or FT_signed_short.
--------------------------------
In traditional implementations of DWARF, DIEs which represent types may not
be reused to the maximum extent possible. Rather, DIEs representing specific
types may appear more than once in the output.
The effect of this is that the .debug section may grow larger than is really
necessary.
In GNU DWARF, type DIEs are reused to the maximum extent possible.
--------------------------------
The output from various compilers producing traditional DWARF may vary
with respect to the ordering of DIEs describing things declared with file-
scope. This is a permissible variation within the definition of DWARF.
In GNU DWARF, DIEs representing entities declared at file scope are (in
general) generated in the same order as the declarations of those entities.
--------------------------------
GNU DWARF Extensions to Handle GNU C Extensions to ANSI C
---------------------------------------------------------
The file dwarfout.c and its associated patches to the GCC sources have been
designed and implemented so as to provide some reasonable DWARF representation
for each and every declarative construct which is accepted by the GNU C
compiler. Since the GNU C compiler accepts a superset of ANSI C, this means
that there are some cases in which the DWARF information produced by GCC
must take some liberties in violating the rules of `traditional DWARF' in
order to represent declarations which are legal in GNU C but illegal in
ANSI C. These are described below.
--------------------------------
GNU C provides a `inline functions' feature (a la C++). At all sites in the
source code where GCC actually `inlines' a given inline function, proper
DWARF information (including proper .line section entries) will be generated
to allow the debugger to fully understand that code from the inlined function
was incorporated at that site. In particular, the block (scope) structure
of the inlined function is preserved and is directly reflected in the DWARF
information generated at the call site. Also, the DWARF representations for
the `location attributes' of all local variables and parameter variables of
the inlined function are adjusted so as to reflect the actual locations of
the corresponding entities after inlining at the call site.
Note that wherever a function gets inlined (at a call site) the DWARF
information generated for that call site will properly reflect the fact
that the formal parameter variables of the called function are effectively
changed into local variables (at the call site) as a result of the inlining.
--------------------------------
GNU C provides a `dynamically sized array' feature in which the declarations of
local (storage class `auto') array variables are allowed to specify non-static
expressions as individual array dimensions.
Traditional DWARF does specify a proper way of representing such dynamically
bounded arrays, however it requires that the value of each upper bound of each
dimension be accessible at run-time throughout the scope of the given array
object.
Normally, GCC makes sure that these (dynamic) upper bound values are in fact
computed and stored (either in stack slots or in registers) such that they
can be made available to a debugger throughout the scope of any such dynamic
arrays, however when optimization (-O) is used, GCC typically (and correctly)
finds it to be unnecessarily inefficient to compute and to save these dynamic
upper bound values. Thus, when both -O and -g are used, GCC can produce
TAG_array_type DIEs in which one or more dimensions are represented as
having dynamic upper bounds, but the `location descriptions' for the upper
bound values themselves will be empty (indicating that the given upper
bound is unknown and unknowable).
Note that while empty location descriptions for array bounds are in fact
allowed in traditional DWARF, their only known (legal) use is as an
indication of an incomplete array type, as in:
typedef int array[];
Other uses of empty location descriptions for particular array bounds (such
as GCC's use of them to represent upper bounds for dynamic dimensions when
-O is in use) may cause some traditional DWARF debuggers to choke.
--------------------------------
GNU DWARF Optional Extensions for G++ and GDB
---------------------------------------------
Each GNU DWARF optional extension is controlled by the presence or
absence of a particular preprocessor #define for a given special
symbol within your target-specific tm-*.h file. These special
symbols are described below.
--------------------------------
Define GPLUSPLUS if you plan to use dwarfout.c with the GNU g++ compiler.
Note that the implementation of full DWARF support for g++ is (as yet)
unfinished. If you want to use DWARF debugging information with the g++
compiler you will have to finish the work yourself. (Note: you may want
to contact John Hassey @ DG <hassey@dg-rtp.dg.com> if you have a serious
interest in this.)
--------------------------------
Define DWARF_DESCRIBE_USED_EXTERNS if you want the DWARF info for any given
object file to include descriptions of things (i.e. data objects and
functions) which are explicitly declared as `extern' and which are actually
referenced somewhere within the current compilation unit. This can be useful
if you have a linker which is capable of doing type checking across object
files (based upon DWARF type specifications). When you define this symbol,
DWARF DIEs will be generated to describe used items declared `extern' and
these DIEs will be placed into the special .externs section (in order to
avoid mixing them with the DIEs used for debugging).
The layout of the special .externs section is very similar to that of the
.debug section. In particular, it begins with an (abbrevaited) source_file
DIE which includes a pointer to the endpoint of the information in the
.externs section for the current compilation unit. Following the source_file
DIE, there will be a sequence of normal DIE for variables, functions, and
function formal parameter types. Not that these DIEs may (and often do)
make corss-section references to the type descriptions contained within
the .debug section. The list of clid DIEs for the source_file DIE is
terminated with a single word with the value 4 (as in the .debug section).
--------------------------------
Define DWARF_LOCATION_ATTRIBUTES if you want the compiler to generate the
special extended DWARF attributes `AT_file' and `AT_line' for DIEs describing
declared entities whose types may differ in different compilation units.
The primary purpose of this option is to allow an intelligent linker (which
has the cross-compilation-unit type checking feature) to identify (in error
messages) the precise locations of conflicting enternal-linkage declarations.
Thus, this option is normally useful only in conjunction with the
DWARF_DESCRIBE_USED_EXTERNS option.
WARNING: Use of this option causes DIEs in the .debug section to include
non-standard DWARF attributes. This may cause trouble for debuggers which
cannot properly cope with non-standard DWARF attributes.
--------------------------------
Define DWARF_DESCRIBE_FILES if you want extra information generated (in the
special .files and .finfo sections) which can give the debugger enhanced
information regarding the source files which contribute to the executable
code generated for each compilation unit.
To understand this GNU DWARF extension, imagine that the sequence of entries
in the .lines section is broken up into several subsections. Each contiguous
sequence of .line entries which relates to a sequence of lines (or statements)
from one particular file (either a `base' file or an `include' file) could
be called a `line entries chunk' (LEC).
For each LEC there is one entry in the .finfo section.
Each *normal* entry in the .finfo section contains two parts:
(1) A 4-byte pointer to the start of the first .line entry in the
given LEC, and
(2) a 4-byte pointer to a string in the .files section.
Obviously, each .finfo entry allows you to find the relevant filename, and
it also points you to the first .line entry that was generated as a result
of having compiled a given source line from the given source file.
Each subsequent .line entry should also be assumed to have been produced
as a result of compiling yet more lines from the same file. The end of
any given LEC is easily found by looking at the first 4-byte pointer in
the *next* .finfo entry. That next .finfo entry points to a new and
different LEC, so the preceeding LEC (implicitly) must have ended with
the last .line section entry which occurs at the 2 1/2 words just before
the address given in the first pointer of the new .finfo entry.
The following picture may help to clarify this feature. Let's assume that
`LE' stands for `.line entry'. Also, assume that `* 'stands for a pointer.
.line section .finfo section .files section
----------------------------------------------------------------
LE <---------------------- *
LE * -----------------> "foobar.c" <---
LE |
LE |
LE <---------------------- * |
LE * -----------------> "foobar.h" <| |
LE | |
LE | |
LE <---------------------- * | |
LE * -----------------> "inner.h" | |
LE | |
LE <---------------------- * | |
LE * ------------------------------- |
LE |
LE |
LE |
LE |
LE <---------------------- * |
LE * -----------------------------------
LE
LE
LE
In effect, each entry in the .finfo section points to *both* a filename
and to (the start of) a block of (consecutive) LEs.
Note that just like in the .line section, there are specialized first and
last entries in the .finfo section for each object file. These special
first and last entries are different from normal ones and they can clearly
indicate (to the debugger) where the set of .finfo entries for that object
file begins and ends. The debugger will need this information in order
to correctly interpret the .finfo entries.
Note also that the first string in the .files section for each object file
will be the full absolute pathname of the directory from which the compiler
was invoked when the given object file was produced. This tells debuggers
which directory all other (relative) pathnames in the .files section are
relative to. Proper use of this `compilation directory' string can make
commands like GDB's `directory' command obsolete.
--------------------------------
Future Directions
-----------------
The codes, formats, and other paraphernalia necessary to provide proper
support for symbolic debugging for languages other than C (and in particular,
C++) is not yet well defined for DWARF. Hopefully, A more complete form
of DWARF which can handle *all* of the symbolic debugging requirements
for C++, FORTRAN, Pascal, Modula, and Ada will evolve in the future.
Efforts are currently underway to develop and promote such extensions to
DWARF under the auspices of the UNIX(r) International Programming Languages
Special Interest Group. Contact the Chairman, Dan Oldman (oldman@dg-rtp.dg.com)
for further information.
As currently defined, DWARF only describes a (binary) language which can
be used to communicate symbolic debugging information from a compiler
through an assembler and a linker, to a debugger. There is no clear
specification of what processing should be (or must be) done by the
assembler and/or the linker. Fortunately, the role of the assembler
is easily inferred (by anyone knowledgeable about assemblers) just by
looking at examples of assembly-level DWARF code. Sadly though, the
allowable (or required) processing steps performed by a linker are
harder to infer and (perhaps) even harder to agree upon. There are
several forms of very useful `post-processing' steps which intelligent
linkers *could* (in theory) perform on object files containing DWARF,
but any and all such link-time transformations are currently both disallowed
and unspecified.
In particular, possible link-time transformations of DWARF code which could
provide dramatic benefits include (but are not limited to):
Commonization of duplicate DIEs obtained from multiple input
(object) files.
Reorganization (i.e. re-ordering) of DIEs (in linked output files)
to provide for decreased I/O (at debug-time) and a corresponding
increase in debugger speed.
Cross-compilation type checking based upon DWARF type information
for objects and functions.
Creation of additional `fast lookup tables' (by the linker) which
could be stored in new and unique output sections designed expressly
for this purpose.
Other possible `compacting' transformations designed to save disk
space and to reduce linker & debugger I/O activity.