aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2021-07-07 22:15:41 +0200
committerJakub Konka <kubkon@jakubkonka.com>2021-07-15 18:49:47 +0200
commite524f43a6fbb5189d24aa42667ababdcd92a2ab2 (patch)
treeec68e9b10d3c6d9e03932db7a09459419ccbf3e4 /src/link
parent7c662db8d95670f8ac0c88e9a2d6f49ef6782f13 (diff)
downloadzig-e524f43a6fbb5189d24aa42667ababdcd92a2ab2.tar.gz
zig-e524f43a6fbb5189d24aa42667ababdcd92a2ab2.zip
zld: save rebase and TLV offset as part of TextBlock
instead of as part of the Symbol. This seems to be more optimal way of handling dyld ops in presence of no splittable input sections in object files.
Diffstat (limited to 'src/link')
-rw-r--r--src/link/MachO/Object.zig28
-rw-r--r--src/link/MachO/Symbol.zig5
-rw-r--r--src/link/MachO/Zld.zig29
-rw-r--r--src/link/MachO/reloc.zig14
4 files changed, 36 insertions, 40 deletions
diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig
index 011aca06c3..f000119edf 100644
--- a/src/link/MachO/Object.zig
+++ b/src/link/MachO/Object.zig
@@ -435,6 +435,8 @@ const TextBlockParser = struct {
.references = std.AutoArrayHashMap(u32, void).init(self.allocator),
.code = try self.allocator.dupe(u8, code),
.relocs = std.ArrayList(Relocation).init(self.allocator),
+ .rebases = std.ArrayList(u64).init(self.allocator),
+ .tlv_offsets = std.ArrayList(u64).init(self.allocator),
.size = size,
.alignment = self.section.@"align",
};
@@ -444,18 +446,6 @@ const TextBlockParser = struct {
try self.object.parseRelocs(self.zld, relocs, block, start_addr);
}
- const is_zerofill = blk: {
- const tseg = self.zld.load_commands.items[self.match.seg].Segment;
- const tsect = tseg.sections.items[self.match.sect];
- const tsect_type = sectionType(tsect);
- break :blk tsect_type == macho.S_ZEROFILL or
- tsect_type == macho.S_THREAD_LOCAL_ZEROFILL or
- tsect_type == macho.S_THREAD_LOCAL_VARIABLES;
- };
- if (is_zerofill) {
- mem.set(u8, block.code, 0);
- }
-
self.index += 1;
return block;
@@ -589,6 +579,8 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
.references = std.AutoArrayHashMap(u32, void).init(self.allocator),
.code = try self.allocator.dupe(u8, code),
.relocs = std.ArrayList(Relocation).init(self.allocator),
+ .rebases = std.ArrayList(u64).init(self.allocator),
+ .tlv_offsets = std.ArrayList(u64).init(self.allocator),
.size = sect.size,
.alignment = sect.@"align",
};
@@ -597,18 +589,6 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
try self.parseRelocs(zld, relocs, block, 0);
}
- const is_zerofill = blk: {
- const tseg = zld.load_commands.items[match.seg].Segment;
- const tsect = tseg.sections.items[match.sect];
- const tsect_type = sectionType(tsect);
- break :blk tsect_type == macho.S_ZEROFILL or
- tsect_type == macho.S_THREAD_LOCAL_ZEROFILL or
- tsect_type == macho.S_THREAD_LOCAL_VARIABLES;
- };
- if (is_zerofill) {
- mem.set(u8, block.code, 0);
- }
-
if (zld.blocks.getPtr(match)) |last| {
last.*.next = block;
block.prev = last.*;
diff --git a/src/link/MachO/Symbol.zig b/src/link/MachO/Symbol.zig
index 5f437dc209..86624653f5 100644
--- a/src/link/MachO/Symbol.zig
+++ b/src/link/MachO/Symbol.zig
@@ -58,8 +58,6 @@ pub const Regular = struct {
local_sym_index: u32 = 0,
- should_rebase: bool = false,
-
pub const Linkage = enum {
translation_unit,
linkage_unit,
@@ -77,9 +75,6 @@ pub const Regular = struct {
if (self.weak_ref) {
try std.fmt.format(writer, ".weak_ref, ", .{});
}
- if (self.should_rebase) {
- try std.fmt.format(writer, ".should_rebase, ", .{});
- }
if (self.file) |file| {
try std.fmt.format(writer, ".file = {s}, ", .{file.name.?});
}
diff --git a/src/link/MachO/Zld.zig b/src/link/MachO/Zld.zig
index 485f6eda42..53bb31a718 100644
--- a/src/link/MachO/Zld.zig
+++ b/src/link/MachO/Zld.zig
@@ -128,6 +128,8 @@ pub const TextBlock = struct {
relocs: std.ArrayList(Relocation),
size: u64,
alignment: u32,
+ rebases: std.ArrayList(u64),
+ tlv_offsets: std.ArrayList(u64),
next: ?*TextBlock = null,
prev: ?*TextBlock = null,
@@ -137,6 +139,8 @@ pub const TextBlock = struct {
}
block.relocs.deinit();
block.references.deinit();
+ block.rebases.deinit();
+ block.tlv_offsets.deinit();
allocator.free(block.code);
}
@@ -144,24 +148,30 @@ pub const TextBlock = struct {
log.warn("TextBlock", .{});
log.warn(" | {}: {}", .{ self.local_sym_index, zld.locals.items[self.local_sym_index] });
if (self.aliases) |aliases| {
- log.warn(" | Aliases:", .{});
+ log.warn(" | aliases:", .{});
for (aliases) |index| {
log.warn(" | {}: {}", .{ index, zld.locals.items[index] });
}
}
if (self.references.count() > 0) {
- log.warn(" | References:", .{});
+ log.warn(" | references:", .{});
for (self.references.keys()) |index| {
log.warn(" | {}: {}", .{ index, zld.locals.items[index] });
}
}
log.warn(" | code.len = {}", .{self.code.len});
if (self.relocs.items.len > 0) {
- log.warn("Relocations:", .{});
+ log.warn(" | relocations:", .{});
for (self.relocs.items) |rel| {
- log.warn(" | {}", .{rel});
+ log.warn(" | {}", .{rel});
}
}
+ if (self.rebases.items.len > 0) {
+ log.warn(" | rebases: {any}", .{self.rebases.items});
+ }
+ if (self.tlv_offsets.items.len > 0) {
+ log.warn(" | TLV offsets: {any}", .{self.tlv_offsets.items});
+ }
log.warn(" | size = {}", .{self.size});
log.warn(" | align = {}", .{self.alignment});
}
@@ -271,6 +281,10 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
try self.addRpaths(args.rpaths);
try self.addDataInCodeLC();
try self.addCodeSignatureLC();
+ // try self.allocateTextSegment();
+ // try self.allocateDataConstSegment();
+ // try self.allocateDataSegment();
+ // self.allocateLinkeditSegment();
var it = self.blocks.iterator();
while (it.next()) |entry| {
@@ -281,11 +295,6 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
entry.value_ptr.*.print(self);
}
return error.TODO;
- // try self.allocateTextSegment();
- // try self.allocateDataConstSegment();
- // try self.allocateDataSegment();
- // self.allocateLinkeditSegment();
- // try self.allocateSymbols();
// try self.flush();
}
@@ -1477,6 +1486,8 @@ fn resolveSymbols(self: *Zld) !void {
.references = std.AutoArrayHashMap(u32, void).init(self.allocator),
.code = code,
.relocs = std.ArrayList(Relocation).init(self.allocator),
+ .rebases = std.ArrayList(u64).init(self.allocator),
+ .tlv_offsets = std.ArrayList(u64).init(self.allocator),
.size = size,
.alignment = alignment,
};
diff --git a/src/link/MachO/reloc.zig b/src/link/MachO/reloc.zig
index d35344c71b..b645ec152e 100644
--- a/src/link/MachO/reloc.zig
+++ b/src/link/MachO/reloc.zig
@@ -405,7 +405,7 @@ pub const Relocation = struct {
pub fn resolve(self: Relocation, zld: *Zld) !void {
const source_addr = blk: {
const sym = zld.locals.items[self.block.local_sym_index];
- break :blk sym.payload.regular.address;
+ break :blk sym.payload.regular.address + self.offset;
};
const target_addr = blk: {
const is_via_got = inner: {
@@ -668,7 +668,17 @@ pub const Parser = struct {
break :rebase true;
};
- source_reg.should_rebase = should_rebase;
+
+ if (should_rebase) {
+ try self.block.rebases.append(out_rel.offset);
+ }
+
+ // TLV is handled via a separate offset mechanism.
+ // Save the offset to the initializer.
+ // TODO I believe this can be simplified a lot!
+ if (sect_type == macho.S_THREAD_LOCAL_VARIABLES) {
+ try self.block.tlv_offsets.append(out_rel.offset);
+ }
},
}
} else if (out_rel.payload == .branch) blk: {