2016-06-19 2 views
9

전역 오프셋 테이블 (GOT) : ELF 심볼 (구현 된 GCC)의 재배치에 사용되며, 각 프로세스에 대한 특정 연결없이 동일한 이진 공유에 도움이됩니다. 따라서 메모리에있는 동일한 이진 이미지의 복사본을 줄입니다.GCC에서 GOT 사용 안 함

제 질문은 재배치 가능한 ELF 이미지에서 R_386_GOT32, R_386_GOTOFF 유형의 재배치 항목을 비활성화하는 방법이 있습니까? 제 말은 GCC가 GOT 타입 재배치 대신에 R_386_PC32 또는 R_386_32 재배치를 사용하도록 강제 할 수 있습니까?

그렇지 않다면 GOT 구현 방법을 설명해 주시겠습니까? ELF 용 동적 링크 및 로딩 라이브러리를 작성 중입니다.

편집 :
참조 링크
https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-74186.html
http://man7.org/linux/man-pages/man8/ld.so.8.html

+1

이것은 유효한 질문입니다. 그러나 자신의 동적 링커를 작성하는 경우 전체 ELF 사양을 읽고 적절한 GOT 재배치를 구현하는 것이 좋습니다. – 3442

+0

@KemyLand 동의하지만, 지금은 제한된 시간 제약으로 제한된 구현을하고 싶습니다. – amaneureka

+0

깔끔하고 내 장난감 OS에 꼭 필요한 것입니다. – minexew

답변

7

http://wiki.osdev.org/ELF 마지막으로 나는 그것을 금이!
아니요, GCC가 non-GOT 유형 재배치로 출력되도록 제한 할 수 없습니다.
GOT 유형 재배치를 해결하는 방법은 무엇입니까?
GOT는 재배치를위한 항목이 들어있는 동적 링커에 의해 할당 된 고정 128KB 메모리 청크 (쓰기시 복사 원칙에 따라 작동)입니다.
Dynamic Linker는 ELF 바이너리에 GOT 재배치 유형이있는 경우에만 GOT를 할당합니다.

R_386_GOTOFF(== 0 * 9)을
이 재배치 타입 심볼의 값과 전역 옵셋 테이블의 주소 사이의 차이를 계산한다. 링커가 전역 옵셋 테이블을 생성하도록 지시합니다. 그것의 계산에 전역 옵셋 테이블의 주소를 사용하는 것을 제외하고

R_386_GOTPC(== 0xa는)
이 재배치 타입은 R_386_PC32 유사하다.

어떻게 구현합니까?
참고 : 다음 코드 스 니펫은 Atom OS 소스 코드의 오픈 소스 라이센스에 의해 보호됩니다. -fPIE 또는 GOT을 해제 할 수있는 -fpie :하지만 (아톰 개발자는) 본인이 코드는 :

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

당신은 GCC 옵션을 사용하려고 할 수 있습니다 무료로 사용할 선언합니다.

+0

에서 볼 수 있습니다. 모든 유형의 재배치가 비활성화됩니다. . 그리고 메모리에서 다른 위치로 이동할 수없는 정적 바이너리로 끝날 것입니다. – amaneureka

+0

@amaneureka'-fPIE'는 정적 링크와 아무 관련이 없습니다. – yugr

+0

예. 나는 재배치 할 수없는 바이너리로 끝날 것임을 의미한다. – amaneureka

1

gcc -fno-plt -fno-pic은 R_386_PC32 및 R_386_32로 재배치 유형을 제한합니다 (또는 적어도 제 경우에는 효과가있었습니다). 수락 된 답변은 불가능하다고 주장하는 데 오해의 소지가 있습니다.