11    Symbol Information

This chapter focuses on the symbol table data used to represent a program's symbols and the scopes in which they occur. This information is primarily used by symbolic debuggers.

11.1    New or Changed Symbol Information Features

Tru64 UNIX V5.1B includes the following new or changed features:

Tru64 UNIX V5.1 includes the following new or changed features:

Version 3.14 of the symbol table includes the following new or changed features:

Version 3.13 of the symbol table includes the following new or changed features:

11.2    Structures, Fields, and Values for Symbol Information

Unless otherwise specified, all structures described in this section are declared in the header file sym.h, and all constants are defined in the header file symconst.h.

11.2.1    Local Symbol Entry (SYMR)

typedef struct {
        coff_long       value;       
        coff_int        iss;           
        coff_uint       st : 6;      
        coff_uint       sc  : 5;    
        coff_uint       reserved : 1; 
        coff_uint       index : 20; 
} SYMR, *pSYMR;

SIZE - 16 bytes, ALIGNMENT - 8 bytes

See Section 11.2.4, Section 8.3, and Section 11.3.3 for related information.

Local Symbol Table Entry Fields

value

A field that can contain an address, size, offset, or index. Its interpretation is determined by the symbol type and storage class combination, as explained in Section 11.2.4.

iss

Byte offset from the issBase field of a file descriptor table entry to the name of the symbol. If the symbol does not have a name, this field is set to issNil (-1). Generally, all user-defined symbols have names. A symbol without a name is one that has been created by the compilation system for its own use.

st

Symbol type (see Table 11-1).

sc

Storage class (see Table 11-2).

reserved

Must be zero.

index

An index into either the local symbol table or auxiliary symbol table, depending on the symbol type and class. The index is used as an offset from the isymBase field in the file descriptor entry for an entry in the local symbol table or an offset from the iauxBase field for an entry in the auxiliary symbol table.

The index field may have a value of indexNil, which is defined as (long)0xfffff. This value is used to indicate that the index is not a valid reference.

The next two tables contain all defined values for the st and sc constants, along with short descriptions. However, these fields must be considered as pairs that have a limited number of possible pairings as explained in Section 11.2.4.

Table 11-1:  Symbol Type (st) Constants

Constant Value Description
stNil 0 Dummy entry
stGlobal 1 Global variable
stStatic 2 Static variable
stParam 3 Procedure argument
stLocal 4 Local variable
stLabel 5 Label
stProc 6 Global procedure
stBlock 7 Start of block
stEnd 8 End of block, file, or procedure
stMember 9 Member of class, structure, union, or enumeration
stTypedef 10 User-defined type definition
stFile 11 Source file name
stStaticProc 14 Static procedure
stConstant 15 Constant data
stBase 17 Base class (for example, C++)
stVirtBase 18 Virtual base class (for example, C++)
stTag 19 Data structure tag value (for example, C++ class or struct)
stInter 20 Interlude (for example, C++)
stModule 22 (V5.1B - ) Fortran90 module definition
stNamespace 22 (V5.0 - ) Namespace definition (for example, C++)
stUsing 23 (V5.0 - ) Namespace use (for example, C++ "using")
stAlias 24 (V5.0 - ) Defines an alias for another symbols. Currently, only used for namespace aliases.
stExternal 30 (V5.1B - ) Local symbol with external linkage
stUseModule 31 (V5.1B - ) Fortran90 module use
stRename 32 (V5.1B - ) Name replacement
stInterface 33 (V5.1B - ) Name replacement
stMax 64 Maximum number of symbol types

General Notes:

Symbol type codes with more than one interpretation are identified by the lang field in the associated file descriptor. This applies to the stModule/ stNamespace symbol types.

Table 11-2:  Storage Class (sc) Constants

Constant Value Description
scNil 0 Dummy entry
scText 1 Symbol allocated in the .text section
scData 2 Symbol allocated in the .data section
scBss 3 Symbol allocated in the .bss section
scRegister 4 Symbol allocated in a register
scAbs 5 Symbol value is absolute
scUndefined 6 Symbol referenced but not defined in the current module
scUnallocated 7 Storage not allocated for this symbol
scTlsUndefined 9 TLS symbol referenced but not defined in the current module
scInfo 11 Symbol contains debugger information
scSData 13 Symbol allocated in the .sdata section
scSBss 14 Symbol allocated in the .sbss section
scRData 15 Symbol allocated in the .rdata section
scVar 16 Parameter passed by reference (for example, Fortran or Pascal)
scCommon 17 Common symbol
scSCommon 18 Small common symbol
scVarRegister 19 Parameter passed by reference in a register
scVariant 20 Variant record (for example, Pascal or Ada)
scFileDesc 20 File descriptor (for example, COBOL)
scSUndefined 21 Small undefined symbol
scInit 22 Symbol allocated in the .init section
scReportDesc 23 Report descriptor (for example, COBOL)
scXData 24 Symbol allocated in the .xdata section
scPData 25 Symbol allocated in the .pdata section
scFini 26 Symbol allocated in the .fini section
scRConst 27 Symbol allocated in the .rconst section
scTlsCommon 29 TLS common symbol
scTlsData 30 Symbol allocated in the .tlsdata section
scTlsBss 31 Symbol allocated in the .tlsbss section
scMax 32 Maximum number of storage classes

Table 11-3:  Use Module Constants

Constant Value Description
USE_MODULE_ONLY 0 Import only the explicitly listed symbols from a Fortran module
USE_MODULE_ALL 1 Import all symbols from a Fortran module


Version Note

Fortran modules are supported in symbol table format V3.14 and greater.


11.2.2    Auxiliary Symbol Table Entry (AUXU)

The auxiliary symbol table entry is a 32-bit union. It is either interpreted as a TIR or RNDXR structure or as an integer value. See Section 11.3.2.3 for detailed instructions on reading the auxiliary symbols.

typedef union {
        TIR             ti;             
        RNDXR           rndx;          
        coff_int        dnLow;        
        coff_int        dnHigh;      
        coff_int        isym;       
        coff_int        iss;       
        coff_int        width;    
        coff_int        count;   
        coff_int        slice;    (V5.0A)
} AUXU, *pAUXU;

SIZE - 4 bytes, ALIGNMENT - 4 bytes

See Section 11.3.2.3 for related information.

Auxiliary Symbol Table Entry Fields

ti

Type information record (TIR), as defined in Section 11.2.2.1.

rndx

Relative index into local or auxiliary symbols (rndx), as defined in Section 11.2.2.2.

dnLow

Lower bound of range or array dimension. For large structures, two of these fields can be used together to form one 64-bit number.

dnHigh

Upper bound of range or array dimension. For large structures, two of these fields can be used together to form one 64-bit number.

isym

For procedures ( stProc or stStaticProc symbols), this field is an index into the local symbols. It is also used as an index into the relative file descriptors.

iss

Unused.

width

Width of a bit field or array stride in bits. Fortran compilers set the array stride to the array element size in bits. Two of these fields can be used together to form one 64-bit number.

count

Count of ranges for variant arm. This field name is only used within the type description of a variant block ( stBlock, scVariant).

slice

Reserved.

General Notes:

The fields dnLow, dnHigh, or width must all use either the 32-bit or 64-bit representation when used together. For example, an array dimension cannot be specified with a 32-bit dnLow and a 64-bit dnHigh.

