Every section banner dies (103 -> 0) across test/lang, the observer suites, the C carriers, and the five comment-heavy corpus fixtures; banner provenance (#N cites, carrier numbers, repair-cluster labels) folded into headers or adjacent WHY comments. Narration deleted; row provenance, ref cites, divergence pins, and layout contracts kept (fwd-ref decl-order guards and bootstrap-gate corpus rationale restored where the sweep over-cut). Comment-only proven: all 3742 wwbuild workdir .s byte-identical before/after; test-commit and test-byteid (161 lang + 1399 data, 0 pinned-divergent) green.
166 lines
5.7 KiB
Plaintext
166 lines
5.7 KiB
Plaintext
package archive_test;
|
|
|
|
// Archive-driven w6l observers (host ar). Ports of the retired native
|
|
// carriers test/wcc/610_arch.c and 632_w6l_manyflags.c; every
|
|
// assertion preserved.
|
|
//
|
|
// selectivity (610) — libfoo.a holds a needed member and a member
|
|
// referencing an undefined extern; the link succeeds (exit 0) because
|
|
// w6l pulls ONLY the needed member — pulling lib_bad would fail with
|
|
// an undefined reference to this_symbol_does_not_exist — and the
|
|
// binary runs with exit 7. The bad member's @symbol extern is the
|
|
// discriminator; keep it verbatim.
|
|
//
|
|
// manyflags (632, drain F-C) — -L/-l arrays must be sized by argc,
|
|
// not a fixed 64-slot cap. -lfoo resolves only through the FINAL real
|
|
// -L placed after N-1 junk dirs, so a successful link (exit 0 +
|
|
// ELF64 ET_EXEC output) proves the Nth -L was honoured. N table
|
|
// {1, 64, 65, 100, 128}; N=65 is the exact pre-fix overflow slot.
|
|
// Both w6l and w6l_ww are driven (the w6l_ww leg was ungated in the
|
|
// carrier too).
|
|
//
|
|
// Dropped C machinery, not assertions: wwtestpkg.h package-clause
|
|
// injection, the 16KB shell-command buffer (argv is a real vector
|
|
// here), and per-file unlink accounting (testenv.clean).
|
|
|
|
import os;
|
|
import os.exec;
|
|
import strconv;
|
|
import strings;
|
|
import testenv;
|
|
import time;
|
|
|
|
fn fail(label: str, why: str) void = {
|
|
let m: str = strings.concat("archive FAIL: ", label, " -- ", why,
|
|
"\n");
|
|
os.write(2, m.ptr, m.len: u64);
|
|
assert(false);
|
|
};
|
|
|
|
fn tmo() time.duration = {
|
|
return (240i64 * (time.second: i64)): time.duration;
|
|
};
|
|
|
|
// -1 encodes an abnormal (non-EXIT) termination, never a valid code.
|
|
fn runcode(dir: str, name: str, argv: []str) i32 = {
|
|
let co: testenv.commandout;
|
|
testenv.runcommand(dir, dir, name, argv, tmo(), &co);
|
|
if (co.termination != exec.termination.EXIT) { return -1; };
|
|
return co.code;
|
|
};
|
|
|
|
// itos returns a view into a static buffer; dup materializes it.
|
|
fn dec(n: i32) str = {
|
|
return strings.dup(strconv.itos(n: int, strconv.base.DEC));
|
|
};
|
|
|
|
// w6c + w6a on one package-main source; leaves <stem>.o next to it.
|
|
fn compile(td: str, stem: str, body: str) void = {
|
|
let src: str = strings.concat(td, "/", stem, ".ww");
|
|
let asmf: str = strings.concat(td, "/", stem, ".s");
|
|
let obj: str = strings.concat(td, "/", stem, ".o");
|
|
testenv.writefile(src, body);
|
|
let cav: []str = [testenv.driver("w6c"), "-o", asmf, src];
|
|
if (runcode(td, strings.concat("c_", stem), cav) != 0) {
|
|
fail(stem, "w6c failed");
|
|
};
|
|
let aav: []str = [testenv.driver("w6a"), "-o", obj, asmf];
|
|
if (runcode(td, strings.concat("a_", stem), aav) != 0) {
|
|
fail(stem, "w6a failed");
|
|
};
|
|
};
|
|
|
|
@test fn selectivity() void = {
|
|
let td: str = testenv.fresh();
|
|
compile(td, "lib_good", strings.concat("package main;\n",
|
|
"export fn f1() i32 = { return 7; };\n"));
|
|
// defines f2 but also references an undefined extern — the
|
|
// discriminator: pulling this member makes the link fail
|
|
compile(td, "lib_bad", strings.concat("package main;\n",
|
|
"@symbol(\"this_symbol_does_not_exist\") fn bogus() i32;\n",
|
|
"export fn f2() i32 = { return bogus(); };\n"));
|
|
// the plain prototype declares f1 in the same (main) module, so
|
|
// the call resolves to main.f1 — matching lib_good's definition
|
|
compile(td, "m", strings.concat("package main;\n",
|
|
"fn f1() i32;\n",
|
|
"fn main() i32 = { return f1(); };\n"));
|
|
|
|
let lib: str = strings.concat(td, "/libfoo.a");
|
|
let arav: []str = ["/usr/bin/ar", "rcs", lib,
|
|
strings.concat(td, "/lib_good.o"),
|
|
strings.concat(td, "/lib_bad.o")];
|
|
if (runcode(td, "ar", arav) != 0) { fail("selectivity", "ar failed"); };
|
|
|
|
let exe: str = strings.concat(td, "/m");
|
|
let start: str = strings.concat(testenv.repo(),
|
|
"/out/obj/rt/start.o");
|
|
let lav: []str = [testenv.driver("w6l"), "-o", exe,
|
|
strings.concat(td, "/m.o"), start, lib];
|
|
let co: testenv.commandout;
|
|
testenv.runcommand(td, td, "link", lav, tmo(), &co);
|
|
if (co.termination != exec.termination.EXIT || co.code != 0) {
|
|
fail("selectivity", strings.concat(
|
|
"link failed (bad member pulled?): ", co.stderr));
|
|
};
|
|
|
|
let rav: []str = [exe];
|
|
if (runcode(td, "run_m", rav) != 7) {
|
|
fail("selectivity", "exit != 7");
|
|
};
|
|
testenv.clean(td);
|
|
};
|
|
|
|
fn linkwith(td: str, lnk: str, n: i32) void = {
|
|
let tag: str = strings.concat(lnk, "_", dec(n));
|
|
let exe: str = strings.concat(td, "/x_", tag);
|
|
let av: []str = alloc([], 8u64)!;
|
|
append(av, testenv.driver(lnk));
|
|
append(av, "-o");
|
|
append(av, exe);
|
|
append(av, strings.concat(td, "/m.o"));
|
|
let i: i32 = 1;
|
|
for (i < n) {
|
|
append(av, strings.concat("-L/nonexist/wwfc_d", dec(i)));
|
|
i += 1;
|
|
};
|
|
append(av, strings.concat("-L", td));
|
|
append(av, "-lfoo");
|
|
if (runcode(td, strings.concat("lnk_", tag), av) != 0) {
|
|
fail("manyflags", strings.concat(lnk, " nflags=", dec(n),
|
|
" link failed (Nth -L not honoured)"));
|
|
};
|
|
let o: str = testenv.readfile(exe);
|
|
if (o.len < 64 || o[0] != 0x7fu8 || o[1] != 0x45u8
|
|
|| o[2] != 0x4cu8 || o[3] != 0x46u8) {
|
|
fail("manyflags", strings.concat(lnk, " nflags=", dec(n),
|
|
" output not an ELF"));
|
|
};
|
|
// ET_EXEC == 2 (Ehdr e_type at 16, LE u16)
|
|
if (testenv.leu16(o, 16) != 2u64) {
|
|
fail("manyflags", strings.concat(lnk, " nflags=", dec(n),
|
|
" output not ET_EXEC"));
|
|
};
|
|
};
|
|
|
|
@test fn manyflags() void = {
|
|
let td: str = testenv.fresh();
|
|
// a standalone main.o (no undefs) + an unrelated archived foo.o
|
|
compile(td, "m", strings.concat("package main;\n",
|
|
"fn main() i32 = { return 42; };\n"));
|
|
compile(td, "f", strings.concat("package main;\n",
|
|
"export fn foo() i32 = { return 7; };\n"));
|
|
let arav: []str = ["/usr/bin/ar", "rcs",
|
|
strings.concat(td, "/libfoo.a"),
|
|
strings.concat(td, "/f.o")];
|
|
if (runcode(td, "ar", arav) != 0) { fail("manyflags", "ar failed"); };
|
|
|
|
let counts: []i32 = [1, 64, 65, 100, 128];
|
|
let i: i32 = 0;
|
|
for (i < 5) {
|
|
linkwith(td, "w6l_ww", counts[i]);
|
|
linkwith(td, "w6l", counts[i]);
|
|
i += 1;
|
|
};
|
|
testenv.clean(td);
|
|
};
|