summaryrefslogtreecommitdiffstats
path: root/build/unix/elfhack/test.c
diff options
context:
space:
mode:
Diffstat (limited to 'build/unix/elfhack/test.c')
-rw-r--r--build/unix/elfhack/test.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/build/unix/elfhack/test.c b/build/unix/elfhack/test.c
new file mode 100644
index 0000000000..f690ad8f6a
--- /dev/null
+++ b/build/unix/elfhack/test.c
@@ -0,0 +1,221 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifdef DEF
+DEF(This)
+DEF(is)
+DEF(a)
+DEF(test)
+DEF(of)
+DEF(string)
+DEF(array)
+DEF(for)
+DEF(use)
+DEF(with)
+DEF(elfhack)
+DEF(to)
+DEF(see)
+DEF(whether)
+DEF(it)
+DEF(breaks)
+DEF(anything)
+DEF(but)
+DEF(one)
+DEF(needs)
+DEF(quite)
+DEF(some)
+DEF(strings)
+DEF(before)
+DEF(the)
+DEF(program)
+DEF(can)
+DEF(do)
+DEF(its)
+DEF(work)
+DEF(efficiently)
+DEF(Without)
+DEF(enough)
+DEF(data)
+DEF(relocation)
+DEF(sections)
+DEF(are)
+// clang-format off
+DEF(not)
+// clang-format on
+DEF(sufficiently)
+DEF(large)
+DEF(and)
+DEF(injected)
+DEF(code)
+DEF(wouldnt)
+DEF(fit)
+DEF(Said)
+DEF(otherwise)
+DEF(we)
+DEF(need)
+DEF(more)
+DEF(words)
+DEF(than)
+DEF(up)
+DEF(here)
+DEF(so)
+DEF(that)
+DEF(relocations)
+DEF(take)
+DEF(significant)
+DEF(bytes)
+DEF(amounts)
+DEF(which)
+DEF(isnt)
+DEF(exactly)
+DEF(easily)
+DEF(achieved)
+DEF(like)
+DEF(this)
+DEF(Actually)
+DEF(I)
+DEF(must)
+DEF(cheat)
+DEF(by)
+DEF(including)
+DEF(these)
+DEF(phrases)
+DEF(several)
+DEF(times)
+
+#else
+# pragma GCC visibility push(default)
+# include <stdlib.h>
+# include <stdio.h>
+
+# define DEF(w) static const char str_##w[] = #w;
+# include "test.c"
+# undef DEF
+
+const char* strings[] = {
+# define DEF(w) str_##w,
+# include "test.c"
+# include "test.c"
+# include "test.c"
+};
+
+/* Create a hole between two zones of relative relocations */
+int small_hole[] = {42, 42, 42, 42};
+
+const char* strings2[] = {
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+};
+
+/* Create a bigger hole between two zones of relative relocations */
+int bigger_hole[] = {
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+};
+
+const char* strings3[] = {
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# undef DEF
+};
+
+static int ret = 1;
+
+int print_status() {
+ fprintf(stderr, "%s\n", ret ? "FAIL" : "PASS");
+ return ret;
+}
+
+/* On ARM, this creates a .tbss section before .init_array, which
+ * elfhack could then pick instead of .init_array.
+ * Also, when .tbss is big enough, elfhack may wrongfully consider
+ * following sections as part of the PT_TLS segment.
+ * Finally, gold makes TLS segments end on an aligned virtual address,
+ * even when the underlying section ends before that, and elfhack
+ * sanity checks may yield an error. */
+__thread int foo;
+__thread long long int bar[512];
+
+/* We need a .bss that can hold at least 2 pointers. The static in
+ * end_test() plus this variable should do. */
+size_t dummy;
+
+void end_test() {
+ static size_t count = 0;
+ /* Only exit when both constructors have been called */
+ if (++count == 2) {
+ ret = 0;
+ // Avoid the dummy variable being stripped out at link time because
+ // it's unused.
+ dummy = 1;
+ }
+}
+
+void test() {
+ int i = 0, j = 0, k = 0;
+# define DEF_(a, i, w) \
+ if (a[i++] != str_##w) return;
+# define DEF(w) DEF_(strings, i, w)
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# undef DEF
+# define DEF(w) DEF_(strings2, j, w)
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# undef DEF
+# define DEF(w) DEF_(strings3, k, w)
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# include "test.c"
+# undef DEF
+ if (i != sizeof(strings) / sizeof(strings[0]) &&
+ j != sizeof(strings2) / sizeof(strings2[0]) &&
+ k != sizeof(strings3) / sizeof(strings3[0]))
+ fprintf(stderr, "WARNING: Test doesn't cover the whole array\n");
+ end_test();
+}
+
+# pragma GCC visibility pop
+#endif