| ... | @@ -82,7 +82,7 @@ unresolved: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, | ... | @@ -82,7 +82,7 @@ unresolved: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, |
| 82 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 82 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 83 | strtab_dir: std.StringHashMapUnmanaged(u32) = .{}, | 83 | strtab_dir: std.StringHashMapUnmanaged(u32) = .{}, |
| 84 | | 84 | |
| 85 | threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{}, | 85 | threadlocal_offsets: std.ArrayListUnmanaged(TlvOffset) = .{}, // TODO merge with Symbol abstraction |
| 86 | local_rebases: std.ArrayListUnmanaged(Pointer) = .{}, | 86 | local_rebases: std.ArrayListUnmanaged(Pointer) = .{}, |
| 87 | stubs: std.ArrayListUnmanaged(*Symbol) = .{}, | 87 | stubs: std.ArrayListUnmanaged(*Symbol) = .{}, |
| 88 | got_entries: std.ArrayListUnmanaged(*Symbol) = .{}, | 88 | got_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, |
| 92 | mappings: std.AutoHashMapUnmanaged(MappingKey, SectionMapping) = .{}, | 92 | mappings: std.AutoHashMapUnmanaged(MappingKey, SectionMapping) = .{}, |
| 93 | unhandled_sections: std.AutoHashMapUnmanaged(MappingKey, u0) = .{}, | 93 | unhandled_sections: std.AutoHashMapUnmanaged(MappingKey, u0) = .{}, |
| 94 | | 94 | |
| | 95 | const 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 | |
| 95 | const MappingKey = struct { | 104 | const 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 { |
| 277 | | 286 | |
| 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 { |
| 288 | | 297 | |
| 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); |
| 1364 | | 1373 | |
| 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); |
| 1371 | | 1377 | |
| ... | @@ -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_bootstrap | 1562 | // 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; |
| 1563 | | 1564 | |
| 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 calculate | 1574 | // 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(); |
| 2104 | | 2104 | |
| | 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 | } |
| 2110 | | 2112 | |
| 2111 | try self.file.?.pwriteAll(buffer, sect.offset); | 2113 | try self.file.?.pwriteAll(buffer, sect.offset); |