mirror of
https://github.com/ziglang/zig.git
synced 2026-02-09 19:10:48 +00:00
zld: sort tlv offsets by source address
This commit is contained in:
parent
ef8a666797
commit
88d40fc005
@ -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;
|
||||
|
||||
@ -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) = .{},
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user