Why does libgcc use global offset table?
I'm trying to build gcc 4.6 for i386-elf target.
My problem is as follows. When compiling libgcc
I get the output-file _fixunsdfdi.o
which make use of the global offset table.
The function is used when converting 'double' to 'unsigned long long'. When i look at the assembly it looks like its the Wtype_MAXp1_F, that is placed in the GOT - but why?
I configured with
--target=i386-elf --enable-languages=c --disable-nls --disable-libssp --disable-libquadmath --enable-shared=no --enable-static=yes
//Code for fixunsdfdi (from libgcc2.c)
#if defined(L_fixunsdfdi) && LIBGCC2_HAS_DF_MODE
UDWtype __fixunsdfDI (DFtype a)
{
/* Get high part of result. The division here will just moves the radix
point and will not cause any rounding. Then the conversion to integral
type chops result as desired. */
const UWtype hi = a / Wtype_MAXp1_F;
/* Get low part of result. Convert `hi' to floating type and scale it back,
then subtract this from the number being converted. This leaves the low
part. Convert that to integral type. */
const UWtype lo = a - (DFtype) hi * Wtype_MAXp1_F;
/* Assemble result from the two parts. */
return ((UDWtype) hi << W_TYPE_SIZE) | lo;
}
#endif
//Dump of the output
Class: 32-bit
Data: Little Endian
Header version: 1[Current Version]
OS/ABI: 0[UNIX System V ABI]
Type: 1[REL (Relocatable file)]
Machine: 0003h[Intel Architecture EM_386]
File version: 1[Current Version]
Entry point address: 00000000h
Start of program headers: 0 (bytes into file)
Start of section headers: 35496 (bytes into file)
Flags: 0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 15
Section header string table index: 12
[file offset:00008AA8h]Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[0] NULL 00000000 000000 000000 00 0 0 0
[1] .text PROGBITS 00000000 000034 000067 00 AX 0 0 4
[2] .rel.text REL 00000000 008E18 000018 08 13 1 4
[3] .data PROGBITS 00000000 00009C 000000 00 WA 0 0 4
[4] .bss NOBITS 00000000 00009C 000000 00 WA 0 0 4
[5] .stab PROGBITS 00000000 00009C 0004D4 0C 7 0 4
[6] .rel.stab REL 00000000 008E30 000030 08 13 5 4
[7] .stabstr STRTAB 00000000 000570 00844A 00 0 0 1
[8] .rodata.cst4 PROGBITS 00000000 0089BC 000008 04 A 0 0 4
[9] .comment PROGBITS 00000000 0089C4 000028 01 0 0 1
[10] .eh_frame PROGBITS 00000000 0089EC 000054 00 A 0 0 4
[11] .rel.eh_frame REL 00000000 008E60 000008 08 13 10 4
[12] .shstrtab STRTAB 00000000 008A40 000067 00 0 0 1
[13] .symtab SYMTAB 00000000 008D00 0000E0 10 14 12 4
[14] .strtab STRTAB 00000000 008DE0 000038 00 0 0 1
[file offset:00008E18h]Relocation section '.rel.text' contains 3 entries:
Type: REL
Num: Offset Info Type Sym.Value Addend To->Sym. Name
0: 0000000E 00000D0A R_386_GOTPC 00000000 00000003 _GLOBAL_OFFSET_TABLE_
1: 0000001A 00000709 R_386_GOTOFF 00000000 00000000 .LC0
2: 0000004A 00000809 R_386_GOTOFF 00000004 00000000 .LC1
[file offset:00008E30h]Relocation section '.rel.stab' contains 6 entries:
Type: REL
Num: Offset Info Type Sym.Value Addend To->Sym. Name
0: 00000014 00000201 R_386_32 00000000 00000000 .text
1: 00000020 00000201 R_386_32 00000000 00000000 .text
2: 00000434 00000C01 R_386_32 00000000 00000000 __fixunsdfdi
3: 0000044C 00000201 R_386_32 00000000 00000000 .text
4: 000004C4 00000201 R_386_32 00000000 00000067 .text
5: 000004D0 00000201 R_386_32 00000000 00000067 .text
[file offset:00008E60h]Relocation section '.rel.eh_frame' contains 1 entries:
Type: REL
Num: Offset Info Type Sym.Value Addend To->Sym. Name
0: 00000020 00000202 R_386_PC32 00000000 00000000 .text
[file offset:00008D00h]Symbol table '.symtab' contains 14 entries:
Num[h]: Value Size Type Bind Vis Ndx Name
000000: 00000000 0000 NOTYPE LOCAL UND
000001: 00000000 0000 FILE LOCAL ABS libgcc2.c
000002: 00000000 0000 SECTION LOCAL 1 .text
000003: 00000000 0000 SECTION LOCAL 3 .data
000004: 00000000 0000 SECTION LOCAL 4 .bss
000005: 00000000 0000 SECTION LOCAL 8 .rodata.cst4
000006: 00000000 0000 SECTION LOCAL 10 .eh_frame
000007: 00000000 0000 NOTYPE LOCAL 8 .LC0
000008: 00000004 0000 NOTYPE LOCAL 8 .LC1
000009: 00000000 0000 SECTION LOCAL 5 .stab
00000A: 00000000 0000 SECTION LOCAL 7 .stabstr
00000B: 00000000 0000 SECTION LOCAL 9 .comment
00000C: 00000000 0067 FUNC GLOBAL 1 __fixunsdfdi
00000D: 00000000 0000 NOTYPE GLOBAL UND _GLOBAL_OFFSET_TABLE_
I would prefer not to create the global offset table as I has no need for it elsewhere, and it is currently not supported in the linker in the project im working on.
Q1: Why does it use symbols in the global offset table?
Q2: Is there anyway to avoid using global offset table? Any help out there?
Ok, I am not sure if I understood completely, but here it goes...
Q1: Why does it use symbols in the global offset table (GOT)?
GOT is used because by the way compiler, linker and loader works, it is impossible to tell where each object will end up in memory at runtime. The compiler proper step sees one module at a time, so it cannot tell from where each (external) function and global var will be referred. Instead, for each one it creates a symbol to be resolved at link time. For static functions/variables, it generates code that access those directly (it is platform dependent: in Linux/x86_64 is uses an offset from the program counter). For externals, it generates indirect access code through a runtime data structure: GOT.
At link time, you can tell which modules call what symbols, so it is the linker job to make sure that all symbols (either those in your program or in its external dependencies) are resolved, meaning they are defined elsewhere in the multiple modules that compose your program. For objects defined in your own code (or linked statically) it is possible to tell its location inside your binary (ELF/COFF/PE/etc), but you do not know where are they going to be in memory until load time. Linker also writes into the binary what are the required shared libraries and (optionally) their likely location at runtime.
When you run your program, the loader! will try to find all dependencies (shared libs), and then as part of process start up will build GOT structure. It will load your program code from binary's text section into memory and for each symbol it will create an entry in the GOT with the actual memory address where to find it. Then it will do the same for each shared library. It is also worth noting that some libraries may keep internal offset tables independent of GOT. This way you can have the same symbol defined multiple times. This is by example what happens with Window SxS! (Microsoft's answer to DLL hell problem).
From the point of view of your program, each access to external symbol requires 2 memory accesses (indirect). If the symbol represents a function, there is another structure PLT, that is a jump table with GOTO instructions to each place.
Q2: Is there anyway to avoid using global offset table? Any help out there?
Yes, the easiest way is to figure out what functions/globals you do not need access outside the module they are defined and declare those as static. In this way, compiler will know that it can generate direct access code to find them (offset from program counter is the way it is done in Linux/x86_64, but it is platform dependent).
I have read that in large projects there is a specialized build teams that identify tightly coupled sets of modules and integrate them in a single big C file in order to minimize the number of exposed symbols into the general product, but I have never seen it first hand.
There are also linker options that help you avoid exposing symbols, but for what I know they are just syntactic sugar. The GOT and PLT is still being used, just you make its contents opaque.
A great resource for this subject is Ulrich Drepper's How to Write Shared Libraries!
链接地址: http://www.djcxy.com/p/75550.html上一篇: python多处理.Pool kill *特定*长时间运行或挂起进程
下一篇: 为什么libgcc使用全局偏移表?