首页
学习
活动
专区
圈层
工具
发布

GCC致残
EN

Stack Overflow用户
提问于 2016-06-19 00:44:39
回答 3查看 6.5K关注 0票数 11

全局偏移表(GOT):用于ELF符号的重新定位(实现GCC),它帮助共享相同的二进制文件,而不对每个进程进行任何特定的链接。从而减少内存中相同二值图像的副本。

我的问题是,在可重定位的ELF图像中是否有任何方法禁用R_386_GOT32R_386_GOTOFF类型的重新定位条目?我的意思是,我可以强迫GCC使用R_386_PC32R_386_32类型的重新定位而不是得到类型的重新定位吗?

如果没有,你能解释一下实现GOT的方法吗?我正在为ELF编写一个动态链接和加载库。

编辑:

参考链接

01/html/819-0690/chapter6-74186.html

http://man7.org/linux/man-pages/man8/ld.so.8.html

http://wiki.osdev.org/ELF

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-06-25 15:33:41

终于破解了!

不,这是不可能限制GCC的产出与未得到的类型搬迁.

现在如何解决得到的类型迁移?

GOT是由动态链接器分配的固定128 by内存块(它工作在写上复制的原理),其中包含用于重定位的条目。

只有当ELF二进制文件中存在任何类型(如下所列)重新定位时,动态链接器才会分配GOT。

R_386_GOTOFF (== 0x9)

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

R_386_GOTPC (== 0xA)

这种重定位类型类似于R_386_PC32,只不过它在计算中使用了全局偏移表的地址。

如何实现?

注意:下面的代码片段属于http://atomixos.com/源代码,它受到封闭源代码许可的保护。但是我(Atom Developer)在此声明这个代码片段是免费使用的:)

代码语言:javascript
复制
    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");
            }
        }
    }
票数 7
EN

Stack Overflow用户

发布于 2017-11-26 05:43:03

gcc -将把迁移类型限制在R_386_PC32和R_386_32 (或者至少在我的情况下有效)。接受的答案是误导的,声称这是不可能的。

票数 2
EN

Stack Overflow用户

发布于 2017-05-10 07:04:11

您可以尝试使用gcc选项:-fPIE或-fpie,可以禁用GOT。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37902940

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档