authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-09 23:43:13+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-16 19:33:05+02:00
log67a02bee2c75faba31bf3f11fb59f7b7b8c2b9ea
tree547dba248b8bb4676ae13269a2a03d65d0d875df
parent81b68c7465580af94ae9a7c2969eb5a7667392db

elf: port more linker tests


1 files changed, 872 insertions(+), 18 deletions(-)

test/link/elf.zig+872-18
...@@ -82,6 +82,26 @@ pub fn build(b: *Build) void {...@@ -82,6 +82,26 @@ pub fn build(b: *Build) void {
82 elf_step.dependOn(testTlsDfStaticTls(b, .{ .target = glibc_target }));82 elf_step.dependOn(testTlsDfStaticTls(b, .{ .target = glibc_target }));
83 elf_step.dependOn(testTlsDso(b, .{ .target = glibc_target }));83 elf_step.dependOn(testTlsDso(b, .{ .target = glibc_target }));
84 elf_step.dependOn(testTlsGd(b, .{ .target = glibc_target }));84 elf_step.dependOn(testTlsGd(b, .{ .target = glibc_target }));
85 elf_step.dependOn(testTlsGdNoPlt(b, .{ .target = glibc_target }));
86 elf_step.dependOn(testTlsGdToIe(b, .{ .target = glibc_target }));
87 elf_step.dependOn(testTlsIe(b, .{ .target = glibc_target }));
88 elf_step.dependOn(testTlsLargeAlignment(b, .{ .target = glibc_target }));
89 elf_step.dependOn(testTlsLargeTbss(b, .{ .target = glibc_target }));
90 elf_step.dependOn(testTlsLargeStaticImage(b, .{ .target = glibc_target }));
91 elf_step.dependOn(testTlsLd(b, .{ .target = glibc_target }));
92 elf_step.dependOn(testTlsLdDso(b, .{ .target = glibc_target }));
93 elf_step.dependOn(testTlsLdNoPlt(b, .{ .target = glibc_target }));
94 // https://github.com/ziglang/zig/issues/17430
95 // elf_step.dependOn(testTlsNoPic(b, .{ .target = glibc_target }));
96 // TODO
97 // elf_step.dependOn(testTlsOffsetAlignment(b, .{ .target = glibc_target }));
98 elf_step.dependOn(testTlsPic(b, .{ .target = glibc_target }));
99 elf_step.dependOn(testTlsSmallAlignment(b, .{ .target = glibc_target }));
100 elf_step.dependOn(testWeakExports(b, .{ .target = glibc_target }));
101 elf_step.dependOn(testWeakUndefsDso(b, .{ .target = glibc_target }));
102 elf_step.dependOn(testZNow(b, .{ .target = glibc_target }));
103 elf_step.dependOn(testZStackSize(b, .{ .target = glibc_target }));
104 elf_step.dependOn(testZText(b, .{ .target = glibc_target }));
85}105}
86106
87fn testAbsSymbols(b: *Build, opts: Options) *Step {107fn testAbsSymbols(b: *Build, opts: Options) *Step {
...@@ -1924,37 +1944,871 @@ fn testTlsGd(b: *Build, opts: Options) *Step {...@@ -1924,37 +1944,871 @@ fn testTlsGd(b: *Build, opts: Options) *Step {
1924 return test_step;1944 return test_step;
1925}1945}
19261946
1927fn testTlsStatic(b: *Build, opts: Options) *Step {1947fn testTlsGdNoPlt(b: *Build, opts: Options) *Step {
1928 const test_step = addTestStep(b, "tls-static", opts);1948 const test_step = addTestStep(b, "tls-gd-no-plt", opts);
19291949
1930 const exe = addExecutable(b, "test", opts);1950 const obj = addObject(b, "obj", opts);
1931 addCSourceBytes(exe,1951 addCSourceBytes(obj,
1932 \\#include <stdio.h>1952 \\#include <stdio.h>
1933 \\_Thread_local int a = 10;1953 \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int x1 = 1;
1934 \\_Thread_local int b;1954 \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int x2;
1935 \\_Thread_local char c = 'a';1955 \\__attribute__((tls_model("global-dynamic"))) extern _Thread_local int x3;
1936 \\int main(int argc, char* argv[]) {1956 \\__attribute__((tls_model("global-dynamic"))) extern _Thread_local int x4;
1937 \\ printf("%d %d %c\n", a, b, c);1957 \\int get_x5();
1938 \\ a += 1;1958 \\int get_x6();
1939 \\ b += 1;1959 \\int main() {
1940 \\ c += 1;1960 \\ x2 = 2;
1941 \\ printf("%d %d %c\n", a, b, c);1961 \\
1962 \\ printf("%d %d %d %d %d %d\n", x1, x2, x3, x4, get_x5(), get_x6());
1963 \\ return 0;
1964 \\}
1965 , &.{"-fno-plt"});
1966 obj.force_pic = true;
1967 obj.linkLibC();
1968
1969 const a_so = addSharedLibrary(b, "a", opts);
1970 addCSourceBytes(a_so,
1971 \\__attribute__((tls_model("global-dynamic"))) _Thread_local int x3 = 3;
1972 \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int x5 = 5;
1973 \\int get_x5() { return x5; }
1974 , &.{"-fno-plt"});
1975
1976 const b_so = addSharedLibrary(b, "b", opts);
1977 addCSourceBytes(b_so,
1978 \\__attribute__((tls_model("global-dynamic"))) _Thread_local int x4 = 4;
1979 \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int x6 = 6;
1980 \\int get_x6() { return x6; }
1981 , &.{"-fno-plt"});
1982 // b_so.link_relax = false; // TODO
1983
1984 {
1985 const exe = addExecutable(b, "main1", opts);
1986 exe.addObject(obj);
1987 exe.linkLibrary(a_so);
1988 exe.linkLibrary(b_so);
1989 exe.linkLibC();
1990
1991 const run = addRunArtifact(exe);
1992 run.expectStdOutEqual("1 2 3 4 5 6\n");
1993 test_step.dependOn(&run.step);
1994 }
1995
1996 {
1997 const exe = addExecutable(b, "main2", opts);
1998 exe.addObject(obj);
1999 exe.linkLibrary(a_so);
2000 exe.linkLibrary(b_so);
2001 exe.linkLibC();
2002 // exe.link_relax = false; // TODO
2003
2004 const run = addRunArtifact(exe);
2005 run.expectStdOutEqual("1 2 3 4 5 6\n");
2006 test_step.dependOn(&run.step);
2007 }
2008
2009 return test_step;
2010}
2011
2012fn testTlsGdToIe(b: *Build, opts: Options) *Step {
2013 const test_step = addTestStep(b, "tls-gd-to-ie", opts);
2014
2015 const a_o = addObject(b, "a", opts);
2016 addCSourceBytes(a_o,
2017 \\#include <stdio.h>
2018 \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int x1 = 1;
2019 \\__attribute__((tls_model("global-dynamic"))) _Thread_local int x2 = 2;
2020 \\__attribute__((tls_model("global-dynamic"))) _Thread_local int x3;
2021 \\int foo() {
2022 \\ x3 = 3;
2023 \\
2024 \\ printf("%d %d %d\n", x1, x2, x3);
1942 \\ return 0;2025 \\ return 0;
1943 \\}2026 \\}
1944 , &.{});2027 , &.{});
2028 a_o.linkLibC();
2029 a_o.force_pic = true;
2030
2031 const b_o = addObject(b, "b", opts);
2032 addCSourceBytes(b_o,
2033 \\int foo();
2034 \\int main() { foo(); }
2035 , &.{});
2036 b_o.force_pic = true;
2037
2038 {
2039 const dso = addSharedLibrary(b, "a", opts);
2040 dso.addObject(a_o);
2041
2042 const exe = addExecutable(b, "main", opts);
2043 exe.addObject(b_o);
2044 exe.linkLibrary(dso);
2045 exe.linkLibC();
2046
2047 const run = addRunArtifact(exe);
2048 run.expectStdOutEqual("1 2 3\n");
2049 test_step.dependOn(&run.step);
2050 }
2051
2052 {
2053 const dso = addSharedLibrary(b, "a", opts);
2054 dso.addObject(a_o);
2055 // dso.link_relax = false; // TODO
2056
2057 const exe = addExecutable(b, "main", opts);
2058 exe.addObject(b_o);
2059 exe.linkLibrary(dso);
2060 exe.linkLibC();
2061
2062 const run = addRunArtifact(exe);
2063 run.expectStdOutEqual("1 2 3\n");
2064 test_step.dependOn(&run.step);
2065 }
2066
2067 // {
2068 // const dso = addSharedLibrary(b, "a", opts);
2069 // dso.addObject(a_o);
2070 // dso.link_z_nodlopen = true;
2071
2072 // const exe = addExecutable(b, "main", opts);
2073 // exe.addObject(b_o);
2074 // exe.linkLibrary(dso);
2075
2076 // const run = addRunArtifact(exe);
2077 // run.expectStdOutEqual("1 2 3\n");
2078 // test_step.dependOn(&run.step);
2079 // }
2080
2081 // {
2082 // const dso = addSharedLibrary(b, "a", opts);
2083 // dso.addObject(a_o);
2084 // dso.link_relax = false;
2085 // dso.link_z_nodlopen = true;
2086
2087 // const exe = addExecutable(b, "main", opts);
2088 // exe.addObject(b_o);
2089 // exe.linkLibrary(dso);
2090
2091 // const run = addRunArtifact(exe);
2092 // run.expectStdOutEqual("1 2 3\n");
2093 // test_step.dependOn(&run.step);
2094 // }
2095
2096 return test_step;
2097}
2098
2099fn testTlsIe(b: *Build, opts: Options) *Step {
2100 const test_step = addTestStep(b, "tls-ie", opts);
2101
2102 const dso = addSharedLibrary(b, "a", opts);
2103 addCSourceBytes(dso,
2104 \\#include <stdio.h>
2105 \\__attribute__((tls_model("initial-exec"))) static _Thread_local int foo;
2106 \\__attribute__((tls_model("initial-exec"))) static _Thread_local int bar;
2107 \\void set() {
2108 \\ foo = 3;
2109 \\ bar = 5;
2110 \\}
2111 \\void print() {
2112 \\ printf("%d %d ", foo, bar);
2113 \\}
2114 , &.{});
2115 dso.linkLibC();
2116
2117 const main_o = addObject(b, "main", opts);
2118 addCSourceBytes(main_o,
2119 \\#include <stdio.h>
2120 \\_Thread_local int baz;
2121 \\void set();
2122 \\void print();
2123 \\int main() {
2124 \\ baz = 7;
2125 \\ print();
2126 \\ set();
2127 \\ print();
2128 \\ printf("%d\n", baz);
2129 \\}
2130 , &.{});
2131 main_o.linkLibC();
2132
2133 const exp_stdout = "0 0 3 5 7\n";
2134
2135 {
2136 const exe = addExecutable(b, "main", opts);
2137 exe.addObject(main_o);
2138 exe.linkLibrary(dso);
2139 exe.linkLibC();
2140
2141 const run = addRunArtifact(exe);
2142 run.expectStdOutEqual(exp_stdout);
2143 test_step.dependOn(&run.step);
2144 }
2145
2146 {
2147 const exe = addExecutable(b, "main", opts);
2148 exe.addObject(main_o);
2149 exe.linkLibrary(dso);
2150 exe.linkLibC();
2151 // exe.link_relax = false; // TODO
2152
2153 const run = addRunArtifact(exe);
2154 run.expectStdOutEqual(exp_stdout);
2155 test_step.dependOn(&run.step);
2156 }
2157
2158 return test_step;
2159}
2160
2161fn testTlsLargeAlignment(b: *Build, opts: Options) *Step {
2162 const test_step = addTestStep(b, "tls-large-alignment", opts);
2163
2164 const a_o = addObject(b, "a", opts);
2165 addCSourceBytes(a_o,
2166 \\__attribute__((section(".tdata1")))
2167 \\_Thread_local int x = 42;
2168 , &.{"-std=c11"});
2169 a_o.force_pic = true;
2170
2171 const b_o = addObject(b, "b", opts);
2172 addCSourceBytes(b_o,
2173 \\__attribute__((section(".tdata2")))
2174 \\_Alignas(256) _Thread_local int y[] = { 1, 2, 3 };
2175 , &.{"-std=c11"});
2176 b_o.force_pic = true;
2177
2178 const c_o = addObject(b, "c", opts);
2179 addCSourceBytes(c_o,
2180 \\#include <stdio.h>
2181 \\extern _Thread_local int x;
2182 \\extern _Thread_local int y[];
2183 \\int main() {
2184 \\ printf("%d %d %d %d\n", x, y[0], y[1], y[2]);
2185 \\}
2186 , &.{});
2187 c_o.force_pic = true;
2188 c_o.linkLibC();
2189
2190 {
2191 const dso = addSharedLibrary(b, "a", opts);
2192 dso.addObject(a_o);
2193 dso.addObject(b_o);
2194
2195 const exe = addExecutable(b, "main", opts);
2196 exe.addObject(c_o);
2197 exe.linkLibrary(dso);
2198 exe.linkLibC();
2199
2200 const run = addRunArtifact(exe);
2201 run.expectStdOutEqual("42 1 2 3\n");
2202 test_step.dependOn(&run.step);
2203 }
2204
2205 {
2206 const exe = addExecutable(b, "main", opts);
2207 exe.addObject(a_o);
2208 exe.addObject(b_o);
2209 exe.addObject(c_o);
2210 exe.linkLibC();
2211
2212 const run = addRunArtifact(exe);
2213 run.expectStdOutEqual("42 1 2 3\n");
2214 test_step.dependOn(&run.step);
2215 }
2216
2217 return test_step;
2218}
2219
2220fn testTlsLargeTbss(b: *Build, opts: Options) *Step {
2221 const test_step = addTestStep(b, "tls-large-tbss", opts);
2222
2223 const exe = addExecutable(b, "main", opts);
2224 addAsmSourceBytes(exe,
2225 \\.globl x, y
2226 \\.section .tbss,"awT",@nobits
2227 \\x:
2228 \\.zero 1024
2229 \\.section .tcommon,"awT",@nobits
2230 \\y:
2231 \\.zero 1024
2232 );
2233 addCSourceBytes(exe,
2234 \\#include <stdio.h>
2235 \\extern _Thread_local char x[1024000];
2236 \\extern _Thread_local char y[1024000];
2237 \\int main() {
2238 \\ x[0] = 3;
2239 \\ x[1023] = 5;
2240 \\ printf("%d %d %d %d %d %d\n", x[0], x[1], x[1023], y[0], y[1], y[1023]);
2241 \\}
2242 , &.{});
1945 exe.linkLibC();2243 exe.linkLibC();
19462244
1947 const run = addRunArtifact(exe);2245 const run = addRunArtifact(exe);
1948 run.expectStdOutEqual(2246 run.expectStdOutEqual("3 0 5 0 0 0\n");
1949 \\10 0 a2247 test_step.dependOn(&run.step);
1950 \\11 1 b2248
1951 \\2249 return test_step;
1952 );2250}
2251
2252fn testTlsLargeStaticImage(b: *Build, opts: Options) *Step {
2253 const test_step = addTestStep(b, "tls-large-static-image", opts);
2254
2255 const exe = addExecutable(b, "main", opts);
2256 addCSourceBytes(exe, "_Thread_local int x[] = { 1, 2, 3, [10000] = 5 };", &.{});
2257 addCSourceBytes(exe,
2258 \\#include <stdio.h>
2259 \\extern _Thread_local int x[];
2260 \\int main() {
2261 \\ printf("%d %d %d %d %d\n", x[0], x[1], x[2], x[3], x[10000]);
2262 \\}
2263 , &.{});
2264 exe.force_pic = true;
2265 exe.linkLibC();
2266
2267 const run = addRunArtifact(exe);
2268 run.expectStdOutEqual("1 2 3 0 5\n");
1953 test_step.dependOn(&run.step);2269 test_step.dependOn(&run.step);
19542270
1955 return test_step;2271 return test_step;
1956}2272}
19572273
2274fn testTlsLd(b: *Build, opts: Options) *Step {
2275 const test_step = addTestStep(b, "tls-ld", opts);
2276
2277 const main_o = addObject(b, "main", opts);
2278 addCSourceBytes(main_o,
2279 \\#include <stdio.h>
2280 \\extern _Thread_local int foo;
2281 \\static _Thread_local int bar;
2282 \\int *get_foo_addr() { return &foo; }
2283 \\int *get_bar_addr() { return &bar; }
2284 \\int main() {
2285 \\ bar = 5;
2286 \\ printf("%d %d %d %d\n", *get_foo_addr(), *get_bar_addr(), foo, bar);
2287 \\ return 0;
2288 \\}
2289 , &.{"-ftls-model=local-dynamic"});
2290 main_o.force_pic = true;
2291 main_o.linkLibC();
2292
2293 const a_o = addObject(b, "a", opts);
2294 addCSourceBytes(a_o, "_Thread_local int foo = 3;", &.{"-ftls-model=local-dynamic"});
2295 a_o.force_pic = true;
2296
2297 const exp_stdout = "3 5 3 5\n";
2298
2299 {
2300 const exe = addExecutable(b, "main", opts);
2301 exe.addObject(main_o);
2302 exe.addObject(a_o);
2303 exe.linkLibC();
2304
2305 const run = addRunArtifact(exe);
2306 run.expectStdOutEqual(exp_stdout);
2307 test_step.dependOn(&run.step);
2308 }
2309
2310 {
2311 const exe = addExecutable(b, "main", opts);
2312 exe.addObject(main_o);
2313 exe.addObject(a_o);
2314 exe.linkLibC();
2315 // exe.link_relax = false; // TODO
2316
2317 const run = addRunArtifact(exe);
2318 run.expectStdOutEqual(exp_stdout);
2319 test_step.dependOn(&run.step);
2320 }
2321
2322 return test_step;
2323}
2324
2325fn testTlsLdDso(b: *Build, opts: Options) *Step {
2326 const test_step = addTestStep(b, "tls-ld-dso", opts);
2327
2328 const dso = addSharedLibrary(b, "a", opts);
2329 addCSourceBytes(dso,
2330 \\static _Thread_local int def, def1;
2331 \\int f0() { return ++def; }
2332 \\int f1() { return ++def1 + def; }
2333 , &.{"-ftls-model=local-dynamic"});
2334
2335 const exe = addExecutable(b, "main", opts);
2336 addCSourceBytes(exe,
2337 \\#include <stdio.h>
2338 \\extern int f0();
2339 \\extern int f1();
2340 \\int main() {
2341 \\ int x = f0();
2342 \\ int y = f1();
2343 \\ printf("%d %d\n", x, y);
2344 \\ return 0;
2345 \\}
2346 , &.{});
2347 exe.linkLibrary(dso);
2348 exe.linkLibC();
2349
2350 const run = addRunArtifact(exe);
2351 run.expectStdOutEqual("1 2\n");
2352 test_step.dependOn(&run.step);
2353
2354 return test_step;
2355}
2356
2357fn testTlsLdNoPlt(b: *Build, opts: Options) *Step {
2358 const test_step = addTestStep(b, "tls-ld-no-plt", opts);
2359
2360 const a_o = addObject(b, "a", opts);
2361 addCSourceBytes(a_o,
2362 \\#include <stdio.h>
2363 \\extern _Thread_local int foo;
2364 \\static _Thread_local int bar;
2365 \\int *get_foo_addr() { return &foo; }
2366 \\int *get_bar_addr() { return &bar; }
2367 \\int main() {
2368 \\ bar = 5;
2369 \\
2370 \\ printf("%d %d %d %d\n", *get_foo_addr(), *get_bar_addr(), foo, bar);
2371 \\ return 0;
2372 \\}
2373 , &.{ "-ftls-model=local-dynamic", "-fno-plt" });
2374 a_o.linkLibC();
2375 a_o.force_pic = true;
2376
2377 const b_o = addObject(b, "b", opts);
2378 addCSourceBytes(b_o, "_Thread_local int foo = 3;", &.{ "-ftls-model=local-dynamic", "-fno-plt" });
2379 b_o.force_pic = true;
2380
2381 {
2382 const exe = addExecutable(b, "main", opts);
2383 exe.addObject(a_o);
2384 exe.addObject(b_o);
2385 exe.linkLibC();
2386
2387 const run = addRunArtifact(exe);
2388 run.expectStdOutEqual("3 5 3 5\n");
2389 test_step.dependOn(&run.step);
2390 }
2391
2392 {
2393 const exe = addExecutable(b, "main", opts);
2394 exe.addObject(a_o);
2395 exe.addObject(b_o);
2396 exe.linkLibC();
2397 // exe.link_relax = false; // TODO
2398
2399 const run = addRunArtifact(exe);
2400 run.expectStdOutEqual("3 5 3 5\n");
2401 test_step.dependOn(&run.step);
2402 }
2403
2404 return test_step;
2405}
2406
2407fn testTlsNoPic(b: *Build, opts: Options) *Step {
2408 const test_step = addTestStep(b, "tls-no-pic", opts);
2409
2410 const exe = addExecutable(b, "main", opts);
2411 addCSourceBytes(exe,
2412 \\#include <stdio.h>
2413 \\__attribute__((tls_model("global-dynamic"))) extern _Thread_local int foo;
2414 \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int bar;
2415 \\int *get_foo_addr() { return &foo; }
2416 \\int *get_bar_addr() { return &bar; }
2417 \\int main() {
2418 \\ foo = 3;
2419 \\ bar = 5;
2420 \\
2421 \\ printf("%d %d %d %d\n", *get_foo_addr(), *get_bar_addr(), foo, bar);
2422 \\ return 0;
2423 \\}
2424 , .{});
2425 addCSourceBytes(exe,
2426 \\__attribute__((tls_model("global-dynamic"))) _Thread_local int foo;
2427 , &.{});
2428 exe.force_pic = false;
2429 exe.linkLibC();
2430
2431 const run = addRunArtifact(exe);
2432 run.expectStdOutEqual("3 5 3 5\n");
2433 test_step.dependOn(&run.step);
2434
2435 return test_step;
2436}
2437
2438fn testTlsOffsetAlignment(b: *Build, opts: Options) *Step {
2439 const test_step = addTestStep(b, "tls-offset-alignment", opts);
2440
2441 const dso = addSharedLibrary(b, "a", opts);
2442 addCSourceBytes(dso,
2443 \\#include <assert.h>
2444 \\#include <stdlib.h>
2445 \\
2446 \\// .tdata
2447 \\_Thread_local int x = 42;
2448 \\// .tbss
2449 \\__attribute__ ((aligned(64)))
2450 \\_Thread_local int y = 0;
2451 \\
2452 \\void *verify(void *unused) {
2453 \\ assert((unsigned long)(&y) % 64 == 0);
2454 \\ return NULL;
2455 \\}
2456 , &.{});
2457 dso.linkLibC();
2458
2459 const exe = addExecutable(b, "main", opts);
2460 addCSourceBytes(exe,
2461 \\#include <pthread.h>
2462 \\#include <dlfcn.h>
2463 \\#include <assert.h>
2464 \\void *(*verify)(void *);
2465 \\
2466 \\int main() {
2467 \\ void *handle = dlopen("a.so", RTLD_NOW);
2468 \\ assert(handle);
2469 \\ *(void**)(&verify) = dlsym(handle, "verify");
2470 \\ assert(verify);
2471 \\
2472 \\ pthread_t thread;
2473 \\
2474 \\ verify(NULL);
2475 \\
2476 \\ pthread_create(&thread, NULL, verify, NULL);
2477 \\ pthread_join(thread, NULL);
2478 \\}
2479 , &.{});
2480 exe.linkLibrary(dso);
2481 exe.linkLibC();
2482 exe.linkSystemLibrary2("dl", .{});
2483 exe.linkSystemLibrary2("pthread", .{});
2484 exe.force_pic = true;
2485
2486 const run = addRunArtifact(exe);
2487 run.expectExitCode(0);
2488 test_step.dependOn(&run.step);
2489
2490 return test_step;
2491}
2492
2493fn testTlsPic(b: *Build, opts: Options) *Step {
2494 const test_step = addTestStep(b, "tls-pic", opts);
2495
2496 const obj = addObject(b, "obj", opts);
2497 addCSourceBytes(obj,
2498 \\#include <stdio.h>
2499 \\__attribute__((tls_model("global-dynamic"))) extern _Thread_local int foo;
2500 \\__attribute__((tls_model("global-dynamic"))) static _Thread_local int bar;
2501 \\int *get_foo_addr() { return &foo; }
2502 \\int *get_bar_addr() { return &bar; }
2503 \\int main() {
2504 \\ bar = 5;
2505 \\
2506 \\ printf("%d %d %d %d\n", *get_foo_addr(), *get_bar_addr(), foo, bar);
2507 \\ return 0;
2508 \\}
2509 , &.{});
2510 obj.linkLibC();
2511 obj.force_pic = true;
2512
2513 const exe = addExecutable(b, "main", opts);
2514 addCSourceBytes(exe,
2515 \\__attribute__((tls_model("global-dynamic"))) _Thread_local int foo = 3;
2516 , &.{});
2517 exe.addObject(obj);
2518 exe.linkLibC();
2519
2520 const run = addRunArtifact(exe);
2521 run.expectStdOutEqual("3 5 3 5\n");
2522 test_step.dependOn(&run.step);
2523
2524 return test_step;
2525}
2526
2527fn testTlsSmallAlignment(b: *Build, opts: Options) *Step {
2528 const test_step = addTestStep(b, "tls-small-alignment", opts);
2529
2530 const a_o = addObject(b, "a", opts);
2531 addAsmSourceBytes(a_o,
2532 \\.text
2533 \\.byte 0
2534 );
2535 a_o.force_pic = true;
2536
2537 const b_o = addObject(b, "b", opts);
2538 addCSourceBytes(b_o, "_Thread_local char x = 42;", &.{"-std=c11"});
2539 b_o.force_pic = true;
2540
2541 const c_o = addObject(b, "c", opts);
2542 addCSourceBytes(c_o,
2543 \\#include <stdio.h>
2544 \\extern _Thread_local char x;
2545 \\int main() {
2546 \\ printf("%d\n", x);
2547 \\}
2548 , &.{});
2549 c_o.linkLibC();
2550 c_o.force_pic = true;
2551
2552 {
2553 const exe = addExecutable(b, "main", opts);
2554 exe.addObject(a_o);
2555 exe.addObject(b_o);
2556 exe.addObject(c_o);
2557 exe.linkLibC();
2558
2559 const run = addRunArtifact(exe);
2560 run.expectStdOutEqual("42\n");
2561 test_step.dependOn(&run.step);
2562 }
2563
2564 {
2565 const dso = addSharedLibrary(b, "a", opts);
2566 dso.addObject(a_o);
2567 dso.addObject(b_o);
2568
2569 const exe = addExecutable(b, "main", opts);
2570 exe.addObject(c_o);
2571 exe.linkLibrary(dso);
2572 exe.linkLibC();
2573
2574 const run = addRunArtifact(exe);
2575 run.expectStdOutEqual("42\n");
2576 test_step.dependOn(&run.step);
2577 }
2578
2579 return test_step;
2580}
2581
2582fn testTlsStatic(b: *Build, opts: Options) *Step {
2583 const test_step = addTestStep(b, "tls-static", opts);
2584
2585 const exe = addExecutable(b, "test", opts);
2586 addCSourceBytes(exe,
2587 \\#include <stdio.h>
2588 \\_Thread_local int a = 10;
2589 \\_Thread_local int b;
2590 \\_Thread_local char c = 'a';
2591 \\int main(int argc, char* argv[]) {
2592 \\ printf("%d %d %c\n", a, b, c);
2593 \\ a += 1;
2594 \\ b += 1;
2595 \\ c += 1;
2596 \\ printf("%d %d %c\n", a, b, c);
2597 \\ return 0;
2598 \\}
2599 , &.{});
2600 exe.linkLibC();
2601
2602 const run = addRunArtifact(exe);
2603 run.expectStdOutEqual(
2604 \\10 0 a
2605 \\11 1 b
2606 \\
2607 );
2608 test_step.dependOn(&run.step);
2609
2610 return test_step;
2611}
2612
2613fn testWeakExports(b: *Build, opts: Options) *Step {
2614 const test_step = addTestStep(b, "weak-exports", opts);
2615
2616 const obj = addObject(b, "obj", opts);
2617 addCSourceBytes(obj,
2618 \\#include <stdio.h>
2619 \\__attribute__((weak)) int foo();
2620 \\int main() {
2621 \\ printf("%d\n", foo ? foo() : 3);
2622 \\}
2623 , &.{});
2624 obj.linkLibC();
2625 obj.force_pic = true;
2626
2627 {
2628 const dso = addSharedLibrary(b, "a", opts);
2629 dso.addObject(obj);
2630 dso.linkLibC();
2631
2632 const check = dso.checkObject();
2633 check.checkInDynamicSymtab();
2634 check.checkContains("UND NOTYPE WEAK DEFAULT foo");
2635 test_step.dependOn(&check.step);
2636 }
2637
2638 {
2639 const exe = addExecutable(b, "main", opts);
2640 exe.addObject(obj);
2641 exe.linkLibC();
2642
2643 const check = exe.checkObject();
2644 check.checkInDynamicSymtab();
2645 check.checkNotPresent("UND NOTYPE WEAK DEFAULT foo");
2646 test_step.dependOn(&check.step);
2647
2648 const run = addRunArtifact(exe);
2649 run.expectStdOutEqual("3\n");
2650 test_step.dependOn(&run.step);
2651 }
2652
2653 return test_step;
2654}
2655
2656fn testWeakUndefsDso(b: *Build, opts: Options) *Step {
2657 const test_step = addTestStep(b, "weak-undef-dso", opts);
2658
2659 const dso = addSharedLibrary(b, "a", opts);
2660 addCSourceBytes(dso,
2661 \\__attribute__((weak)) int foo();
2662 \\int bar() { return foo ? foo() : -1; }
2663 , &.{});
2664
2665 {
2666 const exe = addExecutable(b, "main", opts);
2667 addCSourceBytes(exe,
2668 \\#include <stdio.h>
2669 \\int bar();
2670 \\int main() { printf("bar=%d\n", bar()); }
2671 , &.{});
2672 exe.linkLibrary(dso);
2673 exe.linkLibC();
2674
2675 const run = addRunArtifact(exe);
2676 run.expectStdOutEqual("bar=-1\n");
2677 test_step.dependOn(&run.step);
2678 }
2679
2680 {
2681 const exe = addExecutable(b, "main", opts);
2682 addCSourceBytes(exe,
2683 \\#include <stdio.h>
2684 \\int foo() { return 5; }
2685 \\int bar();
2686 \\int main() { printf("bar=%d\n", bar()); }
2687 , &.{});
2688 exe.linkLibrary(dso);
2689 exe.linkLibC();
2690
2691 const run = addRunArtifact(exe);
2692 run.expectStdOutEqual("bar=5\n");
2693 test_step.dependOn(&run.step);
2694 }
2695
2696 return test_step;
2697}
2698
2699fn testZNow(b: *Build, opts: Options) *Step {
2700 const test_step = addTestStep(b, "z-now", opts);
2701
2702 const obj = addObject(b, "obj", opts);
2703 addCSourceBytes(obj, "int main() { return 0; }", &.{});
2704 obj.force_pic = true;
2705
2706 {
2707 const dso = addSharedLibrary(b, "a", opts);
2708 dso.addObject(obj);
2709
2710 const check = dso.checkObject();
2711 check.checkInDynamicSection();
2712 check.checkContains("NOW");
2713 test_step.dependOn(&check.step);
2714 }
2715
2716 {
2717 const dso = addSharedLibrary(b, "a", opts);
2718 dso.addObject(obj);
2719 dso.link_z_lazy = true;
2720
2721 const check = dso.checkObject();
2722 check.checkInDynamicSection();
2723 check.checkNotPresent("NOW");
2724 test_step.dependOn(&check.step);
2725 }
2726
2727 return test_step;
2728}
2729
2730fn testZStackSize(b: *Build, opts: Options) *Step {
2731 const test_step = addTestStep(b, "z-stack-size", opts);
2732
2733 const exe = addExecutable(b, "main", opts);
2734 addCSourceBytes(exe, "int main() { return 0; }", &.{});
2735 exe.stack_size = 0x800000;
2736 exe.linkLibC();
2737
2738 const check = exe.checkObject();
2739 check.checkStart();
2740 check.checkExact("program headers");
2741 check.checkExact("type GNU_STACK");
2742 check.checkExact("memsz 800000");
2743 test_step.dependOn(&check.step);
2744
2745 return test_step;
2746}
2747
2748fn testZText(b: *Build, opts: Options) *Step {
2749 const test_step = addTestStep(b, "z-text", opts);
2750
2751 // Previously, following mold, this test tested text relocs present in a PIE executable.
2752 // However, as we want to cover musl AND glibc, it is now modified to test presence of
2753 // text relocs in a DSO which is then linked with an executable.
2754 // According to Rich and this thread https://www.openwall.com/lists/musl/2020/09/25/4
2755 // musl supports only a very limited number of text relocations and only in DSOs (and
2756 // rightly so!).
2757
2758 const a_o = addObject(b, "a", opts);
2759 addAsmSourceBytes(a_o,
2760 \\.globl fn1
2761 \\fn1:
2762 \\ sub $8, %rsp
2763 \\ movabs ptr, %rax
2764 \\ call *%rax
2765 \\ add $8, %rsp
2766 \\ ret
2767 );
2768
2769 const b_o = addObject(b, "b", opts);
2770 addCSourceBytes(b_o,
2771 \\int fn1();
2772 \\int fn2() {
2773 \\ return 3;
2774 \\}
2775 \\void *ptr = fn2;
2776 \\int fnn() {
2777 \\ return fn1();
2778 \\}
2779 , &.{});
2780 b_o.force_pic = true;
2781
2782 const dso = addSharedLibrary(b, "a", opts);
2783 dso.addObject(a_o);
2784 dso.addObject(b_o);
2785 dso.link_z_notext = true;
2786
2787 const exe = addExecutable(b, "main", opts);
2788 addCSourceBytes(exe,
2789 \\#include <stdio.h>
2790 \\int fnn();
2791 \\int main() {
2792 \\ printf("%d\n", fnn());
2793 \\}
2794 , &.{});
2795 exe.linkLibrary(dso);
2796 exe.linkLibC();
2797
2798 const run = addRunArtifact(exe);
2799 run.expectStdOutEqual("3\n");
2800 test_step.dependOn(&run.step);
2801
2802 // Check for DT_TEXTREL in a DSO
2803 const check = dso.checkObject();
2804 check.checkInDynamicSection();
2805 // check.checkExact("TEXTREL 0"); // TODO fix in CheckObject parser
2806 check.checkContains("FLAGS TEXTREL");
2807 test_step.dependOn(&check.step);
2808
2809 return test_step;
2810}
2811
1958const Options = struct {2812const Options = struct {
1959 target: CrossTarget = .{ .cpu_arch = .x86_64, .os_tag = .linux },2813 target: CrossTarget = .{ .cpu_arch = .x86_64, .os_tag = .linux },
1960 optimize: std.builtin.OptimizeMode = .Debug,2814 optimize: std.builtin.OptimizeMode = .Debug,