| ... | ... | @@ -82,7 +82,7 @@ unresolved: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, |
| 82 | 82 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 83 | 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 | 86 | local_rebases: std.ArrayListUnmanaged(Pointer) = .{}, |
| 87 | 87 | stubs: std.ArrayListUnmanaged(*Symbol) = .{}, |
| 88 | 88 | got_entries: std.ArrayListUnmanaged(*Symbol) = .{}, |
| ... | ... | @@ -92,6 +92,15 @@ stub_helper_stubs_start_off: ?u64 = null, |
| 92 | 92 | mappings: std.AutoHashMapUnmanaged(MappingKey, SectionMapping) = .{}, |
| 93 | 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 | 104 | const MappingKey = struct { |
| 96 | 105 | object_id: u16, |
| 97 | 106 | source_sect_id: u16, |
| ... | ... | @@ -277,7 +286,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { |
| 277 | 286 | |
| 278 | 287 | object.* = Object.init(self.allocator); |
| 279 | 288 | object.arch = self.arch.?; |
| 280 | | object.name = try self.allocator.dupe(u8, input.name); |
| 289 | object.name = input.name; |
| 281 | 290 | object.file = input.file; |
| 282 | 291 | try object.parse(); |
| 283 | 292 | try self.objects.append(self.allocator, object); |
| ... | ... | @@ -288,7 +297,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { |
| 288 | 297 | |
| 289 | 298 | archive.* = Archive.init(self.allocator); |
| 290 | 299 | archive.arch = self.arch.?; |
| 291 | | archive.name = try self.allocator.dupe(u8, input.name); |
| 300 | archive.name = input.name; |
| 292 | 301 | archive.file = input.file; |
| 293 | 302 | try archive.parse(); |
| 294 | 303 | try self.archives.append(self.allocator, archive); |
| ... | ... | @@ -1362,10 +1371,7 @@ fn resolveSymbols(self: *Zld) !void { |
| 1362 | 1371 | }; |
| 1363 | 1372 | assert(offsets.items.len > 0); |
| 1364 | 1373 | |
| 1365 | | const object = try self.allocator.create(Object); |
| 1366 | | errdefer self.allocator.destroy(object); |
| 1367 | | |
| 1368 | | object.* = try archive.parseObject(offsets.items[0]); |
| 1374 | const object = try archive.parseObject(offsets.items[0]); |
| 1369 | 1375 | try self.objects.append(self.allocator, object); |
| 1370 | 1376 | try self.resolveSymbolsInObject(object); |
| 1371 | 1377 | |
| ... | ... | @@ -1553,16 +1559,9 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1553 | 1559 | // TLV is handled via a separate offset mechanism. |
| 1554 | 1560 | // Calculate the offset to the initializer. |
| 1555 | 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 | 1562 | // TODO we don't want to save offset to tlv_bootstrap |
| 1562 | 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 | 1565 | const base_addr = blk: { |
| 1567 | 1566 | if (self.tlv_data_section_index) |index| { |
| 1568 | 1567 | const tlv_data = target_seg.sections.items[index]; |
| ... | ... | @@ -1572,11 +1571,12 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1572 | 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 | 1574 | // Since we require TLV data to always preceed TLV bss section, we calculate |
| 1578 | 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 | 1582 | .got_page, .got_page_off, .got_load, .got => { |
| ... | ... | @@ -2102,10 +2102,12 @@ fn flush(self: *Zld) !void { |
| 2102 | 2102 | var stream = std.io.fixedBufferStream(buffer); |
| 2103 | 2103 | var writer = stream.writer(); |
| 2104 | 2104 | |
| 2105 | std.sort.sort(TlvOffset, self.threadlocal_offsets.items, {}, TlvOffset.cmp); |
| 2106 | |
| 2105 | 2107 | const seek_amt = 2 * @sizeOf(u64); |
| 2106 | | while (self.threadlocal_offsets.popOrNull()) |offset| { |
| 2108 | for (self.threadlocal_offsets.items) |tlv| { |
| 2107 | 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 | 2113 | try self.file.?.pwriteAll(buffer, sect.offset); |