authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-07 22:15:41+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:47+02:00
loge524f43a6fbb5189d24aa42667ababdcd92a2ab2
treeec68e9b10d3c6d9e03932db7a09459419ccbf3e4
parent7c662db8d95670f8ac0c88e9a2d6f49ef6782f13

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.

4 files changed, 36 insertions(+), 40 deletions(-)

src/link/MachO/Object.zig+4-24
......@@ -435,6 +435,8 @@ const TextBlockParser = struct {
435435 .references = std.AutoArrayHashMap(u32, void).init(self.allocator),
436436 .code = try self.allocator.dupe(u8, code),
437437 .relocs = std.ArrayList(Relocation).init(self.allocator),
438 .rebases = std.ArrayList(u64).init(self.allocator),
439 .tlv_offsets = std.ArrayList(u64).init(self.allocator),
438440 .size = size,
439441 .alignment = self.section.@"align",
440442 };
......@@ -444,18 +446,6 @@ const TextBlockParser = struct {
444446 try self.object.parseRelocs(self.zld, relocs, block, start_addr);
445447 }
446448
447 const is_zerofill = blk: {
448 const tseg = self.zld.load_commands.items[self.match.seg].Segment;
449 const tsect = tseg.sections.items[self.match.sect];
450 const tsect_type = sectionType(tsect);
451 break :blk tsect_type == macho.S_ZEROFILL or
452 tsect_type == macho.S_THREAD_LOCAL_ZEROFILL or
453 tsect_type == macho.S_THREAD_LOCAL_VARIABLES;
454 };
455 if (is_zerofill) {
456 mem.set(u8, block.code, 0);
457 }
458
459449 self.index += 1;
460450
461451 return block;
......@@ -589,6 +579,8 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
589579 .references = std.AutoArrayHashMap(u32, void).init(self.allocator),
590580 .code = try self.allocator.dupe(u8, code),
591581 .relocs = std.ArrayList(Relocation).init(self.allocator),
582 .rebases = std.ArrayList(u64).init(self.allocator),
583 .tlv_offsets = std.ArrayList(u64).init(self.allocator),
592584 .size = sect.size,
593585 .alignment = sect.@"align",
594586 };
......@@ -597,18 +589,6 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
597589 try self.parseRelocs(zld, relocs, block, 0);
598590 }
599591
600 const is_zerofill = blk: {
601 const tseg = zld.load_commands.items[match.seg].Segment;
602 const tsect = tseg.sections.items[match.sect];
603 const tsect_type = sectionType(tsect);
604 break :blk tsect_type == macho.S_ZEROFILL or
605 tsect_type == macho.S_THREAD_LOCAL_ZEROFILL or
606 tsect_type == macho.S_THREAD_LOCAL_VARIABLES;
607 };
608 if (is_zerofill) {
609 mem.set(u8, block.code, 0);
610 }
611
612592 if (zld.blocks.getPtr(match)) |last| {
613593 last.*.next = block;
614594 block.prev = last.*;
src/link/MachO/Symbol.zig-5
......@@ -58,8 +58,6 @@ pub const Regular = struct {
5858
5959 local_sym_index: u32 = 0,
6060
61 should_rebase: bool = false,
62
6361 pub const Linkage = enum {
6462 translation_unit,
6563 linkage_unit,
......@@ -77,9 +75,6 @@ pub const Regular = struct {
7775 if (self.weak_ref) {
7876 try std.fmt.format(writer, ".weak_ref, ", .{});
7977 }
80 if (self.should_rebase) {
81 try std.fmt.format(writer, ".should_rebase, ", .{});
82 }
8378 if (self.file) |file| {
8479 try std.fmt.format(writer, ".file = {s}, ", .{file.name.?});
8580 }
src/link/MachO/Zld.zig+20-9
......@@ -128,6 +128,8 @@ pub const TextBlock = struct {
128128 relocs: std.ArrayList(Relocation),
129129 size: u64,
130130 alignment: u32,
131 rebases: std.ArrayList(u64),
132 tlv_offsets: std.ArrayList(u64),
131133 next: ?*TextBlock = null,
132134 prev: ?*TextBlock = null,
133135
......@@ -137,6 +139,8 @@ pub const TextBlock = struct {
137139 }
138140 block.relocs.deinit();
139141 block.references.deinit();
142 block.rebases.deinit();
143 block.tlv_offsets.deinit();
140144 allocator.free(block.code);
141145 }
142146
......@@ -144,24 +148,30 @@ pub const TextBlock = struct {
144148 log.warn("TextBlock", .{});
145149 log.warn(" | {}: {}", .{ self.local_sym_index, zld.locals.items[self.local_sym_index] });
146150 if (self.aliases) |aliases| {
147 log.warn(" | Aliases:", .{});
151 log.warn(" | aliases:", .{});
148152 for (aliases) |index| {
149153 log.warn(" | {}: {}", .{ index, zld.locals.items[index] });
150154 }
151155 }
152156 if (self.references.count() > 0) {
153 log.warn(" | References:", .{});
157 log.warn(" | references:", .{});
154158 for (self.references.keys()) |index| {
155159 log.warn(" | {}: {}", .{ index, zld.locals.items[index] });
156160 }
157161 }
158162 log.warn(" | code.len = {}", .{self.code.len});
159163 if (self.relocs.items.len > 0) {
160 log.warn("Relocations:", .{});
164 log.warn(" | relocations:", .{});
161165 for (self.relocs.items) |rel| {
162 log.warn(" | {}", .{rel});
166 log.warn(" | {}", .{rel});
163167 }
164168 }
169 if (self.rebases.items.len > 0) {
170 log.warn(" | rebases: {any}", .{self.rebases.items});
171 }
172 if (self.tlv_offsets.items.len > 0) {
173 log.warn(" | TLV offsets: {any}", .{self.tlv_offsets.items});
174 }
165175 log.warn(" | size = {}", .{self.size});
166176 log.warn(" | align = {}", .{self.alignment});
167177 }
......@@ -271,6 +281,10 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
271281 try self.addRpaths(args.rpaths);
272282 try self.addDataInCodeLC();
273283 try self.addCodeSignatureLC();
284 // try self.allocateTextSegment();
285 // try self.allocateDataConstSegment();
286 // try self.allocateDataSegment();
287 // self.allocateLinkeditSegment();
274288
275289 var it = self.blocks.iterator();
276290 while (it.next()) |entry| {
......@@ -281,11 +295,6 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
281295 entry.value_ptr.*.print(self);
282296 }
283297 return error.TODO;
284 // try self.allocateTextSegment();
285 // try self.allocateDataConstSegment();
286 // try self.allocateDataSegment();
287 // self.allocateLinkeditSegment();
288 // try self.allocateSymbols();
289298 // try self.flush();
290299}
291300
......@@ -1477,6 +1486,8 @@ fn resolveSymbols(self: *Zld) !void {
14771486 .references = std.AutoArrayHashMap(u32, void).init(self.allocator),
14781487 .code = code,
14791488 .relocs = std.ArrayList(Relocation).init(self.allocator),
1489 .rebases = std.ArrayList(u64).init(self.allocator),
1490 .tlv_offsets = std.ArrayList(u64).init(self.allocator),
14801491 .size = size,
14811492 .alignment = alignment,
14821493 };
src/link/MachO/reloc.zig+12-2
......@@ -405,7 +405,7 @@ pub const Relocation = struct {
405405 pub fn resolve(self: Relocation, zld: *Zld) !void {
406406 const source_addr = blk: {
407407 const sym = zld.locals.items[self.block.local_sym_index];
408 break :blk sym.payload.regular.address;
408 break :blk sym.payload.regular.address + self.offset;
409409 };
410410 const target_addr = blk: {
411411 const is_via_got = inner: {
......@@ -668,7 +668,17 @@ pub const Parser = struct {
668668
669669 break :rebase true;
670670 };
671 source_reg.should_rebase = should_rebase;
671
672 if (should_rebase) {
673 try self.block.rebases.append(out_rel.offset);
674 }
675
676 // TLV is handled via a separate offset mechanism.
677 // Save the offset to the initializer.
678 // TODO I believe this can be simplified a lot!
679 if (sect_type == macho.S_THREAD_LOCAL_VARIABLES) {
680 try self.block.tlv_offsets.append(out_rel.offset);
681 }
672682 },
673683 }
674684 } else if (out_rel.payload == .branch) blk: {