This chapter describes the format of symbol table entries and how stab assembler directives map to them. It also describes the transformations that the assembler and linker make on data from stabs.
Each time the assembler encounters a stab directive, it puts each field of the stab into a corresponding field in a symbol table entry of its output file. If the stab contains a string field, the symbol table entry for that stab points to a string table entry containing the string data from the stab. Assembler labels become relocatable addresses. Symbol table entries in a.out have the format:
struct internal_nlist { unsigned long n_strx; /* index into string table of name */ unsigned char n_type; /* type of symbol */ unsigned char n_other; /* misc info (usually empty) */ unsigned short n_desc; /* description field */ bfd_vma n_value; /* value of symbol */ };
If the stab has a string, the n_strx
field holds the offset in
bytes of the string within the string table. The string is terminated
by a NUL character. If the stab lacks a string (for example, it was
produced by a .stabn
or .stabd
directive), the
n_strx
field is zero.
Symbol table entries with n_type
field values greater than 0x1f
originated as stabs generated by the compiler (with one random
exception). The other entries were placed in the symbol table of the
executable by the assembler or the linker.
The linker concatenates object files and does fixups of externally defined symbols.
You can see the transformations made on stab data by the assembler and linker by examining the symbol table after each pass of the build. To do this, use `nm -ap', which dumps the symbol table, including debugging information, unsorted. For stab entries the columns are: value, other, desc, type, string. For assembler and linker symbols, the columns are: value, type, string.
The low 5 bits of the stab type tell the linker how to relocate the
value of the stab. Thus for stab types like N_RSYM
and
N_LSYM
, where the value is an offset or a register number, the
low 5 bits are N_ABS
, which tells the linker not to relocate the
value.
Where the value of a stab contains an assembly language label, it is transformed by each build step. The assembler turns it into a relocatable address and the linker turns it into an absolute address.
This source line defines a static variable at file scope:
static int s_g_repeat
The following stab describes the symbol:
.stabs "s_g_repeat:S1",38,0,0,_s_g_repeat
The assembler transforms the stab into this symbol table entry in the `.o' file. The location is expressed as a data segment offset.
00000084 - 00 0000 STSYM s_g_repeat:S1
In the symbol table entry from the executable, the linker has made the relocatable address absolute.
0000e00c - 00 0000 STSYM s_g_repeat:S1
Stabs for global variables do not contain location information. In this case, the debugger finds location information in the assembler or linker symbol table entry describing the variable. The source line:
char g_foo = 'c';
generates the stab:
.stabs "g_foo:G2",32,0,0,0
The variable is represented by two symbol table entries in the object
file (see below). The first one originated as a stab. The second one
is an external symbol. The upper case `D' signifies that the
n_type
field of the symbol table contains 7, N_DATA
with
local linkage. The stab's value is zero since the value is not used for
N_GSYM
stabs. The value of the linker symbol is the relocatable
address corresponding to the variable.
00000000 - 00 0000 GSYM g_foo:G2 00000080 D _g_foo
These entries as transformed by the linker. The linker symbol table entry now holds an absolute address:
00000000 - 00 0000 GSYM g_foo:G2 ... 0000e008 D _g_foo
For object file formats using stabs in separate sections (see section Using Stabs in Their Own Sections), use objdump --stabs
instead of nm
to show the
stabs in an object or executable file. objdump
is a GNU utility;
Sun does not provide any equivalent.
The following example is for a stab whose value is an address is relative to the compilation unit (see section Having the Linker Relocate Stabs in ELF). For example, if the source line
static int ld = 5;
appears within a function, then the assembly language output from the compiler contains:
.Ddata.data: ... .stabs "ld:V(0,3)",0x26,0,4,.L18-Ddata.data # 0x26 is N_STSYM ... .L18: .align 4 .word 0x5
Because the value is formed by subtracting one symbol from another, the value is absolute, not relocatable, and so the object file contains
Symnum n_type n_othr n_desc n_value n_strx String 31 STSYM 0 4 00000004 680 ld:V(0,3)
without any relocations, and the executable file also contains
Symnum n_type n_othr n_desc n_value n_strx String 31 STSYM 0 4 00000004 680 ld:V(0,3)
Go to the first, previous, next, last section, table of contents.