2016-06-19 23 views
9

Globale Offset-Tabelle (GOT): Wird für die Verlagerung von ELF-Symbolen (implementiert GCC) verwendet, Es hilft bei der gemeinsamen Nutzung der gleichen binären ohne spezifische Verknüpfung für jeden Prozess. Dadurch werden Kopien des gleichen Binärbildes im Speicher reduziert.Deaktivieren GOT in GCC

Meine Frage ist, gibt es eine Möglichkeit, R_386_GOT32, R_386_GOTOFF Typ Verschiebungseinträge in verlagernden ELF-Bild zu deaktivieren? Ich meine, kann ich zwingen, GCC zu verwenden R_386_PC32 oder R_386_32 Typ Umzug statt GOT Typ Umzug?

Wenn nicht, könnten Sie die Art der Implementierung von GOT erklären? Ich schreibe eine dynamische Linking und Loading Library für ELF.

Edit:
Referenzen Links
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

Dies ist eine gültige Frage. Wenn Sie jedoch Ihren eigenen dynamischen Linker schreiben, sollten Sie besser die gesamte ELF-Spezifikation lesen und eine korrekte GOT-Verlagerung implementieren. – 3442

+0

@KemyLand Ich stimme zu, aber jetzt möchte ich eine begrenzte Implementierung wegen der Zeitbeschränkung machen. – amaneureka

+0

Ordentlich, das ist genau das, was ich für mein Spielzeug OS brauche – minexew

Antwort

7

schließlich geknackt ich es!
Nein, es ist nicht möglich, GCC auf Ausgaben mit Nicht-GOT-Umlagerung zu beschränken.
Nun, wie GOT Typ Umzug zu lösen?
GOT ist von festen 128KB Speicher Chunk (Es funktioniert nach dem Prinzip der Kopie beim Schreiben) zugewiesen von dynamischen Linker, der Einträge für die Verlagerung enthält.
Dynamic Linker weist GOT nur dann zu, wenn eine beliebige Art von GOT-Verschiebung (unten aufgeführt) in der ELF-Binärdatei vorhanden ist.

R_386_GOTOFF(== 0x9)
Dieser Verschiebungstyp berechnet die Differenz zwischen einem Wert des Symbols und der Adresse der globalen Verschiebungstabelle. Es weist auch den Link-Editor an, die globale Offset-Tabelle zu erstellen.

R_386_GOTPC(== 0xA)
Dieser Verschiebungstyp ähnelt R_386_PC32, außer sie die Adresse der globalen Offset-Tabelle in der Berechnung verwendet.

Wie Sie sie implementieren?
Hinweis: Das folgende Code-Snippet gehört zu Atom OS Quellcode, der durch Closed Source-Lizenz geschützt ist. Aber ich (Atom Developer) erklären hiermit, diese Code-Schnipsel frei :)

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

Sie versuchen, gcc-Option verwenden können verwenden: -fPIE oder -fpie, die die GOT deaktivieren könnte.

+0

, das alle Arten von Standortverlagerungen deaktiviert . Und ich werde mit statischen binären enden, die ich an einen anderen Ort im Gedächtnis nicht verschieben kann. – amaneureka

+0

@amaneureka '-fPIE' hat nichts mit statischer Verknüpfung zu tun. – yugr

+0

Ja. Ich meine, ich werde mit nicht verschiebbaren Binärdateien enden. – amaneureka

1

gcc -fno-plt -fno-pic beschränkt die Umlagerungsarten auf R_386_PC32 und R_386_32 (oder zumindest funktionierte es in meinem Fall). Akzeptierte Antwort ist irreführend in der Behauptung, dass es nicht möglich ist.