-1

动机:

我想在我的 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 这样不错的编辑器来生成更多这样的功能
  • 使用一个像样的代码生成器在预处理时生成这样的代码,比如宏(但我找不到宏的解决方案)

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

问题:

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

4

1 回答 1

1

在测试极限之前,了解极限是什么通常很有帮助。如果您只需要一打,那么声明数千个函数的技巧将是矫枉过正。那么 GOT 的尺寸限制是什么?根据 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 的全局偏移表格式。

于 2019-07-15T04:45:48.637 回答