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 {...@@ -435,6 +435,8 @@ const TextBlockParser = struct {
435 .references = std.AutoArrayHashMap(u32, void).init(self.allocator),435 .references = std.AutoArrayHashMap(u32, void).init(self.allocator),
436 .code = try self.allocator.dupe(u8, code),436 .code = try self.allocator.dupe(u8, code),
437 .relocs = std.ArrayList(Relocation).init(self.allocator),437 .relocs = std.ArrayList(Relocation).init(self.allocator),
438 .rebases = std.ArrayList(u64).init(self.allocator),
439 .tlv_offsets = std.ArrayList(u64).init(self.allocator),
438 .size = size,440 .size = size,
439 .alignment = self.section.@"align",441 .alignment = self.section.@"align",
440 };442 };
...@@ -444,18 +446,6 @@ const TextBlockParser = struct {...@@ -444,18 +446,6 @@ const TextBlockParser = struct {
444 try self.object.parseRelocs(self.zld, relocs, block, start_addr);446 try self.object.parseRelocs(self.zld, relocs, block, start_addr);
445 }447 }
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
459 self.index += 1;449 self.index += 1;
460450
461 return block;451 return block;
...@@ -589,6 +579,8 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {...@@ -589,6 +579,8 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
589 .references = std.AutoArrayHashMap(u32, void).init(self.allocator),579 .references = std.AutoArrayHashMap(u32, void).init(self.allocator),
590 .code = try self.allocator.dupe(u8, code),580 .code = try self.allocator.dupe(u8, code),
591 .relocs = std.ArrayList(Relocation).init(self.allocator),581 .relocs = std.ArrayList(Relocation).init(self.allocator),
582 .rebases = std.ArrayList(u64).init(self.allocator),
583 .tlv_offsets = std.ArrayList(u64).init(self.allocator),
592 .size = sect.size,584 .size = sect.size,
593 .alignment = sect.@"align",585 .alignment = sect.@"align",
594 };586 };
...@@ -597,18 +589,6 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {...@@ -597,18 +589,6 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
597 try self.parseRelocs(zld, relocs, block, 0);589 try self.parseRelocs(zld, relocs, block, 0);
598 }590 }
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
612 if (zld.blocks.getPtr(match)) |last| {592 if (zld.blocks.getPtr(match)) |last| {
613 last.*.next = block;593 last.*.next = block;
614 block.prev = last.*;594 block.prev = last.*;
src/link/MachO/Symbol.zig-5
...@@ -58,8 +58,6 @@ pub const Regular = struct {...@@ -58,8 +58,6 @@ pub const Regular = struct {
5858
59 local_sym_index: u32 = 0,59 local_sym_index: u32 = 0,
6060
61 should_rebase: bool = false,
62
63 pub const Linkage = enum {61 pub const Linkage = enum {
64 translation_unit,62 translation_unit,
65 linkage_unit,63 linkage_unit,
...@@ -77,9 +75,6 @@ pub const Regular = struct {...@@ -77,9 +75,6 @@ pub const Regular = struct {
77 if (self.weak_ref) {75 if (self.weak_ref) {
78 try std.fmt.format(writer, ".weak_ref, ", .{});76 try std.fmt.format(writer, ".weak_ref, ", .{});
79 }77 }
80 if (self.should_rebase) {
81 try std.fmt.format(writer, ".should_rebase, ", .{});
82 }
83 if (self.file) |file| {78 if (self.file) |file| {
84 try std.fmt.format(writer, ".file = {s}, ", .{file.name.?});79 try std.fmt.format(writer, ".file = {s}, ", .{file.name.?});
85 }80 }
src/link/MachO/Zld.zig+20-9
...@@ -128,6 +128,8 @@ pub const TextBlock = struct {...@@ -128,6 +128,8 @@ pub const TextBlock = struct {
128 relocs: std.ArrayList(Relocation),128 relocs: std.ArrayList(Relocation),
129 size: u64,129 size: u64,
130 alignment: u32,130 alignment: u32,
131 rebases: std.ArrayList(u64),
132 tlv_offsets: std.ArrayList(u64),
131 next: ?*TextBlock = null,133 next: ?*TextBlock = null,
132 prev: ?*TextBlock = null,134 prev: ?*TextBlock = null,
133135
...@@ -137,6 +139,8 @@ pub const TextBlock = struct {...@@ -137,6 +139,8 @@ pub const TextBlock = struct {
137 }139 }
138 block.relocs.deinit();140 block.relocs.deinit();
139 block.references.deinit();141 block.references.deinit();
142 block.rebases.deinit();
143 block.tlv_offsets.deinit();
140 allocator.free(block.code);144 allocator.free(block.code);
141 }145 }
142146
...@@ -144,24 +148,30 @@ pub const TextBlock = struct {...@@ -144,24 +148,30 @@ pub const TextBlock = struct {
144 log.warn("TextBlock", .{});148 log.warn("TextBlock", .{});
145 log.warn(" | {}: {}", .{ self.local_sym_index, zld.locals.items[self.local_sym_index] });149 log.warn(" | {}: {}", .{ self.local_sym_index, zld.locals.items[self.local_sym_index] });
146 if (self.aliases) |aliases| {150 if (self.aliases) |aliases| {
147 log.warn(" | Aliases:", .{});151 log.warn(" | aliases:", .{});
148 for (aliases) |index| {152 for (aliases) |index| {
149 log.warn(" | {}: {}", .{ index, zld.locals.items[index] });153 log.warn(" | {}: {}", .{ index, zld.locals.items[index] });
150 }154 }
151 }155 }
152 if (self.references.count() > 0) {156 if (self.references.count() > 0) {
153 log.warn(" | References:", .{});157 log.warn(" | references:", .{});
154 for (self.references.keys()) |index| {158 for (self.references.keys()) |index| {
155 log.warn(" | {}: {}", .{ index, zld.locals.items[index] });159 log.warn(" | {}: {}", .{ index, zld.locals.items[index] });
156 }160 }
157 }161 }
158 log.warn(" | code.len = {}", .{self.code.len});162 log.warn(" | code.len = {}", .{self.code.len});
159 if (self.relocs.items.len > 0) {163 if (self.relocs.items.len > 0) {
160 log.warn("Relocations:", .{});164 log.warn(" | relocations:", .{});
161 for (self.relocs.items) |rel| {165 for (self.relocs.items) |rel| {
162 log.warn(" | {}", .{rel});166 log.warn(" | {}", .{rel});
163 }167 }
164 }168 }
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 }
165 log.warn(" | size = {}", .{self.size});175 log.warn(" | size = {}", .{self.size});
166 log.warn(" | align = {}", .{self.alignment});176 log.warn(" | align = {}", .{self.alignment});
167 }177 }
...@@ -271,6 +281,10 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg...@@ -271,6 +281,10 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
271 try self.addRpaths(args.rpaths);281 try self.addRpaths(args.rpaths);
272 try self.addDataInCodeLC();282 try self.addDataInCodeLC();
273 try self.addCodeSignatureLC();283 try self.addCodeSignatureLC();
284 // try self.allocateTextSegment();
285 // try self.allocateDataConstSegment();
286 // try self.allocateDataSegment();
287 // self.allocateLinkeditSegment();
274288
275 var it = self.blocks.iterator();289 var it = self.blocks.iterator();
276 while (it.next()) |entry| {290 while (it.next()) |entry| {
...@@ -281,11 +295,6 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg...@@ -281,11 +295,6 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
281 entry.value_ptr.*.print(self);295 entry.value_ptr.*.print(self);
282 }296 }
283 return error.TODO;297 return error.TODO;
284 // try self.allocateTextSegment();
285 // try self.allocateDataConstSegment();
286 // try self.allocateDataSegment();
287 // self.allocateLinkeditSegment();
288 // try self.allocateSymbols();
289 // try self.flush();298 // try self.flush();
290}299}
291300
...@@ -1477,6 +1486,8 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1477,6 +1486,8 @@ fn resolveSymbols(self: *Zld) !void {
1477 .references = std.AutoArrayHashMap(u32, void).init(self.allocator),1486 .references = std.AutoArrayHashMap(u32, void).init(self.allocator),
1478 .code = code,1487 .code = code,
1479 .relocs = std.ArrayList(Relocation).init(self.allocator),1488 .relocs = std.ArrayList(Relocation).init(self.allocator),
1489 .rebases = std.ArrayList(u64).init(self.allocator),
1490 .tlv_offsets = std.ArrayList(u64).init(self.allocator),
1480 .size = size,1491 .size = size,
1481 .alignment = alignment,1492 .alignment = alignment,
1482 };1493 };
src/link/MachO/reloc.zig+12-2
...@@ -405,7 +405,7 @@ pub const Relocation = struct {...@@ -405,7 +405,7 @@ pub const Relocation = struct {
405 pub fn resolve(self: Relocation, zld: *Zld) !void {405 pub fn resolve(self: Relocation, zld: *Zld) !void {
406 const source_addr = blk: {406 const source_addr = blk: {
407 const sym = zld.locals.items[self.block.local_sym_index];407 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;
409 };409 };
410 const target_addr = blk: {410 const target_addr = blk: {
411 const is_via_got = inner: {411 const is_via_got = inner: {
...@@ -668,7 +668,17 @@ pub const Parser = struct {...@@ -668,7 +668,17 @@ pub const Parser = struct {
668668
669 break :rebase true;669 break :rebase true;
670 };670 };
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 }
672 },682 },
673 }683 }
674 } else if (out_rel.payload == .branch) blk: {684 } else if (out_rel.payload == .branch) blk: {