如何填写全局偏移表?

时间:2019-07-15 01:28:18

标签: c++ c linker shared-libraries got

动机:

我想在我的arch(x86)上测试gcc的全局偏移表的限制大小。

我做了什么:

在共享库(gcc -nostdlib -shared -o got.so ./got.c)中使用多个未声明的函数

// got.c
extern int itestvariable1;
extern int testvariable2;

 void test(void)
{
  fun1();
  ...
  fun8();
}

readelf --relocs ./got.so

Relocation section '.rela.plt' at offset 0x3a8 contains 8 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000004018  000100000007 R_X86_64_JUMP_SLO 0000000000000000 fun7 + 0
000000004020  000200000007 R_X86_64_JUMP_SLO 0000000000000000 fun3 + 0
000000004028  000300000007 R_X86_64_JUMP_SLO 0000000000000000 fun4 + 0
000000004030  000400000007 R_X86_64_JUMP_SLO 0000000000000000 fun8 + 0
000000004038  000500000007 R_X86_64_JUMP_SLO 0000000000000000 fun2 + 0
000000004040  000600000007 R_X86_64_JUMP_SLO 0000000000000000 fun6 + 0
000000004048  000700000007 R_X86_64_JUMP_SLO 0000000000000000 fun1 + 0
000000004050  000800000007 R_X86_64_JUMP_SLO 0000000000000000 fun5 + 0
......

如上所示,全局偏移表由fun1-8填充,但要填充以达到限制大小,还远远不够。我可以想到两种方式:

  • 使用像emacs这样的体面的编辑器来生成更多类似的功能
  • 使用像样的代码生成器在预处理时像宏一样生成此类代码(但我找不到宏解决方案)

当然,可能有更多方法可以实现此目标。

问题:

如何达到全局偏移表的极限?

1 个答案:

答案 0 :(得分:1)

在测试极限值之前,了解极限值通常会很有帮助。如果您只需要一打,那么声明数千个功能的技巧就太过分了。那么,GOT的尺寸限制是什么? According to Red Hat“ SPARC的最大值为8k,m68k和RS / 6000的最大值为32k。386没有这样的限制。”

了解限制有两个要点。首先,试图使GOT过载确实需要一种可以合理地轻松生成数千个GOT条目的方法。其次,在您的体系结构(x86)上,这是没有希望的任务,因为它没有限制。

(对于那些对我如何找到该链接感兴趣的人:我只是在网上搜索“全局偏移表大小限制”。)


对于其他架构的人,我想扩展问题示例代码的一种简单方法是编写另一个程序来生成它。

#include <fstream>

constexpr unsigned NUM_FUN = 70000;

int main()
{
    std::ofstream out("got.c");

    out << "void test(void)\n{\n";
    for ( unsigned i = 0; i < NUM_FUN; ++i )
        out << "\tfun" << i << "();\n";
    out << "}\n";
}

编译并运行该文件,以生成一个got.c文件,该文件调用的功能比m68k的全局偏移表格式所能容纳的功能更多。