From 88d40fc005894ef84eb8bf54314da293772c4bba Mon Sep 17 00:00:00 2001 From: Jakub Konka <kubkon@jakubkonka.com> Date: Thu, 6 May 2021 17:02:39 +0200 Subject: [PATCH] zld: sort tlv offsets by source address --- src/link/MachO/Archive.zig | 9 ++++++--- src/link/MachO/Object.zig | 2 +- src/link/MachO/Zld.zig | 40 ++++++++++++++++++++------------------ 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/link/MachO/Archive.zig b/src/link/MachO/Archive.zig index 5a0b9609ad99..702a807a4d4e 100644 --- a/src/link/MachO/Archive.zig +++ b/src/link/MachO/Archive.zig @@ -16,7 +16,7 @@ allocator: *Allocator, arch: ?std.Target.Cpu.Arch = null, file: ?fs.File = null, header: ?ar_hdr = null, -name: ?[]u8 = null, +name: ?[]const u8 = null, /// Parsed table of contents. /// Each symbol name points to a list of all definition @@ -195,7 +195,7 @@ fn parseTableOfContents(self: *Archive, reader: anytype) !void { } /// Caller owns the Object instance. -pub fn parseObject(self: Archive, offset: u32) !Object { +pub fn parseObject(self: Archive, offset: u32) !*Object { var reader = self.file.?.reader(); try reader.context.seekTo(offset); @@ -217,7 +217,10 @@ pub fn parseObject(self: Archive, offset: u32) !Object { break :name try std.fmt.allocPrint(self.allocator, "{s}({s})", .{ path, object_name }); }; - var object = Object.init(self.allocator); + var object = try self.allocator.create(Object); + errdefer self.allocator.destroy(object); + + object.* = Object.init(self.allocator); object.arch = self.arch.?; object.file = try fs.cwd().openFile(self.name.?, .{}); object.name = name; diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 3b8aa7a6cf52..4d2ade7aadb0 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -22,7 +22,7 @@ arch: ?std.Target.Cpu.Arch = null, header: ?macho.mach_header_64 = null, file: ?fs.File = null, file_offset: ?u32 = null, -name: ?[]u8 = null, +name: ?[]const u8 = null, load_commands: std.ArrayListUnmanaged(LoadCommand) = .{}, sections: std.ArrayListUnmanaged(Section) = .{}, diff --git a/src/link/MachO/Zld.zig b/src/link/MachO/Zld.zig index 50a4f7710983..4d19da1e9790 100644 --- a/src/link/MachO/Zld.zig +++ b/src/link/MachO/Zld.zig @@ -82,7 +82,7 @@ unresolved: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, strtab: std.ArrayListUnmanaged(u8) = .{}, strtab_dir: std.StringHashMapUnmanaged(u32) = .{}, -threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{}, +threadlocal_offsets: std.ArrayListUnmanaged(TlvOffset) = .{}, // TODO merge with Symbol abstraction local_rebases: std.ArrayListUnmanaged(Pointer) = .{}, stubs: std.ArrayListUnmanaged(*Symbol) = .{}, got_entries: std.ArrayListUnmanaged(*Symbol) = .{}, @@ -92,6 +92,15 @@ stub_helper_stubs_start_off: ?u64 = null, mappings: std.AutoHashMapUnmanaged(MappingKey, SectionMapping) = .{}, unhandled_sections: std.AutoHashMapUnmanaged(MappingKey, u0) = .{}, +const TlvOffset = struct { + source_addr: u64, + offset: u64, + + fn cmp(context: void, a: TlvOffset, b: TlvOffset) bool { + return a.source_addr < b.source_addr; + } +}; + const MappingKey = struct { object_id: u16, source_sect_id: u16, @@ -277,7 +286,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { object.* = Object.init(self.allocator); object.arch = self.arch.?; - object.name = try self.allocator.dupe(u8, input.name); + object.name = input.name; object.file = input.file; try object.parse(); try self.objects.append(self.allocator, object); @@ -288,7 +297,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { archive.* = Archive.init(self.allocator); archive.arch = self.arch.?; - archive.name = try self.allocator.dupe(u8, input.name); + archive.name = input.name; archive.file = input.file; try archive.parse(); try self.archives.append(self.allocator, archive); @@ -1362,10 +1371,7 @@ fn resolveSymbols(self: *Zld) !void { }; assert(offsets.items.len > 0); - const object = try self.allocator.create(Object); - errdefer self.allocator.destroy(object); - - object.* = try archive.parseObject(offsets.items[0]); + const object = try archive.parseObject(offsets.items[0]); try self.objects.append(self.allocator, object); try self.resolveSymbolsInObject(object); @@ -1553,16 +1559,9 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { // TLV is handled via a separate offset mechanism. // Calculate the offset to the initializer. if (target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: { - log.warn("HIT", .{}); - log.warn(" | rel {any}", .{rel.cast(reloc.Unsigned).?}); - log.warn(" | name {s}", .{rel.target.symbol.name}); - log.warn(" | target address 0x{x}", .{args.target_addr}); - // TODO we don't want to save offset to tlv_bootstrap if (mem.eql(u8, rel.target.symbol.name, "__tlv_bootstrap")) break :tlv; - log.warn(" | object {s}", .{rel.target.symbol.cast(Symbol.Regular).?.file.name.?}); - const base_addr = blk: { if (self.tlv_data_section_index) |index| { const tlv_data = target_seg.sections.items[index]; @@ -1572,11 +1571,12 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { break :blk tlv_bss.addr; } }; - log.warn(" | base address 0x{x}", .{base_addr}); - log.warn(" | offset 0x{x}", .{args.target_addr - base_addr}); // Since we require TLV data to always preceed TLV bss section, we calculate // offsets wrt to the former if it is defined; otherwise, wrt to the latter. - try self.threadlocal_offsets.append(self.allocator, args.target_addr - base_addr); + try self.threadlocal_offsets.append(self.allocator, .{ + .source_addr = args.source_addr, + .offset = args.target_addr - base_addr, + }); } }, .got_page, .got_page_off, .got_load, .got => { @@ -2102,10 +2102,12 @@ fn flush(self: *Zld) !void { var stream = std.io.fixedBufferStream(buffer); var writer = stream.writer(); + std.sort.sort(TlvOffset, self.threadlocal_offsets.items, {}, TlvOffset.cmp); + const seek_amt = 2 * @sizeOf(u64); - while (self.threadlocal_offsets.popOrNull()) |offset| { + for (self.threadlocal_offsets.items) |tlv| { try writer.context.seekBy(seek_amt); - try writer.writeIntLittle(u64, offset); + try writer.writeIntLittle(u64, tlv.offset); } try self.file.?.pwriteAll(buffer, sect.offset);