11.2.2.1    Type Information Record (TIR)

typedef struct {
        coff_uint       fBitfield : 1;
        coff_uint       continued : 1;
        coff_uint       bt  : 6;     
        coff_uint       tq4 : 4;
        coff_uint       tq5 : 4;
        coff_uint       tq0 : 4;
        coff_uint       tq1 : 4;    
        coff_uint       tq2 : 4;
        coff_uint       tq3 : 4;
} TIR, *pTIR;

SIZE - 4 bytes, ALIGNMENT - 4 bytes

Type Information Record Entry Fields

fBitfield

Flag set if bit width is specified.

continued

Flag set to indicate that the type description is continued in another TIR record. This will happen if the type is represented with more than six type qualifiers.

bt

Basic type (see Table 11-4 and Section 11.3.2.1).

tq0, tq1, tq2, tq3, tq4, tq5

Type qualifiers (see Table 11-5 and Section 11.3.2.2). The lower-numbered tq fields must be used first, and all unneeded fields must be set to tqNil (0).

Table 11-4:  Basic Type (bt) Constants

Constant Value Description
btNil 0 Undefined or void
btAdr32 1 Address (32 bits)
btChar 2 Character
btUChar 3 Unsigned character
btShort 4 Short (16 bits)
btUShort 5 Unsigned short (16 bits)
btInt 6 Integer (32 bits)
btUInt 7 Unsigned integer (32 bits)
btLong32 8 Long (32 bits)
btULong32 9 Unsigned long (32 bits)
btFloat 10 Floating point
btDouble 11 Double-precision floating point
btStruct 12 Structure or record
btUnion 13 Union
btEnum 14 Enumeration
btTypedef 15 Defined by means of a user-defined type definition
btRange 16 Range of values (for example, Pascal subrange)
btSet 17 Sets (for example, Pascal)
btComplex 18 Single complex (for example, Fortran COMPLEX*8)
btDComplex 19 Double complex (for example, Fortran COMPLEX*16)
btIndirect 20 Indirect definition; following rndx points to an entry in the auxiliary symbol table that contains a TIR (type information record)
btFixedBin 21 Fixed binary (for example, COBOL)
btDecimal 22 Packed or unpacked decimal (for example, COBOL)
btPicture 25 Picture (for example, COBOL)
btVoid 26 Void
btPtrMem 27 Currently unused
btScaledBin 27 Scaled binary (for example, COBOL)
btVptr 28 Virtual function table (for example, C++)
btArrayDesc 28 Array descriptor (for example, Fortran, Pascal)
btClass 29 Class (for example, C++)
btLong64 30 Address (64 bits)
btLong 30 Long (64 bits)
btULong64 31 Unsigned long (64 bits)
btULong 31 Unsigned long (64 bits)
btLongLong 32 Long long (64 bits)
btULongLong 33 Unsigned long long (64 bits)
btAdr64 34 Address (64 bits)
btAdr 34 Address (64 bits)
btInt64 35 Integer (64 bits)
btUInt64 36 Unsigned integer (64 bits)
btLDouble 37 Long double floating point (128 bits)
btInt8 38 Integer (8 bits)
btUInt8 39 Unsigned integer (8 bits)
btRange_64 41 (V5.0 - ) 64-bit range
btProc 42 (V5.0 - ) Procedure or function
btCobolIndex 43 (not supported) COBOL index variables
btQComplex 46 (V5.1 - ) Quad complex (for example Fortran COMPLEX*32)
btBool 47 (V5.1B - ) 1 byte boolean (false=0, true=1)
btWchar_t 48 (V5.1B - ) 4 byte wchar_t
btChecksum 63 Symbol table checksum value stored in auxiliary record
btMax 64 Number of basic type codes

Table Notes:

  1. btInt and btLong32 are synonymous.

  2. btUInt and btULong32 are synonymous.

  3. btLong, btLong64, btLongLong, and btInt64 are synonymous.

  4. btULong64, btULongLong, and btUInt64 are synonymous.

Table 11-5:  Type Qualifier (tq) Constants

Constant Value Description
tqNil 0 No qualifier (placeholder)
tqPtr 1 Pointer
tqProc 2 (obsolete) Procedure or function
tqArray 3 Array
tqFar 4 32-bit pointer; used with the -xtaso emulation
tqVol 5 Volatile
tqConst 6 Constant
tqRef 7 Reference
tqArray_64 8 (V5.0 - ) Large array
tqShar 10 (V5.0A - ) Reserved
tqExpArray_64 11 (V5.0A - ) Reserved
tqMax 16 Number of type qualifier codes

11.2.2.2    Relative Index Record (RNDXR)

typedef struct {
        coff_uint       rfd : 12;    
        coff_uint       index : 20; 
} RNDXR, *pRNDXR;

SIZE - 4, ALIGNMENT - 4

Relative Index Record Fields

rfd

Index into relative file descriptor table if it exists; otherwise, index into file descriptor table.

This field may have a value of ST_RFDESCAPE, defined as 0xfff in the header file cmplrs/stsupport.h. This value is used to indicate that the next auxiliary entry, interpreted as an isym, contains the actual rfd index.

index

Symbol index. Used as an offset from either FDR.isymbase or FDR.iauxbase, depending on context.

11.2.3    String Table

Objects can contain two string tables: the local string table (corresponding to local symbols) and the external string table (corresponding to external symbols). The local string table is present only for objects created with full debugging information; it is removed if an object is locally stripped.

The storage format for the string tables is a list of null-terminated character strings. It is correctly considered as one long character array, not an array of strings. Fields in the symbolic header and file headers represent string table sizes and offsets in bytes.

11.2.4    Symbol Type Combinations

Entries in the symbol table are primarily identified by the combination of their symbol type (st) and storage class (sc) values. Not all combinations are valid. Figure 11-1 indicates which combinations are currently in use.

Figure 11-1:  st/sc Combination Matrix

A symbol's type and class taken together determines interpretation of other fields in the symbol table entry. The same combination can be used for different purposes in different contexts. As a result, to understand the symbol entry, it also may be necessary to access type information in the auxiliary table or the source language information in the file descriptor.

The contents of the value and index fields for each combination, with a brief explanation of the symbol's use, are described in the following list of combinations. For many combinations, greater detail can be found in Section 11.3.2 and Section 11.3.3.

stGlobal/ scAbs

stGlobal/ scSData, stGlobal/ scData, stGlobal/ scSBss, stGlobal/ scBss, stGlobal/ scRData, stGlobal/ scRConst

stGlobal/ scTlsData, stGlobal/ scTlsBss

stGlobal/ scSCommon, stGlobal/ scCommon, stGlobal/ scTlsCommon

stGlobal/ scSUndefined, stGlobal/ scUndefined, stGlobal/ scTlsUndefined

stStatic/ scAbs

stStatic/ scSData, stStatic/ scData, stStatic/ scSBss, stStatic/ scBss, stStatic/ scRData, stStatic/ scRConst

stStatic/ scTlsData, stStatic/ scTlsBss

stStatic/ scCommon

stStatic/ scInfo

stParam/ scAbs

stParam/ scRegister

stParam/ scVar

stParam/ scVarRegister

stParam/ scInfo

stParam/ scSData, stParam/ scData, stParam/ scSBss, stParam/ scBss, stParam/ scRData, stParam/ scRConst


Version Note

