This chapter describes the symbol table and the routines used to create and make entries in the table. The chapter addresses the following major topics:
The symbol table is created by the compiler front-end as a stand-alone file. The purpose of the table is to provide information that the linker and the debugger need to perform their respective functions. At the option of the user, the linker includes information from the symbol table in the final object file for use by the debugger. (See Figure 7-1 for details about object file format.)
The elements (subtables) contained by the symbol table are shown in Figure 8-1.
The compiler front-end creates one group of subtables that contain global information relative to the entire compilation. It also creates a unique group of subtables for the source file and each of its include files. (Figure 8-1 uses shading to differentiate the two types of subtables: compilation-wide subtables are shaded and file-specific subtables are unshaded.)
Compiler front-ends, the assembler, and the linker interact with the symbol table in the following ways:
The symbol table elements shown in Figure 8-1 are summarized in the paragraphs that follow. Some of the major elements are described in more detail later in the chapter.
ifd
)
and an index
(isym
)
into the local symbol table. The table facilitates symbol look-up
for the assembler, optimizer, and code generator by allowing direct
table access to be used instead of hashing.
A unique local symbol table exists for every source and include file; the compiler locates the table through an offset from the file descriptor entry that exists for every file. The entries in the local symbol table can reference related information in the local string table and auxiliary symbol table. This relationship is shown in Figure 8-3. (See Section 8.2.4 for additional information on the local symbol table.)
-g
compilation options) is in effect.
(See
Section 8.2.5
for additional information on the auxiliary symbol table.)
The file descriptor entry allows the compiler to access a group of subtables unique to one file. The logical relationship between entries in the file descriptor table and its subtables is shown in Figure 8-5.
The symbol table is comprised of several subtables. The symbolic header acts as a directory for the subtables; it provides the locations of the subtables and gives their sizes.
The following sections describe the symbolic header and the subtables.
The structure of the symbolic header is shown in
Table 8-1.
The header file
sym.h
contains the header declaration.
Declaration | Name | Description |
short
|
magic
|
To verify validity of the table |
short
|
vstamp
|
Version stamp |
int
|
ilineMax
|
Number of line number entries |
int
|
idnMax
|
Maximum index into dense numbers |
int
|
ipdMax
|
Number of procedures |
int
|
isymMax
|
Number of local symbols |
int
|
ioptMax
|
Maximum index into optimization entries |
int
|
iauxMax
|
Number of auxiliary symbols |
int
|
issMax
|
Maximum index into local strings |
int
|
issExtMax
|
Maximum index into external strings |
int
|
ifdMax
|
Number of file descriptors |
int
|
crfd
|
Number of relative file descriptors |
int
|
iextMax
|
Maximum index into external symbols |
long
|
cbLine
|
Number of bytes for line number entries |
long
|
cbLineOffset
|
Index to start of line numbers |
long
|
cbDnOffset
|
Index to start dense numbers |
long
|
cbPdOffset
|
Index to procedure descriptors |
long
|
cbSymOffset
|
Index to start of local symbols |
long
|
cbOptOffset
|
Index to start of optimization entries |
long
|
cbAuxOffset
|
Index to the start of auxiliary symbols |
long
|
cbSsOffset
|
Index to start of local strings |
long
|
cbSsExtOffset
|
Index to the start of external strings |
long
|
cbFdOffset
|
Index to file descriptor |
long
|
cbRfdOffset
|
Index to relative file descriptors |
|
|
|
long
|
cbExtOffset
|
Index to the start of external symbols |
The lower byte of the
vstamp
field contains
LS_STAMP
and the upper byte contains
MS_STAMP
(see the header file
stamp.h
).
These values are defined in the
stamp.h
file.
The
iMax
fields and the
cbOffset
fields must be set to zero if one of the tables shown in
Table 8-1
is not present.
The
magic
field must contain the constant
magicSym
,
which is also defined in
symconst.h
.
Table 8-2
shows the format of an entry in the line number table; the header file
sym.h
contains its declaration.
Declaration | Name |
int
|
LINER
|
int *
|
pLINER
|
The line number section in the symbol table is rounded to the nearest 4-byte boundary.
Line numbers map executable instructions to source lines; one line number is stored for each instruction associated with a source line. Line numbers are stored as integers in memory and in packed format on disk. Figure 8-6 shows the layout of a line number entry on disk.
The compiler assigns a line number only to those lines of source code that generate executable instructions.
The uses of the delta and count fields are as follows:
lnLow
field in the procedure descriptor table.
An extended format of the line number entry is used when the delta value is outside the range -7 to 7. Figure 8-7 shows the layout of an extended line number entry on disk.
Note
Between two source lines that produce executable code, the compiler allows a maximum of 32,767 comment lines, blank lines, continuation lines, and other lines not producing executable instructions.
The following source listing can be used to show how the compiler assigns line numbers:
1 #include <stdio.h> 2 main() 3 { 4 char c; 5 6 printf("this program just prints input\n"); 7 for (;;) { 8 if ((c =fgetc(stdin)) != EOF) break; 9 /* this is a greater than 7-line comment 10 * 1 11 * 2 12 * 3 13 * 4 14 * 5 15 * 6 16 * 7 17 */ 18 printf("%c", c); 19 } /* end for */ 20 } /* end main */
The compiler generates line numbers only for the lines 3, 6, 8, 18, and 20; the other lines are either blank or contain comments.
The following table shows the
LINER
entries for each source line:
Source | LINER | |
Line | Contents | Meaning |
3 |
03
|
Delta 0, count 3 |
6 |
35
|
Delta 3, count 5 |
8 |
2a
|
Delta 2, count 10 |
18 |
89 00 0a
|
Delta 10, count 9 |
20 |
23
|
Delta 2, count 3 |
Table Note:
The compiler generates the following instructions for the example program:
[main.c: 3] 0x0: 27bb0001 ldah gp, 1(t12) [main.c: 3] 0x4: 23bd80d0 lda gp, -32560(gp) [main.c: 3] 0x8: 23deffe0 lda sp, -32(sp) [main.c: 3] 0xc: b75e0008 stq ra, 8(sp) [main.c: 6] 0x10: a61d8010 ldq a0, -32752(gp) [main.c: 6] 0x14: 22108000 lda a0, -32768(a0) [main.c: 6] 0x18: a77d8018 ldq t12, -32744(gp) [main.c: 6] 0x1c: 6b5b4000 jsr ra, (t12), printf [main.c: 6] 0x20: 27ba0001 ldah gp, 1(ra) [main.c: 6] 0x24: 23bd80b0 lda gp, -32592(gp) [main.c: 8] 0x28: a61d8020 ldq a0, -32736(gp) [main.c: 8] 0x2c: a77d8028 ldq t12, -32728(gp) [main.c: 8] 0x30: 6b5b4000 jsr ra, (t12), fgetc [main.c: 8] 0x34: 27ba0001 ldah gp, 1(ra) [main.c: 8] 0x38: 23bd809c lda gp, -32612(gp) [main.c: 8] 0x3c: b41e0018 stq v0, 24(sp) [main.c: 8] 0x40: 44000401 bis v0, v0, t0 [main.c: 8] 0x44: 48203f41 extqh t0, 0x1, t0 [main.c: 8] 0x48: 48271781 sra t0, 0x38, t0 [main.c: 8] 0x4c: 40203402 addq t0, 0x1, t1 [main.c: 8] 0x50: f440000a bne t1, 0x7c [main.c: 18] 0x54: a61d8010 ldq a0, -32752(gp) [main.c: 18] 0x58: 22108020 lda a0, -32736(a0) [main.c: 18] 0x5c: 44000411 bis v0, v0, a1 [main.c: 18] 0x60: 4a203f51 extqh a1, 0x1, a1 [main.c: 18] 0x64: 4a271791 sra a1, 0x38, a1 [main.c: 18] 0x68: a77d8018 ldq t12, -32744(gp) [main.c: 18] 0x6c: 6b5b4000 jsr ra, (t12), printf [main.c: 18] 0x70: 27ba0001 ldah gp, 1(ra) [main.c: 18] 0x74: 23bd8060 lda gp, -32672(gp) [main.c: 18] 0x78: c3ffffeb br zero, 0x28 [main.c: 20] 0x7c: 47ff0400 bis zero, zero, v0 [main.c: 20] 0x80: a75e0008 ldq ra, 8(sp) [main.c: 20] 0x84: 23de0020 lda sp, 32(sp) [main.c: 20] 0x88: 6bfa8001 ret zero, (ra), 1
Table 8-3
shows the format of an entry in the procedure descriptor table; the
header file
sym.h
contains its declaration.
Declaration | Name | Description |
unsigned long |
adr
|
Memory address of start of procedure |
long |
cbLineOffset
|
Byte offset for this procedure from the base of the file descriptor entry |
int |
isym
|
Start of local symbols |
int |
iline
|
Procedure's line numbers |
int |
regmask
|
Saved register mask |
int |
regoffset
|
Saved register offset |
int |
iopt
|
Procedure's optimization symbol entries |
int |
fregmask
|
Save floating-point register mask |
int |
fregoffset
|
Save floating-point register offset |
int |
frameoffset
|
Frame size |
int |
lnLow
|
Lowest line in the procedure |
int |
lnHigh
|
Highest line in the procedure |
unsigned |
gp_prologue : 8
|
Byte size of gp prologue |
unsigned |
gp_used : 1
|
True if the procedures uses gp |
unsigned |
reg_frame : 1
|
True if register frame procedure |
unsigned |
reserved : 14
|
N/A |
unsigned |
localoff : 8
|
Offset of local variables from vfp |
short |
framereg
|
Frame pointer register |
short |
pcreg
|
Index or reg of return program counter |
Table Notes:
iline
is null and the
cycm
field in the file descriptor table is zero, the
iline
field is indexed to the actual table.
reg_frame
is 1, the
regoffset
field contains the register number of the register in which the return
address is stored.
gp_prologue
is zero and
gp_used
is 1, a gp prologue is present but has been scheduled into the
procedure prologue.
Table 8-4
shows the format of an entry in the local symbol table; the header file
sym.h
contains its declaration.
Declaration | Name | Description |
long
|
value
|
Value of symbol |
int
|
iss
|
Index into local strings of symbol name |
unsigned
|
st : 6
|
Symbol type |
unsigned
|
sc : 5
|
Storage class |
unsigned
|
reserved : 1
|
N/A |
unsigned
|
index : 20
|
Index into local or auxiliary symbols |
Table Notes:
iss
)
is an offset from the
issBase
field of an entry in the file descriptor table to the name
of the symbol.
st
)
defines the symbol.
The valid
st
Constants are given in
Table 8-6.
These constants are defined in
symconst.h
.
sc
),
where applicable, explains how to access the symbol
type in memory.
The valid
sc
constants are given in
Table 8-7.
These constants are defined in
symconst.h
.
st
)
as shown in
Table 8-5.
The compiler uses
isymBase
in the file descriptor entry as the base for an entry in the local
symbol table and
iauxBase
for an entry in the auxiliary symbol table.
Symbol Type | Storage Class | Index | Value |
stFile
|
scText
|
isymMac
|
Address of symbol |
stLabel
|
scText
|
indexNil
|
Address of symbol |
stGlobal
|
scD/B
|
iaux
|
Address of symbol |
stStatic
|
scD/B
|
iaux
|
Address of symbol |
stParam
|
scAbs
|
iaux
|
Frame offset |
|
scRegister
|
iaux
|
Register containing address of symbol |
|
scSymRef
|
isymFull
|
Frame offset |
|
scVar
|
iaux
|
Frame offset |
|
scVarRegister
|
iaux
|
Register containing address of symbol |
stLocal
|
scAbs
|
iaux
|
Frame offset |
|
scRegister
|
iaux
|
Register containing address of symbol |
stProc
|
scText
|
iaux
|
Address of symbol |
|
scNil
|
iaux
|
(unused) |
|
scUndefined
|
iaux
|
(unused) |
|
scVar
|
iaux
|
Frame offset |
|
scVarRegister
|
iaux
|
Register containing address of symbol |
stStaticProc
|
scText
|
iaux
|
Address of symbol |
stMember
|
|
|
|
enumeration
|
scInfo
|
indexNil
|
Ordinal |
structure
|
scInfo
|
iaux
|
Bit offset |
union
|
scInfo
|
iaux
|
Bit offset |
stBlock
|
|
|
|
enumeration
|
scInfo
|
isymMac
|
Max enumeration |
structure
|
scInfo
|
isymMac
|
Size |
text block
|
scText
|
isymMac
|
Relative address |
common block
|
scCommon
|
isymMac
|
Size |
variant
|
scVariant
|
isymMac
|
isymTag |
variant arm
|
scInfo
|
isymMac
|
iauxRanges |
union
|
scInfo
|
isymMac
|
Size |
stEnd
|
|
|
|
enumeration
|
scInfo
|
isymStart
|
0 |
file
|
scText
|
isymStart
|
Relative address |
procedure
|
scText
|
isymStart
|
Relative address |
structure
|
scInfo
|
isymStart
|
0 |
text block
|
scText
|
isymStart
|
Relative address |
union
|
scInfo
|
isymStart
|
0 |
common block
|
scCommon
|
isymStart
|
0 |
variant
|
scVariant
|
isymStart
|
0 |
variant arm
|
scInfo
|
isymStart
|
0 |
|
|
|
|
stTypedef
|
scInfo
|
iaux
|
0 |
Table Notes:
scD/B
storage class (data, sdata, bss, or sbss) is determined by the
assembler.
isymFull
index is the
isym
of the corresponding full parameter description.
isymMac
index is the
isym
of the corresponding
stEnd
symbol plus 1.
isymTag
index is the
isym
to the symbol that is the tag for the variant.
iauxRanges
index is the
iaux
to the ranges for the variant arm.
isymStart
index is the
isym
of the corresponding begin block (for example,
stBlock
,
stFile
,
or
stProc
).
The linker ignores all symbols except the types that it will relocate:
stLabel
,
stStatic
,
stProc
,
and
stStaticProc
.
Other symbols are used only by the debugger and need to be entered in
the table only when one of the debugging options
(-g
compilation options) is in effect.
Table 8-6
gives the allowable constants that can be specified in the
st
field of entries in the local symbol table; the header file
symconst.h
contains the declarations for the constants.
Constant | Value | Description |
stNil
|
0 | Dummy entry |
stGlobal
|
1 | External symbol |
stStatic
|
2 | Static |
stParam
|
3 | Procedure argument |
stLocal
|
4 | Local variable |
stLabel
|
5 | Label |
stProc
|
6 | Procedure |
stBlock
|
7 | Start of block |
stEnd
|
8 | End block, file, or procedures |
stMember
|
9 | Member of structure, union, or enumeration |
stTypedef
|
10 | Type definition |
stFile
|
11 | File name |
stStaticProc
|
14 | Load-time-only static procs |
stConstant
|
15 | Constant |
stStaParam
|
16 | Fortran static parameters |
stBase
|
17 | C++ base class |
stVirtBase
|
18 | C++ virtual base class |
stTag
|
19 | C++ tag |
stInter
|
20 | C++ interlude |
stSplit
|
21 | Split lifetime variable |
stModule
|
22 | Module definition |
stModview
|
23 | Modifiers for current view of given module |
Table 8-7
gives the allowable
constants that can be specified in the
sc
field of entries in the local symbol table; the header file
symconst.h
contains the declarations for the constants.
Constant | Value | Description |
scNil
|
0 | Dummy entry |
scText
|
1 | Text symbol |
scData
|
2 | Initialized data symbol |
scBss
|
3 | Uninitialized data symbol |
scRegister
|
4 | Value of symbol is register number |
scAbs
|
5 | Symbol value is absolute; not to be relocated |
scUndefined
|
6 | Used but undefined in the current module |
scUnallocated
|
7 | No storage or register allocated |
scBits
|
8 | Bit field |
scDbx
|
9 |
Used internally by
dbx
|
scRegImage
|
10 | Register value saved on stack |
scInfo
|
11 | Symbol contains debugger information |
scUserStruct
|
12 | Address in struct user for current process |
scSData
|
13 | Small data (load time only) |
scSBss
|
14 | Small common (load time only) |
scRData
|
15 | Read only data (load time only) |
scVar
|
16 | Fortran or Pascal: Var parameter |
scCommon
|
17 | Common variable |
scSCommon
|
18 | Small common |
scVarRegister
|
19 | Var parameter in a register |
scVariant
|
20 | Variant records |
scFileDesc
|
20 | COBOL: File descriptor |
scSUndefined
|
21 | Small undefined |
scInit
|
22 |
init
section symbol
|
scReportDesc
|
23 | COBOL: Report descriptor |
scXData
|
24 | Exception handling data |
scPData
|
25 | Exception procedure section |
scFini
|
26 |
fini
section symbol
|
scRConst
|
27 | Read-only constant symbol |
scSymRef
|
28 | Parameter is described by referenced symbol |
scMax
|
32 | Maximum number of storage classes |
Table 8-8
shows the format of an entry in the auxiliary symbol table; the
sym.h
file contains its declaration.
Note that the entry is declared as a union;
Table 8-8
lists the members of the union.
Declaration | Name | Description |
TIR
|
ti
|
Type information record |
RNDXR
|
rndx
|
Relative index into local symbols |
int
|
dnLow
|
Low dimension of array |
int
|
dnHigh
|
High dimension of array |
int
|
isym
|
Index into local symbols for
stEnd
|
int
|
iss
|
Index into local strings (not used) |
int
|
width
|
Width of a structured field not declared with the default value for size |
int
|
count
|
Count of ranges for variant arm |
Table Notes:
ti
entry; the
sym.h
file contains its declaration.
stEnd
entry denoting the end of a procedure.
Declaration | Name | Description |
unsigned
|
fBitfield : 1
|
Set if bit width is specified |
unsigned
|
continued : 1
|
Next auxiliary entry has
tq
information
|
unsigned
|
bt : 6
|
Basic type |
unsigned
|
tq4 : 4
|
Type qualifier |
unsigned
|
tq5 : 4
|
Type qualifier |
unsigned
|
tq0 : 4
|
Type qualifier |
unsigned
|
tq1 : 4
|
Type qualifier |
unsigned
|
tq2 : 4
|
Type qualifier |
unsigned
|
tq3 : 4
|
Type qualifier |
All groups of auxiliary entries have a type information record with the following entries:
fbitfield
is set if the basic type
(bt
)
is of nonstandard width.
bt
(for basic type) specifies the type of the symbol (for example,
integer, real, complex, or structure).
The valid entries for this field are shown in
Table 8-10;
the
sym.h
file contains its declaration.
tq
(for type qualifier) defines whether the basic type
(bt
)
has an
array of,
function returning,
or
pointer to
qualifier. The valid entries for this field are shown in
Table 8-11;
the
sym.h
file contains its declaration.
Default | |||
Constant | Value |
Size |
Description |
btNil
|
0 | 0 | Undefined, void |
btAdr32
|
1 | 32 | Address (32 bits) |
btChar
|
2 | 8 | Symbol character |
btUChar
|
3 | 8 | Unsigned character |
btShort
|
4 | 16 | Short (16 bits) |
btUShort
|
5 | 16 | Unsigned short |
btInt
|
6 | 32 | Integer |
btUInt
|
7 | 32 | Unsigned integer |
btLong32
|
8 | 32 | Long (32 bits) |
btULong32
|
9 | 32 | Unsigned long (32 bits) |
btFloat
|
10 | 32 | Floating point (real) |
btDouble
|
11 | 64 | Double-precision floating-point real |
btStruct
|
12 | n/a | Structure (record) |
btUnion
|
13 | n/a | Union (variant) |
btEnum
|
14 | 32 | Enumerated |
btTypedef
|
15 | n/a |
Defined by means of a typedef;
rndx
points at a
stTypedef
symbol
|
btRange
|
16 | 32 | Subrange of integer |
btSet
|
17 | 32 | Pascal: Sets |
btComplex
|
18 | 64 | Fortran: Complex |
btDComplex
|
19 | 128 | Fortran: Double complex |
btIndirect
|
20 | n/a |
Indirect definition;
rndx
points to an entry in the auxiliary symbol table that contains a
TIR (type information record)
|
btFixedBin
|
21 | n/a | COBOL: Fixed binary |
btDecimal
|
22 | n/a | COBOL: Packed or unpacked decimal |
btVoid
|
26 | n/a | Void |
btPtrMem
|
27 | 64 | C++: Pointer to member |
btScaledBin
|
27 | n/a | COBOL: Scaled binary |
btVptr
|
28 | n/a | C++: Virtual function table |
btArrayDesc
|
28 | n/a | Fortran90: Array descriptor |
btClass
|
29 | n/a | C++: Class (record) |
btLong64
|
30 | 64 | Address (64 bits) |
btLong
|
30 | 64 |
Synonym for
btLong64
|
btULong64
|
31 | 64 | Unsigned long (64 bits) |
btULong
|
31 | 64 |
Synonym for
btUlong64
|
btLongLong
|
32 | 64 | Long long (64 bits) |
btULongLong
|
33 | 64 | Unsigned long long (64 bits) |
btAdr64
|
34 | 64 | Address (64 bits) |
btAdr
|
34 | 64 |
Synonym for
btAdr64
|
btInt64
|
35 | 64 | 64-bit integer |
btUInt64
|
36 | 64 | 64-bit unsigned integer |
btLDouble
|
37 | 128 | Long double (real*15) |
btInt8
|
38 | 8 | 8-bit integer |
btUInt8
|
39 | 8 | 8-bit unsigned integer |
btMax
|
64 | n/a |
Table Notes:
Constant | Value | Description |
tqNil
|
0 | Place holder; no qualifier |
tqPtr
|
1 | Pointer |
tqProc
|
2 | Procedure or function |
tqArray
|
3 | Array |
tqVol
|
5 | Volatile |
tqConst
|
6 | Constant |
tqRef
|
7 | Reference |
tqMax
|
8 | Number of type qualifiers |
Table 8-12
shows the format of an entry in the file descriptor table; the header
file
sym.h
contains its declaration.
Declaration | Name | Description |
unsigned long
|
adr
|
Memory address of start of file |
long
|
cbLineOffset
|
Byte offset from header or file lines |
long
|
cbLine
|
Size of lines for the file |
long
|
cbSs
|
Number of bytes in local strings |
int
|
rss
|
Source file name |
int
|
issBase
|
Start of local strings |
int
|
isymBase
|
Start of local symbol entries |
int
|
csym
|
Count of local symbol entries |
int
|
ilineBase
|
Start of line number entries |
int
|
cline
|
Count of line number entries |
int
|
ioptBase
|
Start of optimization symbol entries |
int
|
copt
|
Count of optimization symbol entries |
int
|
ipdFirst
|
Start of procedure descriptor table |
int
|
cpd
|
Count of procedures descriptors |
int
|
iauxBase
|
Start of auxiliary symbol entries |
int
|
caux
|
Count of auxiliary symbol entries |
int
|
rfdBase
|
Index into relative file descriptors |
int
|
crfd
|
Relative file descriptor count |
unsigned
|
lang : 5
|
Language for this file |
unsigned
|
fMerge : 1
|
Whether this file can be merged |
unsigned
|
fReadin : 1
|
True if it was read in (not just created) |
unsigned
|
fBigendian : 1
|
Not used |
unsigned
|
glevel : 2
|
Level this file was compiled with |
unsigned
|
reserved : 22
|
Reserved for future use |
The external symbol table has the same format as the local symbol
table, except an offset
(ifd
)
field has been added to the file descriptor table. This field is used
to locate information associated with the symbol in an auxiliary
symbol table.
Table 8-13
shows the format of an entry in the external symbol table; the
sym.h
file contains its declaration.
Declaration | Name | Description |
SYMR
|
asym
|
Same as local symbol table |
unsigned short
|
weakext : 1
|
Symbol is weak external |
unsigned short
|
reserved : 15
|
Reserved for future use |
int
|
ifd
|
Pointer to entry in file descriptor table |