diff --git a/test/elf.zig b/test/elf.zig index 0defd9fb..b424edc9 100644 --- a/test/elf.zig +++ b/test/elf.zig @@ -13,6 +13,7 @@ pub fn addElfTests(b: *Build, opts: Options) *Step { elf_step.dependOn(testCopyrelAlignment(b, opts)); elf_step.dependOn(testDsoIfunc(b, opts)); elf_step.dependOn(testDsoPlt(b, opts)); + elf_step.dependOn(testDsoUndef(b, opts)); elf_step.dependOn(testIfuncAlias(b, opts)); elf_step.dependOn(testIfuncDynamic(b, opts)); elf_step.dependOn(testIfuncFuncPtr(b, opts)); @@ -164,9 +165,10 @@ fn testAsNeeded(b: *Build, opts: Options) *Step { test_step.dependOn(run.step()); const check = exe.check(); - check.checkStart("NEEDED libfoo.so"); - check.checkNext("NEEDED libbar.so"); - check.checkNext("NEEDED libbaz.so"); + check.checkInDynamicSection(); + check.checkExact("NEEDED libfoo.so"); + check.checkExact("NEEDED libbar.so"); + check.checkExact("NEEDED libbaz.so"); test_step.dependOn(&check.step); } @@ -186,9 +188,11 @@ fn testAsNeeded(b: *Build, opts: Options) *Step { test_step.dependOn(run.step()); const check = exe.check(); - check.checkStart("NEEDED libfoo.so"); + check.checkInDynamicSection(); check.checkNotPresent("NEEDED libbar.so"); - check.checkStart("NEEDED libbaz.so"); + check.checkInDynamicSection(); + check.checkExact("NEEDED libfoo.so"); + check.checkExact("NEEDED libbaz.so"); test_step.dependOn(&check.step); } @@ -463,9 +467,9 @@ fn testCopyrelAlignment(b: *Build, opts: Options) *Step { test_step.dependOn(run.step()); const check = exe.check(); - check.checkStart("shdr {*}"); - check.checkNext("name .copyrel"); - check.checkNext("addralign 20"); + check.checkStart(); + check.checkExact("name .copyrel"); + check.checkExact("addralign 20"); test_step.dependOn(&check.step); } @@ -481,9 +485,9 @@ fn testCopyrelAlignment(b: *Build, opts: Options) *Step { test_step.dependOn(run.step()); const check = exe.check(); - check.checkStart("shdr {*}"); - check.checkNext("name .copyrel"); - check.checkNext("addralign 8"); + check.checkStart(); + check.checkExact("name .copyrel"); + check.checkExact("addralign 8"); test_step.dependOn(&check.step); } @@ -499,9 +503,9 @@ fn testCopyrelAlignment(b: *Build, opts: Options) *Step { test_step.dependOn(run.step()); const check = exe.check(); - check.checkStart("shdr {*}"); - check.checkNext("name .copyrel"); - check.checkNext("addralign 100"); + check.checkStart(); + check.checkExact("name .copyrel"); + check.checkExact("addralign 100"); test_step.dependOn(&check.step); } @@ -587,6 +591,49 @@ fn testDsoPlt(b: *Build, opts: Options) *Step { return test_step; } +fn testDsoUndef(b: *Build, opts: Options) *Step { + const test_step = b.step("test-elf-dso-undef", ""); + + const dso = cc(b, opts); + dso.addCSource( + \\extern int foo; + \\int bar = 5; + \\int baz() { return foo; } + ); + dso.addArgs(&.{ "-shared", "-fPIC" }); + const dso_out = dso.saveOutputAs("a.so"); + + const obj = cc(b, opts); + obj.addCSource("int foo = 3;"); + obj.addArg("-c"); + const obj_out = obj.saveOutputAs("b.o"); + + const lib = ar(b); + lib.addFileSource(obj_out.file); + const lib_out = lib.saveOutputAs("c.a"); + + const exe = cc(b, opts); + exe.addFileSource(dso_out.file); + exe.addPrefixedDirectorySource("-Wl,-rpath,", dso_out.dir); + exe.addFileSource(lib_out.file); + exe.addCSource( + \\extern int bar; + \\int main() { + \\ return bar - 5; + \\} + ); + + const run = exe.run(); + test_step.dependOn(run.step()); + + const check = exe.check(); + check.checkInDynamicSymtab(); + check.checkContains("foo"); + test_step.dependOn(&check.step); + + return test_step; +} + fn testIfuncAlias(b: *Build, opts: Options) *Step { const test_step = b.step("test-elf-ifunc-alias", ""); @@ -775,11 +822,12 @@ fn testIfuncStaticPie(b: *Build, opts: Options) *Step { test_step.dependOn(run.step()); const check = exe.check(); - check.checkStart("header"); - check.checkNext("type DYN"); - check.checkStart("shdr {*}"); - check.checkNext("name .dynamic"); - check.checkStart("shdr {*}"); + check.checkStart(); + check.checkExact("header"); + check.checkExact("type DYN"); + check.checkStart(); + check.checkExact("name .dynamic"); + check.checkStart(); check.checkNotPresent("name .interp"); test_step.dependOn(&check.step); @@ -803,9 +851,10 @@ fn testHelloStatic(b: *Build, opts: Options) *Step { test_step.dependOn(run.step()); const check = exe.check(); - check.checkStart("header"); - check.checkNext("type EXEC"); - check.checkStart("shdr {*}"); + check.checkStart(); + check.checkExact("header"); + check.checkExact("type EXEC"); + check.checkStart(); check.checkNotPresent("name .dynamic"); test_step.dependOn(&check.step); @@ -824,10 +873,11 @@ fn testHelloDynamic(b: *Build, opts: Options) *Step { test_step.dependOn(run.step()); const check = exe.check(); - check.checkStart("header"); - check.checkNext("type EXEC"); - check.checkStart("shdr {*}"); - check.checkNext("name .dynamic"); + check.checkStart(); + check.checkExact("header"); + check.checkExact("type EXEC"); + check.checkStart(); + check.checkExact("name .dynamic"); test_step.dependOn(&check.step); return test_step; @@ -845,10 +895,11 @@ fn testHelloPie(b: *Build, opts: Options) *Step { test_step.dependOn(run.step()); const check = exe.check(); - check.checkStart("header"); - check.checkNext("type DYN"); - check.checkStart("shdr {*}"); - check.checkNext("name .dynamic"); + check.checkStart(); + check.checkExact("header"); + check.checkExact("type DYN"); + check.checkStart(); + check.checkExact("name .dynamic"); test_step.dependOn(&check.step); return test_step; diff --git a/test/macho.zig b/test/macho.zig index 020b33b6..1e0284b1 100644 --- a/test/macho.zig +++ b/test/macho.zig @@ -51,7 +51,7 @@ fn testDeadStrip(b: *Build, opts: Options) *Step { const check = exe.check(); check.checkInSymtab(); - check.checkNotPresent("{*} (__TEXT,__text) external _iAmUnused"); + check.checkNotPresent("(__TEXT,__text) external _iAmUnused"); test_step.dependOn(&check.step); return test_step; @@ -78,10 +78,12 @@ fn testDeadStripDylibs(b: *Build, opts: Options) *Step { exe.addArgs(&.{ "-framework", "Cocoa" }); const check = exe.check(); - check.checkStart("cmd LOAD_DYLIB"); - check.checkNext("name {*}Cocoa"); - check.checkStart("cmd LOAD_DYLIB"); - check.checkNext("name {*}libobjc{*}.dylib"); + check.checkStart(); + check.checkExact("cmd LOAD_DYLIB"); + check.checkContains("Cocoa"); + check.checkStart(); + check.checkExact("cmd LOAD_DYLIB"); + check.checkContains("libobjc"); test_step.dependOn(&check.step); const run = exe.run(); @@ -166,12 +168,14 @@ fn testEntryPoint(b: *Build, opts: Options) *Step { test_step.dependOn(run.step()); const check = exe.check(); - check.checkStart("segname __TEXT"); - check.checkNext("vmaddr {vmaddr}"); - check.checkStart("cmd MAIN"); - check.checkNext("entryoff {entryoff}"); + check.checkStart(); + check.checkExact("segname __TEXT"); + check.checkExtract("vmaddr {vmaddr}"); + check.checkStart(); + check.checkExact("cmd MAIN"); + check.checkExtract("entryoff {entryoff}"); check.checkInSymtab(); - check.checkNext("{n_value} (__TEXT,__text) external _non_main"); + check.checkExtract("{n_value} (__TEXT,__text) external _non_main"); check.checkComputeCompare("vmaddr entryoff +", .{ .op = .eq, .value = .{ .variable = "n_value" } }); test_step.dependOn(&check.step); @@ -222,12 +226,15 @@ fn testEntryPointDylib(b: *Build, opts: Options) *Step { exe.addPrefixedDirectorySource("-L", dylib.saveOutputAs("libbootstrap.dylib").dir); const check = exe.check(); - check.checkStart("segname __TEXT"); - check.checkNext("vmaddr {text_vmaddr}"); - check.checkStart("sectname __stubs"); - check.checkNext("addr {stubs_vmaddr}"); - check.checkStart("cmd MAIN"); - check.checkNext("entryoff {entryoff}"); + check.checkStart(); + check.checkExact("segname __TEXT"); + check.checkExtract("vmaddr {text_vmaddr}"); + check.checkStart(); + check.checkExact("sectname __stubs"); + check.checkExtract("addr {stubs_vmaddr}"); + check.checkStart(); + check.checkExact("cmd MAIN"); + check.checkExtract("entryoff {entryoff}"); check.checkComputeCompare("text_vmaddr entryoff +", .{ .op = .eq, .value = .{ .variable = "stubs_vmaddr" }, // The entrypoint should be a synthetic stub @@ -271,8 +278,9 @@ fn testHeaderpad(b: *Build, opts: Options) *Step { exe.addEmptyMain(); const check = exe.check(); - check.checkStart("sectname __text"); - check.checkNext("offset {offset}"); + check.checkStart(); + check.checkExact("sectname __text"); + check.checkExtract("offset {offset}"); switch (builtin.cpu.arch) { .aarch64 => check.checkComputeCompare("offset", .{ .op = .gte, .value = .{ .literal = 0x4000 } }), .x86_64 => check.checkComputeCompare("offset", .{ .op = .gte, .value = .{ .literal = 0x1000 } }), @@ -291,8 +299,9 @@ fn testHeaderpad(b: *Build, opts: Options) *Step { exe.addEmptyMain(); const check = exe.check(); - check.checkStart("sectname __text"); - check.checkNext("offset {offset}"); + check.checkStart(); + check.checkExact("sectname __text"); + check.checkExtract("offset {offset}"); check.checkComputeCompare("offset", .{ .op = .gte, .value = .{ .literal = 0x10000 } }); test_step.dependOn(&check.step); @@ -308,8 +317,9 @@ fn testHeaderpad(b: *Build, opts: Options) *Step { exe.addEmptyMain(); const check = exe.check(); - check.checkStart("sectname __text"); - check.checkNext("offset {offset}"); + check.checkStart(); + check.checkExact("sectname __text"); + check.checkExtract("offset {offset}"); check.checkComputeCompare("offset", .{ .op = .gte, .value = .{ .literal = 0x10000 } }); test_step.dependOn(&check.step); @@ -325,8 +335,9 @@ fn testHeaderpad(b: *Build, opts: Options) *Step { exe.addEmptyMain(); const check = exe.check(); - check.checkStart("sectname __text"); - check.checkNext("offset {offset}"); + check.checkStart(); + check.checkExact("sectname __text"); + check.checkExtract("offset {offset}"); switch (builtin.cpu.arch) { .aarch64 => check.checkComputeCompare("offset", .{ .op = .gte, .value = .{ .literal = 0x4000 } }), .x86_64 => check.checkComputeCompare("offset", .{ .op = .gte, .value = .{ .literal = 0x1000 } }), @@ -361,39 +372,46 @@ fn testLayout(b: *Build, opts: Options) *Step { exe.addHelloWorldMain(); const check = exe.check(); - check.checkStart("cmd SEGMENT_64"); - check.checkNext("segname __LINKEDIT"); - check.checkNext("fileoff {fileoff}"); - check.checkNext("filesz {filesz}"); - check.checkStart("cmd DYLD_INFO_ONLY"); - check.checkNext("rebaseoff {rebaseoff}"); - check.checkNext("rebasesize {rebasesize}"); - check.checkNext("bindoff {bindoff}"); - check.checkNext("bindsize {bindsize}"); - check.checkNext("lazybindoff {lazybindoff}"); - check.checkNext("lazybindsize {lazybindsize}"); - check.checkNext("exportoff {exportoff}"); - check.checkNext("exportsize {exportsize}"); - check.checkStart("cmd FUNCTION_STARTS"); - check.checkNext("dataoff {fstartoff}"); - check.checkNext("datasize {fstartsize}"); - check.checkStart("cmd DATA_IN_CODE"); - check.checkNext("dataoff {diceoff}"); - check.checkNext("datasize {dicesize}"); - check.checkStart("cmd SYMTAB"); - check.checkNext("symoff {symoff}"); - check.checkNext("nsyms {symnsyms}"); - check.checkNext("stroff {stroff}"); - check.checkNext("strsize {strsize}"); - check.checkStart("cmd DYSYMTAB"); - check.checkNext("indirectsymoff {dysymoff}"); - check.checkNext("nindirectsyms {dysymnsyms}"); + check.checkStart(); + check.checkExact("cmd SEGMENT_64"); + check.checkExact("segname __LINKEDIT"); + check.checkExtract("fileoff {fileoff}"); + check.checkExtract("filesz {filesz}"); + check.checkStart(); + check.checkExact("cmd DYLD_INFO_ONLY"); + check.checkExtract("rebaseoff {rebaseoff}"); + check.checkExtract("rebasesize {rebasesize}"); + check.checkExtract("bindoff {bindoff}"); + check.checkExtract("bindsize {bindsize}"); + check.checkExtract("lazybindoff {lazybindoff}"); + check.checkExtract("lazybindsize {lazybindsize}"); + check.checkExtract("exportoff {exportoff}"); + check.checkExtract("exportsize {exportsize}"); + check.checkStart(); + check.checkExact("cmd FUNCTION_STARTS"); + check.checkExtract("dataoff {fstartoff}"); + check.checkExtract("datasize {fstartsize}"); + check.checkStart(); + check.checkExact("cmd DATA_IN_CODE"); + check.checkExtract("dataoff {diceoff}"); + check.checkExtract("datasize {dicesize}"); + check.checkStart(); + check.checkExact("cmd SYMTAB"); + check.checkExtract("symoff {symoff}"); + check.checkExtract("nsyms {symnsyms}"); + check.checkExtract("stroff {stroff}"); + check.checkExtract("strsize {strsize}"); + check.checkStart(); + check.checkExact("cmd DYSYMTAB"); + check.checkExtract("indirectsymoff {dysymoff}"); + check.checkExtract("nindirectsyms {dysymnsyms}"); switch (builtin.cpu.arch) { .aarch64 => { - check.checkStart("cmd CODE_SIGNATURE"); - check.checkNext("dataoff {codesigoff}"); - check.checkNext("datasize {codesigsize}"); + check.checkStart(); + check.checkExact("cmd CODE_SIGNATURE"); + check.checkExtract("dataoff {codesigoff}"); + check.checkExtract("datasize {codesigsize}"); }, .x86_64 => {}, else => unreachable, @@ -469,8 +487,9 @@ fn testNeededFramework(b: *Build, opts: Options) *Step { exe.addEmptyMain(); const check = exe.check(); - check.checkStart("cmd LOAD_DYLIB"); - check.checkNext("name {*}Cocoa"); + check.checkStart(); + check.checkExact("cmd LOAD_DYLIB"); + check.checkContains("Cocoa"); test_step.dependOn(&check.step); const run = exe.run(); @@ -494,8 +513,9 @@ fn testNeededLibrary(b: *Build, opts: Options) *Step { exe.addPrefixedDirectorySource("-Wl,-rpath,", dylib_out.dir); const check = exe.check(); - check.checkStart("cmd LOAD_DYLIB"); - check.checkNext("name {*}liba.dylib"); + check.checkStart(); + check.checkExact("cmd LOAD_DYLIB"); + check.checkContains("liba.dylib"); test_step.dependOn(&check.step); const run = exe.run(); @@ -513,12 +533,14 @@ fn testPagezeroSize(b: *Build, opts: Options) *Step { exe.addEmptyMain(); const check = exe.check(); - check.checkStart("LC 0"); - check.checkNext("segname __PAGEZERO"); - check.checkNext("vmaddr 0"); - check.checkNext("vmsize 4000"); - check.checkStart("segname __TEXT"); - check.checkNext("vmaddr 4000"); + check.checkStart(); + check.checkExact("LC 0"); + check.checkExact("segname __PAGEZERO"); + check.checkExact("vmaddr 0"); + check.checkExact("vmsize 4000"); + check.checkStart(); + check.checkExact("segname __TEXT"); + check.checkExact("vmaddr 4000"); test_step.dependOn(&check.step); } @@ -528,9 +550,10 @@ fn testPagezeroSize(b: *Build, opts: Options) *Step { exe.addEmptyMain(); const check = exe.check(); - check.checkStart("LC 0"); - check.checkNext("segname __TEXT"); - check.checkNext("vmaddr 0"); + check.checkStart(); + check.checkExact("LC 0"); + check.checkExact("segname __TEXT"); + check.checkExact("vmaddr 0"); test_step.dependOn(&check.step); } @@ -583,8 +606,9 @@ fn testSearchStrategy(b: *Build, opts: Options) *Step { test_step.dependOn(run.step()); const check = exe.check(); - check.checkStart("cmd LOAD_DYLIB"); - check.checkNext("name {*}liba.dylib"); + check.checkStart(); + check.checkExact("cmd LOAD_DYLIB"); + check.checkContains("liba.dylib"); test_step.dependOn(&check.step); } @@ -601,8 +625,9 @@ fn testSearchStrategy(b: *Build, opts: Options) *Step { test_step.dependOn(run.step()); const check = exe.check(); - check.checkStart("cmd LOAD_DYLIB"); - check.checkNotPresent("name {*}liba.dylib"); + check.checkStart(); + check.checkExact("cmd LOAD_DYLIB"); + check.checkNotPresent("liba.dylib"); test_step.dependOn(&check.step); } @@ -620,8 +645,9 @@ fn testStackSize(b: *Build, opts: Options) *Step { test_step.dependOn(run.step()); const check = exe.check(); - check.checkStart("cmd MAIN"); - check.checkNext("stacksize 100000000"); + check.checkStart(); + check.checkExact("cmd MAIN"); + check.checkExact("stacksize 100000000"); test_step.dependOn(&check.step); return test_step; @@ -820,7 +846,7 @@ fn testUnwindInfo(b: *Build, opts: Options) *Step { const check = exe.check(); check.checkInSymtab(); - check.checkNext("{*} external ___gxx_personality_v0"); + check.checkContains("external ___gxx_personality_v0"); test_step.dependOn(&check.step); return test_step; @@ -837,8 +863,9 @@ fn testWeakFramework(b: *Build, opts: Options) *Step { test_step.dependOn(run.step()); const check = exe.check(); - check.checkStart("cmd LOAD_WEAK_DYLIB"); - check.checkNext("name {*}Cocoa"); + check.checkStart(); + check.checkExact("cmd LOAD_WEAK_DYLIB"); + check.checkContais("Cocoa"); test_step.dependOn(&check.step); return test_step; @@ -875,12 +902,13 @@ fn testWeakLibrary(b: *Build, opts: Options) *Step { exe.addPrefixedDirectorySource("-Wl,-rpath,", dylib_out.dir); const check = exe.check(); - check.checkStart("cmd LOAD_WEAK_DYLIB"); - check.checkNext("name {*}liba.dylib"); + check.checkStart(); + check.checkExact("cmd LOAD_WEAK_DYLIB"); + check.checkContains("liba.dylib"); check.checkInSymtab(); - check.checkNext("(undefined) weak external _a (from liba)"); + check.checkExact("(undefined) weak external _a (from liba)"); check.checkInSymtab(); - check.checkNext("(undefined) weak external _asStr (from liba)"); + check.checkExact("(undefined) weak external _asStr (from liba)"); test_step.dependOn(&check.step); const run = exe.run();