Static parameters are supported in symbol table format V3.13 and greater.


stParam/ scUnallocated

stLocal/ scAbs

stLocal/ scRegister

stLocal/ scVar

stLocal/ scVarRegister

stLocal/ scUnallocated


Version Note

The use of scUnallocated is supported in symbol table format V3.13 and greater.


stLocal/ scText, stLocal/ scInit, stLocal/ scFini, stLocal/ scSData, stLocal/ scData, stLocal/ scSBss, stLocal/ scBss, stLocal/ scRData, stLocal/ scRConst, stLocal/ scTlsData, stLocal/ scTlsBss

stLabel/ scAbs

stLabel/ scText, stLabel/ scInit, stLabel/ scFini, stLabel/ scSData, stLabel/ scData, stLabel/ scXData, stLabel/ scPData, stLabel/ scSBss, stLabel/ scBss, stLabel/ scRData, stLabel/ scRConst, stLabel/ scTlsData, stLabel/ scTlsBss

stLabel/ scUnallocated

stProc/ scNil

stProc/ scText

stProc/ scUndefined

stProc/ scInfo

stBlock/ scText

stBlock/ scInfo

stBlock/ scCommon

stBlock/ scVariant

stBlock/ scFileDesc, stBlock/ scReportDesc

stEnd/ scText

stEnd/ scInfo

stEnd/ scCommon

stEnd/ scVariant

stEnd/ scFileDesc, stEnd/ scReportDesc

stMember/ scInfo

stMember/ scFileDesc, stMember/ scReportDesc

stTypedef/ scInfo

stFile/ scText

stStaticProc/ scText

stStaticProc/ scInit, stStaticProc/ scFini

stConstant/ scAbs

stConstant/ scSData, stConstant/ scData, stConstant/ scSBss, stConstant/ scBss, stConstant/ scRData, stConstant/ scRConst

stBase/ scInfo

stVirtBase/ scInfo

stTag/ scInfo

stInter/ scInfo

stNamespace/ scInfo


Version Note

Namespace symbols are supported in symbol table format V3.13 and greater.


stModule/ scInfo


Version Note

Fortran modules are supported in symbol table format V3.14 and greater.


stUsing/ scInfo


Version Note

Namespace USING directives are supported in symbol table format V3.13 and greater.


stAlias/ scInfo


Version Note

Namespace aliases are supported in symbol table format V3.13 and greater.


stExternal/ scInfo


Version Note

Local visibility for externals is supported in symbol table format V3.14 and greater.


stUseModule/ scInfo


Version Note

Fortran modules are supported in symbol table format V3.14 and greater.


stRename/ scInfo


Version Note

Fortran modules are supported in symbol table format V3.14 and greater.


stInterface/ scInfo


Version Note

Generic names are supported in symbol table format V3.14 and greater.


Combinations may be valid in the local symbol table, the external symbol table, or both. Table 11-6 shows which combinations are valid in which table, based on the symbol type value and also the storage class value where necessary. Only combinations previously specified as valid apply where the storage class value is shown as a wildcard value with the character '*'.

Table 11-6:  Valid Placement for st/sc Combinations

st/sc Combination External Symbol Table Local Symbol Table
stNil, sc* X X
stGlobal, sc* X  
stStatic, sc*   X
stParam, sc*   X
stLocal, scSCN 1 X  
stLocal, not scSCN 1   X
stLabel, sc* X X
stProc, scInfo   X
stProc, scText X X
stProc, scUndefined X  
stBlock, sc*   X
stEnd, sc*   X
stMember, sc*   X
stTypedef, sc*   X
stFile, sc*   X
stStaticProc, scText   X
stStaticProc, scInit/ scFini X  
stConstant, sc* X X
stBase, sc*   X
stVirtBase, sc*   X
stTag, *   X
stInter, sc*   X
stNamespace, sc*   X
stUsing, sc*   X
stAlias, *   X
stExternal, *   X
stUseModule, *   X
stRename, *   X
stInterface, *   X

Table Notes:

  1. scSCN is a section storage class: scData, scSData, scBss, scSBss, scRConst, scRData, scInit, scFini, scText, scXData, scPData, scTlsData, scTlsBss

11.3    Symbol Information Usage

11.3.1    Scopes

From a user-program's point of view, an identifer's scope determines its visibility in different parts of the program. Programming languages provide facilities for declaring and defining names of procedures, variables and other program components inside various scoping levels. This section briefly discusses the concept of scope and then explains how it is represented in the symbol table. References are made to structures in the auxiliary symbol table; see Section 11.3.2.3 for details.

Generally speaking, the four main scoping levels in a program are block scope, procedure scope, file scope, and program scope. Most programming languages have constructs to implement at least these scoping levels. Figure 11-2 shows the hierarchy of these scopes.

Figure 11-2:  Basic Scopes

Names with block scope can only be referenced inside the declaring block. Blocks are delimited by begin and end markers, the syntax of which varies among languages.

Names with procedure scope are only recognized inside their enclosing subroutines. For instance, the names of formal parameters and local variables declared inside a procedure are accessible only to that procedure's executable statements.

Names with file scope can be referenced by any instruction within the file where they are declared. A file can be composed of procedures and data external to any procedure. Both external data names and procedure names can have file scope or program scope. Note that in a compilation involving only a single file or in a compilation for a programming language with no separate-compilation facilities, file scope and program scope are equivalent.

Names with program scope are visible everywhere in the program, even when the executable program is built from many source and header files. The linker must resolve these names or pass them to the dynamic loader to resolve. See Chapter 13 for more information about symbol resolution.

In the symbol table, procedure scope, file scope, and program scope correspond to local, static, and global symbols, respectively. Block scope names are also local symbols. Local and static symbols appear in the local symbol table, and global symbols are in the external symbol table.

11.3.1.1    Local Symbols with External Linkage


Version Note

Local symbols with external linkage are supported in symbol table format V3.14 and greater.


Any scope below program scope can import symbols that are defined in program scope. For example, external declarations in C programs import program scope symbols to file, procedure, or block scope. Source language semantics normally limit the use of externally defined symbols to those that are declared within the local scope, but debuggers will assume that all external symbols are visible from any local scope when the symbol table excludes information on external declarations.

If a file descriptor's fullExternals flag is set, debuggers can limit the visibility of externally defined symbols to those with external declarations in that compilation unit.

External declarations are recorded as local symbol table entries with symbol type stExternal and storage class scInfo. If the name being declared is unique to the containing scope (shared only with other instances or copies of that scope), then the name must be mangled in some way. The symbol is known locally by the demangled name, but globally by the mangled name. The rule for demangling the name must be either built into an appropriate language specific demangling module as is done for C++ or known to debuggers on a language specific basis as is done for the Fortran trailing underscore convention.

If there is no corresponding external symbol table entry for an external declaration, then the local name is considered unallocated. This is not necessarily an error.

External declarations may include type information. The local symbol's index field is interpreted as an AUX index. In addition, the symbol's value field provides a hint as to how best to regenerate the source language declaration. See the stExternal/ scInfo entry in Section 11.2.4 for details.

11.3.1.2    Procedure Scope

Although procedure symbols can only be global or static (with symbol types stProc and stStaticProc, respectively), procedure entries appear in the local symbol table to identify the containing scope of their local data. The set of symbols appearing in the local symbol table to describe a procedure scope and their associated auxiliary entries is shown in Figure 11-3. Global procedures also have entries in the external symbol table. As illustrated, the indices of these external entries point to the scoping entries in the local symbol table.

