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 {...@@ -535,8 +535,11 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
535 // How does it tie with incremental space allocs?535 // How does it tie with incremental space allocs?
536 const tseg = &zld.load_commands.items[match.seg].Segment;536 const tseg = &zld.load_commands.items[match.seg].Segment;
537 const tsect = &tseg.sections.items[match.sect];537 const tsect = &tseg.sections.items[match.sect];
538 tsect.size += block.size;538 const new_alignment = math.max(tsect.@"align", block.alignment);
539 tsect.@"align" = 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
541 if (zld.blocks.getPtr(match)) |last| {544 if (zld.blocks.getPtr(match)) |last| {
542 last.*.next = block;545 last.*.next = block;
...@@ -621,8 +624,11 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {...@@ -621,8 +624,11 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
621 // How does it tie with incremental space allocs?624 // How does it tie with incremental space allocs?
622 const tseg = &zld.load_commands.items[match.seg].Segment;625 const tseg = &zld.load_commands.items[match.seg].Segment;
623 const tsect = &tseg.sections.items[match.sect];626 const tsect = &tseg.sections.items[match.sect];
624 tsect.size += block.size;627 const new_alignment = math.max(tsect.@"align", block.alignment);
625 tsect.@"align" = 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
627 if (zld.blocks.getPtr(match)) |last| {633 if (zld.blocks.getPtr(match)) |last| {
628 last.*.next = block;634 last.*.next = block;
src/link/MachO/Zld.zig+162-102
...@@ -173,6 +173,12 @@ pub const TextBlock = struct {...@@ -173,6 +173,12 @@ pub const TextBlock = struct {
173 self.tlv_offsets.deinit();173 self.tlv_offsets.deinit();
174 }174 }
175175
176 pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void {
177 for (self.relocs.items) |rel| {
178 try rel.resolve(zld);
179 }
180 }
181
176 pub fn print_this(self: *const TextBlock, zld: *Zld) void {182 pub fn print_this(self: *const TextBlock, zld: *Zld) void {
177 log.warn("TextBlock", .{});183 log.warn("TextBlock", .{});
178 log.warn(" | {}: {}", .{ self.local_sym_index, zld.locals.items[self.local_sym_index] });184 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...@@ -328,11 +334,10 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
328 const sect = seg.sections.items[entry.key_ptr.sect];334 const sect = seg.sections.items[entry.key_ptr.sect];
329335
330 log.warn("\n\n{s},{s} contents:", .{ segmentName(sect), sectionName(sect) });336 log.warn("\n\n{s},{s} contents:", .{ segmentName(sect), sectionName(sect) });
331 log.warn("{}", .{sect});337 log.warn(" {}", .{sect});
332 entry.value_ptr.*.print(self);338 entry.value_ptr.*.print(self);
333 }339 }
334 return error.TODO;340 try self.flush();
335 // try self.flush();
336}341}
337342
338fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u8) !void {343fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u8) !void {
...@@ -1041,6 +1046,8 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void {...@@ -1041,6 +1046,8 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void {
1041}1046}
10421047
1043fn allocateTextBlocks(self: *Zld) !void {1048fn allocateTextBlocks(self: *Zld) !void {
1049 log.warn("allocating text blocks", .{});
1050
1044 var it = self.blocks.iterator();1051 var it = self.blocks.iterator();
1045 while (it.next()) |entry| {1052 while (it.next()) |entry| {
1046 const match = entry.key_ptr.*;1053 const match = entry.key_ptr.*;
...@@ -1050,13 +1057,34 @@ fn allocateTextBlocks(self: *Zld) !void {...@@ -1050,13 +1057,34 @@ fn allocateTextBlocks(self: *Zld) !void {
1050 const sect = seg.sections.items[match.sect];1057 const sect = seg.sections.items[match.sect];
1051 var base_addr: u64 = sect.addr + sect.size;1058 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
1053 while (true) {1063 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
1056 const sym = self.locals.items[block.local_sym_index];1067 const sym = self.locals.items[block.local_sym_index];
1057 assert(sym.payload == .regular);1068 assert(sym.payload == .regular);
1058 sym.payload.regular.address = base_addr;1069 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
1060 // Update each symbol contained within the TextBlock1088 // Update each symbol contained within the TextBlock
1061 if (block.contained) |contained| {1089 if (block.contained) |contained| {
1062 for (contained) |sym_at_off| {1090 for (contained) |sym_at_off| {
...@@ -1073,6 +1101,37 @@ fn allocateTextBlocks(self: *Zld) !void {...@@ -1073,6 +1101,37 @@ fn allocateTextBlocks(self: *Zld) !void {
1073 }1101 }
1074}1102}
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
1076fn writeStubHelperCommon(self: *Zld) !void {1135fn writeStubHelperCommon(self: *Zld) !void {
1077 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;1136 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1078 const stub_helper = &text_segment.sections.items[self.stub_helper_section_index.?];1137 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 {...@@ -1941,104 +2000,105 @@ fn addRpaths(self: *Zld, rpaths: []const []const u8) !void {
1941}2000}
19422001
1943fn flush(self: *Zld) !void {2002fn flush(self: *Zld) !void {
1944 try self.writeStubHelperCommon();2003 try self.writeTextBlocks();
19452004 // try self.writeStubHelperCommon();
1946 if (self.common_section_index) |index| {2005
1947 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;2006 // if (self.common_section_index) |index| {
1948 const sect = &seg.sections.items[index];2007 // const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1949 sect.offset = 0;2008 // const sect = &seg.sections.items[index];
1950 }2009 // sect.offset = 0;
19512010 // }
1952 if (self.bss_section_index) |index| {2011
1953 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;2012 // if (self.bss_section_index) |index| {
1954 const sect = &seg.sections.items[index];2013 // const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1955 sect.offset = 0;2014 // const sect = &seg.sections.items[index];
1956 }2015 // sect.offset = 0;
19572016 // }
1958 if (self.tlv_bss_section_index) |index| {2017
1959 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;2018 // if (self.tlv_bss_section_index) |index| {
1960 const sect = &seg.sections.items[index];2019 // const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1961 sect.offset = 0;2020 // const sect = &seg.sections.items[index];
1962 }2021 // sect.offset = 0;
19632022 // }
1964 if (self.tlv_section_index) |index| {2023
1965 const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;2024 // if (self.tlv_section_index) |index| {
1966 const sect = &seg.sections.items[index];2025 // const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
19672026 // const sect = &seg.sections.items[index];
1968 var buffer = try self.allocator.alloc(u8, @intCast(usize, sect.size));2027
1969 defer self.allocator.free(buffer);2028 // var buffer = try self.allocator.alloc(u8, @intCast(usize, sect.size));
1970 _ = try self.file.?.preadAll(buffer, sect.offset);2029 // defer self.allocator.free(buffer);
19712030 // _ = try self.file.?.preadAll(buffer, sect.offset);
1972 var stream = std.io.fixedBufferStream(buffer);2031
1973 var writer = stream.writer();2032 // var stream = std.io.fixedBufferStream(buffer);
19742033 // var writer = stream.writer();
1975 std.sort.sort(TlvOffset, self.threadlocal_offsets.items, {}, TlvOffset.cmp);2034
19762035 // std.sort.sort(TlvOffset, self.threadlocal_offsets.items, {}, TlvOffset.cmp);
1977 const seek_amt = 2 * @sizeOf(u64);2036
1978 for (self.threadlocal_offsets.items) |tlv| {2037 // const seek_amt = 2 * @sizeOf(u64);
1979 try writer.context.seekBy(seek_amt);2038 // for (self.threadlocal_offsets.items) |tlv| {
1980 try writer.writeIntLittle(u64, tlv.offset);2039 // try writer.context.seekBy(seek_amt);
1981 }2040 // try writer.writeIntLittle(u64, tlv.offset);
19822041 // }
1983 try self.file.?.pwriteAll(buffer, sect.offset);2042
1984 }2043 // try self.file.?.pwriteAll(buffer, sect.offset);
19852044 // }
1986 if (self.mod_init_func_section_index) |index| {2045
1987 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;2046 // if (self.mod_init_func_section_index) |index| {
1988 const sect = &seg.sections.items[index];2047 // const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
19892048 // const sect = &seg.sections.items[index];
1990 var initializers = std.ArrayList(u64).init(self.allocator);2049
1991 defer initializers.deinit();2050 // var initializers = std.ArrayList(u64).init(self.allocator);
19922051 // defer initializers.deinit();
1993 for (self.objects.items) |object| {2052
1994 for (object.initializers.items) |sym_id| {2053 // for (self.objects.items) |object| {
1995 const address = object.symbols.items[sym_id].payload.regular.address;2054 // for (object.initializers.items) |sym_id| {
1996 try initializers.append(address);2055 // const address = object.symbols.items[sym_id].payload.regular.address;
1997 }2056 // try initializers.append(address);
1998 }2057 // }
19992058 // }
2000 _ = try self.file.?.pwriteAll(mem.sliceAsBytes(initializers.items), sect.offset);2059
2001 sect.size = @intCast(u32, initializers.items.len * @sizeOf(u64));2060 // _ = try self.file.?.pwriteAll(mem.sliceAsBytes(initializers.items), sect.offset);
2002 }2061 // sect.size = @intCast(u32, initializers.items.len * @sizeOf(u64));
20032062 // }
2004 try self.writeGotEntries();2063
2005 try self.setEntryPoint();2064 // try self.writeGotEntries();
2006 try self.writeRebaseInfoTable();2065 // try self.setEntryPoint();
2007 try self.writeBindInfoTable();2066 // try self.writeRebaseInfoTable();
2008 try self.writeLazyBindInfoTable();2067 // try self.writeBindInfoTable();
2009 try self.writeExportInfo();2068 // try self.writeLazyBindInfoTable();
2010 try self.writeDataInCode();2069 // try self.writeExportInfo();
20112070 // try self.writeDataInCode();
2012 {2071
2013 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;2072 // {
2014 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;2073 // const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
2015 symtab.symoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);2074 // const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
2016 }2075 // symtab.symoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);
20172076 // }
2018 try self.writeSymbolTable();2077
2019 try self.writeStringTable();2078 // try self.writeSymbolTable();
20202079 // try self.writeStringTable();
2021 {2080
2022 // Seal __LINKEDIT size2081 // {
2023 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;2082 // // Seal __LINKEDIT size
2024 seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);2083 // const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
2025 }2084 // seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);
20262085 // }
2027 if (self.target.?.cpu.arch == .aarch64) {2086
2028 try self.writeCodeSignaturePadding();2087 // if (self.target.?.cpu.arch == .aarch64) {
2029 }2088 // try self.writeCodeSignaturePadding();
20302089 // }
2031 try self.writeLoadCommands();2090
2032 try self.writeHeader();2091 // try self.writeLoadCommands();
20332092 // try self.writeHeader();
2034 if (self.target.?.cpu.arch == .aarch64) {2093
2035 try self.writeCodeSignature();2094 // if (self.target.?.cpu.arch == .aarch64) {
2036 }2095 // try self.writeCodeSignature();
20372096 // }
2038 if (comptime std.Target.current.isDarwin() and std.Target.current.cpu.arch == .aarch64) {2097
2039 const out_path = self.output.?.path;2098 // if (comptime std.Target.current.isDarwin() and std.Target.current.cpu.arch == .aarch64) {
2040 try fs.cwd().copyFile(out_path, fs.cwd(), out_path, .{});2099 // const out_path = self.output.?.path;
2041 }2100 // try fs.cwd().copyFile(out_path, fs.cwd(), out_path, .{});
2101 // }
2042}2102}
20432103
2044fn writeGotEntries(self: *Zld) !void {2104fn writeGotEntries(self: *Zld) !void {
src/link/MachO/reloc.zig+22-17
...@@ -52,7 +52,7 @@ pub const Relocation = struct {...@@ -52,7 +52,7 @@ pub const Relocation = struct {
5252
53 pub fn resolve(self: Unsigned, base: Relocation, source_addr: u64, target_addr: u64) !void {53 pub fn resolve(self: Unsigned, base: Relocation, source_addr: u64, target_addr: u64) !void {
54 const addend = if (self.source_sect_addr) |addr|54 const addend = if (self.source_sect_addr) |addr|
55 self.addend - addr55 self.addend - @intCast(i64, addr)
56 else56 else
57 self.addend;57 self.addend;
5858
...@@ -86,13 +86,13 @@ pub const Relocation = struct {...@@ -86,13 +86,13 @@ pub const Relocation = struct {
86 arch: Arch,86 arch: Arch,
8787
88 pub fn resolve(self: Branch, base: Relocation, source_addr: u64, target_addr: u64) !void {88 pub fn resolve(self: Branch, base: Relocation, source_addr: u64, target_addr: u64) !void {
89 switch (arch) {89 switch (self.arch) {
90 .aarch64 => {90 .aarch64 => {
91 const displacement = try math.cast(i28, @intCast(i64, target_addr) - @intCast(i64, source_addr));91 const displacement = try math.cast(i28, @intCast(i64, target_addr) - @intCast(i64, source_addr));
92 var inst = aarch64.Instruction{92 var inst = aarch64.Instruction{
93 .unconditional_branch_immediate = mem.bytesToValue(93 .unconditional_branch_immediate = mem.bytesToValue(
94 meta.TagPayload(94 meta.TagPayload(
95 aarch.Instruction,95 aarch64.Instruction,
96 aarch64.Instruction.unconditional_branch_immediate,96 aarch64.Instruction.unconditional_branch_immediate,
97 ),97 ),
98 base.block.code[base.offset..][0..4],98 base.block.code[base.offset..][0..4],
...@@ -236,13 +236,15 @@ pub const Relocation = struct {...@@ -236,13 +236,15 @@ pub const Relocation = struct {
236 },236 },
237 .got => {237 .got => {
238 const narrowed = @truncate(u12, target_addr);238 const narrowed = @truncate(u12, target_addr);
239 var inst = mem.bytesToValue(239 var inst: aarch64.Instruction = .{
240 meta.TagPayload(240 .load_store_register = mem.bytesToValue(
241 aarch64.Instruction,241 meta.TagPayload(
242 aarch64.Instruction.load_store_register,242 aarch64.Instruction,
243 aarch64.Instruction.load_store_register,
244 ),
245 base.block.code[base.offset..][0..4],
243 ),246 ),
244 base.block.code[base.offset..][0..4],247 };
245 );
246 const offset = try math.divExact(u12, narrowed, 8);248 const offset = try math.divExact(u12, narrowed, 8);
247 inst.load_store_register.offset = offset;249 inst.load_store_register.offset = offset;
248 mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], inst.toU32());250 mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], inst.toU32());
...@@ -408,14 +410,12 @@ pub const Relocation = struct {...@@ -408,14 +410,12 @@ pub const Relocation = struct {
408 break :blk sym.payload.regular.address + self.offset;410 break :blk sym.payload.regular.address + self.offset;
409 };411 };
410 const target_addr = blk: {412 const target_addr = blk: {
411 const is_via_got = inner: {413 const is_via_got = switch (self.payload) {
412 switch (self.payload) {414 .pointer_to_got => true,
413 .pointer_to_got => break :inner true,415 .page => |page| page.kind == .got,
414 .page => |page| page.kind == .got,416 .page_off => |page_off| page_off.kind == .got,
415 .page_off => |page_off| page_off == .got,417 .load => |load| load.kind == .got,
416 .load => {},418 else => false,
417 else => break :inner false,
418 }
419 };419 };
420420
421 if (is_via_got) {421 if (is_via_got) {
...@@ -459,6 +459,11 @@ pub const Relocation = struct {...@@ -459,6 +459,11 @@ pub const Relocation = struct {
459 },459 },
460 }460 }
461 };461 };
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
462 switch (self.payload) {467 switch (self.payload) {
463 .unsigned => |unsigned| try unsigned.resolve(self, source_addr, target_addr),468 .unsigned => |unsigned| try unsigned.resolve(self, source_addr, target_addr),
464 .branch => |branch| try branch.resolve(self, source_addr, target_addr),469 .branch => |branch| try branch.resolve(self, source_addr, target_addr),