2016-06-19 10 views
9

Globalna tabela przesunięcia (GOT): Jest używana do przenoszenia symboli ELF (zaimplementowane GCC), Pomaga w dzieleniu tego samego pliku binarnego bez żadnego konkretnego łączenia dla każdego procesu. W ten sposób zmniejsza liczbę kopii tego samego obrazu binarnego w pamięci.Wyłączyć GOT w GCC

Moje pytanie brzmi, czy jest jakiś sposób na wyłączenie wpisów przenoszenia typu R_386_GOT32, R_386_GOTOFF w relokowalnym obrazie ELF? Mam na myśli, czy mogę zmusić GCC do używania przenoszenia typu R_386_PC32 lub R_386_32 zamiast przenoszenia typu GOT?

Jeśli nie, czy mógłbyś wyjaśnić sposób wdrożenia GOT? Piszę dynamiczną bibliotekę łączącą i ładującą dla ELF.

Edit:
referencyjny Linki
https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-74186.html
http://man7.org/linux/man-pages/man8/ld.so.8.html
http://wiki.osdev.org/ELF

+1

To jest prawidłowe pytanie. Jeśli jednak tworzysz własny dynamiczny linker, powinieneś lepiej przeczytać całą specyfikację ELF i zaimplementować właściwą relokację GOT. – 3442

+0

@KemyLand Zgadzam się, ale na razie chcę wprowadzić ograniczoną implementację z powodu ograniczeń czasowych. – amaneureka

+0

Schludnie, to jest dokładnie to, czego potrzebuję do mojej zabawki OS – minexew

Odpowiedz

7

końcu pęknięty to!
Nie, Nie można ograniczyć GCC do wyjścia z relokacją typu innego niż GOT.
Teraz, jak rozwiązać problem przeniesienia typu GOT?
GOT ma ustaloną porcję pamięci 128KB (działa na zasadzie kopiowania przy zapisie) przydzieloną przez dynamiczny linker, który zawiera wpisy do przeniesienia.
Dynamiczny linker przydziela GOT tylko wtedy, gdy w binarnym ELF istnieje dowolny rodzaj przenoszenia (wymieniony poniżej).

R_386_GOTOFF(== 0x9)
Ten typ relokacji oblicza różnicę między wartością symbol i adresu globalnego przesunięcia stołu. Instruuje także edytor linków do tworzenia globalnej tabeli przesunięć.

typ R_386_GOTPC(== 0xA)
Ten relokacji przypomina R_386_PC32, oprócz tego, że używa adresu globalnego przesunięcia stołu w swoich obliczeniach.

Jak je wdrożyć?
Uwaga: Poniższy fragment kodu należy do Atom OS kodu źródłowego chronionego licencją typu zamkniętego. Ale ja (Atom Developer) Oświadczamy, ten fragment kodu do korzystania :)

uint GOT = Heap.kmalloc(1024 * 128); // 128 KB 
    ... 
    private static void Relocate(Elf_Header* aHeader, Elf_Shdr* aShdr, uint GOT) 
    { 
     uint BaseAddress = (uint)aHeader; 
     Elf32_Rel* Reloc = (Elf32_Rel*)aShdr->sh_addr; 
     Elf_Shdr* TargetSection = (Elf_Shdr*)(BaseAddress + aHeader->e_shoff) + aShdr->sh_info; 

     uint RelocCount = aShdr->sh_size/aShdr->sh_entsize; 

     uint SymIdx, SymVal, RelocType; 
     for (int i = 0; i < RelocCount; i++, Reloc++) 
     { 
      SymVal = 0; 
      SymIdx = (Reloc->r_info >> 8); 
      RelocType = Reloc->r_info & 0xFF; 

      if (SymIdx != SHN_UNDEF) 
      { 
       if (RelocType == R_386_GOTPC) 
        SymVal = GOT; 
       else 
        SymVal = GetSymValue(aHeader, TargetSection->sh_link, SymIdx); 
      } 

      uint* add_ref = (uint*)(TargetSection->sh_addr + Reloc->r_offset); 
      switch(RelocType) 
      { 
       case R_386_32: 
        *add_ref = SymVal + *add_ref; // S + A 
        break; 
       case R_386_GOTOFF: 
        *add_ref = SymVal + *add_ref - GOT; // S + A - GOT 
        break; 
       case R_386_PLT32: // L + A - P 
       case R_386_PC32: // S + A - P 
       case R_386_GOTPC: // GOT + A - P 
        *add_ref = SymVal + *add_ref - (uint)add_ref; 
        break; 
       default: 
        throw new Exception("[ELF]: Unsupported Relocation type"); 
      } 
     } 
    } 
0

Można spróbować użyć opcji gcc: -fPIE lub -fpie które mogłyby wyłączyć GOT.

+0

, który wyłączy wszystkie rodzaje przenoszenia . I otrzymam statyczny plik binarny, którego nie mogę przenieść do innej lokalizacji w pamięci. – amaneureka

+0

@amaneureka '-fPIE' nie ma nic wspólnego z łączeniem statycznym. – yugr

+0

Tak. Mam na myśli to, że skończę z binarnymi, które nie mogą być przeniesione. – amaneureka

1

gcc -fno-plt -fno-pic ograniczy typy relokacji do R_386_PC32 i R_386_32 (a przynajmniej zadziałało w moim przypadku). Przyjęta odpowiedź jest myląca w twierdzeniu, że nie jest to możliwe.

Powiązane problemy