Note

In this chapter, all diagrams of symbol table representations use arrows to show that one entry contains an index to another entry. For external and local symbol table entries, the index used is contained in the index field. For auxiliary symbols, the isym or RNDXR field is the index used. Any exceptions to this general rule are noted in the diagrams.

Figure 11-3:  Procedure Representation

A special instance of a procedure definition occurs for a procedure with no text. This type of procedure occurs only in the local symbol table and is very similar to the representation of other procedures. It is generally used for procedures that have been optimized away that still need to be represented for debugging or profiling information.

Figure 11-4:  Procedure with No Text

A procedure with no code can contain only nested procedures that also have no code associated with them. If a procedure with no code does not contain any nested procedures, the stBlock/ stEnd symbol pair can be omitted from the representation.

The stProc symbol included in this representation is distinguished from similar stProc symbols by its value field that is set to addressNil (-1).


Version Note

Procedures with no code are supported in symbol table format V3.13 and greater.


11.3.1.3    File Scope

As in the case of procedures, file name entries appear in the local symbol table to define the file's scope. This representation is shown in Figure 11-5. Note that file symbols appear in the local symbol table only.

Figure 11-5:  File Representation

11.3.1.4    Block Scope

In general, the local symbol table denotes scoping levels with stBlock and stEnd pairs, as shown in Figure 11-6.

All symbols contained between these two entries belong to the scope they describe. Nested blocks are possible, and stEnd symbols match the most recent occurrences of stBlock (or other opening symbol entries such as stProc or stTag).

Figure 11-6:  Block Representation

Block scopes occur in many languages. In C, they take the form of lexical blocks. In C++, declarations can occur anywhere in the code. In Pascal and Ada, nested procedures are possible, with local variables at any or all levels.

11.3.1.5    Namespaces (C++)


Version Note

Namespaces are supported in symbol table format V3.13 and greater.


A C++ namespace is a mechanism that allows the partitioning of the program global name space. This partitioning is intended to reduce name clashing and provide greater program manageability to C++ developers.

Figure 11-7:  C++ Namespace Representation

A namespace definition may exist only at the global scope or within another namespace. The namespace representation in Figure 11-7 shows a single contribution to a namespace. This representation may be replicated many times in the symbol table for a single namespace. A namespace definition may be continued within the same file or over multiple source files.

A single namespace contribution that spans multiple source files is represented as if it were contained entirely within the source file in which it began.

Namespaces may be aliased, allowing a single namespace to be referred to by multiple names. Namespace components may also be referenced without their namespace qualification if they are included within a scope by a using directive or using declaration. The representations of namespace aliases, using directives, and using declarations are shown in Figure 11-7. Namespace definitions, namespace component declarations, namespace aliases, using directives, and using declarations occur only in the local symbol table. Namespace component definitions may occur in the local or external symbol table.

11.3.1.5.1    Namespace Components

The components of a namespace are represented in two parts: declarations and definitions. Namespace components that do not require definition must be declared in the namespace definition. Namespace components that are referenced by a using declaration must be declared in the namespace definition. All other namespace component declarations may be omitted from the namespace definition.

Namespace component names are mangled only as needed. Function and data definitions have mangled name definitions in the local or external symbol table. These entries are mangled for type-safe linkage and as a method of matching components with the namespaces to which they belong. Names of component declarations within a namespace definition may or may not be mangled. They are not required to include the namespace name in their mangled form.

Empty namespace contributions can be omitted, but at least one instance of a namespace definition must occur somewhere in the local symbol table. This definition is required because name mangling rules do not distinguish namespace component definitions from class member definitions.

11.3.1.5.2    Namespace Aliases

Namespace aliases can occur in namespace, file, procedure, or block scope in the local symbol table. The index value for the stAlias entry is an auxiliary table index. The auxiliary entry is a RNDXR record containing the local symbol table index of the stNamespace symbol in the first instance of a namespace definition within a compilation unit. For an alias of an alias, the RNDXR record can also contain the index of another stAlias symbol in the local symbol table. Section 17.2.5 provides an example of a namespace alias.

The stAlias symbol type may be used in future versions of the symbol table format as a general purpose symbol alias representation. The semantic interpretation of the stAlias symbol depends on the type of the symbol it aliases.

11.3.1.5.3    Unnamed Namespace

An unnamed namespace can be declared at the global scope or within another namespace. An unnamed namespace is unique within a compilation unit. Multiple contributions to a unique unnamed namespace are not allowed. Unnamed namespace contributions are included in the non-mergeable portion of a C++ header file.

Unnamed namespace components are subject to the same rules as named namespaces for declarations and definitions.

The stNamespace symbol for an unnamed namespace has a compiler generated name starting with __N1. This same name is used to identify the unnamed namespace in the mangled names of components of that namespace. (See the unnamed namespace example in Section 17.2.4.)

11.3.1.5.4    Usage of Namespaces

A C++ using directive or a using declaration is represented by a symbol of type stUsing. It may occur in any scope in the local symbol table. The index value for the stUsing entry is an auxiliary table index. If the stUsing entry represents a using declaration for a single namespace component, the auxiliary entry is a RNDXR record containing the local symbol table index of a namespace component declaration. If the stUsing entry represents a using directive, its RNDXR auxiliary contains the local symbol table index of the stNamespace symbol in the first definition of that namespace in the compilation unit.

A using directive for a namespace alias is represented with a RNDXR auxiliary that directly references the aliased namespace. This representation contains no record of the alias referenced by the using directive.

A using directive for a global symbol is represented with a RNDXR auxiliary that references a local symbol table stExternal/ scInfo entry with a name matching the global symbol as it is recorded in the external symbol table.


Version Note

Using directives for global symbols are supported in Tru64 UNIX V5.1B and greater.


Names are not required for stUsing entries, but they can be set to match the namespace or namespace component to which they refer.

Namespace components that are referenced by an stUsing symbol must be declared in the namespace definition.

Section 17.2.3 provides an example of namespace definitions and uses.

11.3.1.6    Fortran Modules


Version Note

Fortran modules are supported in symbol table format V3.14 and greater.


A Fortran 90 module provides a way of grouping symbol names and controlling naming conflicts. The definition of a Fortran 90 module is very similar to the definition of a C++ namespace, but the uses of these two constructs are very different. See Section 11.3.1.5 for a description of C++ namespaces.

The compilation of a Fortran 90 module unit will result in a complete local symbol table for the module. The module will be represented as shown in Figure 11-8 using the stModule and stEnd symbols to delimit the start and end of the module. Declarations within the module are represented in the normal manner. The stModule symbol type shares the same value as the stNamespace symbol type. The lang field in the containing file descriptor determines which interpretation is valid.

Figure 11-8:  Fortran 90 Module Representation

External symbol table entries for declarations contained in modules use a simple form of name mangling. As illustrated in Section 17.3.4, the external name is constructed by converting names to lower case and assembling them as:

     $module$symbol_

Modules can contain interface declarations and contained procedure definitions. Contained procedures are defined inside the module. They are represented the same as any other procedure in Fortran. Procedure definitions are described in Section 11.3.1.2. Interface declarations identify procedures that can be accessed as members of the module, but they are defined outside of the module context. The representation of an interface declaration is illustrated in Figure 11-9. Examples of contained procedures and interface declarations can be found in Section 17.3.5 and Section 17.3.6, respectively.

