diff --git a/lib/compiler/objdump.zig b/lib/compiler/objdump.zig index 5b006fb72bd641ee6b2e304085cbc105e2079cc1..ae0a375e8081345697028572dc6cd331e13a4a1a 100644 --- a/lib/compiler/objdump.zig +++ b/lib/compiler/objdump.zig @@ -401,12 +401,13 @@ const coff = struct { , .{ expected_kind, num_symbols }); if (d.opts.linker_member == .first_linker) { - try w.writeAll( - \\ - \\Archive symbols: - \\& Member Symbol - \\ - ); + if (d.element(.@"table-header")) + try w.writeAll( + \\ + \\Archive symbols: + \\& Member Symbol + \\ + ); const offsets = try r.readAlloc(gpa, num_symbols * 4); defer gpa.free(offsets); diff --git a/test/link.zig b/test/link.zig index eba9d1ca0b07e9e902c8bb9a3eeaeb9730937681..5b76036e7dc84c0a15d17bd472e0c1d263391439 100644 --- a/test/link.zig +++ b/test/link.zig @@ -1,29 +1,5 @@ pub fn addCases(ctx: *LinkContext) void { - if (ctx.includeTest("exports-static")) |case| { - const lib = case.addLibrary(.static, .{ - .name = "lib", - .zig_source_file = ctx.sourcePath("exports.zig"), - }); - case.verifyObjdump(lib, &.{ - "-s", - "--symbols", - "--only-symbol=foo", - }, .{}); - } - - if (ctx.includeTest("exports-dynamic")) |case| { - const lib = case.addLibrary(.dynamic, .{ - .name = "lib", - .zig_source_file = ctx.sourcePath("exports.zig"), - }); - case.verifyObjdump(lib, &.{ - "-s", - "--exports", - "--only-symbol=foo", - }, .{}); - } - - if (ctx.includeTest("emit-static-lib")) |case| { + if (ctx.includeTest("static-lib")) |case| { const obj1 = case.addObject(.{ .name = "obj1", .name_prefix = false, @@ -43,14 +19,14 @@ pub fn addCases(ctx: *LinkContext) void { .name_prefix = false, .name_target = false, .zig_source_bytes = - \\fn weakFoo() callconv(.c) usize { + \\fn fooWeak() callconv(.c) usize { \\ return 0xaabbccddaabbccdd; \\} - \\export var array_foo: [2]u16 = .{ 0xffff, 0xabcd }; - \\export var strong_foo: usize = 0x1122334411223344; + \\export var foo_array: [2]u16 = .{ 0xffff, 0xabcd }; + \\export var foo_strong: usize = 0x1122334411223344; \\comptime { - \\ @export(&weakFoo, .{ .name = "weakFoo", .linkage = .weak }); - \\ @export(&strong_foo, .{ .name = "strong_foo_alias", .linkage = .strong }); + \\ @export(&fooWeak, .{ .name = "fooWeak", .linkage = .weak }); + \\ @export(&foo_strong, .{ .name = "foo_strong_alias", .linkage = .strong }); \\} , }); @@ -63,25 +39,109 @@ pub fn addCases(ctx: *LinkContext) void { lib.root_module.addObject(obj1); lib.root_module.addObject(obj2); - case.verifyObjdump(lib, &.{ + case.verifyObjdump(lib.getEmittedBin(), &.{ "-s", "--elements=file-type", "--symbols", "--only-symbol=foo", - "--only-symbol=Foo", }, .{}); const exe = case.addExecutable(.{ .name = "test", .zig_source_bytes = \\extern fn fooBar() c_uint; - \\extern fn weakFoo() usize; + \\extern fn fooWeak() usize; + \\extern var foo_array: [2]u16; + \\extern var foo_strong: usize; + \\extern var foo_strong_alias: usize; + \\pub fn main() !u8 { + \\ return @intFromBool(0xcd003365cd00df35 != fooBar() + + \\ fooWeak() + + \\ foo_array[1] + + \\ foo_strong + + \\ foo_strong_alias); + \\} + , + }); + exe.root_module.linkLibrary(lib); + + const run = case.addRunArtifact(exe); + run.addCheck(.{ .expect_term = .{ .exited = 0 } }); + } + + if (ctx.includeTest("dynamic-lib-code")) |case| { + const lib = case.addLibrary(.dynamic, .{ + .name = "lib", + .zig_source_bytes = + \\export fn foo1() callconv(.c) u64 { + \\ return 0x1122334411223344; + \\} + \\export fn foo2() callconv(.c) u64 { + \\ return 0xaabbccddaabbccdd; + \\} + , + }); + + case.verifyObjdump(lib.getEmittedBin(), &.{ + "-s", + "--exports", + "--only-symbol=foo", + }, .{ .os = true }); + + if (ctx.target.result.os.tag == .windows) { + case.verifyObjdump(lib.getEmittedImplib(), &.{ + "-s", + "--exports", + "--only-symbol=foo", + }, .{ .sub_name = "implib", .os = true }); + } + + const exe = case.addExecutable(.{ + .name = "test", + .zig_source_bytes = + \\extern fn foo1() u64; + \\pub fn main() !u8 { + \\ const foo2 = @extern( + \\ *const fn () callconv(.c) u64, + \\ .{ .name = "foo2", .is_dll_import = true }, + \\ ); + \\ return @intFromBool(0xbbde0021bbde0021 != foo1() + foo2()); + \\} + , + }); + exe.root_module.linkLibrary(lib); + + const run = case.addRunArtifact(exe); + run.addCheck(.{ .expect_term = .{ .exited = 0 } }); + } + + if (ctx.includeTest("dynamic-lib-data")) |case| { + const lib = case.addLibrary(.dynamic, .{ + .name = "lib", + .zig_source_bytes = + \\export var array_foo: [2]u16 = .{ 0xffff, 0xabcd }; + \\export var strong_foo: usize = 0x1122334411223344; + , + }); + + case.verifyObjdump(lib.getEmittedBin(), &.{ + "-s", + "--exports", + "--only-symbol=foo", + }, .{}); + + if (ctx.target.result.os.tag == .windows) { + // TODO: objdump implib on windows + } + + const exe = case.addExecutable(.{ + .name = "test", + .zig_source_bytes = \\extern var array_foo: [2]u16; \\extern var strong_foo: usize; \\extern var strong_foo_alias: usize; \\pub fn main() !u8 { - \\ return @intFromBool(0xcd003365cd00df35 != fooBar() + - \\ weakFoo() + + \\ return @intFromBool(0x2244668822451255 != \\ array_foo[1] + \\ strong_foo + \\ strong_foo_alias); @@ -118,7 +178,7 @@ pub fn addCases(ctx: *LinkContext) void { , }); - case.verifyObjdump(abs_reloc, &.{ + case.verifyObjdump(abs_reloc.getEmittedBin(), &.{ "-s", "--relocs", }, .{ .arch = true }); diff --git a/test/link/snapshots/abs-symbol-x86_64.dmp b/test/link/snapshots/abs-symbol-x86_64.dmp deleted file mode 100644 index 747546649b082633b0097b1be311a382e0b98e2b..0000000000000000000000000000000000000000 --- a/test/link/snapshots/abs-symbol-x86_64.dmp +++ /dev/null @@ -1 +0,0 @@ -xxxxxxxx ADDR32 xxxxxxxx UNDEF | foo diff --git a/test/link/snapshots/dynamic-lib-code.implib-windows.dmp b/test/link/snapshots/dynamic-lib-code.implib-windows.dmp new file mode 100644 index 0000000000000000000000000000000000000000..fdc53a6e7fc007ff24a7459b9914b910ac1bf467 --- /dev/null +++ b/test/link/snapshots/dynamic-lib-code.implib-windows.dmp @@ -0,0 +1,32 @@ + 0 date + 0 user_id + 0 group_id + 0 file_mode +xxxxxxxxxxxxxxxx size + second_linker type + | 7 symbols + | 5 members +xxxxxxxx __imp_foo1 +xxxxxxxx __imp_foo2 +xxxxxxxx foo1 +xxxxxxxx foo2 + 0 version + 8664 machine (AMD64) + 0 time_date_stamp +xxxxxxxxxxxxxxxx size_of_data + 0 hint + CODE import_type + NAME name_type + symbol name | foo1 + import name | foo1 + dll | dynamic-lib-code-lib-x86_64-windows.win10...win11_dt-msvc-Debug-llvm-lld-libc.dll + 0 version + 8664 machine (AMD64) + 0 time_date_stamp +xxxxxxxxxxxxxxxx size_of_data + 0 hint + CODE import_type + NAME name_type + symbol name | foo2 + import name | foo2 + dll | dynamic-lib-code-lib-x86_64-windows.win10...win11_dt-msvc-Debug-llvm-lld-libc.dll diff --git a/test/link/snapshots/dynamic-lib-code.windows.dmp b/test/link/snapshots/dynamic-lib-code.windows.dmp new file mode 100644 index 0000000000000000000000000000000000000000..a9396675f8f34175fc4b3a5f488a003cc60bc63d --- /dev/null +++ b/test/link/snapshots/dynamic-lib-code.windows.dmp @@ -0,0 +1,13 @@ +Export directory: + 0 flags + 0 time_date_stamp + 0.00 version +xxxxxxxxxxxxxxxx name_rva + 1 ordinal_base +xxxxxxxxxxxxxxxx number_of_entries +xxxxxxxxxxxxxxxx number_of_names +xxxxxxxxxxxxxxxx export_address_table_rva +xxxxxxxxxxxxxxxx name_pointer_table_rva +xxxxxxxxxxxxxxxx ordinal_table_rva +xxxx xxxx xxxxxxxx | foo1 +xxxx xxxx xxxxxxxx | foo2 diff --git a/test/link/snapshots/emit-static-lib.dmp b/test/link/snapshots/emit-static-lib.dmp deleted file mode 100644 index 41932df9785ea10382d73473f93e8e4b16a3fe72..0000000000000000000000000000000000000000 --- a/test/link/snapshots/emit-static-lib.dmp +++ /dev/null @@ -1,10 +0,0 @@ -lib.lib: COFF archive -lib.lib(obj1.obj): COFF object -xxxx 00000000 1 NULL() EXTERNAL | fooBar -xxxx 00000000 2 NULL EXTERNAL | foo1 -xxxx 00000004 2 NULL EXTERNAL | foo2 -lib.lib(this_is_a_long_name.obj): COFF object -xxxx 00000000 4 NULL() EXTERNAL | weakFoo -xxxx 00000010 2 NULL EXTERNAL | array_foo -xxxx 00000000 2 NULL EXTERNAL | strong_foo_alias -xxxx 00000000 2 NULL EXTERNAL | strong_foo diff --git a/test/link/snapshots/exports-dynamic.dmp b/test/link/snapshots/exports-dynamic.dmp deleted file mode 100644 index fbd6415e5f9564d2299ab13ca81b75dde3100001..0000000000000000000000000000000000000000 --- a/test/link/snapshots/exports-dynamic.dmp +++ /dev/null @@ -1,14 +0,0 @@ -Export directory: - 0 flags - 0 time_date_stamp - 0.00 version -xxxxxxxxxxxxxxxx name_rva - 1 ordinal_base -xxxxxxxxxxxxxxxx number_of_entries -xxxxxxxxxxxxxxxx number_of_names -xxxxxxxxxxxxxxxx export_address_table_rva -xxxxxxxxxxxxxxxx name_pointer_table_rva -xxxxxxxxxxxxxxxx ordinal_table_rva -xxxx xxxx xxxxxxxx | foo_const -xxxx xxxx xxxxxxxx | foo_fn -xxxx xxxx xxxxxxxx | foo_var diff --git a/test/link/snapshots/exports-static.dmp b/test/link/snapshots/exports-static.dmp deleted file mode 100644 index d112fcbe7191bc481d50ad89592d86e2d0b4b576..0000000000000000000000000000000000000000 --- a/test/link/snapshots/exports-static.dmp +++ /dev/null @@ -1,3 +0,0 @@ -xxxx 00000000 4 NULL() EXTERNAL | foo_fn -xxxx 00000000 2 NULL EXTERNAL | foo_var -xxxx 00000008 3 NULL EXTERNAL | foo_const diff --git a/test/src/Link.zig b/test/src/Link.zig index 6d064eaf27bc13e47a89fd454bbd818d0e373294..4b621d5be89d0cebaddee9c20fefef8578bfea9d 100644 --- a/test/src/Link.zig +++ b/test/src/Link.zig @@ -101,7 +101,7 @@ pub const Case = struct { } const SnapshotScope = struct { - /// If a test case has multiple verifyObjdump calls, `opt_sub_name` can + /// If a test case has multiple verifyObjdump calls, `opt_sub_name` should /// be used to differentiate them. sub_name: ?[]const u8 = null, arch: bool = false, @@ -120,7 +120,7 @@ pub const Case = struct { /// pub fn verifyObjdump( self: *const Case, - compile: *Step.Compile, + file: Build.LazyPath, args: []const []const u8, scope: SnapshotScope, ) void { @@ -140,7 +140,7 @@ pub const Case = struct { .{ snapshot_name, ctx.target_desc }, )); run_step.addArgs(&.{ ctx.b.graph.zig_exe, "objdump" }); - run_step.addArtifactArg(compile); + run_step.addFileArg(file); run_step.addArgs(args); run_step.addCheck(.{ .expect_term = .{ .exited = 0 } }); @@ -166,22 +166,39 @@ pub const Case = struct { const w = &snapshot_name.writer; try w.writeAll(self.prefix); - if (scope.sub_name) |sub_name| { - try w.writeByte('.'); - try w.writeAll(sub_name); - } + var sep: u8 = '.'; - if (scope.arch) try w.print("-{t}", .{ctx.target.result.cpu.arch}); - if (scope.os) try w.print("-{t}", .{ctx.target.result.os.tag}); - if (scope.abi) try w.print("-{t}", .{ctx.target.result.abi}); - if (scope.optimize) try w.print("-{t}", .{ctx.optimize}); - if (scope.use_llvm) try w.writeAll(if (ctx.use_llvm) "-llvm" else "-no-llvm"); - if (scope.use_lld) try w.writeAll(if (ctx.use_lld) "-lld" else "-no-lld"); - if (scope.link_libc) try w.writeAll(if (ctx.link_libc) "-libc" else "-no-libc"); - try w.writeAll(".dmp"); + if (try snapshotNameInner(w, scope.sub_name != null, &sep)) + try w.writeAll(scope.sub_name.?); + if (try snapshotNameInner(w, scope.arch, &sep)) + try w.print("{t}", .{ctx.target.result.cpu.arch}); + if (try snapshotNameInner(w, scope.os, &sep)) + try w.print("{t}", .{ctx.target.result.os.tag}); + if (try snapshotNameInner(w, scope.abi, &sep)) + try w.print("{t}", .{ctx.target.result.abi}); + if (try snapshotNameInner(w, scope.optimize, &sep)) + try w.print("{t}", .{ctx.optimize}); + if (try snapshotNameInner(w, scope.use_llvm, &sep)) + try w.writeAll(if (ctx.use_llvm) "llvm" else "no-llvm"); + if (try snapshotNameInner(w, scope.use_lld, &sep)) + try w.writeAll(if (ctx.use_lld) "lld" else "no-lld"); + if (try snapshotNameInner(w, scope.link_libc, &sep)) + try w.writeAll(if (ctx.link_libc) "libc" else "no-libc"); + + if (sep == '-') try w.writeByte('.'); + try w.writeAll("dmp"); return try snapshot_name.toOwnedSlice(); } + + fn snapshotNameInner(w: *std.Io.Writer, cond: bool, sep: *u8) !bool { + if (cond) { + try w.writeByte(sep.*); + sep.* = '-'; + } + + return cond; + } }; fn createModule(self: *const Link, overlay: OverlayOptions) *Build.Module { diff --git a/test/tests.zig b/test/tests.zig index 80366c7f5c7937f3c07b40ac90611c72ec2bf890..2159d8a8a05ea45b900ed4beec64141ddb9624cf 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -2094,12 +2094,48 @@ const link_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .x86_64, + .os_tag = .windows, + .abi = .gnu, + }, + .use_llvm = true, + .use_lld = true, + }, + .{ + .target = .{ + .cpu_arch = .x86_64, + .os_tag = .windows, + .abi = .gnu, + }, + .link_libc = true, + .use_llvm = true, + .use_lld = true, + }, + .{ + .target = .{ + .cpu_arch = .x86_64, + .os_tag = .windows, + .abi = .msvc, + }, + }, + .{ + .target = .{ + .cpu_arch = .x86_64, + .os_tag = .windows, + .abi = .msvc, + }, + .link_libc = true, + }, .{ .target = .{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .msvc, }, + .use_llvm = true, + .use_lld = true, }, .{ .target = .{ @@ -2108,6 +2144,8 @@ const link_targets = blk: { .abi = .msvc, }, .link_libc = true, + .use_llvm = true, + .use_lld = true, }, }; };