authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-05-06 17:02:39+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-05-06 17:10:05+02:00
log88d40fc005894ef84eb8bf54314da293772c4bba
tree275aaa9bb1e1921817a424840b90302034fa5aa3
parentef8a666797d6fb2849762dd157379ca227762c90

zld: sort tlv offsets by source address


3 files changed, 28 insertions(+), 23 deletions(-)

src/link/MachO/Archive.zig+6-3
...@@ -16,7 +16,7 @@ allocator: *Allocator,...@@ -16,7 +16,7 @@ allocator: *Allocator,
16arch: ?std.Target.Cpu.Arch = null,16arch: ?std.Target.Cpu.Arch = null,
17file: ?fs.File = null,17file: ?fs.File = null,
18header: ?ar_hdr = null,18header: ?ar_hdr = null,
19name: ?[]u8 = null,19name: ?[]const u8 = null,
2020
21/// Parsed table of contents.21/// Parsed table of contents.
22/// Each symbol name points to a list of all definition22/// Each symbol name points to a list of all definition
...@@ -195,7 +195,7 @@ fn parseTableOfContents(self: *Archive, reader: anytype) !void {...@@ -195,7 +195,7 @@ fn parseTableOfContents(self: *Archive, reader: anytype) !void {
195}195}
196196
197/// Caller owns the Object instance.197/// Caller owns the Object instance.
198pub fn parseObject(self: Archive, offset: u32) !Object {198pub fn parseObject(self: Archive, offset: u32) !*Object {
199 var reader = self.file.?.reader();199 var reader = self.file.?.reader();
200 try reader.context.seekTo(offset);200 try reader.context.seekTo(offset);
201201
...@@ -217,7 +217,10 @@ pub fn parseObject(self: Archive, offset: u32) !Object {...@@ -217,7 +217,10 @@ pub fn parseObject(self: Archive, offset: u32) !Object {
217 break :name try std.fmt.allocPrint(self.allocator, "{s}({s})", .{ path, object_name });217 break :name try std.fmt.allocPrint(self.allocator, "{s}({s})", .{ path, object_name });
218 };218 };
219219
220 var object = Object.init(self.allocator);220 var object = try self.allocator.create(Object);
221 errdefer self.allocator.destroy(object);
222
223 object.* = Object.init(self.allocator);
221 object.arch = self.arch.?;224 object.arch = self.arch.?;
222 object.file = try fs.cwd().openFile(self.name.?, .{});225 object.file = try fs.cwd().openFile(self.name.?, .{});
223 object.name = name;226 object.name = name;
src/link/MachO/Object.zig+1-1
...@@ -22,7 +22,7 @@ arch: ?std.Target.Cpu.Arch = null,...@@ -22,7 +22,7 @@ arch: ?std.Target.Cpu.Arch = null,
22header: ?macho.mach_header_64 = null,22header: ?macho.mach_header_64 = null,
23file: ?fs.File = null,23file: ?fs.File = null,
24file_offset: ?u32 = null,24file_offset: ?u32 = null,
25name: ?[]u8 = null,25name: ?[]const u8 = null,
2626
27load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},27load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},
28sections: std.ArrayListUnmanaged(Section) = .{},28sections: std.ArrayListUnmanaged(Section) = .{},
src/link/MachO/Zld.zig+21-19
...@@ -82,7 +82,7 @@ unresolved: std.StringArrayHashMapUnmanaged(*Symbol) = .{},...@@ -82,7 +82,7 @@ unresolved: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
82strtab: std.ArrayListUnmanaged(u8) = .{},82strtab: std.ArrayListUnmanaged(u8) = .{},
83strtab_dir: std.StringHashMapUnmanaged(u32) = .{},83strtab_dir: std.StringHashMapUnmanaged(u32) = .{},
8484
85threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{},85threadlocal_offsets: std.ArrayListUnmanaged(TlvOffset) = .{}, // TODO merge with Symbol abstraction
86local_rebases: std.ArrayListUnmanaged(Pointer) = .{},86local_rebases: std.ArrayListUnmanaged(Pointer) = .{},
87stubs: std.ArrayListUnmanaged(*Symbol) = .{},87stubs: std.ArrayListUnmanaged(*Symbol) = .{},
88got_entries: std.ArrayListUnmanaged(*Symbol) = .{},88got_entries: std.ArrayListUnmanaged(*Symbol) = .{},
...@@ -92,6 +92,15 @@ stub_helper_stubs_start_off: ?u64 = null,...@@ -92,6 +92,15 @@ stub_helper_stubs_start_off: ?u64 = null,
92mappings: std.AutoHashMapUnmanaged(MappingKey, SectionMapping) = .{},92mappings: std.AutoHashMapUnmanaged(MappingKey, SectionMapping) = .{},
93unhandled_sections: std.AutoHashMapUnmanaged(MappingKey, u0) = .{},93unhandled_sections: std.AutoHashMapUnmanaged(MappingKey, u0) = .{},
9494
95const TlvOffset = struct {
96 source_addr: u64,
97 offset: u64,
98
99 fn cmp(context: void, a: TlvOffset, b: TlvOffset) bool {
100 return a.source_addr < b.source_addr;
101 }
102};
103
95const MappingKey = struct {104const MappingKey = struct {
96 object_id: u16,105 object_id: u16,
97 source_sect_id: u16,106 source_sect_id: u16,
...@@ -277,7 +286,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {...@@ -277,7 +286,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
277286
278 object.* = Object.init(self.allocator);287 object.* = Object.init(self.allocator);
279 object.arch = self.arch.?;288 object.arch = self.arch.?;
280 object.name = try self.allocator.dupe(u8, input.name);289 object.name = input.name;
281 object.file = input.file;290 object.file = input.file;
282 try object.parse();291 try object.parse();
283 try self.objects.append(self.allocator, object);292 try self.objects.append(self.allocator, object);
...@@ -288,7 +297,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {...@@ -288,7 +297,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
288297
289 archive.* = Archive.init(self.allocator);298 archive.* = Archive.init(self.allocator);
290 archive.arch = self.arch.?;299 archive.arch = self.arch.?;
291 archive.name = try self.allocator.dupe(u8, input.name);300 archive.name = input.name;
292 archive.file = input.file;301 archive.file = input.file;
293 try archive.parse();302 try archive.parse();
294 try self.archives.append(self.allocator, archive);303 try self.archives.append(self.allocator, archive);
...@@ -1362,10 +1371,7 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1362,10 +1371,7 @@ fn resolveSymbols(self: *Zld) !void {
1362 };1371 };
1363 assert(offsets.items.len > 0);1372 assert(offsets.items.len > 0);
13641373
1365 const object = try self.allocator.create(Object);1374 const object = try archive.parseObject(offsets.items[0]);
1366 errdefer self.allocator.destroy(object);
1367
1368 object.* = try archive.parseObject(offsets.items[0]);
1369 try self.objects.append(self.allocator, object);1375 try self.objects.append(self.allocator, object);
1370 try self.resolveSymbolsInObject(object);1376 try self.resolveSymbolsInObject(object);
13711377
...@@ -1553,16 +1559,9 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1553,16 +1559,9 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1553 // TLV is handled via a separate offset mechanism.1559 // TLV is handled via a separate offset mechanism.
1554 // Calculate the offset to the initializer.1560 // Calculate the offset to the initializer.
1555 if (target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: {1561 if (target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: {
1556 log.warn("HIT", .{});
1557 log.warn(" | rel {any}", .{rel.cast(reloc.Unsigned).?});
1558 log.warn(" | name {s}", .{rel.target.symbol.name});
1559 log.warn(" | target address 0x{x}", .{args.target_addr});
1560
1561 // TODO we don't want to save offset to tlv_bootstrap1562 // TODO we don't want to save offset to tlv_bootstrap
1562 if (mem.eql(u8, rel.target.symbol.name, "__tlv_bootstrap")) break :tlv;1563 if (mem.eql(u8, rel.target.symbol.name, "__tlv_bootstrap")) break :tlv;
15631564
1564 log.warn(" | object {s}", .{rel.target.symbol.cast(Symbol.Regular).?.file.name.?});
1565
1566 const base_addr = blk: {1565 const base_addr = blk: {
1567 if (self.tlv_data_section_index) |index| {1566 if (self.tlv_data_section_index) |index| {
1568 const tlv_data = target_seg.sections.items[index];1567 const tlv_data = target_seg.sections.items[index];
...@@ -1572,11 +1571,12 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1572,11 +1571,12 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1572 break :blk tlv_bss.addr;1571 break :blk tlv_bss.addr;
1573 }1572 }
1574 };1573 };
1575 log.warn(" | base address 0x{x}", .{base_addr});
1576 log.warn(" | offset 0x{x}", .{args.target_addr - base_addr});
1577 // Since we require TLV data to always preceed TLV bss section, we calculate1574 // Since we require TLV data to always preceed TLV bss section, we calculate
1578 // offsets wrt to the former if it is defined; otherwise, wrt to the latter.1575 // offsets wrt to the former if it is defined; otherwise, wrt to the latter.
1579 try self.threadlocal_offsets.append(self.allocator, args.target_addr - base_addr);1576 try self.threadlocal_offsets.append(self.allocator, .{
1577 .source_addr = args.source_addr,
1578 .offset = args.target_addr - base_addr,
1579 });
1580 }1580 }
1581 },1581 },
1582 .got_page, .got_page_off, .got_load, .got => {1582 .got_page, .got_page_off, .got_load, .got => {
...@@ -2102,10 +2102,12 @@ fn flush(self: *Zld) !void {...@@ -2102,10 +2102,12 @@ fn flush(self: *Zld) !void {
2102 var stream = std.io.fixedBufferStream(buffer);2102 var stream = std.io.fixedBufferStream(buffer);
2103 var writer = stream.writer();2103 var writer = stream.writer();
21042104
2105 std.sort.sort(TlvOffset, self.threadlocal_offsets.items, {}, TlvOffset.cmp);
2106
2105 const seek_amt = 2 * @sizeOf(u64);2107 const seek_amt = 2 * @sizeOf(u64);
2106 while (self.threadlocal_offsets.popOrNull()) |offset| {2108 for (self.threadlocal_offsets.items) |tlv| {
2107 try writer.context.seekBy(seek_amt);2109 try writer.context.seekBy(seek_amt);
2108 try writer.writeIntLittle(u64, offset);2110 try writer.writeIntLittle(u64, tlv.offset);
2109 }2111 }
21102112
2111 try self.file.?.pwriteAll(buffer, sect.offset);2113 try self.file.?.pwriteAll(buffer, sect.offset);