authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-08 14:37:33+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:47+02:00
log12187586d15b6eae0330a652a6b1532d2b457991
treeca1edcffde851d39b21f5bd0142c75c8d7fefb3d
parent961b463fad37e00fa8a2ca2bbfcb58a2b1d2bea9

zld: fix alloc alignment and resolve relocs


3 files changed, 194 insertions(+), 123 deletions(-)

src/link/MachO/Object.zig+10-4
......@@ -535,8 +535,11 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
535535 // How does it tie with incremental space allocs?
536536 const tseg = &zld.load_commands.items[match.seg].Segment;
537537 const tsect = &tseg.sections.items[match.sect];
538 tsect.size += block.size;
539 tsect.@"align" = math.max(tsect.@"align", block.alignment);
538 const new_alignment = math.max(tsect.@"align", block.alignment);
539 const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment);
540 const new_size = mem.alignForwardGeneric(u64, tsect.size + block.size, new_alignment_pow_2);
541 tsect.size = new_size;
542 tsect.@"align" = new_alignment;
540543
541544 if (zld.blocks.getPtr(match)) |last| {
542545 last.*.next = block;
......@@ -621,8 +624,11 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
621624 // How does it tie with incremental space allocs?
622625 const tseg = &zld.load_commands.items[match.seg].Segment;
623626 const tsect = &tseg.sections.items[match.sect];
624 tsect.size += block.size;
625 tsect.@"align" = math.max(tsect.@"align", block.alignment);
627 const new_alignment = math.max(tsect.@"align", block.alignment);
628 const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment);
629 const new_size = mem.alignForwardGeneric(u64, tsect.size + block.size, new_alignment_pow_2);
630 tsect.size = new_size;
631 tsect.@"align" = new_alignment;
626632
627633 if (zld.blocks.getPtr(match)) |last| {
628634 last.*.next = block;
src/link/MachO/Zld.zig+162-102
......@@ -173,6 +173,12 @@ pub const TextBlock = struct {
173173 self.tlv_offsets.deinit();
174174 }
175175
176 pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void {
177 for (self.relocs.items) |rel| {
178 try rel.resolve(zld);
179 }
180 }
181
176182 pub fn print_this(self: *const TextBlock, zld: *Zld) void {
177183 log.warn("TextBlock", .{});
178184 log.warn(" | {}: {}", .{ self.local_sym_index, zld.locals.items[self.local_sym_index] });
......@@ -328,11 +334,10 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
328334 const sect = seg.sections.items[entry.key_ptr.sect];
329335
330336 log.warn("\n\n{s},{s} contents:", .{ segmentName(sect), sectionName(sect) });
331 log.warn("{}", .{sect});
337 log.warn(" {}", .{sect});
332338 entry.value_ptr.*.print(self);
333339 }
334 return error.TODO;
335 // try self.flush();
340 try self.flush();
336341}
337342
338343fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u8) !void {
......@@ -1041,6 +1046,8 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void {
10411046}
10421047
10431048fn allocateTextBlocks(self: *Zld) !void {
1049 log.warn("allocating text blocks", .{});
1050
10441051 var it = self.blocks.iterator();
10451052 while (it.next()) |entry| {
10461053 const match = entry.key_ptr.*;
......@@ -1050,13 +1057,34 @@ fn allocateTextBlocks(self: *Zld) !void {
10501057 const sect = seg.sections.items[match.sect];
10511058 var base_addr: u64 = sect.addr + sect.size;
10521059
1060 log.warn(" within section {s},{s}", .{ segmentName(sect), sectionName(sect) });
1061 log.warn(" {}", .{sect});
1062
10531063 while (true) {
1054 base_addr -= block.size;
1064 const block_alignment = try math.powi(u32, 2, block.alignment);
1065 base_addr = mem.alignBackwardGeneric(u64, base_addr - block.size, block_alignment);
10551066
10561067 const sym = self.locals.items[block.local_sym_index];
10571068 assert(sym.payload == .regular);
10581069 sym.payload.regular.address = base_addr;
10591070
1071 log.warn(" {s}: start=0x{x}, end=0x{x}, size={}, align={}", .{
1072 sym.name,
1073 base_addr,
1074 base_addr + block.size,
1075 block.size,
1076 block.alignment,
1077 });
1078
1079 // Update each alias (if any)
1080 if (block.aliases) |aliases| {
1081 for (aliases) |index| {
1082 const alias_sym = self.locals.items[index];
1083 assert(alias_sym.payload == .regular);
1084 alias_sym.payload.regular.address = base_addr;
1085 }
1086 }
1087
10601088 // Update each symbol contained within the TextBlock
10611089 if (block.contained) |contained| {
10621090 for (contained) |sym_at_off| {
......@@ -1073,6 +1101,37 @@ fn allocateTextBlocks(self: *Zld) !void {
10731101 }
10741102}
10751103
1104fn writeTextBlocks(self: *Zld) !void {
1105 var it = self.blocks.iterator();
1106 while (it.next()) |entry| {
1107 const match = entry.key_ptr.*;
1108 var block: *TextBlock = entry.value_ptr.*;
1109
1110 const seg = self.load_commands.items[match.seg].Segment;
1111 const sect = seg.sections.items[match.sect];
1112
1113 log.warn("writing text blocks for section {s},{s}", .{ segmentName(sect), sectionName(sect) });
1114
1115 var code = try self.allocator.alloc(u8, sect.size);
1116 defer self.allocator.free(code);
1117
1118 var base_off: u64 = sect.size;
1119
1120 while (true) {
1121 base_off -= block.size;
1122
1123 try block.resolveRelocs(self);
1124 mem.copy(u8, code[base_off..][0..block.size], block.code);
1125
1126 if (block.prev) |prev| {
1127 block = prev;
1128 } else break;
1129 }
1130
1131 try self.file.?.pwriteAll(code, sect.offset);
1132 }
1133}
1134
10761135fn writeStubHelperCommon(self: *Zld) !void {
10771136 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
10781137 const stub_helper = &text_segment.sections.items[self.stub_helper_section_index.?];
......@@ -1941,104 +2000,105 @@ fn addRpaths(self: *Zld, rpaths: []const []const u8) !void {
19412000}
19422001
19432002fn flush(self: *Zld) !void {
1944 try self.writeStubHelperCommon();
1945
1946 if (self.common_section_index) |index| {
1947 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1948 const sect = &seg.sections.items[index];
1949 sect.offset = 0;
1950 }
1951
1952 if (self.bss_section_index) |index| {
1953 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1954 const sect = &seg.sections.items[index];
1955 sect.offset = 0;
1956 }
1957
1958 if (self.tlv_bss_section_index) |index| {
1959 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1960 const sect = &seg.sections.items[index];
1961 sect.offset = 0;
1962 }
1963
1964 if (self.tlv_section_index) |index| {
1965 const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1966 const sect = &seg.sections.items[index];
1967
1968 var buffer = try self.allocator.alloc(u8, @intCast(usize, sect.size));
1969 defer self.allocator.free(buffer);
1970 _ = try self.file.?.preadAll(buffer, sect.offset);
1971
1972 var stream = std.io.fixedBufferStream(buffer);
1973 var writer = stream.writer();
1974
1975 std.sort.sort(TlvOffset, self.threadlocal_offsets.items, {}, TlvOffset.cmp);
1976
1977 const seek_amt = 2 * @sizeOf(u64);
1978 for (self.threadlocal_offsets.items) |tlv| {
1979 try writer.context.seekBy(seek_amt);
1980 try writer.writeIntLittle(u64, tlv.offset);
1981 }
1982
1983 try self.file.?.pwriteAll(buffer, sect.offset);
1984 }
1985
1986 if (self.mod_init_func_section_index) |index| {
1987 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
1988 const sect = &seg.sections.items[index];
1989
1990 var initializers = std.ArrayList(u64).init(self.allocator);
1991 defer initializers.deinit();
1992
1993 for (self.objects.items) |object| {
1994 for (object.initializers.items) |sym_id| {
1995 const address = object.symbols.items[sym_id].payload.regular.address;
1996 try initializers.append(address);
1997 }
1998 }
1999
2000 _ = try self.file.?.pwriteAll(mem.sliceAsBytes(initializers.items), sect.offset);
2001 sect.size = @intCast(u32, initializers.items.len * @sizeOf(u64));
2002 }
2003
2004 try self.writeGotEntries();
2005 try self.setEntryPoint();
2006 try self.writeRebaseInfoTable();
2007 try self.writeBindInfoTable();
2008 try self.writeLazyBindInfoTable();
2009 try self.writeExportInfo();
2010 try self.writeDataInCode();
2011
2012 {
2013 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
2014 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
2015 symtab.symoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);
2016 }
2017
2018 try self.writeSymbolTable();
2019 try self.writeStringTable();
2020
2021 {
2022 // Seal __LINKEDIT size
2023 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
2024 seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);
2025 }
2026
2027 if (self.target.?.cpu.arch == .aarch64) {
2028 try self.writeCodeSignaturePadding();
2029 }
2030
2031 try self.writeLoadCommands();
2032 try self.writeHeader();
2033
2034 if (self.target.?.cpu.arch == .aarch64) {
2035 try self.writeCodeSignature();
2036 }
2037
2038 if (comptime std.Target.current.isDarwin() and std.Target.current.cpu.arch == .aarch64) {
2039 const out_path = self.output.?.path;
2040 try fs.cwd().copyFile(out_path, fs.cwd(), out_path, .{});
2041 }
2003 try self.writeTextBlocks();
2004 // try self.writeStubHelperCommon();
2005
2006 // if (self.common_section_index) |index| {
2007 // const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2008 // const sect = &seg.sections.items[index];
2009 // sect.offset = 0;
2010 // }
2011
2012 // if (self.bss_section_index) |index| {
2013 // const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2014 // const sect = &seg.sections.items[index];
2015 // sect.offset = 0;
2016 // }
2017
2018 // if (self.tlv_bss_section_index) |index| {
2019 // const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2020 // const sect = &seg.sections.items[index];
2021 // sect.offset = 0;
2022 // }
2023
2024 // if (self.tlv_section_index) |index| {
2025 // const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2026 // const sect = &seg.sections.items[index];
2027
2028 // var buffer = try self.allocator.alloc(u8, @intCast(usize, sect.size));
2029 // defer self.allocator.free(buffer);
2030 // _ = try self.file.?.preadAll(buffer, sect.offset);
2031
2032 // var stream = std.io.fixedBufferStream(buffer);
2033 // var writer = stream.writer();
2034
2035 // std.sort.sort(TlvOffset, self.threadlocal_offsets.items, {}, TlvOffset.cmp);
2036
2037 // const seek_amt = 2 * @sizeOf(u64);
2038 // for (self.threadlocal_offsets.items) |tlv| {
2039 // try writer.context.seekBy(seek_amt);
2040 // try writer.writeIntLittle(u64, tlv.offset);
2041 // }
2042
2043 // try self.file.?.pwriteAll(buffer, sect.offset);
2044 // }
2045
2046 // if (self.mod_init_func_section_index) |index| {
2047 // const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
2048 // const sect = &seg.sections.items[index];
2049
2050 // var initializers = std.ArrayList(u64).init(self.allocator);
2051 // defer initializers.deinit();
2052
2053 // for (self.objects.items) |object| {
2054 // for (object.initializers.items) |sym_id| {
2055 // const address = object.symbols.items[sym_id].payload.regular.address;
2056 // try initializers.append(address);
2057 // }
2058 // }
2059
2060 // _ = try self.file.?.pwriteAll(mem.sliceAsBytes(initializers.items), sect.offset);
2061 // sect.size = @intCast(u32, initializers.items.len * @sizeOf(u64));
2062 // }
2063
2064 // try self.writeGotEntries();
2065 // try self.setEntryPoint();
2066 // try self.writeRebaseInfoTable();
2067 // try self.writeBindInfoTable();
2068 // try self.writeLazyBindInfoTable();
2069 // try self.writeExportInfo();
2070 // try self.writeDataInCode();
2071
2072 // {
2073 // const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
2074 // const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
2075 // symtab.symoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);
2076 // }
2077
2078 // try self.writeSymbolTable();
2079 // try self.writeStringTable();
2080
2081 // {
2082 // // Seal __LINKEDIT size
2083 // const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
2084 // seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);
2085 // }
2086
2087 // if (self.target.?.cpu.arch == .aarch64) {
2088 // try self.writeCodeSignaturePadding();
2089 // }
2090
2091 // try self.writeLoadCommands();
2092 // try self.writeHeader();
2093
2094 // if (self.target.?.cpu.arch == .aarch64) {
2095 // try self.writeCodeSignature();
2096 // }
2097
2098 // if (comptime std.Target.current.isDarwin() and std.Target.current.cpu.arch == .aarch64) {
2099 // const out_path = self.output.?.path;
2100 // try fs.cwd().copyFile(out_path, fs.cwd(), out_path, .{});
2101 // }
20422102}
20432103
20442104fn writeGotEntries(self: *Zld) !void {
src/link/MachO/reloc.zig+22-17
......@@ -52,7 +52,7 @@ pub const Relocation = struct {
5252
5353 pub fn resolve(self: Unsigned, base: Relocation, source_addr: u64, target_addr: u64) !void {
5454 const addend = if (self.source_sect_addr) |addr|
55 self.addend - addr
55 self.addend - @intCast(i64, addr)
5656 else
5757 self.addend;
5858
......@@ -86,13 +86,13 @@ pub const Relocation = struct {
8686 arch: Arch,
8787
8888 pub fn resolve(self: Branch, base: Relocation, source_addr: u64, target_addr: u64) !void {
89 switch (arch) {
89 switch (self.arch) {
9090 .aarch64 => {
9191 const displacement = try math.cast(i28, @intCast(i64, target_addr) - @intCast(i64, source_addr));
9292 var inst = aarch64.Instruction{
9393 .unconditional_branch_immediate = mem.bytesToValue(
9494 meta.TagPayload(
95 aarch.Instruction,
95 aarch64.Instruction,
9696 aarch64.Instruction.unconditional_branch_immediate,
9797 ),
9898 base.block.code[base.offset..][0..4],
......@@ -236,13 +236,15 @@ pub const Relocation = struct {
236236 },
237237 .got => {
238238 const narrowed = @truncate(u12, target_addr);
239 var inst = mem.bytesToValue(
240 meta.TagPayload(
241 aarch64.Instruction,
242 aarch64.Instruction.load_store_register,
239 var inst: aarch64.Instruction = .{
240 .load_store_register = mem.bytesToValue(
241 meta.TagPayload(
242 aarch64.Instruction,
243 aarch64.Instruction.load_store_register,
244 ),
245 base.block.code[base.offset..][0..4],
243246 ),
244 base.block.code[base.offset..][0..4],
245 );
247 };
246248 const offset = try math.divExact(u12, narrowed, 8);
247249 inst.load_store_register.offset = offset;
248250 mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], inst.toU32());
......@@ -408,14 +410,12 @@ pub const Relocation = struct {
408410 break :blk sym.payload.regular.address + self.offset;
409411 };
410412 const target_addr = blk: {
411 const is_via_got = inner: {
412 switch (self.payload) {
413 .pointer_to_got => break :inner true,
414 .page => |page| page.kind == .got,
415 .page_off => |page_off| page_off == .got,
416 .load => {},
417 else => break :inner false,
418 }
413 const is_via_got = switch (self.payload) {
414 .pointer_to_got => true,
415 .page => |page| page.kind == .got,
416 .page_off => |page_off| page_off.kind == .got,
417 .load => |load| load.kind == .got,
418 else => false,
419419 };
420420
421421 if (is_via_got) {
......@@ -459,6 +459,11 @@ pub const Relocation = struct {
459459 },
460460 }
461461 };
462
463 log.warn("relocating {}", .{self});
464 log.warn(" | source_addr = 0x{x}", .{source_addr});
465 log.warn(" | target_addr = 0x{x}", .{target_addr});
466
462467 switch (self.payload) {
463468 .unsigned => |unsigned| try unsigned.resolve(self, source_addr, target_addr),
464469 .branch => |branch| try branch.resolve(self, source_addr, target_addr),