0

Motivation:

I want to test gcc's limition size of global offset table on my arch(x86).

What I have done:

use multiple undeclared functions in a shared library (gcc -nostdlib -shared -o got.so ./got.c)

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

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

and 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
......

As above shows, the global offset table filled by fun1-8, but to fill reach the limition size, it is far from enough. I can think of two ways:

  • use a decent editor like emacs to generate more functions like these
  • use a decent codegen to generate such codes at preprocess time like macro (but I cannot find a solution with macro)

Of course, there may be more ways to achieve this goal.

Question:

How to reach the limit of the global offset table?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Chen Li
  • 4,824
  • 3
  • 28
  • 55
  • Is there, in fact, a limit? Most GNU programs try to avoid fixed limits, and I would certainly expect gcc to aspire to that. – Steve Summit Jul 15 '19 at 01:35
  • @SteveSummit It does have(with given arch). https://www.quora.com/What-is-the-difference-between-the-GCC-compiler-flags-fPIC-and-fpic-When-should-one-use-one-the-other-or-both – Chen Li Jul 15 '19 at 01:39
  • Well, there's an almost unlimited number of ways of automatically creating long lists of repetitive code like `extern int testvariable1, testvariable2, testvariable3;` or `fun1(); fun2(); fun3();`. Me, I have a handy program [`count`](https://www.eskimo.com/~scs/src/#count) that I'd use like this: `count 1 1000 1 "extern int testvariable%d;"` or `count 1 1000 1 "fun%d();"` – Steve Summit Jul 15 '19 at 02:21

1 Answers1

1

Before testing a limit, it is often helpful to know what the limit is. The tricks for declaring thousands of functions would be overkill if all you need is a dozen. So what are the size limitations of a GOT? According to Red Hat: "These maximums are 8k on the SPARC and 32k on the m68k and RS/6000. The 386 has no such limit."

There are two takeaways from knowing the limits. First, trying to overload the GOT does require a method that can reasonably easily generate thousands of GOT entries. Second, on your architecture (x86), this is a hopeless task as there is no limit.

(For those interested in how I found that link: I just searched the web for "global offset table size restriction".)


For those on other architectures, I suppose an easy way to expand the question's example code is to write another program to generate it.

#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";
}

Compile and run this to generate a got.c file that calls more functions than will fit in a m68k's global offset table format.

JaMiT
  • 14,422
  • 4
  • 15
  • 31
  • Admittedly, to find out that there is no limit on the x86, all one has to do is follow the link provided by @陳力 in a comment and read to the part that says "On other platforms (like x86), it makes no difference". – JaMiT Jul 15 '19 at 04:48