在GCC中禁用GOT

ama*_*eka 9 gcc operating-system elf relocation

全局偏移表(GOT):用于重定位ELF符号(实现GCC),它有助于共享相同的二进制文件,而不需要为每个进程进行任何特定链接.因此减少了存储器中相同二进制图像的副本.

我的问题是,有没有办法禁用R_386_GOT32,R_386_GOTOFF在可重定位的ELF图像中键入重定位条目?我的意思是,我可以强制GCC使用R_386_PC32R_386_32键入重定位而不是GOT类型重定位吗?

如果没有,你能解释实施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
http://wiki.osdev.org/ELF

ama*_*eka 7

最后我破解了!
不,不可能将GCC限制为使用非GOT类型重定位输出.
现在如何解决GOT类型的重定位?
GOT是由动态链接器分配的固定128KB内存块(它的工作原理是写入时复制),它包含重定位条目.
仅当ELF二进制文件中存在任何类型的(下面列出的)GOT重定位时,动态链接器才会分配GOT.

R_386_GOTOFF (== 0x9)
此重定位类型计算符号的值与全局偏移表的地址之间的差异.它还指示链接编辑器创建全局偏移表.

R_386_GOTPC (== 0xA)
此重定位类型类似于R_386_PC32,除了它在计算中使用全局偏移表的地址.

如何实施?
注意:以下代码段属于受闭源许可证保护的Atom OS源代码.但我(Atom Developer)特此声明此代码段可以免费使用:)

    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");
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)