$ python evil_linker_torture.py 2000 50 100 2000000 ok so it's pretty basic, and arguments of "2000 50 10 1000000" resulted in around a 10-15 second linker phase, which top showed to be getting up to around the 2-3GB resident memory range. "2000 50 100 2000000" should start to make even a system with 64GB RAM start to feel the pain.
evil_linker_torture.py N M O P generates N files with M functions calling O randomly-selected functions where each file contains a static char of size P that is *deliberately* put into the code segment by being initialised with a non-zero value, exactly and precisely as you should never do because... surpriiise! it adversely impacts the binary size. i'm just running the above, will hit "send" now in case i can't hit ctrl-c in time on the linker phase... goodbye world... :) l.
#!/usr/bin/env python import sys import random maketemplate = """\ CC := gcc CFILES:=$(shell ls | grep "\.c") OBJS:=$(CFILES:%.c=%.o) DEPS := $(CFILES:%.c=%.d) CFLAGS := -g -g -g LDFLAGS := -g -g -g %.d: %.c $(CC) $(CFLAGS) -MM -o $@ $< %.o: %.c $(CC) $(CFLAGS) -o $@ -c $< # $(CC) $(CFLAGS) -include $(DEPS) -o $@ $< main: $(OBJS) $(CC) $(OBJS) $(LDFLAGS) -o main """ def gen_makefile(): with open("Makefile", "w") as f: f.write(maketemplate) def gen_headers(num_files, num_fns): for fnum in range(num_files): with open("hdr{}.h".format(fnum), "w") as f: for fn_num in range(num_fns): f.write("extern int fn_{}_{}(int arg1);\n".format(fnum, fn_num)) def gen_c_code(num_files, num_fns, num_calls, static_sz): for fnum in range(num_files): with open("src{}.c".format(fnum), "w") as f: for hfnum in range(num_files): f.write('#include "hdr{}.h"\n'.format(hfnum)) f.write('static char data[%d] = {1};\n' % static_sz) for fn_num in range(num_fns): f.write("int fn_%d_%d(int arg1)\n{\n" % (fnum, fn_num)) f.write("\tint arg = arg1 + 1;\n") for nc in range(num_calls): cnum = random.randint(0, num_fns-1) cfile = random.randint(0, num_files-1) f.write("\targ += fn_{}_{}(arg);\n".format(cfile, cnum)) f.write("\treturn arg;\n") f.write("}\n") if fnum != 0: continue f.write("int main(int argc, char *argv[])\n{\n") f.write("\tint arg = 0;\n") for nc in range(num_calls): cnum = random.randint(0, num_fns-1) cfile = random.randint(0, num_files-1) f.write("\targ += fn_{}_{}(arg);\n".format(cfile, cnum)) f.write("\treturn 0;\n") f.write("}\n") if __name__ == '__main__': num_files = int(sys.argv[1]) num_fns = int(sys.argv[2]) num_calls = int(sys.argv[3]) static_sz = int(sys.argv[4]) gen_makefile() gen_headers(num_files, num_fns) gen_c_code(num_files, num_fns, num_calls, static_sz)