Figure 11-9:  Fortran 90 Module with Interface Declaration

11.3.1.6.1    Modules with Use Statements

The Fortran 90 USE statement imports symbols from a module defined in a separate compilation unit. Variations of the statement allow importing all of a module's symbols or only those that are specified. The USE statement also allows imported symbols to be renamed in the local context.

Figure 11-10 shows the representation of a USE statement that imports all symbols from a module without renaming any of them. Note that the stUseModule symbol index field is isymNil and the value field is USE_MODULE_ALL.

Figure 11-10:  Fortran 90 Module USE (ALL) Representation

Module names must be unique across all compilation units, so debuggers can resolve the stUseModule entry by searching all compilation units for the definition of a module with the same name. A debugger cannot resolve all module uses by searching the external symbol table. It must access the definition of the exporting module to resolve symbols that it imports from other modules. The example in Section 17.3.4 illustrates the Fortran 90 USE statement used in a module definition to import symbols from another module.

Figure 11-11 shows the representation of a USE statement that imports all symbols from a module renaming some of them. Note that the stUseModule symbol index field is the index of the local symbol table entry following the corresponding stEnd symbol and the value field is USE_MODULE_ALL. Specific symbols are renamed with stRename entries. For these entries the iss field is the local string table index of the symbol name in the local context. The value field is the local string table index for the symbol name as it is appears in the module definition.

Figure 11-11:  Fortran 90 Module USE with Renaming

Figure 11-12 shows the representation of a USE statement that imports selected symbols from a module. Note that the stUseModule symbol index field is the index of the local symbol table entry following the corresponding stEnd symbol and the value field is USE_MODULE_ONLY. Specific symbols are imported with stRename entries. If a symbol is renamed its stRename iss field is the local string table index of the symbol's name in the local context. Otherwise, both the iss and value fields contain the same local string table index for the symbol name as it is appears in the module definition.

Figure 11-12:  Fortran 90 Module USE (ONLY) Representation

11.3.1.6.2    Fortran Generic Interfaces

The Fortran 90 INTERFACE statement can be used to create a single generic interface name for a set of procedure names that are distinguished by parameter types. The representation of generic interfaces is illustrated in Figure 11-13 and an example is shown in Section 17.3.7.

Figure 11-13:  Fortran 90 Generic Interface Representation

11.3.1.7    Exception Handling Blocks (C++)

In C++, a special scoping mechanism is introduced to expand user-defined exception-handling capabilities. Exception handlers are defined to "catch" exceptions that are "thrown" by other functions. The symbol table must contain sufficient information to recognize the scope of a handler. The compiler generates special symbols to identify where exception handlers are valid.

Figure 11-14:  C++ Exception Handler Representation

11.3.1.8    Fortran Common Blocks

Fortran common blocks constitute another scoping level. Fortran uses common blocks as a way of specifying data that is global or shared between program units. A common block is global storage that can be named, allocated, accessed, and used by various subroutines. The block can be named or unnamed; unnamed blocks are known as "blank commons". Internal to the symbol table, blank commons are named _BLNK__.

Figure 11-15 shows the symbolic representation of Fortran common blocks.

Figure 11-15:  Fortran Common Block Representation

Because a Fortran common is represented as a synthesized file, it also has an entry in the file descriptor table. Furthermore, a global symbol with the same name is also present in the external symbol table.

An example of a Fortran common block can be found in Section 17.3.1.

11.3.1.9    Alternate Entry Points

Fortran also has a facility for creating alternate entry points in procedures. An alternate entry point is represented using an stProc/ scText symbol. In the procedure descriptor table, an alternate entry point is identified by a lnHigh field with a value of -1. Procedure descriptors for alternate entry points follow the procedure descriptor for the primary entry point. In the local symbol table, an alternate entry point has an entry inside the scope of the procedure's primary entry.

The representation of a procedure with an alternate entry point is shown in Figure 11-16


Version Note

The stBlock symbol that follows the alternate entry's stProc symbol in Figure 11-16 is supported in symbol table format V3.13 and greater. In symbol table formats less than V3.13 alternate entries do not have a start block symbol, and their prologue size is unknown.


Figure 11-16:  Alternate Entry Point Representation

An example of Fortran alternate entries can be found in Section 17.3.2.

11.3.2    Data Types in the Symbol Table

A data element's type dictates its size and interpretation in a programming environment. One of the symbol table's most important tasks is to represent data types in a compact and complete manner.

Type information is stored in the local and auxiliary symbol tables. This section provides guidelines for understanding the type information plus specific examples for depicting a range of types.

11.3.2.1    Basic Types

All programming languages have a set of simple types that are built into the language and from which other data types can be derived. Examples of simple types are integer, character, and floating point. Languages also provide constructs for creating user-defined types based on the simple types. For example, a C++ class can be built using any simple type or previously defined user-defined type and the language facility for declaring classes.

Similarly, a basic type in the symbol table is a building block from which each language constructs its type information. Basic type (bt) values directly represent many of the simple types for supported languages; for instance, the value btChar indicates a character. Other bt values represent language constructs for building aggregate types; a value of btStruct may be used, for example, to represent a C structure or Pascal record.

The symbol table uses approximately forty basic type values. The interpretation of some of these values is language dependent. See Table 11-4 for a list of all values.

11.3.2.2    Type Qualifiers

Type qualifiers can be applied to basic types to create other data types. Examples are "pointer to", "array of", and "function returning". Generally the number and order of type qualifiers is unrestricted.

See Table 11-5 for a list of type qualifiers and their meanings.

11.3.2.3    Interpreting Type Descriptions in the Auxiliary Table

This section explains in detail the encoding of type descriptions in the symbol table. To fully describe the type of a symbol, the auxiliary symbol table must be created and referenced. Compilation with full symbolic information (-g option on system compilers) results in the creation of this table.

To correctly decode the type information, proceed sequentially, beginning with the symbol table entry. Several fields may be required from other symbol table structures:

The first step is to determine whether the symbol contains an index of an auxiliary table description.

Table 11-7:  Symbols with Auxiliary Type Descriptions

Symbol Type Storage Class Conditions AUXU Index Field
stGlobal Any None index
stStatic Any None index
stParam Any None index
stLocal Any Local symbol table index
stProc Any Local symbol table index
stBlock scInfo Inside an scVariant block value
stMember scInfo None index
stTypedef scInfo None index
stStaticProc Any Local symbol table index
stConstant Any None index
stBase scInfo None index
stVirtBase scInfo None index
stTag scInfo None index
stInter scInfo None index
stNamespace scInfo None index
stUsing scInfo None index
stAlias scInfo None index
stExternal scInfo None index

If the index does represent a record in the auxiliary symbol table, the interpretation of the first auxiliary entry (AUXU) depends on the type of the symbol:

The next task is to examine the contents of the TIR. The TIR contains constants representing the basic type of the symbol and up to six type qualifiers, labeled tq0-tq5. If a type has more than one qualifier, they are ordered from lowest to highest. Lower qualifiers are applied to the basic type before higher qualifiers. All unused tq fields are set to tqNil, and no tqNil fields are present before or between other type qualifiers.

