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.
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.)
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:
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:
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:
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:
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:
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:
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 |