authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-07 13:47:04+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:47+02:00
loga04bc1ed14319bf22769b01709bb7174388734f0
tree1d49c86fc82a250ece34fc0b46244ddcb042ba08
parentdfa69e3c308fe7a5cb8b78c494312e1d280afa18

zld: update relocs and start prepping for segment allocs


3 files changed, 144 insertions(+), 309 deletions(-)

src/link/MachO/Object.zig+8-19
......@@ -48,8 +48,6 @@ dwarf_debug_ranges_index: ?u16 = null,
4848
4949symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
5050strtab: std.ArrayListUnmanaged(u8) = .{},
51
52initializers: std.ArrayListUnmanaged(u32) = .{},
5351data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},
5452
5553symbols: std.ArrayListUnmanaged(*Symbol) = .{},
......@@ -157,7 +155,6 @@ pub fn deinit(self: *Object) void {
157155 }
158156 self.load_commands.deinit(self.allocator);
159157 self.data_in_code_entries.deinit(self.allocator);
160 self.initializers.deinit(self.allocator);
161158 self.symtab.deinit(self.allocator);
162159 self.strtab.deinit(self.allocator);
163160 self.symbols.deinit(self.allocator);
......@@ -573,6 +570,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
573570 symbol.payload = .{
574571 .regular = .{
575572 .linkage = .translation_unit,
573 .address = sect.addr,
576574 .segment_id = match.seg,
577575 .section_id = match.sect,
578576 .file = self,
......@@ -657,6 +655,13 @@ pub fn symbolFromReloc(self: *Object, rel: macho.relocation_info) !*Symbol {
657655 });
658656 defer self.allocator.free(name);
659657 const symbol = try Symbol.new(self.allocator, name);
658 symbol.payload = .{
659 .regular = .{
660 .linkage = .translation_unit,
661 .address = sect.addr,
662 .file = self,
663 },
664 };
660665 try self.sections_as_symbols.putNoClobber(self.allocator, sect_id, symbol);
661666 break :symbol symbol;
662667 };
......@@ -666,22 +671,6 @@ pub fn symbolFromReloc(self: *Object, rel: macho.relocation_info) !*Symbol {
666671 return symbol;
667672}
668673
669pub fn parseInitializers(self: *Object) !void {
670 const index = self.mod_init_func_section_index orelse return;
671 const section = self.sections.items[index];
672
673 log.debug("parsing initializers in {s}", .{self.name.?});
674
675 // Parse C++ initializers
676 const relocs = section.relocs orelse unreachable;
677 try self.initializers.ensureCapacity(self.allocator, relocs.len);
678 for (relocs) |rel| {
679 self.initializers.appendAssumeCapacity(rel.target.symbol);
680 }
681
682 mem.reverse(u32, self.initializers.items);
683}
684
685674fn parseSymtab(self: *Object) !void {
686675 const index = self.symtab_cmd_index orelse return;
687676 const symtab_cmd = self.load_commands.items[index].Symtab;
src/link/MachO/Zld.zig+6-219
......@@ -120,16 +120,6 @@ pub const Output = struct {
120120 install_name: ?[]const u8 = null,
121121};
122122
123const TlvOffset = struct {
124 source_addr: u64,
125 offset: u64,
126
127 fn cmp(context: void, a: TlvOffset, b: TlvOffset) bool {
128 _ = context;
129 return a.source_addr < b.source_addr;
130 }
131};
132
133123pub const TextBlock = struct {
134124 local_sym_index: u32,
135125 aliases: ?[]u32 = null,
......@@ -274,12 +264,11 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
274264 try self.parseLibs(args.libs, args.syslibroot);
275265 try self.resolveSymbols();
276266 try self.parseTextBlocks();
267 try self.sortSections();
268 try self.addRpaths(args.rpaths);
269 try self.addDataInCodeLC();
270 try self.addCodeSignatureLC();
277271 return error.TODO;
278 // try self.updateMetadata();
279 // try self.sortSections();
280 // try self.addRpaths(args.rpaths);
281 // try self.addDataInCodeLC();
282 // try self.addCodeSignatureLC();
283272 // try self.allocateTextSegment();
284273 // try self.allocateDataConstSegment();
285274 // try self.allocateDataSegment();
......@@ -343,106 +332,6 @@ fn parseLibs(self: *Zld, libs: []const []const u8, syslibroot: ?[]const u8) !voi
343332 }
344333}
345334
346fn mapAndUpdateSections(
347 self: *Zld,
348 object: *Object,
349 source_sect_id: u16,
350 target_seg_id: u16,
351 target_sect_id: u16,
352) !void {
353 const source_sect = &object.sections.items[source_sect_id];
354 const target_seg = &self.load_commands.items[target_seg_id].Segment;
355 const target_sect = &target_seg.sections.items[target_sect_id];
356
357 const alignment = try math.powi(u32, 2, target_sect.@"align");
358 const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment);
359 const size = mem.alignForwardGeneric(u64, source_sect.inner.size, alignment);
360
361 log.debug("{s}: '{s},{s}' mapped to '{s},{s}' from 0x{x} to 0x{x}", .{
362 object.name.?,
363 segmentName(source_sect.inner),
364 sectionName(source_sect.inner),
365 segmentName(target_sect.*),
366 sectionName(target_sect.*),
367 offset,
368 offset + size,
369 });
370 log.debug(" | flags 0x{x}", .{source_sect.inner.flags});
371
372 source_sect.target_map = .{
373 .segment_id = target_seg_id,
374 .section_id = target_sect_id,
375 .offset = @intCast(u32, offset),
376 };
377 target_sect.size = offset + size;
378}
379
380fn updateMetadata(self: *Zld) !void {
381 for (self.objects.items) |object| {
382 // Find ideal section alignment and update section mappings
383 for (object.sections.items) |sect, sect_id| {
384 const match = (try self.getMatchingSection(sect.inner)) orelse {
385 log.debug("{s}: unhandled section type 0x{x} for '{s},{s}'", .{
386 object.name.?,
387 sect.inner.flags,
388 segmentName(sect.inner),
389 sectionName(sect.inner),
390 });
391 continue;
392 };
393 const target_seg = &self.load_commands.items[match.seg].Segment;
394 const target_sect = &target_seg.sections.items[match.sect];
395 target_sect.@"align" = math.max(target_sect.@"align", sect.inner.@"align");
396
397 try self.mapAndUpdateSections(object, @intCast(u16, sect_id), match.seg, match.sect);
398 }
399 }
400
401 tlv_align: {
402 const has_tlv =
403 self.tlv_section_index != null or
404 self.tlv_data_section_index != null or
405 self.tlv_bss_section_index != null;
406
407 if (!has_tlv) break :tlv_align;
408
409 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
410
411 if (self.tlv_section_index) |index| {
412 const sect = &seg.sections.items[index];
413 sect.@"align" = 3; // __thread_vars is always 8byte aligned
414 }
415
416 // Apparently __tlv_data and __tlv_bss need to have matching alignment, so fix it up.
417 // <rdar://problem/24221680> All __thread_data and __thread_bss sections must have same alignment
418 // https://github.com/apple-opensource/ld64/blob/e28c028b20af187a16a7161d89e91868a450cadc/src/ld/ld.cpp#L1172
419 const data_align: u32 = data: {
420 if (self.tlv_data_section_index) |index| {
421 const sect = &seg.sections.items[index];
422 break :data sect.@"align";
423 }
424 break :tlv_align;
425 };
426 const bss_align: u32 = bss: {
427 if (self.tlv_bss_section_index) |index| {
428 const sect = &seg.sections.items[index];
429 break :bss sect.@"align";
430 }
431 break :tlv_align;
432 };
433 const max_align = math.max(data_align, bss_align);
434
435 if (self.tlv_data_section_index) |index| {
436 const sect = &seg.sections.items[index];
437 sect.@"align" = max_align;
438 }
439 if (self.tlv_bss_section_index) |index| {
440 const sect = &seg.sections.items[index];
441 sect.@"align" = max_align;
442 }
443 }
444}
445
446335pub const MatchingSection = struct {
447336 seg: u16,
448337 sect: u16,
......@@ -946,36 +835,6 @@ fn sortSections(self: *Zld) !void {
946835 maybe_index.* = new_index;
947836 }
948837 }
949
950 for (self.objects.items) |object| {
951 for (object.sections.items) |*sect| {
952 const target_map = sect.target_map orelse continue;
953
954 const new_index = blk: {
955 if (self.text_segment_cmd_index.? == target_map.segment_id) {
956 break :blk text_index_mapping.get(target_map.section_id) orelse unreachable;
957 } else if (self.data_const_segment_cmd_index.? == target_map.segment_id) {
958 break :blk data_const_index_mapping.get(target_map.section_id) orelse unreachable;
959 } else if (self.data_segment_cmd_index.? == target_map.segment_id) {
960 break :blk data_index_mapping.get(target_map.section_id) orelse unreachable;
961 } else unreachable;
962 };
963
964 log.debug("remapping in {s}: '{s},{s}': {} => {}", .{
965 object.name.?,
966 segmentName(sect.inner),
967 sectionName(sect.inner),
968 target_map.section_id,
969 new_index,
970 });
971
972 sect.target_map = .{
973 .segment_id = target_map.segment_id,
974 .section_id = new_index,
975 .offset = target_map.offset,
976 };
977 }
978 }
979838}
980839
981840fn allocateTextSegment(self: *Zld) !void {
......@@ -1431,6 +1290,7 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {
14311290 symbol.payload = .{
14321291 .regular = .{
14331292 .linkage = .translation_unit,
1293 .address = sym.n_value,
14341294 .weak_ref = Symbol.isWeakRef(sym),
14351295 .file = object,
14361296 .local_sym_index = @intCast(u32, self.locals.items.len),
......@@ -1470,6 +1330,7 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {
14701330 symbol.payload = .{
14711331 .regular = .{
14721332 .linkage = linkage,
1333 .address = sym.n_value,
14731334 .weak_ref = Symbol.isWeakRef(sym),
14741335 .file = object,
14751336 },
......@@ -1672,80 +1533,6 @@ fn parseTextBlocks(self: *Zld) !void {
16721533 }
16731534}
16741535
1675fn resolveRelocsAndWriteSections(self: *Zld) !void {
1676 for (self.objects.items) |object| {
1677 log.debug("relocating object {s}", .{object.name});
1678
1679 for (object.sections.items) |sect| {
1680 if (sectionType(sect.inner) == macho.S_MOD_INIT_FUNC_POINTERS or
1681 sectionType(sect.inner) == macho.S_MOD_TERM_FUNC_POINTERS) continue;
1682
1683 const segname = segmentName(sect.inner);
1684 const sectname = sectionName(sect.inner);
1685
1686 log.debug("relocating section '{s},{s}'", .{ segname, sectname });
1687
1688 // Get target mapping
1689 const target_map = sect.target_map orelse {
1690 log.debug("no mapping for '{s},{s}'; skipping", .{ segname, sectname });
1691 continue;
1692 };
1693 const target_seg = self.load_commands.items[target_map.segment_id].Segment;
1694 const target_sect = target_seg.sections.items[target_map.section_id];
1695 const target_sect_addr = target_sect.addr + target_map.offset;
1696 const target_sect_off = target_sect.offset + target_map.offset;
1697
1698 if (sect.relocs) |relocs| {
1699 for (relocs) |rel| {
1700 const source_addr = target_sect_addr + rel.offset;
1701
1702 var args: reloc.Relocation.ResolveArgs = .{
1703 .source_addr = source_addr,
1704 .target_addr = undefined,
1705 };
1706
1707 switch (rel.@"type") {
1708 .unsigned => {
1709 args.target_addr = try self.relocTargetAddr(object, rel.target);
1710
1711 const unsigned = rel.cast(reloc.Unsigned) orelse unreachable;
1712 if (unsigned.subtractor) |subtractor| {
1713 args.subtractor = try self.relocTargetAddr(object, subtractor);
1714 }
1715 if (rel.target == .section) {
1716 const source_sect = object.sections.items[rel.target.section];
1717 args.source_source_sect_addr = sect.inner.addr;
1718 args.source_target_sect_addr = source_sect.inner.addr;
1719 }
1720 },
1721 .got_page, .got_page_off, .got_load, .got, .pointer_to_got => {
1722 const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
1723 const got = dc_seg.sections.items[self.got_section_index.?];
1724 const sym = object.symbols.items[rel.target.symbol];
1725 const got_index = sym.got_index orelse {
1726 log.err("expected GOT index relocating symbol '{s}'", .{sym.name});
1727 log.err("this is an internal linker error", .{});
1728 return error.FailedToResolveRelocationTarget;
1729 };
1730 args.target_addr = got.addr + got_index * @sizeOf(u64);
1731 },
1732 else => |tt| {
1733 if (tt == .signed and rel.target == .section) {
1734 const source_sect = object.sections.items[rel.target.section];
1735 args.source_source_sect_addr = sect.inner.addr;
1736 args.source_target_sect_addr = source_sect.inner.addr;
1737 }
1738 args.target_addr = try self.relocTargetAddr(object, rel.target);
1739 },
1740 }
1741
1742 try rel.resolve(args);
1743 }
1744 }
1745 }
1746 }
1747}
1748
17491536fn populateMetadata(self: *Zld) !void {
17501537 if (self.pagezero_segment_cmd_index == null) {
17511538 self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
src/link/MachO/reloc.zig+130-71
......@@ -48,33 +48,24 @@ pub const Relocation = struct {
4848 /// => * is unreachable
4949 is_64bit: bool,
5050
51 source_sect_addr: ?u64 = null,
52
5153 pub fn resolve(self: Unsigned, base: Relocation, source_addr: u64, target_addr: u64) !void {
52 // const addend = if (unsigned.base.target == .section)
53 // unsigned.addend - @intCast(i64, args.source_target_sect_addr.?)
54 // else
55 // unsigned.addend;
56
57 // const result = if (args.subtractor) |subtractor|
58 // @intCast(i64, args.target_addr) - @intCast(i64, subtractor) + addend
59 // else
60 // @intCast(i64, args.target_addr) + addend;
61
62 // log.debug(" | calculated addend 0x{x}", .{addend});
63 // log.debug(" | calculated unsigned value 0x{x}", .{result});
64
65 // if (unsigned.is_64bit) {
66 // mem.writeIntLittle(
67 // u64,
68 // unsigned.base.code[0..8],
69 // @bitCast(u64, result),
70 // );
71 // } else {
72 // mem.writeIntLittle(
73 // u32,
74 // unsigned.base.code[0..4],
75 // @truncate(u32, @bitCast(u64, result)),
76 // );
77 // }
54 const addend = if (self.source_sect_addr) |addr|
55 self.addend - addr
56 else
57 self.addend;
58
59 const result = if (self.subtractor) |subtractor|
60 @intCast(i64, target_addr) - @intCast(i64, subtractor.payload.regular.address) + addend
61 else
62 @intCast(i64, target_addr) + addend;
63
64 if (self.is_64bit) {
65 mem.writeIntLittle(u64, base.block.code[base.offset..][0..8], @bitCast(u64, result));
66 } else {
67 mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], @truncate(u32, @bitCast(u64, result)));
68 }
7869 }
7970
8071 pub fn format(self: Unsigned, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
......@@ -191,56 +182,119 @@ pub const Relocation = struct {
191182 pub fn resolve(self: PageOff, base: Relocation, source_addr: u64, target_addr: u64) !void {
192183 switch (self.kind) {
193184 .page => {
194 // const target_addr = if (page_off.addend) |addend| args.target_addr + addend else args.target_addr;
195 // const narrowed = @truncate(u12, target_addr);
196
197 // log.debug(" | narrowed address within the page 0x{x}", .{narrowed});
198 // log.debug(" | {s} opcode", .{page_off.op_kind});
199
200 // var inst = page_off.inst;
201 // if (page_off.op_kind == .arithmetic) {
202 // inst.add_subtract_immediate.imm12 = narrowed;
203 // } else {
204 // const offset: u12 = blk: {
205 // if (inst.load_store_register.size == 0) {
206 // if (inst.load_store_register.v == 1) {
207 // // 128-bit SIMD is scaled by 16.
208 // break :blk try math.divExact(u12, narrowed, 16);
209 // }
210 // // Otherwise, 8-bit SIMD or ldrb.
211 // break :blk narrowed;
212 // } else {
213 // const denom: u4 = try math.powi(u4, 2, inst.load_store_register.size);
214 // break :blk try math.divExact(u12, narrowed, denom);
215 // }
216 // };
217 // inst.load_store_register.offset = offset;
218 // }
219
220 // mem.writeIntLittle(u32, page_off.base.code[0..4], inst.toU32());
185 const actual_target_addr = if (self.addend) |addend| target_addr + addend else target_addr;
186 const narrowed = @truncate(u12, actual_target_addr);
187
188 const op_kind = self.op_kind orelse unreachable;
189 var inst: aarch64.Instruction = blk: {
190 switch (op_kind) {
191 .arithmetic => {
192 break :blk .{
193 .add_subtract_immediate = mem.bytesToValue(
194 meta.TagPayload(
195 aarch64.Instruction,
196 aarch64.Instruction.add_subtract_immediate,
197 ),
198 base.block.code[base.offset..][0..4],
199 ),
200 };
201 },
202 .load => {
203 break :blk .{
204 .load_store_register = mem.bytesToValue(
205 meta.TagPayload(
206 aarch64.Instruction,
207 aarch64.Instruction.load_store_register,
208 ),
209 base.block.code[base.offset..][0..4],
210 ),
211 };
212 },
213 }
214 };
215
216 if (op_kind == .arithmetic) {
217 inst.add_subtract_immediate.imm12 = narrowed;
218 } else {
219 const offset: u12 = blk: {
220 if (inst.load_store_register.size == 0) {
221 if (inst.load_store_register.v == 1) {
222 // 128-bit SIMD is scaled by 16.
223 break :blk try math.divExact(u12, narrowed, 16);
224 }
225 // Otherwise, 8-bit SIMD or ldrb.
226 break :blk narrowed;
227 } else {
228 const denom: u4 = try math.powi(u4, 2, inst.load_store_register.size);
229 break :blk try math.divExact(u12, narrowed, denom);
230 }
231 };
232 inst.load_store_register.offset = offset;
233 }
221234
235 mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], inst.toU32());
222236 },
223237 .got => {
224 // const narrowed = @truncate(u12, args.target_addr);
225
226 // log.debug(" | narrowed address within the page 0x{x}", .{narrowed});
227
228 // var inst = page_off.inst;
229 // const offset = try math.divExact(u12, narrowed, 8);
230 // inst.load_store_register.offset = offset;
231
232 // mem.writeIntLittle(u32, page_off.base.code[0..4], inst.toU32());
238 const narrowed = @truncate(u12, target_addr);
239 var inst = mem.bytesToValue(
240 meta.TagPayload(
241 aarch64.Instruction,
242 aarch64.Instruction.load_store_register,
243 ),
244 base.block.code[base.offset..][0..4],
245 );
246 const offset = try math.divExact(u12, narrowed, 8);
247 inst.load_store_register.offset = offset;
248 mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], inst.toU32());
233249 },
234250 .tlvp => {
235
236 // const narrowed = @truncate(u12, args.target_addr);
237
238 // log.debug(" | narrowed address within the page 0x{x}", .{narrowed});
239
240 // var inst = page_off.inst;
241 // inst.add_subtract_immediate.imm12 = narrowed;
242
243 // mem.writeIntLittle(u32, page_off.base.code[0..4], inst.toU32());
251 const RegInfo = struct {
252 rd: u5,
253 rn: u5,
254 size: u1,
255 };
256 const reg_info: RegInfo = blk: {
257 if (isArithmeticOp(base.block.code[base.offset..][0..4])) {
258 const inst = mem.bytesToValue(
259 meta.TagPayload(
260 aarch64.Instruction,
261 aarch64.Instruction.add_subtract_immediate,
262 ),
263 base.block.code[base.offset..][0..4],
264 );
265 break :blk .{
266 .rd = inst.rd,
267 .rn = inst.rn,
268 .size = inst.sf,
269 };
270 } else {
271 const inst = mem.bytesToValue(
272 meta.TagPayload(
273 aarch64.Instruction,
274 aarch64.Instruction.load_store_register,
275 ),
276 base.block.code[base.offset..][0..4],
277 );
278 break :blk .{
279 .rd = inst.rt,
280 .rn = inst.rn,
281 .size = @truncate(u1, inst.size),
282 };
283 }
284 };
285 const narrowed = @truncate(u12, target_addr);
286 var inst = aarch64.Instruction{
287 .add_subtract_immediate = .{
288 .rd = reg_info.rd,
289 .rn = reg_info.rn,
290 .imm12 = narrowed,
291 .sh = 0,
292 .s = 0,
293 .op = 0,
294 .sf = reg_info.size,
295 },
296 };
297 mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], inst.toU32());
244298 },
245299 }
246300 }
......@@ -661,12 +715,17 @@ pub const Parser = struct {
661715 mem.readIntLittle(i64, self.block.code[parsed.offset..][0..8])
662716 else
663717 mem.readIntLittle(i32, self.block.code[parsed.offset..][0..4]);
718 const source_sect_addr = if (rel.r_extern == 0) blk: {
719 if (parsed.target.payload == .regular) break :blk parsed.target.payload.regular.address;
720 break :blk null;
721 } else null;
664722
665723 parsed.payload = .{
666724 .unsigned = .{
667725 .subtractor = self.subtractor,
668726 .is_64bit = is_64bit,
669727 .addend = addend,
728 .source_sect_addr = source_sect_addr,
670729 },
671730 };
672731