In addition to the basic type and type qualifiers, the TIR contains two flags: an fBitfield flag to mark whether the size of the type is explicitly recorded, and a continued flag to indicate that the type description is continued in another TIR. If fBitfield is set, the TIR is immediately followed by a width entry. If more than six type qualifiers are required for the current definition, the description is continued, and the continued flag is set. If exactly six type qualifiers are needed, all six fields are used and the continued flag is cleared.

To illustrate, consider the type "array of pointers to integers". The basic type is "integer" and has two qualifiers, "array of" and "pointer to". Each element of the array is a "pointer to integer". Therefore, the qualifier "pointer to" must be applied first to the basic type "integer". In this example, the qualifier "pointer to" is lower than the qualifier "array of". The contents of the TIR are as follows:

        bt: btInt
        tq0: tqPtr
        tq1: tqArray
        tq2: tqNil
        tq3: tqNil
        tq4: tqNil
        tq5: tqNil
        continued: 0
        fBitfield: 0

The contents of the TIR dictate how to interpret any subsequent records. The records appear in a prescribed order:

For a type description containing more than one TIR, the fields of all TIR records are interpreted in the same way. When a TIR is reached with the flag cleared and any records associated with that TIR have been decoded, the type description is complete.

As an example, consider an array of structures with the fBitfield flag set. A total of seven auxiliary records can be used to describe the type:

  1. The TIR with a basic type of btStruct and with tq0 set to tqArray.

  2. A width record. The size of the basic type.

  3. A RNDXR record. A pointer to the structure definition in the local symbol table.

  4. A RNDXR record. A pointer to the array index type description elsewhere in the auxiliary table.

  5. A dnlow record. The lower bound of the array's range.

  6. A dnhigh record. The upper bound of the array's range.

  7. A width record. The distance in bits between each element in the array.

If the continued flag of the TIR is cleared, the width record corresponding to the array qualifier is the final AUXU for this type description.

For another view of this process, see Figure 11-17. Each box represents one auxiliary entry belonging to the symbol's type description. Using the flowchart, an ordered list of entries can be assembled.

Figure 11-17:  Auxiliary Table Interpretation

Figure 11-18:  Auxiliary Table "ti" Interpretation

Figure 11-19:  Auxiliary Table "arrays" Interpretation

Figure 11-20:  Auxiliary Table "bt vals" Interpretation

Figure 11-21:  Auxiliary Table Range Interpretation

Figure 11-22:  Auxiliary Table RNDXR Interpretation

The final step is to decode the RNDXR records. The basic types that are followed by RNDXR records require reference to another local or auxiliary symbol to complete the type description. Interpret the RNDXR records as follows:

Additionally, the index of every RNDXR used as a pointer must be mapped through the relative file descriptor table (see Section 6.3.2), if the table exists. The rfd field of the record controls this mapping. The following algorithm can be used to locate the symbol referenced by the relative index record:

if (RNDXR.rfd == ST_RFDESCAPE)
    RFD = (++AUXU).isym
else 
    RFD = RNDXR.rfd 
