authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-03-03 01:52:21+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-03-17 19:59:13+01:00
loga1b0ec5277c08b82411f830ab0e82487a6a00184
tree5eae262cd55db0709bd2213a807fe725b1da3819
parent066c1386a3dfe0acf4c9d11ba436e7e339d2310b

zld: start bringing x64 up to speed


4 files changed, 334 insertions(+), 152 deletions(-)

lib/std/macho.zig+14
......@@ -1615,3 +1615,17 @@ pub const GenericBlob = extern struct {
16151615 /// Total length of blob
16161616 length: u32,
16171617};
1618
1619/// The LC_DATA_IN_CODE load commands uses a linkedit_data_command
1620/// to point to an array of data_in_code_entry entries. Each entry
1621/// describes a range of data in a code section.
1622pub const data_in_code_entry = extern struct {
1623 /// From mach_header to start of data range.
1624 offset: u32,
1625
1626 /// Number of bytes in data range.
1627 length: u16,
1628
1629 /// A DICE_KIND value.
1630 kind: u16,
1631};
src/link/MachO/Archive.zig+2
......@@ -210,6 +210,8 @@ fn readObject(self: *Archive, arch: std.Target.Cpu.Arch, ar_name: []const u8, re
210210 try object.readSymtab();
211211 try object.readStrtab();
212212
213 if (object.data_in_code_cmd_index != null) try object.readDataInCode();
214
213215 log.debug("\n\n", .{});
214216 log.debug("{s} defines symbols", .{object.name});
215217 for (object.symtab.items) |sym| {
src/link/MachO/Object.zig+30
......@@ -3,6 +3,7 @@ const Object = @This();
33const std = @import("std");
44const assert = std.debug.assert;
55const fs = std.fs;
6const io = std.io;
67const log = std.log.scoped(.object);
78const macho = std.macho;
89const mem = std.mem;
......@@ -24,6 +25,7 @@ segment_cmd_index: ?u16 = null,
2425symtab_cmd_index: ?u16 = null,
2526dysymtab_cmd_index: ?u16 = null,
2627build_version_cmd_index: ?u16 = null,
28data_in_code_cmd_index: ?u16 = null,
2729text_section_index: ?u16 = null,
2830
2931// __DWARF segment sections
......@@ -36,6 +38,8 @@ dwarf_debug_ranges_index: ?u16 = null,
3638symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
3739strtab: std.ArrayListUnmanaged(u8) = .{},
3840
41data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},
42
3943pub fn deinit(self: *Object) void {
4044 for (self.load_commands.items) |*lc| {
4145 lc.deinit(self.allocator);
......@@ -43,6 +47,7 @@ pub fn deinit(self: *Object) void {
4347 self.load_commands.deinit(self.allocator);
4448 self.symtab.deinit(self.allocator);
4549 self.strtab.deinit(self.allocator);
50 self.data_in_code_entries.deinit(self.allocator);
4651 self.allocator.free(self.name);
4752 self.file.close();
4853}
......@@ -83,6 +88,8 @@ pub fn initFromFile(allocator: *Allocator, arch: std.Target.Cpu.Arch, name: []co
8388 try self.readSymtab();
8489 try self.readStrtab();
8590
91 if (self.data_in_code_cmd_index != null) try self.readDataInCode();
92
8693 log.debug("\n\n", .{});
8794 log.debug("{s} defines symbols", .{self.name});
8895 for (self.symtab.items) |sym| {
......@@ -148,6 +155,9 @@ pub fn readLoadCommands(self: *Object, reader: anytype, offset: ReadOffset) !voi
148155 macho.LC_BUILD_VERSION => {
149156 self.build_version_cmd_index = i;
150157 },
158 macho.LC_DATA_IN_CODE => {
159 self.data_in_code_cmd_index = i;
160 },
151161 else => {
152162 log.debug("Unknown load command detected: 0x{x}.", .{cmd.cmd()});
153163 },
......@@ -189,3 +199,23 @@ pub fn readSection(self: Object, allocator: *Allocator, index: u16) ![]u8 {
189199 _ = try self.file.preadAll(buffer, sect.offset);
190200 return buffer;
191201}
202
203pub fn readDataInCode(self: *Object) !void {
204 const index = self.data_in_code_cmd_index orelse return;
205 const data_in_code = self.load_commands.items[index].LinkeditData;
206
207 var buffer = try self.allocator.alloc(u8, data_in_code.datasize);
208 defer self.allocator.free(buffer);
209
210 _ = try self.file.preadAll(buffer, data_in_code.dataoff);
211
212 var stream = io.fixedBufferStream(buffer);
213 var reader = stream.reader();
214 while (true) {
215 const dice = reader.readStruct(macho.data_in_code_entry) catch |err| switch (err) {
216 error.EndOfStream => break,
217 else => |e| return e,
218 };
219 try self.data_in_code_entries.append(self.allocator, dice);
220 }
221}
src/link/MachO/Zld.zig+288-152
......@@ -332,7 +332,7 @@ fn mapAndUpdateSections(
332332 const target_seg = &self.load_commands.items[target_seg_id].Segment;
333333 const target_sect = &target_seg.sections.items[target_sect_id];
334334
335 const alignment = try math.powi(u32, 2, source_sect.@"align");
335 const alignment = try math.powi(u32, 2, target_sect.@"align");
336336 const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment);
337337 const size = mem.alignForwardGeneric(u64, source_sect.size, alignment);
338338 const key = MappingKey{
......@@ -345,7 +345,7 @@ fn mapAndUpdateSections(
345345 .target_sect_id = target_sect_id,
346346 .offset = @intCast(u32, offset),
347347 });
348 log.debug("{s}: {s},{s} mapped to {s},{s} from 0x{x} to 0x{x}", .{
348 log.warn("{s}: {s},{s} mapped to {s},{s} from 0x{x} to 0x{x}", .{
349349 object.name,
350350 parseName(&source_sect.segname),
351351 parseName(&source_sect.sectname),
......@@ -355,7 +355,6 @@ fn mapAndUpdateSections(
355355 offset + size,
356356 });
357357
358 target_sect.@"align" = math.max(target_sect.@"align", source_sect.@"align");
359358 target_sect.size = offset + size;
360359}
361360
......@@ -514,120 +513,117 @@ fn updateMetadata(self: *Zld, object_id: u16) !void {
514513 });
515514 },
516515 else => {
517 log.debug("unhandled section type 0x{x} for '{s}/{s}'", .{ flags, segname, sectname });
516 log.warn("unhandled section type 0x{x} for '{s}/{s}'", .{ flags, segname, sectname });
518517 },
519518 }
520519 }
521520
522 // Update section mappings
523 // __TEXT,__text has to be always defined!
524 try self.mapAndUpdateSections(
525 object_id,
526 object.text_section_index.?,
527 self.text_segment_cmd_index.?,
528 self.text_section_index.?,
529 );
521 // Find ideal section alignment.
522 for (object_seg.sections.items) |source_sect, id| {
523 if (self.getMatchingSection(source_sect)) |res| {
524 const target_seg = &self.load_commands.items[res.seg].Segment;
525 const target_sect = &target_seg.sections.items[res.sect];
526 target_sect.@"align" = math.max(target_sect.@"align", source_sect.@"align");
527 }
528 }
530529
530 // Update section mappings
531531 for (object_seg.sections.items) |source_sect, id| {
532532 const source_sect_id = @intCast(u16, id);
533 if (id == object.text_section_index.?) continue;
533 if (self.getMatchingSection(source_sect)) |res| {
534 try self.mapAndUpdateSections(object_id, source_sect_id, res.seg, res.sect);
535 continue;
536 }
534537
535538 const segname = parseName(&source_sect.segname);
536539 const sectname = parseName(&source_sect.sectname);
537 const flags = source_sect.flags;
540 log.warn("section '{s}/{s}' will be unmapped", .{ segname, sectname });
541 try self.unhandled_sections.putNoClobber(self.allocator, .{
542 .object_id = object_id,
543 .source_sect_id = source_sect_id,
544 }, 0);
545 }
546}
538547
539 switch (flags) {
548const MatchingSection = struct {
549 seg: u16,
550 sect: u16,
551};
552
553fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
554 const segname = parseName(&section.segname);
555 const sectname = parseName(&section.sectname);
556 const res: ?MatchingSection = blk: {
557 switch (section.flags) {
540558 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
541 try self.mapAndUpdateSections(
542 object_id,
543 source_sect_id,
544 self.text_segment_cmd_index.?,
545 self.text_const_section_index.?,
546 );
559 break :blk .{
560 .seg = self.text_segment_cmd_index.?,
561 .sect = self.text_const_section_index.?,
562 };
547563 },
548564 macho.S_CSTRING_LITERALS => {
549 try self.mapAndUpdateSections(
550 object_id,
551 source_sect_id,
552 self.text_segment_cmd_index.?,
553 self.cstring_section_index.?,
554 );
565 break :blk .{
566 .seg = self.text_segment_cmd_index.?,
567 .sect = self.cstring_section_index.?,
568 };
555569 },
556570 macho.S_ZEROFILL => {
557 try self.mapAndUpdateSections(
558 object_id,
559 source_sect_id,
560 self.data_segment_cmd_index.?,
561 self.bss_section_index.?,
562 );
571 break :blk .{
572 .seg = self.data_segment_cmd_index.?,
573 .sect = self.bss_section_index.?,
574 };
563575 },
564576 macho.S_THREAD_LOCAL_VARIABLES => {
565 try self.mapAndUpdateSections(
566 object_id,
567 source_sect_id,
568 self.data_segment_cmd_index.?,
569 self.tlv_section_index.?,
570 );
577 break :blk .{
578 .seg = self.data_segment_cmd_index.?,
579 .sect = self.tlv_section_index.?,
580 };
571581 },
572582 macho.S_THREAD_LOCAL_REGULAR => {
573 try self.mapAndUpdateSections(
574 object_id,
575 source_sect_id,
576 self.data_segment_cmd_index.?,
577 self.tlv_data_section_index.?,
578 );
583 break :blk .{
584 .seg = self.data_segment_cmd_index.?,
585 .sect = self.tlv_data_section_index.?,
586 };
579587 },
580588 macho.S_THREAD_LOCAL_ZEROFILL => {
581 try self.mapAndUpdateSections(
582 object_id,
583 source_sect_id,
584 self.data_segment_cmd_index.?,
585 self.tlv_bss_section_index.?,
586 );
589 break :blk .{
590 .seg = self.data_segment_cmd_index.?,
591 .sect = self.tlv_bss_section_index.?,
592 };
593 },
594 macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS => {
595 break :blk .{
596 .seg = self.text_segment_cmd_index.?,
597 .sect = self.text_section_index.?,
598 };
587599 },
588600 macho.S_REGULAR => {
589601 if (mem.eql(u8, segname, "__TEXT")) {
590 try self.mapAndUpdateSections(
591 object_id,
592 source_sect_id,
593 self.text_segment_cmd_index.?,
594 self.text_const_section_index.?,
595 );
596 continue;
602 break :blk .{
603 .seg = self.text_segment_cmd_index.?,
604 .sect = self.text_const_section_index.?,
605 };
597606 } else if (mem.eql(u8, segname, "__DATA")) {
598607 if (mem.eql(u8, sectname, "__data")) {
599 try self.mapAndUpdateSections(
600 object_id,
601 source_sect_id,
602 self.data_segment_cmd_index.?,
603 self.data_section_index.?,
604 );
605 continue;
608 break :blk .{
609 .seg = self.data_segment_cmd_index.?,
610 .sect = self.data_section_index.?,
611 };
606612 } else if (mem.eql(u8, sectname, "__const")) {
607 try self.mapAndUpdateSections(
608 object_id,
609 source_sect_id,
610 self.data_segment_cmd_index.?,
611 self.data_const_section_index.?,
612 );
613 continue;
613 break :blk .{
614 .seg = self.data_segment_cmd_index.?,
615 .sect = self.data_const_section_index.?,
616 };
614617 }
615618 }
616 log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname });
617 try self.unhandled_sections.putNoClobber(self.allocator, .{
618 .object_id = object_id,
619 .source_sect_id = source_sect_id,
620 }, 0);
619 break :blk null;
621620 },
622621 else => {
623 log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname });
624 try self.unhandled_sections.putNoClobber(self.allocator, .{
625 .object_id = object_id,
626 .source_sect_id = source_sect_id,
627 }, 0);
622 break :blk null;
628623 },
629624 }
630 }
625 };
626 return res;
631627}
632628
633629fn sortSections(self: *Zld) !void {
......@@ -784,7 +780,7 @@ fn resolveImports(self: *Zld) !void {
784780 mem.eql(u8, sym_name, "___stack_chk_guard") or
785781 mem.eql(u8, sym_name, "_environ"))
786782 {
787 log.debug("writing nonlazy symbol '{s}'", .{sym_name});
783 log.warn("writing nonlazy symbol '{s}'", .{sym_name});
788784 const index = @intCast(u32, self.nonlazy_imports.items().len);
789785 try self.nonlazy_imports.putNoClobber(self.allocator, key, .{
790786 .symbol = new_sym,
......@@ -792,7 +788,7 @@ fn resolveImports(self: *Zld) !void {
792788 .index = index,
793789 });
794790 } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) {
795 log.debug("writing threadlocal symbol '{s}'", .{sym_name});
791 log.warn("writing threadlocal symbol '{s}'", .{sym_name});
796792 const index = @intCast(u32, self.threadlocal_imports.items().len);
797793 try self.threadlocal_imports.putNoClobber(self.allocator, key, .{
798794 .symbol = new_sym,
......@@ -800,7 +796,7 @@ fn resolveImports(self: *Zld) !void {
800796 .index = index,
801797 });
802798 } else {
803 log.debug("writing lazy symbol '{s}'", .{sym_name});
799 log.warn("writing lazy symbol '{s}'", .{sym_name});
804800 const index = @intCast(u32, self.lazy_imports.items().len);
805801 try self.lazy_imports.putNoClobber(self.allocator, key, .{
806802 .symbol = new_sym,
......@@ -812,7 +808,7 @@ fn resolveImports(self: *Zld) !void {
812808
813809 const n_strx = try self.makeString("dyld_stub_binder");
814810 const name = try self.allocator.dupe(u8, "dyld_stub_binder");
815 log.debug("writing nonlazy symbol 'dyld_stub_binder'", .{});
811 log.warn("writing nonlazy symbol 'dyld_stub_binder'", .{});
816812 const index = @intCast(u32, self.nonlazy_imports.items().len);
817813 try self.nonlazy_imports.putNoClobber(self.allocator, name, .{
818814 .symbol = .{
......@@ -1016,7 +1012,7 @@ fn writeStubHelperCommon(self: *Zld) !void {
10161012 const new_this_addr = this_addr + @sizeOf(u32);
10171013 const displacement = math.divExact(u64, target_addr - new_this_addr, 4) catch |_| break :binder_blk;
10181014 const literal = math.cast(u18, displacement) catch |_| break :binder_blk;
1019 log.debug("2: disp=0x{x}, literal=0x{x}", .{ displacement, literal });
1015 log.warn("2: disp=0x{x}, literal=0x{x}", .{ displacement, literal });
10201016 // Pad with nop to please division.
10211017 // nop
10221018 mem.writeIntLittle(u32, code[12..16], Arm64.nop().toU32());
......@@ -1069,7 +1065,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void {
10691065 var buf: [@sizeOf(u64)]u8 = undefined;
10701066 mem.writeIntLittle(u64, &buf, end);
10711067 const off = la_symbol_ptr.offset + index * @sizeOf(u64);
1072 log.debug("writing lazy symbol pointer entry 0x{x} at 0x{x}", .{ end, off });
1068 log.warn("writing lazy symbol pointer entry 0x{x} at 0x{x}", .{ end, off });
10731069 try self.file.?.pwriteAll(&buf, off);
10741070}
10751071
......@@ -1082,7 +1078,7 @@ fn writeStub(self: *Zld, index: u32) !void {
10821078 const stub_off = stubs.offset + index * stubs.reserved2;
10831079 const stub_addr = stubs.addr + index * stubs.reserved2;
10841080 const la_ptr_addr = la_symbol_ptr.addr + index * @sizeOf(u64);
1085 log.debug("writing stub at 0x{x}", .{stub_off});
1081 log.warn("writing stub at 0x{x}", .{stub_off});
10861082 var code = try self.allocator.alloc(u8, stubs.reserved2);
10871083 defer self.allocator.free(code);
10881084 switch (self.arch.?) {
......@@ -1229,7 +1225,7 @@ fn resolveSymbols(self: *Zld) !void {
12291225 const target_addr = target_sect.addr + target_mapping.offset;
12301226 const n_value = sym.n_value - source_sect.addr + target_addr;
12311227
1232 log.debug("resolving '{s}':{} as {s} symbol at 0x{x}", .{ sym_name, sym, tt, n_value });
1228 log.warn("resolving '{s}':{} as {s} symbol at 0x{x}", .{ sym_name, sym, tt, n_value });
12331229
12341230 // TODO this assumes only two symbol-filled segments. Also, there might be a more
12351231 // generic way of doing this.
......@@ -1259,8 +1255,8 @@ fn resolveSymbols(self: *Zld) !void {
12591255
12601256fn doRelocs(self: *Zld) !void {
12611257 for (self.objects.items) |object, object_id| {
1262 log.debug("\n\n", .{});
1263 log.debug("relocating object {s}", .{object.name});
1258 log.warn("\n\n", .{});
1259 log.warn("relocating object {s}", .{object.name});
12641260
12651261 const seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
12661262
......@@ -1283,7 +1279,7 @@ fn doRelocs(self: *Zld) !void {
12831279 .object_id = @intCast(u16, object_id),
12841280 .source_sect_id = @intCast(u16, source_sect_id),
12851281 }) orelse {
1286 log.debug("no mapping for {s},{s}; skipping", .{ segname, sectname });
1282 log.warn("no mapping for {s},{s}; skipping", .{ segname, sectname });
12871283 continue;
12881284 };
12891285 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
......@@ -1301,34 +1297,34 @@ fn doRelocs(self: *Zld) !void {
13011297 switch (self.arch.?) {
13021298 .aarch64 => {
13031299 const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type);
1304 log.debug("{s}", .{rel_type});
1305 log.debug(" | source address 0x{x}", .{this_addr});
1306 log.debug(" | offset 0x{x}", .{off});
1300 log.warn("{s}", .{rel_type});
1301 log.warn(" | source address 0x{x}", .{this_addr});
1302 log.warn(" | offset 0x{x}", .{off});
13071303
13081304 if (rel_type == .ARM64_RELOC_ADDEND) {
13091305 addend = rel.r_symbolnum;
1310 log.debug(" | calculated addend = 0x{x}", .{addend});
1306 log.warn(" | calculated addend = 0x{x}", .{addend});
13111307 // TODO followed by either PAGE21 or PAGEOFF12 only.
13121308 continue;
13131309 }
13141310 },
13151311 .x86_64 => {
13161312 const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type);
1317 log.debug("{s}", .{rel_type});
1318 log.debug(" | source address 0x{x}", .{this_addr});
1319 log.debug(" | offset 0x{x}", .{off});
1313 log.warn("{s}", .{rel_type});
1314 log.warn(" | source address 0x{x}", .{this_addr});
1315 log.warn(" | offset 0x{x}", .{off});
13201316 },
13211317 else => {},
13221318 }
13231319
13241320 const target_addr = try self.relocTargetAddr(@intCast(u16, object_id), rel);
1325 log.debug(" | target address 0x{x}", .{target_addr});
1321 log.warn(" | target address 0x{x}", .{target_addr});
13261322 if (rel.r_extern == 1) {
13271323 const target_symname = object.getString(object.symtab.items[rel.r_symbolnum].n_strx);
1328 log.debug(" | target symbol '{s}'", .{target_symname});
1324 log.warn(" | target symbol '{s}'", .{target_symname});
13291325 } else {
13301326 const target_sectname = seg.sections.items[rel.r_symbolnum - 1].sectname;
1331 log.debug(" | target section '{s}'", .{parseName(&target_sectname)});
1327 log.warn(" | target section '{s}'", .{parseName(&target_sectname)});
13321328 }
13331329
13341330 switch (self.arch.?) {
......@@ -1361,13 +1357,12 @@ fn doRelocs(self: *Zld) !void {
13611357 => {
13621358 assert(rel.r_length == 2);
13631359 const inst = code[off..][0..4];
1364 const offset: i32 = blk: {
1360 const offset = @intCast(i64, mem.readIntLittle(i32, inst));
1361 log.warn(" | calculated addend 0x{x}", .{offset});
1362 const actual_target_addr = blk: {
13651363 if (rel.r_extern == 1) {
1366 break :blk mem.readIntLittle(i32, inst);
1364 break :blk @intCast(i64, target_addr) + offset;
13671365 } else {
1368 // TODO it might be required here to parse the offset from the instruction placeholder,
1369 // compare the displacement with the original displacement in the .o file, and adjust
1370 // the displacement in the resultant binary file.
13711366 const correction: i4 = switch (rel_type) {
13721367 .X86_64_RELOC_SIGNED => 0,
13731368 .X86_64_RELOC_SIGNED_1 => 1,
......@@ -1375,11 +1370,28 @@ fn doRelocs(self: *Zld) !void {
13751370 .X86_64_RELOC_SIGNED_4 => 4,
13761371 else => unreachable,
13771372 };
1378 break :blk correction;
1373 log.warn(" | calculated correction 0x{x}", .{correction});
1374
1375 // The value encoded in the instruction is a displacement - 4 - correction.
1376 // To obtain the adjusted target address in the final binary, we need
1377 // calculate the original target address within the object file, establish
1378 // what the offset from the original target section was, and apply this
1379 // offset to the resultant target section with this relocated binary.
1380 const orig_sect_id = @intCast(u16, rel.r_symbolnum - 1);
1381 const target_map = self.mappings.get(.{
1382 .object_id = @intCast(u16, object_id),
1383 .source_sect_id = orig_sect_id,
1384 }) orelse unreachable;
1385 const orig_seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
1386 const orig_sect = orig_seg.sections.items[orig_sect_id];
1387 const orig_offset = off + offset + 4 + correction - @intCast(i64, orig_sect.addr);
1388 log.warn(" | original offset 0x{x}", .{orig_offset});
1389 const adjusted = @intCast(i64, target_addr) + orig_offset;
1390 log.warn(" | adjusted target address 0x{x}", .{adjusted});
1391 break :blk adjusted - correction;
13791392 }
13801393 };
1381 log.debug(" | calculated addend 0x{x}", .{offset});
1382 const result = @intCast(i64, target_addr) - @intCast(i64, this_addr) - 4 + offset;
1394 const result = actual_target_addr - @intCast(i64, this_addr) - 4;
13831395 const displacement = @bitCast(u32, @intCast(i32, result));
13841396 mem.writeIntLittle(u32, inst, displacement);
13851397 },
......@@ -1391,11 +1403,40 @@ fn doRelocs(self: *Zld) !void {
13911403 3 => {
13921404 const inst = code[off..][0..8];
13931405 const offset = mem.readIntLittle(i64, inst);
1394 log.debug(" | calculated addend 0x{x}", .{offset});
1395 const result = if (sub) |s|
1396 @intCast(i64, target_addr) - s + offset
1397 else
1398 @intCast(i64, target_addr) + offset;
1406
1407 const result = outer: {
1408 if (rel.r_extern == 1) {
1409 log.warn(" | calculated addend 0x{x}", .{offset});
1410 if (sub) |s| {
1411 break :outer @intCast(i64, target_addr) - s + offset;
1412 } else {
1413 break :outer @intCast(i64, target_addr) + offset;
1414 }
1415 } else {
1416 // The value encoded in the instruction is an absolute offset
1417 // from the start of MachO header to the target address in the
1418 // object file. To extract the address, we calculate the offset from
1419 // the beginning of the source section to the address, and apply it to
1420 // the target address value.
1421 const orig_sect_id = @intCast(u16, rel.r_symbolnum - 1);
1422 const target_map = self.mappings.get(.{
1423 .object_id = @intCast(u16, object_id),
1424 .source_sect_id = orig_sect_id,
1425 }) orelse unreachable;
1426 const orig_seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
1427 const orig_sect = orig_seg.sections.items[orig_sect_id];
1428 const orig_offset = offset - @intCast(i64, orig_sect.addr);
1429 const actual_target_addr = inner: {
1430 if (sub) |s| {
1431 break :inner @intCast(i64, target_addr) - s + orig_offset;
1432 } else {
1433 break :inner @intCast(i64, target_addr) + orig_offset;
1434 }
1435 };
1436 log.warn(" | adjusted target address 0x{x}", .{actual_target_addr});
1437 break :outer actual_target_addr;
1438 }
1439 };
13991440 mem.writeIntLittle(u64, inst, @bitCast(u64, result));
14001441 sub = null;
14011442
......@@ -1422,7 +1463,7 @@ fn doRelocs(self: *Zld) !void {
14221463 2 => {
14231464 const inst = code[off..][0..4];
14241465 const offset = mem.readIntLittle(i32, inst);
1425 log.debug(" | calculated addend 0x{x}", .{offset});
1466 log.warn(" | calculated addend 0x{x}", .{offset});
14261467 const result = if (sub) |s|
14271468 @intCast(i64, target_addr) - s + offset
14281469 else
......@@ -1459,7 +1500,7 @@ fn doRelocs(self: *Zld) !void {
14591500 const this_page = @intCast(i32, this_addr >> 12);
14601501 const target_page = @intCast(i32, ta >> 12);
14611502 const pages = @bitCast(u21, @intCast(i21, target_page - this_page));
1462 log.debug(" | moving by {} pages", .{pages});
1503 log.warn(" | moving by {} pages", .{pages});
14631504 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Address), inst);
14641505 parsed.immhi = @truncate(u19, pages >> 2);
14651506 parsed.immlo = @truncate(u2, pages);
......@@ -1470,14 +1511,14 @@ fn doRelocs(self: *Zld) !void {
14701511 => {
14711512 const inst = code[off..][0..4];
14721513 if (Arm64.isArithmetic(inst)) {
1473 log.debug(" | detected ADD opcode", .{});
1514 log.warn(" | detected ADD opcode", .{});
14741515 // add
14751516 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Add), inst);
14761517 const ta = if (addend) |a| target_addr + a else target_addr;
14771518 const narrowed = @truncate(u12, ta);
14781519 parsed.offset = narrowed;
14791520 } else {
1480 log.debug(" | detected LDR/STR opcode", .{});
1521 log.warn(" | detected LDR/STR opcode", .{});
14811522 // ldr/str
14821523 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.LoadRegister), inst);
14831524 const ta = if (addend) |a| target_addr + a else target_addr;
......@@ -1518,7 +1559,7 @@ fn doRelocs(self: *Zld) !void {
15181559 };
15191560 const ta = if (addend) |a| target_addr + a else target_addr;
15201561 const narrowed = @truncate(u12, ta);
1521 log.debug(" | rewriting TLV access to ADD opcode", .{});
1562 log.warn(" | rewriting TLV access to ADD opcode", .{});
15221563 // For TLV, we always generate an add instruction.
15231564 mem.writeIntLittle(u32, inst, Arm64.add(parsed.rt, parsed.rn, narrowed, parsed.size).toU32());
15241565 },
......@@ -1530,7 +1571,7 @@ fn doRelocs(self: *Zld) !void {
15301571 3 => {
15311572 const inst = code[off..][0..8];
15321573 const offset = mem.readIntLittle(i64, inst);
1533 log.debug(" | calculated addend 0x{x}", .{offset});
1574 log.warn(" | calculated addend 0x{x}", .{offset});
15341575 const result = if (sub) |s|
15351576 @intCast(i64, target_addr) - s + offset
15361577 else
......@@ -1561,7 +1602,7 @@ fn doRelocs(self: *Zld) !void {
15611602 2 => {
15621603 const inst = code[off..][0..4];
15631604 const offset = mem.readIntLittle(i32, inst);
1564 log.debug(" | calculated addend 0x{x}", .{offset});
1605 log.warn(" | calculated addend 0x{x}", .{offset});
15651606 const result = if (sub) |s|
15661607 @intCast(i64, target_addr) - s + offset
15671608 else
......@@ -1583,7 +1624,7 @@ fn doRelocs(self: *Zld) !void {
15831624 }
15841625 }
15851626
1586 log.debug("writing contents of '{s},{s}' section from '{s}' from 0x{x} to 0x{x}", .{
1627 log.warn("writing contents of '{s},{s}' section from '{s}' from 0x{x} to 0x{x}", .{
15871628 segname,
15881629 sectname,
15891630 object.name,
......@@ -1595,7 +1636,7 @@ fn doRelocs(self: *Zld) !void {
15951636 target_sect.flags == macho.S_THREAD_LOCAL_ZEROFILL or
15961637 target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES)
15971638 {
1598 log.debug("zeroing out '{s},{s}' from 0x{x} to 0x{x}", .{
1639 log.warn("zeroing out '{s},{s}' from 0x{x} to 0x{x}", .{
15991640 parseName(&target_sect.segname),
16001641 parseName(&target_sect.sectname),
16011642 target_sect_off,
......@@ -1629,7 +1670,7 @@ fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64
16291670 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
16301671 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
16311672 const target_sect_addr = target_sect.addr + target_mapping.offset;
1632 log.debug(" | symbol local to object", .{});
1673 log.warn(" | symbol local to object", .{});
16331674 break :blk target_sect_addr + sym.n_value - source_sect.addr;
16341675 } else if (isImport(&sym)) {
16351676 // Relocate to either the artifact's local symbol, or an import from
......@@ -2059,6 +2100,18 @@ fn populateMetadata(self: *Zld) !void {
20592100 },
20602101 });
20612102 }
2103
2104 if (self.data_in_code_cmd_index == null and self.arch.? == .x86_64) {
2105 self.data_in_code_cmd_index = @intCast(u16, self.load_commands.items.len);
2106 try self.load_commands.append(self.allocator, .{
2107 .LinkeditData = .{
2108 .cmd = macho.LC_DATA_IN_CODE,
2109 .cmdsize = @sizeOf(macho.linkedit_data_command),
2110 .dataoff = 0,
2111 .datasize = 0,
2112 },
2113 });
2114 }
20622115}
20632116
20642117fn flush(self: *Zld) !void {
......@@ -2077,6 +2130,9 @@ fn flush(self: *Zld) !void {
20772130 try self.writeBindInfoTable();
20782131 try self.writeLazyBindInfoTable();
20792132 try self.writeExportInfo();
2133 if (self.arch.? == .x86_64) {
2134 try self.writeDataInCode();
2135 }
20802136
20812137 {
20822138 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
......@@ -2169,12 +2225,42 @@ fn writeRebaseInfoTable(self: *Zld) !void {
21692225 }
21702226
21712227 try pointers.ensureCapacity(pointers.items.len + self.local_rebases.items.len);
2172
2173 const nlocals = self.local_rebases.items.len;
2174 var i = nlocals;
2175 while (i > 0) : (i -= 1) {
2176 pointers.appendAssumeCapacity(self.local_rebases.items[i - 1]);
2177 }
2228 pointers.appendSliceAssumeCapacity(self.local_rebases.items);
2229
2230 // const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2231 // const base_id = text_seg.sections.items.len;
2232 // for (self.locals.items()) |entry| {
2233 // for (entry.value.items) |symbol| {
2234 // const local = symbol.inner;
2235
2236 // if (self.data_const_section_index) |index| {
2237 // if (local.n_sect == base_id + index) {
2238 // const offset = local.n_value - data_seg.inner.vmaddr;
2239 // try pointers.append(.{
2240 // .offset = offset,
2241 // .segment_id = @intCast(u16, self.data_segment_cmd_index.?),
2242 // });
2243 // }
2244 // }
2245 // if (self.data_section_index) |index| {
2246 // if (local.n_sect == base_id + index) {
2247 // const offset = local.n_value - data_seg.inner.vmaddr;
2248 // try pointers.append(.{
2249 // .offset = offset,
2250 // .segment_id = @intCast(u16, self.data_segment_cmd_index.?),
2251 // });
2252 // }
2253 // }
2254 // }
2255 // }
2256
2257 std.sort.sort(Pointer, pointers.items, {}, pointerCmp);
2258
2259 // const nlocals = self.local_rebases.items.len;
2260 // var i = nlocals;
2261 // while (i > 0) : (i -= 1) {
2262 // pointers.appendAssumeCapacity(self.local_rebases.items[i - 1]);
2263 // }
21782264
21792265 const size = try rebaseInfoSize(pointers.items);
21802266 var buffer = try self.allocator.alloc(u8, @intCast(usize, size));
......@@ -2189,11 +2275,19 @@ fn writeRebaseInfoTable(self: *Zld) !void {
21892275 dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @sizeOf(u64)));
21902276 seg.inner.filesize += dyld_info.rebase_size;
21912277
2192 log.debug("writing rebase info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + dyld_info.rebase_size });
2278 log.warn("writing rebase info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + dyld_info.rebase_size });
21932279
21942280 try self.file.?.pwriteAll(buffer, dyld_info.rebase_off);
21952281}
21962282
2283fn pointerCmp(context: void, a: Pointer, b: Pointer) bool {
2284 if (a.segment_id < b.segment_id) return true;
2285 if (a.segment_id == b.segment_id) {
2286 return a.offset < b.offset;
2287 }
2288 return false;
2289}
2290
21972291fn writeBindInfoTable(self: *Zld) !void {
21982292 const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
21992293
......@@ -2242,7 +2336,7 @@ fn writeBindInfoTable(self: *Zld) !void {
22422336 dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
22432337 seg.inner.filesize += dyld_info.bind_size;
22442338
2245 log.debug("writing binding info from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + dyld_info.bind_size });
2339 log.warn("writing binding info from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + dyld_info.bind_size });
22462340
22472341 try self.file.?.pwriteAll(buffer, dyld_info.bind_off);
22482342}
......@@ -2281,7 +2375,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void {
22812375 dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
22822376 seg.inner.filesize += dyld_info.lazy_bind_size;
22832377
2284 log.debug("writing lazy binding info from 0x{x} to 0x{x}", .{ dyld_info.lazy_bind_off, dyld_info.lazy_bind_off + dyld_info.lazy_bind_size });
2378 log.warn("writing lazy binding info from 0x{x} to 0x{x}", .{ dyld_info.lazy_bind_off, dyld_info.lazy_bind_off + dyld_info.lazy_bind_size });
22852379
22862380 try self.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);
22872381 try self.populateLazyBindOffsetsInStubHelper(buffer);
......@@ -2383,7 +2477,7 @@ fn writeExportInfo(self: *Zld) !void {
23832477 dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
23842478 seg.inner.filesize += dyld_info.export_size;
23852479
2386 log.debug("writing export info from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size });
2480 log.warn("writing export info from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size });
23872481
23882482 try self.file.?.pwriteAll(buffer, dyld_info.export_off);
23892483}
......@@ -2517,7 +2611,7 @@ fn writeDebugInfo(self: *Zld) !void {
25172611
25182612 const stabs_off = symtab.symoff;
25192613 const stabs_size = symtab.nsyms * @sizeOf(macho.nlist_64);
2520 log.debug("writing symbol stabs from 0x{x} to 0x{x}", .{ stabs_off, stabs_size + stabs_off });
2614 log.warn("writing symbol stabs from 0x{x} to 0x{x}", .{ stabs_off, stabs_size + stabs_off });
25212615 try self.file.?.pwriteAll(mem.sliceAsBytes(stabs.items), stabs_off);
25222616
25232617 linkedit.inner.filesize += stabs_size;
......@@ -2535,12 +2629,12 @@ fn writeSymbolTable(self: *Zld) !void {
25352629 defer locals.deinit();
25362630
25372631 for (self.locals.items()) |entries| {
2538 log.debug("'{s}': {} entries", .{ entries.key, entries.value.items.len });
2632 log.warn("'{s}': {} entries", .{ entries.key, entries.value.items.len });
25392633 // var symbol: ?macho.nlist_64 = null;
25402634 for (entries.value.items) |entry| {
2541 log.debug(" | {}", .{entry.inner});
2542 log.debug(" | {}", .{entry.tt});
2543 log.debug(" | {s}", .{self.objects.items[entry.object_id].name});
2635 log.warn(" | {}", .{entry.inner});
2636 log.warn(" | {}", .{entry.tt});
2637 log.warn(" | {s}", .{self.objects.items[entry.object_id].name});
25442638 // switch (entry.tt) {
25452639 // .Global => {
25462640 // symbol = entry.inner;
......@@ -2585,17 +2679,17 @@ fn writeSymbolTable(self: *Zld) !void {
25852679
25862680 const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);
25872681 const locals_size = nlocals * @sizeOf(macho.nlist_64);
2588 log.debug("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off });
2682 log.warn("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off });
25892683 try self.file.?.pwriteAll(mem.sliceAsBytes(locals.items), locals_off);
25902684
25912685 const exports_off = locals_off + locals_size;
25922686 const exports_size = nexports * @sizeOf(macho.nlist_64);
2593 log.debug("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off });
2687 log.warn("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off });
25942688 try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off);
25952689
25962690 const undefs_off = exports_off + exports_size;
25972691 const undefs_size = nundefs * @sizeOf(macho.nlist_64);
2598 log.debug("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off });
2692 log.warn("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off });
25992693 try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off);
26002694
26012695 symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs);
......@@ -2626,7 +2720,7 @@ fn writeDynamicSymbolTable(self: *Zld) !void {
26262720 const needed_size = dysymtab.nindirectsyms * @sizeOf(u32);
26272721 seg.inner.filesize += needed_size;
26282722
2629 log.debug("writing indirect symbol table from 0x{x} to 0x{x}", .{
2723 log.warn("writing indirect symbol table from 0x{x} to 0x{x}", .{
26302724 dysymtab.indirectsymoff,
26312725 dysymtab.indirectsymoff + needed_size,
26322726 });
......@@ -2665,7 +2759,7 @@ fn writeStringTable(self: *Zld) !void {
26652759 symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64)));
26662760 seg.inner.filesize += symtab.strsize;
26672761
2668 log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize });
2762 log.warn("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize });
26692763
26702764 try self.file.?.pwriteAll(self.strtab.items, symtab.stroff);
26712765
......@@ -2675,6 +2769,48 @@ fn writeStringTable(self: *Zld) !void {
26752769 }
26762770}
26772771
2772fn writeDataInCode(self: *Zld) !void {
2773 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
2774 const dice_cmd = &self.load_commands.items[self.data_in_code_cmd_index.?].LinkeditData;
2775 const fileoff = seg.inner.fileoff + seg.inner.filesize;
2776
2777 var buf = std.ArrayList(u8).init(self.allocator);
2778 defer buf.deinit();
2779
2780 const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2781 const text_sect = text_seg.sections.items[self.text_section_index.?];
2782 for (self.objects.items) |object, object_id| {
2783 const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
2784 const source_sect = source_seg.sections.items[object.text_section_index.?];
2785 const target_mapping = self.mappings.get(.{
2786 .object_id = @intCast(u16, object_id),
2787 .source_sect_id = object.text_section_index.?,
2788 }) orelse continue;
2789
2790 // TODO Currently assume that Dice will always be within the __TEXT,__text section.
2791 try buf.ensureCapacity(
2792 buf.items.len + object.data_in_code_entries.items.len * @sizeOf(macho.data_in_code_entry),
2793 );
2794 for (object.data_in_code_entries.items) |dice| {
2795 const new_dice: macho.data_in_code_entry = .{
2796 .offset = text_sect.offset + target_mapping.offset + dice.offset - source_sect.offset,
2797 .length = dice.length,
2798 .kind = dice.kind,
2799 };
2800 buf.appendSliceAssumeCapacity(mem.asBytes(&new_dice));
2801 }
2802 }
2803 const datasize = @intCast(u32, buf.items.len);
2804
2805 dice_cmd.dataoff = @intCast(u32, fileoff);
2806 dice_cmd.datasize = datasize;
2807 seg.inner.filesize += datasize;
2808
2809 log.warn("writing data-in-code from 0x{x} to 0x{x}", .{ fileoff, fileoff + datasize });
2810
2811 try self.file.?.pwriteAll(buf.items, fileoff);
2812}
2813
26782814fn writeCodeSignaturePadding(self: *Zld) !void {
26792815 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
26802816 const code_sig_cmd = &self.load_commands.items[self.code_signature_cmd_index.?].LinkeditData;
......@@ -2691,7 +2827,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void {
26912827 seg.inner.filesize += needed_size;
26922828 seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);
26932829
2694 log.debug("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size });
2830 log.warn("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size });
26952831
26962832 // Pad out the space. We need to do this to calculate valid hashes for everything in the file
26972833 // except for code signature data.
......@@ -2717,7 +2853,7 @@ fn writeCodeSignature(self: *Zld) !void {
27172853 var stream = std.io.fixedBufferStream(buffer);
27182854 try code_sig.write(stream.writer());
27192855
2720 log.debug("writing code signature from 0x{x} to 0x{x}", .{ code_sig_cmd.dataoff, code_sig_cmd.dataoff + buffer.len });
2856 log.warn("writing code signature from 0x{x} to 0x{x}", .{ code_sig_cmd.dataoff, code_sig_cmd.dataoff + buffer.len });
27212857
27222858 try self.file.?.pwriteAll(buffer, code_sig_cmd.dataoff);
27232859}
......@@ -2736,7 +2872,7 @@ fn writeLoadCommands(self: *Zld) !void {
27362872 }
27372873
27382874 const off = @sizeOf(macho.mach_header_64);
2739 log.debug("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds });
2875 log.warn("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds });
27402876 try self.file.?.pwriteAll(buffer, off);
27412877}
27422878
......@@ -2774,7 +2910,7 @@ fn writeHeader(self: *Zld) !void {
27742910 for (self.load_commands.items) |cmd| {
27752911 header.sizeofcmds += cmd.cmdsize();
27762912 }
2777 log.debug("writing Mach-O header {}", .{header});
2913 log.warn("writing Mach-O header {}", .{header});
27782914 try self.file.?.pwriteAll(mem.asBytes(&header), 0);
27792915}
27802916
......@@ -2788,7 +2924,7 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 {
27882924fn makeString(self: *Zld, bytes: []const u8) !u32 {
27892925 try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1);
27902926 const offset = @intCast(u32, self.strtab.items.len);
2791 log.debug("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset });
2927 log.warn("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset });
27922928 self.strtab.appendSliceAssumeCapacity(bytes);
27932929 self.strtab.appendAssumeCapacity(0);
27942930 return offset;