From 59284a1085a6ce77c7e582d344ee37c20f85ae9f Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Wed, 26 Jul 2023 13:37:37 +0200 Subject: [PATCH 1/2] macho: create export trie root explicitly with Trie.init --- src/link/MachO.zig | 1 + src/link/MachO/Trie.zig | 24 +++++++++++++----------- src/link/MachO/zld.zig | 1 + 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 6953cda929..d124a1f51c 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -3227,6 +3227,7 @@ fn writeDyldInfoData(self: *MachO) !void { var trie: Trie = .{}; defer trie.deinit(gpa); + try trie.init(gpa); try self.collectExportData(&trie); const link_seg = self.getLinkeditSegmentPtr(); diff --git a/src/link/MachO/Trie.zig b/src/link/MachO/Trie.zig index cabe611b64..962ead72fa 100644 --- a/src/link/MachO/Trie.zig +++ b/src/link/MachO/Trie.zig @@ -309,7 +309,6 @@ pub const ExportSymbol = struct { /// This operation may change the layout of the trie by splicing edges in /// certain circumstances. pub fn put(self: *Trie, allocator: Allocator, symbol: ExportSymbol) !void { - try self.createRoot(allocator); const node = try self.root.?.put(allocator, symbol.name); node.terminal_info = .{ .vmaddr_offset = symbol.vmaddr_offset, @@ -362,7 +361,6 @@ const ReadError = error{ /// Parse the trie from a byte stream. pub fn read(self: *Trie, allocator: Allocator, reader: anytype) ReadError!usize { - try self.createRoot(allocator); return self.root.?.read(allocator, reader); } @@ -377,6 +375,14 @@ pub fn write(self: Trie, writer: anytype) !u64 { return counting_writer.bytes_written; } +pub fn init(self: *Trie, allocator: Allocator) !void { + assert(self.root == null); + const root = try allocator.create(Node); + root.* = .{ .base = self }; + self.root = root; + self.node_count += 1; +} + pub fn deinit(self: *Trie, allocator: Allocator) void { if (self.root) |root| { root.deinit(allocator); @@ -385,19 +391,11 @@ pub fn deinit(self: *Trie, allocator: Allocator) void { self.ordered_nodes.deinit(allocator); } -fn createRoot(self: *Trie, allocator: Allocator) !void { - if (self.root == null) { - const root = try allocator.create(Node); - root.* = .{ .base = self }; - self.root = root; - self.node_count += 1; - } -} - test "Trie node count" { var gpa = testing.allocator; var trie: Trie = .{}; defer trie.deinit(gpa); + try trie.init(gpa); try testing.expectEqual(trie.node_count, 0); try testing.expect(trie.root == null); @@ -443,6 +441,7 @@ test "Trie basic" { var gpa = testing.allocator; var trie: Trie = .{}; defer trie.deinit(gpa); + try trie.init(gpa); // root --- _st ---> node try trie.put(gpa, .{ @@ -508,6 +507,7 @@ test "write Trie to a byte stream" { var gpa = testing.allocator; var trie: Trie = .{}; defer trie.deinit(gpa); + try trie.init(gpa); try trie.put(gpa, .{ .name = "__mh_execute_header", @@ -566,6 +566,7 @@ test "parse Trie from byte stream" { var in_stream = std.io.fixedBufferStream(&in_buffer); var trie: Trie = .{}; defer trie.deinit(gpa); + try trie.init(gpa); const nread = try trie.read(gpa, in_stream.reader()); try testing.expect(nread == in_buffer.len); @@ -583,6 +584,7 @@ test "ordering bug" { var gpa = testing.allocator; var trie: Trie = .{}; defer trie.deinit(gpa); + try trie.init(gpa); try trie.put(gpa, .{ .name = "_asStr", diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 3e828984a9..0ba55a217c 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -2107,6 +2107,7 @@ pub const Zld = struct { var trie = Trie{}; defer trie.deinit(gpa); + try trie.init(gpa); try self.collectExportData(&trie); const link_seg = self.getLinkeditSegmentPtr(); From 780f0b872a964fe4a411a603b733a3d39700ec1c Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Wed, 26 Jul 2023 13:38:24 +0200 Subject: [PATCH 2/2] link-test: add test case for MachO bug 16308 --- test/link.zig | 4 ++++ test/link/macho/bugs/16308/build.zig | 23 +++++++++++++++++++++++ test/link/macho/bugs/16308/main.zig | 1 + 3 files changed, 28 insertions(+) create mode 100644 test/link/macho/bugs/16308/build.zig create mode 100644 test/link/macho/bugs/16308/main.zig diff --git a/test/link.zig b/test/link.zig index ac0bcf3df8..c877e6c357 100644 --- a/test/link.zig +++ b/test/link.zig @@ -92,6 +92,10 @@ pub const cases = [_]Case{ .build_root = "test/link/macho/bugs/13457", .import = @import("link/macho/bugs/13457/build.zig"), }, + .{ + .build_root = "test/link/macho/bugs/16308", + .import = @import("link/macho/bugs/16308/build.zig"), + }, .{ .build_root = "test/link/macho/dead_strip", .import = @import("link/macho/dead_strip/build.zig"), diff --git a/test/link/macho/bugs/16308/build.zig b/test/link/macho/bugs/16308/build.zig new file mode 100644 index 0000000000..a6329074a0 --- /dev/null +++ b/test/link/macho/bugs/16308/build.zig @@ -0,0 +1,23 @@ +const std = @import("std"); + +pub const requires_symlinks = true; + +pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + const target: std.zig.CrossTarget = .{ .os_tag = .macos }; + + const lib = b.addSharedLibrary(.{ + .name = "a", + .root_source_file = .{ .path = "main.zig" }, + .optimize = .Debug, + .target = target, + }); + + const check = lib.checkObject(); + check.checkInSymtab(); + check.checkNotPresent("external"); + + test_step.dependOn(&check.step); +} diff --git a/test/link/macho/bugs/16308/main.zig b/test/link/macho/bugs/16308/main.zig new file mode 100644 index 0000000000..fd94789461 --- /dev/null +++ b/test/link/macho/bugs/16308/main.zig @@ -0,0 +1 @@ +fn abc() void {}