if (HDRR.crfd) /* RFD table exists */
    IFD = (current FDR's RFD table)[RFD]
else
    IFD = RFD
 
if (SYMR needed)
    SYMBASE = FDR[IFD].isymBase
    SYMR = SYMBASE[RNDXR.index]
else if (AUXU needed)
    AUXBASE = FDR[IFD].iauxBase
    AUXU = AUXBASE[RNDXR.index]

11.3.3    Individual Type Representations

This section provides sketches of type representations in the local and auxiliary symbol tables. The connections between the two tables is depicted for each type. This form of representation is only possible when full symbolic information is present.

Note that external symbols as well as local symbols reference the auxiliary table, although the examples in this chapter use local symbols only.

11.3.3.1    Pointer Type

A pointer is a variable containing the address of another variable. A pointer is represented by a tqPtr type qualifier modifying another type. A pointer is represented by a single symbol with an entry in the auxiliary table, as shown in Figure 11-23.

Note that if the pointer referenced a user-defined type, such as a class or structure, the TIR would be followed by an RNDXR (and possibly an isym).

Figure 11-23:  Pointer Representation

The combination of type qualifiers tqFar and tqPtr are used to represent a short (32-bit) pointer. This pointer type is used with the XTASO emulation.

11.3.3.2    Array Type

An array is a list of elements that all have the same type. Arrays may be fixed size and allocated at compile time or dynamically sized and allocated at run time. This section describes the fixed-size array symbol table representation. For information on Fortran dynamic arrays, see Section 11.3.3.9. For conformant arrays in Pascal and Ada, see Section 11.3.3.10.

An array is represented by a tqArray or tqArray_64 type qualifier applied to another type. This second type describes the type of all elements in the array. In the local or external symbol table, a single entry represents an array. Figure 11-24 shows the symbol table description for an array.

Figure 11-24:  Array Representation

Note that for an array of elements of a user-defined type, such as a class or structure, another RNDXR (and possibly an isym) would be inserted between the TIR and the RNDXR describing the subscript type.

If an array has multiple dimensions, the symbols describing the dimension appear in the order of innermost to outermost. For example, the following declaration produces a TIR with the tqArray qualifier followed by the RNDXR and range description for 0-1 followed by the entries for the dimension 0-99:

float floattable[100][2]

Some arrays may have dimensions too large to represent in the 32-bit format shown in Figure 11-24. Such arrays are represented using a 64-bit format in which two auxiliary entries are used for the dimension bounds and size. Figure 11-25 illustrates the 64-bit representation.


Version Note

The 64-bit representation of arrays is supported in symbol table format V3.13 and greater.


Figure 11-25:  64-Bit Array Representation

11.3.3.3    Structure, Union, and Enumerated Types

This section applies to data structures in languages other than C++. For the C++ structure, union, or enumerated type representation, see Section 11.3.3.6.

Structures, unions, and enumerated types have a common representation. All three are identified using "tags" and contain zero or more fields. In the symbol table, the tag is the name associated with the starting stBlock symbol for the structure's set of local symbols. Note that it may be empty because the tag is optional. Symbols for fields follow. The definition is completed by a block-end symbol matching the block-start symbol.

Figure 11-26 contains a graphical depiction of this set of symbols.

Figure 11-26:  Structure Representation

The structure members have auxiliary table indices pointing to their type descriptions.

Untagged structures and unions are represented with a NULL tag name. Unnamed structures can be embedded in other structures and are represented as a NULL-named member of the outer structure. See Section 17.1.1 for an example of an unnamed structure.


Version Note

Unnamed member structures are supported in symbol table format V3.13 and greater. As of Tru64 UNIX V5.1 dbx will display structures with unnamed member structures, but neither dbx nor ladebug provide specific access to members of unnamed member structures.


A structure can contain a field that is a pointer to itself. This field is represented by an stMember symbol with an auxiliary table entry that references the beginning of the structure's block of local symbols, as shown in Figure 11-27.

Figure 11-27:  Recursive Structure Representation

When a field within a structure is itself a structure, the compiler may choose to generate the structure definitions either sequentially or embedded, as shown in Figure 11-28.

Figure 11-28:  Nested Structure Representation

The following declaration might result in the nested structure representation:

struct line { 
        struct point { 
            float x, y;
        }  p1, p2;
};

11.3.3.4    Typedef Type

Most languages allow programmers to choose alternate names, or aliases, for data types. The alias created by such a facility (such as C's typedef) is represented as a single local symbol entry that has a pointer to its type description in the auxiliary table. The auxiliary entry contains a pointer to the definition of the type name, as shown in Figure 11-29.

Figure 11-29:  Typedef Representation

11.3.3.5    Function Pointer Type


Version Note

The following function pointer representation is the preferred representation for symbol table format V3.13 and greater.


Languages such as C and C++, which allow pointers to functions, represent the type of the function pointer using a special stProc/ scInfo block describing the parameters and return value for the function as shown in Figure 11-30.

Figure 11-30:  Function Pointer Representation

The stProc/ scInfo entry has its value set to -2, which distinguishes it from similar entries used to represent procedures with no text and C++ member functions. The stProc/ scInfo and stEnd/ scInfo entries have null names in the function pointer representation. The parameters are optional and may or may not be named.


Version Note

For symbol table formats less than V3.13 the preceding representation for function pointers is not supported, and the following alternate representation is used exclusively.


An alternate representation of function pointers is shown in Figure 11-31. This representation describes the return type of the function pointer but not its parameters, and it is valid for all symbol table format versions. The combination of type qualifiers tqPtr and tqProc is interpreted as "pointer to function returning". The function return type may be the base type (bt) in the TIR or it may be constructed from the base type augmented by additional type qualifiers.

Figure 11-31:  Function Pointer Alternate Representation

11.3.3.6    Class Type (C++)

A C++ class resembles an extended C structure. One major distinction is that class fields (referred to as "members") can be functions as well as variables. The set of symbols created for a class is organized as follows:

Another characteristic of classes is that symbols are defined implicitly. For example, all classes have an operator= operator-overloading function included in the class definition and a this pointer to its own type as a parameter to all member functions. These symbols are always included explicitly in the symbol table description.

Figure 11-32 is a graphical representation of the set of symbols for a class.

Figure 11-32:  Class Representation

Class members, including member functions, have auxiliary references that point to their type descriptions. Note that member functions are represented as prototypes. The set of symbols defining the member function is elsewhere in the symbol table. To locate the definition of a member function, a name lookup can be performed using the mangled name of the member function with its class name qualifier. See Section 13.3.3 for information on name mangling.

C++ structures, unions, and enumerated types are represented the same way as classes. The different data structures are distinguished by basic type value.

The symbol table does not represent class member access attributes.

Examples of base and derived classes can be found in Section 17.2.1.

11.3.3.6.1    Empty Class or Structure (C++)

The representation of an empty class in C++ is shown in Figure 11-33. Empty structures in C++ are represented in a similar manner with the TIR.bt set to btStruct.

Figure 11-33:  Empty Class or Structure (C++)


Version Note

This empty class or structure representation is supported in Tru64 UNIX V5.1. Prior to Tru64 UNIX V5.1, the default compilers did not distinguish empty classes and structures from opaque classes and structures. See Section 11.3.3.6.2 for more details.


11.3.3.6.2    Opaque Class or Structure (C++)

Opaque classes and structures are incomplete types. They have no member information, and they are distinguished from empty classes and structures that have no members. The representation of an opaque class in C++ is shown in Figure 11-34. Opaque structures in C++ are represented in a similar manner with TIR.bt set to btStruct.

Figure 11-34:  Opaque Class or Structure (C++)


Version Note

Prior to Tru64 UNIX V5.1 the default compilers used the preceding representation for empty classes and structures as well as opaque classes and structures.


11.3.3.6.3    Base and Derived Classes (C++)

Hierarchical groups of classes can be designed in C++. A base class serves as a wider classification for its derived classes, and a derived class has all of the members and methods of the base class, plus additional members of its own. In the symbol table, the set of symbols denoting a derived class is nearly identical to that for a non-derived class. The derived class includes an additional stBase or stVirtBase symbol that identifies its corresponding base class, and it does not need to duplicate the definitions for the base class members. This representation is shown in Figure 11-35.

Figure 11-35:  Base Class Representation

The representation of virtual base classes for C++ relies on the definition of a special symbol that identifies the virtual base table. The name for this symbol is derived from the name of the class to which it belongs. For example, the virtual base table symbol for class C5 would be named "_btbl_2C5". This table contains entries for base class run-time descriptions.

A class can include the special member _bptr. This class member is a pointer to the virtual base table for that class.

The value field for a virtual base class symbol ( stVirtBase/ scInfo) serves as an index (starting at 1) into the virtual base class table.

11.3.3.7    Template Type (C++)

Templates are a C++-specific language construct allowing the parameterization of types. C++ class templates are represented in the symbol table for each instantiation, but not for the template itself. The set of class symbols is unchanged from the set shown in Figure 11-32.

11.3.3.8    Interlude Type (C++)

Interludes are compiler generated functions in C++. They are represented in the local symbol table with special names starting with the "__INTER__" prefix. Their representation in the symbol table makes use of two RNDXR aux entries to identify the related member function and the actual interlude function, both of which are local symbol table entries.

Figure 11-36:  Interlude Representation

11.3.3.9    Array Descriptor Type (Fortran90)

A Fortran90 array descriptor is a structure that describes an array: its location, dimensions, bounds, sizes, and other attributes. Array descriptors are described in detail in the Fortran 90 User Manual for Tru64 UNIX. Fortran90 includes several types of arrays for which the dimensions or dimension bounds are determined at run time: allocatable arrays, assumed shape arrays, and array pointers.

Two symbol table representations have been used for array descriptors. The current representation describes the array descriptor itself. The retired representation described attributes of the array known at compile time.

For both representations, symbols of this type point to a data location at which the array descriptor is allocated. One of the array descriptor fields contains a pointer to the actual array. Other fields are used to describe the attributes of the array. Fields that describe the number of dimensions and upper and lower bounds are filled in at run time.

By default, array descriptors are described by a structure tag representation. Most of the array descriptor fields are represented as structure members. (Excluded fields are not needed by debuggers.) Special tag names are used to identify array descriptor structure definitions: $f90$f90_array_desc (assumed-shape array), $f90$f90_ptr_desc (pointer to array) and $f90$f90_alloc_desc (allocatable array). Figure 11-37 shows the format of this representation.

Some compilers may emit other fields in addition to those shown in Figure 11-37. A consumer's ability to interpret additional fields depends on its knowledge of the producing compiler.

Figure 11-37:  Array Descriptor Representation

An example of the default Fortran array descriptor representation can be found in Section 17.3.3.


Version Note

The following representation of Fortan array descriptors is supported in symbol table formats less than V3.13. It is not supported in symbol table format V3.13 and greater.


This retired representation of Fortran array descriptors is substantially more compact in the local symbol table, but it provides no way to distinguish between the different array descriptor types.

The overloaded basic type value 28 indicates an array descriptor in the TIR, and dimension bounds are set to [1:1] indicating their true size is unknown. The alternate representation does not provide any information describing the contents of the array descriptor itself, so debuggers must assume a static representation for the descriptor and lookup the fields at their expected offsets.

Figure 11-38 shows this representation of array descriptors.

Figure 11-38:  Array Descriptor Representation (retired)

11.3.3.10    Conformant Array Type (Pascal)

Full details are not currently available for Pascal's conformant array representation. A Pascal conformant array is very similar to Fortran's assumed shape arrays. It is an array parameter with upper and lower dimension bounds that are determined by the input argument. A conformant array is represented by an array descriptor. The special names used and the format of the array descriptor differ from those used for Fortran. The DEC Pascal release notes contain additional information on conformant arrays.

11.3.3.11    Variant Record Type (Pascal and Ada)

A variant record is an extension to the record data type, which is a Pascal or Ada data structure akin to a C structure and is represented in the same manner in the symbol table. The variant part of the record consists of sets of one or more fields associated with a range of values. Only one such set is part of the record, and it is selected based on the value of another record field. Any number of variant parts can be embedded in a single record.


Version Note

The following variant record representation is for symbol table format V3.13 and greater.


The local symbol table entries for the variant part of a record are contained within a block with the storage class (sc value) scVariant. The value field of the stBlock entry contains the index of the local symbol entry for the member of the record whose value determines which variant arm is used. The variant block contains multiple inner blocks, each representing a variant arm. The value field of each of these block entries is an auxiliary table index. Each auxiliary table entry starts with a count, which indicates how many range entries follow. The range entries describe the values associated with the block.

Figure 11-39 is a graphical representation of a variant record.

Figure 11-39:  Variant Record Representation


Version Note

The following variant record representation is for symbol table formats less than V3.13. It is not supported in symbol table format V3.13 and greater.


The representation of variant records depicted in Figure 11-40 does not include TIR auxiliaries.

Figure 11-40:  Variant Record Representation (retired)

An example of a Pascal variant record can be found in Section 17.4.3.

11.3.3.12    Subrange Type (Pascal and Ada)

A subrange data type defines a subset of the values associated with a particular ordinal type (the "base type" of the subrange). Ordinal types in Pascal include integers, characters, and enumerated types. The symbol table representation of a subrange uses the btRange or btRange_64 type followed by an auxiliary index identifying the base type and entries providing the bounds of the subrange. The 32-bit representation is shown in Figure 11-41 and the 64-bit representation is shown in Figure 11-42.

Figure 11-41:  Subrange Representation

Figure 11-42:  64-bit Range Representation


Version Note

The 64-bit range representation is supported in symbol table format V3.13 and greater.


An example of a Pascal subrange can be found in Section 17.4.2.

11.3.3.13    Set Type (Pascal)

A set is a data type that groups ordinal elements in an unordered list. The arithmetic and logical operators are overloaded in Pascal; this enables them to be used with set variables to perform classic set operations such as union and intersection. A special auxiliary type definition btSet exists to identify this type. The symbol table representation is depicted in Figure 11-43.

Figure 11-43:  Set Representation

The element type for a set is typically a range or an enumeration. An example of a Pascal set can be found in Section 17.4.1.

11.3.4    Special Debug Symbols

A variety of special symbols are used throughout the symbol table to convey call frame information, special type semantics, or other language specific information. These names are reserved for use by compilers and other tools that produce Tru64 UNIX object files.

Table 11-8:  Special Debug Symbols

Name Purpose
Name Purpose
__StaticLink.* (SV3.13 - ) Uplevel link. See Section 8.3.4.
_BLNK__ Fortran unnamed common block. See Section 11.3.1.8.
MAIN__ Fortran alias for main program unit. See Section 13.3.4.
ARGNAME.len Generated parameter for Fortran routines. It contains the length of ARGNAME, a parameter of character type.

.lb_<ARRAY>.<dim>
.ub_<ARRAY>.<dim>

Lower and upper bounds of particular dimensions of arrays - when the array has an explicit shape, yet some bounds come from non-constant specification expressions (array arguments in Pascal and Fortran routines).

$f90$f90_array_desc
$f90$f90_alloc_desc
$f90$f90_ptr_desc

Variants of Fortran-90 described arrays (assumed shape, ALLOCATABLE, and POINTER, respectively). See Section 11.3.3.9.
cray pointee Fortran-generated typedef describing the type of a variable pointed to by a CRAY pointer.
pointer Fortran generated typedef describing the type of a scalar with the POINTER attribute.
_DECCXX_generated_name_* DECC++ compiler-inserted name for unnamed classes and enumerations.
this Hidden parameter in C++ member functions that is a pointer to the current instance of the class. See Section 11.3.3.6.
__vptr Hidden C++ class member containing the virtual function table. See example in Section 17.2.2.
__bptr Hidden C++ class member containing the virtual base class table. See example in Section 17.2.2.
__vtbl_* Global symbols for C++ virtual function tables. See example in Section 17.2.2.
__btbl_* Global symbols for C++ virtual base class tables. See example in Section 17.2.2.
__control Hidden argument to C++ constructors controlling descent (in the face of virtual base classes).
__t*__evdf Structure used to maintain a list of C++ global deconstructors.
t*__iviw C++ static procedure used for global constructors.
t*__evdw C++ static procedure used for global destructors.
__t*_thunk C++ static procedure used to provide a defaulted argument value.
__INTER__* C++ interlude. See example in Section 17.2.2.
__N1* C++ unnamed namespaces. See example in Section 17.2.4.

11.4    Language-Specific Symbol Information Features

Language-specific characteristics are pervasive in the symbol table, particularly in the local, external, and auxiliary symbol tables. See Section 6.2 and Section 11.3.2 for information on language-specific values.

The lang field of the file descriptor entry encodes the source language of the file. This field should be accessed prior to decoding symbolic information, especially type descriptions. This section highlights, by language, language-specific features represented in the symbol table. Additional information on certain features is available elsewhere in this chapter.

11.4.1    Fortran77 and Fortran90

In Fortran, it is possible to create multiple entry points in subroutines. A subroutine has one main entry point and zero or more alternate entry points, indicated by ENTRY statements. See Section 11.3.1.9 for their representation in the symbol table.

Fortran90 array descriptors include allocatable arrays, assumed-shape arrays, and pointers to arrays. Their representation in the symbol table is discussed in Section 11.3.3.9.

Modules provide another scoping level in Fortran90 programs. Their symbol table representation is described in Section 11.3.1.6.

11.4.2    C++

C++ classes encapsulate functions and data inside a single structure. Classes are represented in the symbol table using a btClass basic type and the stBlock/ stEnd scoping mechanism. See Section 11.3.3.6.

Templates provide for parameterized types. At present, no special symbol table values are related to templates. The template itself is not represented; rather, entries that correspond to each instantiation are generated. Template instantiations are distinguished by mangled names based on their type signatures.

C++ namespaces, like Fortran modules, offer an additional scope for program identifiers.

The C++ concepts of private, protected, and public data attributes are not currently represented in the symbol table. The C++ concept of "friend" classes and functions are also not represented.

11.4.3    Pascal and Ada

Pascal conformant arrays are function parameters with array dimensions that are determined by the arguments passed to the function at run time. See Section 11.3.3.10.

Variant records are an extension of the record data structure. Variant records allow different sets of fields depending on the value of a particular record member. See Section 11.3.3.11.

Nested procedures are supported in these languages. They are represented using standard scoping mechanisms discussed in Section 11.3.1 and uplevel references described in Section 8.3.4.

Sets and subranges are user-defined subsets of ordinal types. Sets are unordered groups of elements, which can be manipulated with the classic set operations. Subranges are ordered and are used with the usual operators. See Section 11.3.3.12 and Section 11.3.3.13.

Ada subtypes of ordinal types are represented in the same manner as Pascal subranges.