stabs 已经被 DWARF 替代......
stabs是什么
Stabs (Symbol Table String) refers to a format for information that describes a program to a debugger.
GNU C compiler如何使用stabs
overview
The GNU C compiler compiles C source in a .c file into assembly language in a .s file, which the assembler translates into a .o file, which the linker combines with other .o files and libraries to produce an executable file.
With the ‘-g’ option, GCC puts in the .s file additional debugging information, which is slightly transformed by the assembler and linker, and carried through into the final executable. This debugging information describes features of the source file like line numbers, the types and scopes of variables, and function names, parameters, and scopes.
The assembler adds the information from stabs to the symbol information it places by default in the symbol table and the string table of the .o file it is building. The linker consolidates the .o files into one executable file, with one symbol table and one string table. Debuggers use the symbol and string tables in the executable as a source of debugging information about the program.
To generate stabs now, we need -gstabs option since DWARF has been used for debug information by default now.
$ gcc -gstabs tst.c # generate stabs debug info
$ gcc -g tst.c # generate DWARF
$ readelf --debug-dump=info a.out # check which version is used in executable file
Contents of the .debug_info section:
Compilation Unit @ offset 0x0:
Length: 0x7f (32-bit)
Version: 4
Abbrev Offset: 0x0
Pointer Size: 8
<0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
The format of stab
.stabs "string",type,other,desc,value
The number in the type field gives some basic information about which type of stab this is (or whether it is a stab, as opposed to an ordinary symbol). Each valid type number defines a different stab type; further, the stab type defines the exact interpretation of, and possible values for, any remaining string, desc, or value fields present in the stab.
the format of symbol table entries and how stab assembler directives map to them
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.
picture for stabs workflow
example
source code
-----------------------
# tst.h
#ifndef INC_TST_H
#define INC_TST_H
static inline int inb()
{
return 5;
}
#endif
-----------------------
# tst.c
#include <tst.h>
void func3()
{
int a = 2;
a = inb();
a += 1;
}
int func2(char c)
{
int a = 1;
a += c;
func3();
a = 2;
}
char func(int i)
{
char c = 'a';
func2(c);
c = 'b';
}
int main()
{
int a;
a = 1;
func(a);
a = 2;
return 0;
}
-----------------------
# tst2.c
char t2_func(int i)
{
char c = 'a';
func2(c);
}
-----------------------
# tst3.c
char t3_func(int i)
{
char c = 'a';
func2(c);
}
stabs
$ gcc -gstabs -I./ tst*.c -S
$ cat tst.s # each tst*.c has its own .s file
.file "tst.c"
.stabs "tst.c",100,0,2,.Ltext0
.text
.Ltext0:
.stabs "gcc2_compiled.",60,0,0,0
.stabs "int:t(0,1)=r(0,1);-2147483648;2147483647;",128,0,0,0
.stabs "char:t(0,2)=r(0,2);0;127;",128,0,0,0
.stabs "long int:t(0,3)=r(0,3);-0;4294967295;",128,0,0,0
.stabs "unsigned int:t(0,4)=r(0,4);0;4294967295;",128,0,0,0
.stabs "long unsigned int:t(0,5)=r(0,5);0;-1;",128,0,0,0
.stabs "__int128:t(0,6)=r(0,6);0;-1;",128,0,0,0
.stabs "__int128 unsigned:t(0,7)=r(0,7);0;-1;",128,0,0,0
.stabs "long long int:t(0,8)=r(0,8);-0;4294967295;",128,0,0,0
.stabs "long long unsigned int:t(0,9)=r(0,9);0;-1;",128,0,0,0
.stabs "short int:t(0,10)=r(0,10);-32768;32767;",128,0,0,0
.stabs "short unsigned int:t(0,11)=r(0,11);0;65535;",128,0,0,0
.stabs "signed char:t(0,12)=r(0,1