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 {...@@ -1615,3 +1615,17 @@ pub const GenericBlob = extern struct {
1615 /// Total length of blob1615 /// Total length of blob
1616 length: u32,1616 length: u32,
1617};1617};
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...@@ -210,6 +210,8 @@ fn readObject(self: *Archive, arch: std.Target.Cpu.Arch, ar_name: []const u8, re
210 try object.readSymtab();210 try object.readSymtab();
211 try object.readStrtab();211 try object.readStrtab();
212212
213 if (object.data_in_code_cmd_index != null) try object.readDataInCode();
214
213 log.debug("\n\n", .{});215 log.debug("\n\n", .{});
214 log.debug("{s} defines symbols", .{object.name});216 log.debug("{s} defines symbols", .{object.name});
215 for (object.symtab.items) |sym| {217 for (object.symtab.items) |sym| {
src/link/MachO/Object.zig+30
...@@ -3,6 +3,7 @@ const Object = @This();...@@ -3,6 +3,7 @@ const Object = @This();
3const std = @import("std");3const std = @import("std");
4const assert = std.debug.assert;4const assert = std.debug.assert;
5const fs = std.fs;5const fs = std.fs;
6const io = std.io;
6const log = std.log.scoped(.object);7const log = std.log.scoped(.object);
7const macho = std.macho;8const macho = std.macho;
8const mem = std.mem;9const mem = std.mem;
...@@ -24,6 +25,7 @@ segment_cmd_index: ?u16 = null,...@@ -24,6 +25,7 @@ segment_cmd_index: ?u16 = null,
24symtab_cmd_index: ?u16 = null,25symtab_cmd_index: ?u16 = null,
25dysymtab_cmd_index: ?u16 = null,26dysymtab_cmd_index: ?u16 = null,
26build_version_cmd_index: ?u16 = null,27build_version_cmd_index: ?u16 = null,
28data_in_code_cmd_index: ?u16 = null,
27text_section_index: ?u16 = null,29text_section_index: ?u16 = null,
2830
29// __DWARF segment sections31// __DWARF segment sections
...@@ -36,6 +38,8 @@ dwarf_debug_ranges_index: ?u16 = null,...@@ -36,6 +38,8 @@ dwarf_debug_ranges_index: ?u16 = null,
36symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},38symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
37strtab: std.ArrayListUnmanaged(u8) = .{},39strtab: std.ArrayListUnmanaged(u8) = .{},
3840
41data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},
42
39pub fn deinit(self: *Object) void {43pub fn deinit(self: *Object) void {
40 for (self.load_commands.items) |*lc| {44 for (self.load_commands.items) |*lc| {
41 lc.deinit(self.allocator);45 lc.deinit(self.allocator);
...@@ -43,6 +47,7 @@ pub fn deinit(self: *Object) void {...@@ -43,6 +47,7 @@ pub fn deinit(self: *Object) void {
43 self.load_commands.deinit(self.allocator);47 self.load_commands.deinit(self.allocator);
44 self.symtab.deinit(self.allocator);48 self.symtab.deinit(self.allocator);
45 self.strtab.deinit(self.allocator);49 self.strtab.deinit(self.allocator);
50 self.data_in_code_entries.deinit(self.allocator);
46 self.allocator.free(self.name);51 self.allocator.free(self.name);
47 self.file.close();52 self.file.close();
48}53}
...@@ -83,6 +88,8 @@ pub fn initFromFile(allocator: *Allocator, arch: std.Target.Cpu.Arch, name: []co...@@ -83,6 +88,8 @@ pub fn initFromFile(allocator: *Allocator, arch: std.Target.Cpu.Arch, name: []co
83 try self.readSymtab();88 try self.readSymtab();
84 try self.readStrtab();89 try self.readStrtab();
8590
91 if (self.data_in_code_cmd_index != null) try self.readDataInCode();
92
86 log.debug("\n\n", .{});93 log.debug("\n\n", .{});
87 log.debug("{s} defines symbols", .{self.name});94 log.debug("{s} defines symbols", .{self.name});
88 for (self.symtab.items) |sym| {95 for (self.symtab.items) |sym| {
...@@ -148,6 +155,9 @@ pub fn readLoadCommands(self: *Object, reader: anytype, offset: ReadOffset) !voi...@@ -148,6 +155,9 @@ pub fn readLoadCommands(self: *Object, reader: anytype, offset: ReadOffset) !voi
148 macho.LC_BUILD_VERSION => {155 macho.LC_BUILD_VERSION => {
149 self.build_version_cmd_index = i;156 self.build_version_cmd_index = i;
150 },157 },
158 macho.LC_DATA_IN_CODE => {
159 self.data_in_code_cmd_index = i;
160 },
151 else => {161 else => {
152 log.debug("Unknown load command detected: 0x{x}.", .{cmd.cmd()});162 log.debug("Unknown load command detected: 0x{x}.", .{cmd.cmd()});
153 },163 },
...@@ -189,3 +199,23 @@ pub fn readSection(self: Object, allocator: *Allocator, index: u16) ![]u8 {...@@ -189,3 +199,23 @@ pub fn readSection(self: Object, allocator: *Allocator, index: u16) ![]u8 {
189 _ = try self.file.preadAll(buffer, sect.offset);199 _ = try self.file.preadAll(buffer, sect.offset);
190 return buffer;200 return buffer;
191}201}
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(...@@ -332,7 +332,7 @@ fn mapAndUpdateSections(
332 const target_seg = &self.load_commands.items[target_seg_id].Segment;332 const target_seg = &self.load_commands.items[target_seg_id].Segment;
333 const target_sect = &target_seg.sections.items[target_sect_id];333 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");
336 const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment);336 const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment);
337 const size = mem.alignForwardGeneric(u64, source_sect.size, alignment);337 const size = mem.alignForwardGeneric(u64, source_sect.size, alignment);
338 const key = MappingKey{338 const key = MappingKey{
...@@ -345,7 +345,7 @@ fn mapAndUpdateSections(...@@ -345,7 +345,7 @@ fn mapAndUpdateSections(
345 .target_sect_id = target_sect_id,345 .target_sect_id = target_sect_id,
346 .offset = @intCast(u32, offset),346 .offset = @intCast(u32, offset),
347 });347 });
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}", .{
349 object.name,349 object.name,
350 parseName(&source_sect.segname),350 parseName(&source_sect.segname),
351 parseName(&source_sect.sectname),351 parseName(&source_sect.sectname),
...@@ -355,7 +355,6 @@ fn mapAndUpdateSections(...@@ -355,7 +355,6 @@ fn mapAndUpdateSections(
355 offset + size,355 offset + size,
356 });356 });
357357
358 target_sect.@"align" = math.max(target_sect.@"align", source_sect.@"align");
359 target_sect.size = offset + size;358 target_sect.size = offset + size;
360}359}
361360
...@@ -514,120 +513,117 @@ fn updateMetadata(self: *Zld, object_id: u16) !void {...@@ -514,120 +513,117 @@ fn updateMetadata(self: *Zld, object_id: u16) !void {
514 });513 });
515 },514 },
516 else => {515 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 });
518 },517 },
519 }518 }
520 }519 }
521520
522 // Update section mappings521 // Find ideal section alignment.
523 // __TEXT,__text has to be always defined!522 for (object_seg.sections.items) |source_sect, id| {
524 try self.mapAndUpdateSections(523 if (self.getMatchingSection(source_sect)) |res| {
525 object_id,524 const target_seg = &self.load_commands.items[res.seg].Segment;
526 object.text_section_index.?,525 const target_sect = &target_seg.sections.items[res.sect];
527 self.text_segment_cmd_index.?,526 target_sect.@"align" = math.max(target_sect.@"align", source_sect.@"align");
528 self.text_section_index.?,527 }
529 );528 }
530529
530 // Update section mappings
531 for (object_seg.sections.items) |source_sect, id| {531 for (object_seg.sections.items) |source_sect, id| {
532 const source_sect_id = @intCast(u16, id);532 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
535 const segname = parseName(&source_sect.segname);538 const segname = parseName(&source_sect.segname);
536 const sectname = parseName(&source_sect.sectname);539 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) {
540 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {558 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
541 try self.mapAndUpdateSections(559 break :blk .{
542 object_id,560 .seg = self.text_segment_cmd_index.?,
543 source_sect_id,561 .sect = self.text_const_section_index.?,
544 self.text_segment_cmd_index.?,562 };
545 self.text_const_section_index.?,
546 );
547 },563 },
548 macho.S_CSTRING_LITERALS => {564 macho.S_CSTRING_LITERALS => {
549 try self.mapAndUpdateSections(565 break :blk .{
550 object_id,566 .seg = self.text_segment_cmd_index.?,
551 source_sect_id,567 .sect = self.cstring_section_index.?,
552 self.text_segment_cmd_index.?,568 };
553 self.cstring_section_index.?,
554 );
555 },569 },
556 macho.S_ZEROFILL => {570 macho.S_ZEROFILL => {
557 try self.mapAndUpdateSections(571 break :blk .{
558 object_id,572 .seg = self.data_segment_cmd_index.?,
559 source_sect_id,573 .sect = self.bss_section_index.?,
560 self.data_segment_cmd_index.?,574 };
561 self.bss_section_index.?,
562 );
563 },575 },
564 macho.S_THREAD_LOCAL_VARIABLES => {576 macho.S_THREAD_LOCAL_VARIABLES => {
565 try self.mapAndUpdateSections(577 break :blk .{
566 object_id,578 .seg = self.data_segment_cmd_index.?,
567 source_sect_id,579 .sect = self.tlv_section_index.?,
568 self.data_segment_cmd_index.?,580 };
569 self.tlv_section_index.?,
570 );
571 },581 },
572 macho.S_THREAD_LOCAL_REGULAR => {582 macho.S_THREAD_LOCAL_REGULAR => {
573 try self.mapAndUpdateSections(583 break :blk .{
574 object_id,584 .seg = self.data_segment_cmd_index.?,
575 source_sect_id,585 .sect = self.tlv_data_section_index.?,
576 self.data_segment_cmd_index.?,586 };
577 self.tlv_data_section_index.?,
578 );
579 },587 },
580 macho.S_THREAD_LOCAL_ZEROFILL => {588 macho.S_THREAD_LOCAL_ZEROFILL => {
581 try self.mapAndUpdateSections(589 break :blk .{
582 object_id,590 .seg = self.data_segment_cmd_index.?,
583 source_sect_id,591 .sect = self.tlv_bss_section_index.?,
584 self.data_segment_cmd_index.?,592 };
585 self.tlv_bss_section_index.?,593 },
586 );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 };
587 },599 },
588 macho.S_REGULAR => {600 macho.S_REGULAR => {
589 if (mem.eql(u8, segname, "__TEXT")) {601 if (mem.eql(u8, segname, "__TEXT")) {
590 try self.mapAndUpdateSections(602 break :blk .{
591 object_id,603 .seg = self.text_segment_cmd_index.?,
592 source_sect_id,604 .sect = self.text_const_section_index.?,
593 self.text_segment_cmd_index.?,605 };
594 self.text_const_section_index.?,
595 );
596 continue;
597 } else if (mem.eql(u8, segname, "__DATA")) {606 } else if (mem.eql(u8, segname, "__DATA")) {
598 if (mem.eql(u8, sectname, "__data")) {607 if (mem.eql(u8, sectname, "__data")) {
599 try self.mapAndUpdateSections(608 break :blk .{
600 object_id,609 .seg = self.data_segment_cmd_index.?,
601 source_sect_id,610 .sect = self.data_section_index.?,
602 self.data_segment_cmd_index.?,611 };
603 self.data_section_index.?,
604 );
605 continue;
606 } else if (mem.eql(u8, sectname, "__const")) {612 } else if (mem.eql(u8, sectname, "__const")) {
607 try self.mapAndUpdateSections(613 break :blk .{
608 object_id,614 .seg = self.data_segment_cmd_index.?,
609 source_sect_id,615 .sect = self.data_const_section_index.?,
610 self.data_segment_cmd_index.?,616 };
611 self.data_const_section_index.?,
612 );
613 continue;
614 }617 }
615 }618 }
616 log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname });619 break :blk null;
617 try self.unhandled_sections.putNoClobber(self.allocator, .{
618 .object_id = object_id,
619 .source_sect_id = source_sect_id,
620 }, 0);
621 },620 },
622 else => {621 else => {
623 log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname });622 break :blk null;
624 try self.unhandled_sections.putNoClobber(self.allocator, .{
625 .object_id = object_id,
626 .source_sect_id = source_sect_id,
627 }, 0);
628 },623 },
629 }624 }
630 }625 };
626 return res;
631}627}
632628
633fn sortSections(self: *Zld) !void {629fn sortSections(self: *Zld) !void {
...@@ -784,7 +780,7 @@ fn resolveImports(self: *Zld) !void {...@@ -784,7 +780,7 @@ fn resolveImports(self: *Zld) !void {
784 mem.eql(u8, sym_name, "___stack_chk_guard") or780 mem.eql(u8, sym_name, "___stack_chk_guard") or
785 mem.eql(u8, sym_name, "_environ"))781 mem.eql(u8, sym_name, "_environ"))
786 {782 {
787 log.debug("writing nonlazy symbol '{s}'", .{sym_name});783 log.warn("writing nonlazy symbol '{s}'", .{sym_name});
788 const index = @intCast(u32, self.nonlazy_imports.items().len);784 const index = @intCast(u32, self.nonlazy_imports.items().len);
789 try self.nonlazy_imports.putNoClobber(self.allocator, key, .{785 try self.nonlazy_imports.putNoClobber(self.allocator, key, .{
790 .symbol = new_sym,786 .symbol = new_sym,
...@@ -792,7 +788,7 @@ fn resolveImports(self: *Zld) !void {...@@ -792,7 +788,7 @@ fn resolveImports(self: *Zld) !void {
792 .index = index,788 .index = index,
793 });789 });
794 } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) {790 } 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});
796 const index = @intCast(u32, self.threadlocal_imports.items().len);792 const index = @intCast(u32, self.threadlocal_imports.items().len);
797 try self.threadlocal_imports.putNoClobber(self.allocator, key, .{793 try self.threadlocal_imports.putNoClobber(self.allocator, key, .{
798 .symbol = new_sym,794 .symbol = new_sym,
...@@ -800,7 +796,7 @@ fn resolveImports(self: *Zld) !void {...@@ -800,7 +796,7 @@ fn resolveImports(self: *Zld) !void {
800 .index = index,796 .index = index,
801 });797 });
802 } else {798 } else {
803 log.debug("writing lazy symbol '{s}'", .{sym_name});799 log.warn("writing lazy symbol '{s}'", .{sym_name});
804 const index = @intCast(u32, self.lazy_imports.items().len);800 const index = @intCast(u32, self.lazy_imports.items().len);
805 try self.lazy_imports.putNoClobber(self.allocator, key, .{801 try self.lazy_imports.putNoClobber(self.allocator, key, .{
806 .symbol = new_sym,802 .symbol = new_sym,
...@@ -812,7 +808,7 @@ fn resolveImports(self: *Zld) !void {...@@ -812,7 +808,7 @@ fn resolveImports(self: *Zld) !void {
812808
813 const n_strx = try self.makeString("dyld_stub_binder");809 const n_strx = try self.makeString("dyld_stub_binder");
814 const name = try self.allocator.dupe(u8, "dyld_stub_binder");810 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'", .{});
816 const index = @intCast(u32, self.nonlazy_imports.items().len);812 const index = @intCast(u32, self.nonlazy_imports.items().len);
817 try self.nonlazy_imports.putNoClobber(self.allocator, name, .{813 try self.nonlazy_imports.putNoClobber(self.allocator, name, .{
818 .symbol = .{814 .symbol = .{
...@@ -1016,7 +1012,7 @@ fn writeStubHelperCommon(self: *Zld) !void {...@@ -1016,7 +1012,7 @@ fn writeStubHelperCommon(self: *Zld) !void {
1016 const new_this_addr = this_addr + @sizeOf(u32);1012 const new_this_addr = this_addr + @sizeOf(u32);
1017 const displacement = math.divExact(u64, target_addr - new_this_addr, 4) catch |_| break :binder_blk;1013 const displacement = math.divExact(u64, target_addr - new_this_addr, 4) catch |_| break :binder_blk;
1018 const literal = math.cast(u18, displacement) catch |_| break :binder_blk;1014 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 });
1020 // Pad with nop to please division.1016 // Pad with nop to please division.
1021 // nop1017 // nop
1022 mem.writeIntLittle(u32, code[12..16], Arm64.nop().toU32());1018 mem.writeIntLittle(u32, code[12..16], Arm64.nop().toU32());
...@@ -1069,7 +1065,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void {...@@ -1069,7 +1065,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void {
1069 var buf: [@sizeOf(u64)]u8 = undefined;1065 var buf: [@sizeOf(u64)]u8 = undefined;
1070 mem.writeIntLittle(u64, &buf, end);1066 mem.writeIntLittle(u64, &buf, end);
1071 const off = la_symbol_ptr.offset + index * @sizeOf(u64);1067 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 });
1073 try self.file.?.pwriteAll(&buf, off);1069 try self.file.?.pwriteAll(&buf, off);
1074}1070}
10751071
...@@ -1082,7 +1078,7 @@ fn writeStub(self: *Zld, index: u32) !void {...@@ -1082,7 +1078,7 @@ fn writeStub(self: *Zld, index: u32) !void {
1082 const stub_off = stubs.offset + index * stubs.reserved2;1078 const stub_off = stubs.offset + index * stubs.reserved2;
1083 const stub_addr = stubs.addr + index * stubs.reserved2;1079 const stub_addr = stubs.addr + index * stubs.reserved2;
1084 const la_ptr_addr = la_symbol_ptr.addr + index * @sizeOf(u64);1080 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});
1086 var code = try self.allocator.alloc(u8, stubs.reserved2);1082 var code = try self.allocator.alloc(u8, stubs.reserved2);
1087 defer self.allocator.free(code);1083 defer self.allocator.free(code);
1088 switch (self.arch.?) {1084 switch (self.arch.?) {
...@@ -1229,7 +1225,7 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1229,7 +1225,7 @@ fn resolveSymbols(self: *Zld) !void {
1229 const target_addr = target_sect.addr + target_mapping.offset;1225 const target_addr = target_sect.addr + target_mapping.offset;
1230 const n_value = sym.n_value - source_sect.addr + target_addr;1226 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
1234 // TODO this assumes only two symbol-filled segments. Also, there might be a more1230 // TODO this assumes only two symbol-filled segments. Also, there might be a more
1235 // generic way of doing this.1231 // generic way of doing this.
...@@ -1259,8 +1255,8 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1259,8 +1255,8 @@ fn resolveSymbols(self: *Zld) !void {
12591255
1260fn doRelocs(self: *Zld) !void {1256fn doRelocs(self: *Zld) !void {
1261 for (self.objects.items) |object, object_id| {1257 for (self.objects.items) |object, object_id| {
1262 log.debug("\n\n", .{});1258 log.warn("\n\n", .{});
1263 log.debug("relocating object {s}", .{object.name});1259 log.warn("relocating object {s}", .{object.name});
12641260
1265 const seg = object.load_commands.items[object.segment_cmd_index.?].Segment;1261 const seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
12661262
...@@ -1283,7 +1279,7 @@ fn doRelocs(self: *Zld) !void {...@@ -1283,7 +1279,7 @@ fn doRelocs(self: *Zld) !void {
1283 .object_id = @intCast(u16, object_id),1279 .object_id = @intCast(u16, object_id),
1284 .source_sect_id = @intCast(u16, source_sect_id),1280 .source_sect_id = @intCast(u16, source_sect_id),
1285 }) orelse {1281 }) orelse {
1286 log.debug("no mapping for {s},{s}; skipping", .{ segname, sectname });1282 log.warn("no mapping for {s},{s}; skipping", .{ segname, sectname });
1287 continue;1283 continue;
1288 };1284 };
1289 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;1285 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
...@@ -1301,34 +1297,34 @@ fn doRelocs(self: *Zld) !void {...@@ -1301,34 +1297,34 @@ fn doRelocs(self: *Zld) !void {
1301 switch (self.arch.?) {1297 switch (self.arch.?) {
1302 .aarch64 => {1298 .aarch64 => {
1303 const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type);1299 const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type);
1304 log.debug("{s}", .{rel_type});1300 log.warn("{s}", .{rel_type});
1305 log.debug(" | source address 0x{x}", .{this_addr});1301 log.warn(" | source address 0x{x}", .{this_addr});
1306 log.debug(" | offset 0x{x}", .{off});1302 log.warn(" | offset 0x{x}", .{off});
13071303
1308 if (rel_type == .ARM64_RELOC_ADDEND) {1304 if (rel_type == .ARM64_RELOC_ADDEND) {
1309 addend = rel.r_symbolnum;1305 addend = rel.r_symbolnum;
1310 log.debug(" | calculated addend = 0x{x}", .{addend});1306 log.warn(" | calculated addend = 0x{x}", .{addend});
1311 // TODO followed by either PAGE21 or PAGEOFF12 only.1307 // TODO followed by either PAGE21 or PAGEOFF12 only.
1312 continue;1308 continue;
1313 }1309 }
1314 },1310 },
1315 .x86_64 => {1311 .x86_64 => {
1316 const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type);1312 const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type);
1317 log.debug("{s}", .{rel_type});1313 log.warn("{s}", .{rel_type});
1318 log.debug(" | source address 0x{x}", .{this_addr});1314 log.warn(" | source address 0x{x}", .{this_addr});
1319 log.debug(" | offset 0x{x}", .{off});1315 log.warn(" | offset 0x{x}", .{off});
1320 },1316 },
1321 else => {},1317 else => {},
1322 }1318 }
13231319
1324 const target_addr = try self.relocTargetAddr(@intCast(u16, object_id), rel);1320 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});
1326 if (rel.r_extern == 1) {1322 if (rel.r_extern == 1) {
1327 const target_symname = object.getString(object.symtab.items[rel.r_symbolnum].n_strx);1323 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});
1329 } else {1325 } else {
1330 const target_sectname = seg.sections.items[rel.r_symbolnum - 1].sectname;1326 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)});
1332 }1328 }
13331329
1334 switch (self.arch.?) {1330 switch (self.arch.?) {
...@@ -1361,13 +1357,12 @@ fn doRelocs(self: *Zld) !void {...@@ -1361,13 +1357,12 @@ fn doRelocs(self: *Zld) !void {
1361 => {1357 => {
1362 assert(rel.r_length == 2);1358 assert(rel.r_length == 2);
1363 const inst = code[off..][0..4];1359 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: {
1365 if (rel.r_extern == 1) {1363 if (rel.r_extern == 1) {
1366 break :blk mem.readIntLittle(i32, inst);1364 break :blk @intCast(i64, target_addr) + offset;
1367 } else {1365 } 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.
1371 const correction: i4 = switch (rel_type) {1366 const correction: i4 = switch (rel_type) {
1372 .X86_64_RELOC_SIGNED => 0,1367 .X86_64_RELOC_SIGNED => 0,
1373 .X86_64_RELOC_SIGNED_1 => 1,1368 .X86_64_RELOC_SIGNED_1 => 1,
...@@ -1375,11 +1370,28 @@ fn doRelocs(self: *Zld) !void {...@@ -1375,11 +1370,28 @@ fn doRelocs(self: *Zld) !void {
1375 .X86_64_RELOC_SIGNED_4 => 4,1370 .X86_64_RELOC_SIGNED_4 => 4,
1376 else => unreachable,1371 else => unreachable,
1377 };1372 };
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;
1379 }1392 }
1380 };1393 };
1381 log.debug(" | calculated addend 0x{x}", .{offset});1394 const result = actual_target_addr - @intCast(i64, this_addr) - 4;
1382 const result = @intCast(i64, target_addr) - @intCast(i64, this_addr) - 4 + offset;
1383 const displacement = @bitCast(u32, @intCast(i32, result));1395 const displacement = @bitCast(u32, @intCast(i32, result));
1384 mem.writeIntLittle(u32, inst, displacement);1396 mem.writeIntLittle(u32, inst, displacement);
1385 },1397 },
...@@ -1391,11 +1403,40 @@ fn doRelocs(self: *Zld) !void {...@@ -1391,11 +1403,40 @@ fn doRelocs(self: *Zld) !void {
1391 3 => {1403 3 => {
1392 const inst = code[off..][0..8];1404 const inst = code[off..][0..8];
1393 const offset = mem.readIntLittle(i64, inst);1405 const offset = mem.readIntLittle(i64, inst);
1394 log.debug(" | calculated addend 0x{x}", .{offset});1406
1395 const result = if (sub) |s|1407 const result = outer: {
1396 @intCast(i64, target_addr) - s + offset1408 if (rel.r_extern == 1) {
1397 else1409 log.warn(" | calculated addend 0x{x}", .{offset});
1398 @intCast(i64, target_addr) + 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 };
1399 mem.writeIntLittle(u64, inst, @bitCast(u64, result));1440 mem.writeIntLittle(u64, inst, @bitCast(u64, result));
1400 sub = null;1441 sub = null;
14011442
...@@ -1422,7 +1463,7 @@ fn doRelocs(self: *Zld) !void {...@@ -1422,7 +1463,7 @@ fn doRelocs(self: *Zld) !void {
1422 2 => {1463 2 => {
1423 const inst = code[off..][0..4];1464 const inst = code[off..][0..4];
1424 const offset = mem.readIntLittle(i32, inst);1465 const offset = mem.readIntLittle(i32, inst);
1425 log.debug(" | calculated addend 0x{x}", .{offset});1466 log.warn(" | calculated addend 0x{x}", .{offset});
1426 const result = if (sub) |s|1467 const result = if (sub) |s|
1427 @intCast(i64, target_addr) - s + offset1468 @intCast(i64, target_addr) - s + offset
1428 else1469 else
...@@ -1459,7 +1500,7 @@ fn doRelocs(self: *Zld) !void {...@@ -1459,7 +1500,7 @@ fn doRelocs(self: *Zld) !void {
1459 const this_page = @intCast(i32, this_addr >> 12);1500 const this_page = @intCast(i32, this_addr >> 12);
1460 const target_page = @intCast(i32, ta >> 12);1501 const target_page = @intCast(i32, ta >> 12);
1461 const pages = @bitCast(u21, @intCast(i21, target_page - this_page));1502 const pages = @bitCast(u21, @intCast(i21, target_page - this_page));
1462 log.debug(" | moving by {} pages", .{pages});1503 log.warn(" | moving by {} pages", .{pages});
1463 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Address), inst);1504 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Address), inst);
1464 parsed.immhi = @truncate(u19, pages >> 2);1505 parsed.immhi = @truncate(u19, pages >> 2);
1465 parsed.immlo = @truncate(u2, pages);1506 parsed.immlo = @truncate(u2, pages);
...@@ -1470,14 +1511,14 @@ fn doRelocs(self: *Zld) !void {...@@ -1470,14 +1511,14 @@ fn doRelocs(self: *Zld) !void {
1470 => {1511 => {
1471 const inst = code[off..][0..4];1512 const inst = code[off..][0..4];
1472 if (Arm64.isArithmetic(inst)) {1513 if (Arm64.isArithmetic(inst)) {
1473 log.debug(" | detected ADD opcode", .{});1514 log.warn(" | detected ADD opcode", .{});
1474 // add1515 // add
1475 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Add), inst);1516 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Add), inst);
1476 const ta = if (addend) |a| target_addr + a else target_addr;1517 const ta = if (addend) |a| target_addr + a else target_addr;
1477 const narrowed = @truncate(u12, ta);1518 const narrowed = @truncate(u12, ta);
1478 parsed.offset = narrowed;1519 parsed.offset = narrowed;
1479 } else {1520 } else {
1480 log.debug(" | detected LDR/STR opcode", .{});1521 log.warn(" | detected LDR/STR opcode", .{});
1481 // ldr/str1522 // ldr/str
1482 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.LoadRegister), inst);1523 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.LoadRegister), inst);
1483 const ta = if (addend) |a| target_addr + a else target_addr;1524 const ta = if (addend) |a| target_addr + a else target_addr;
...@@ -1518,7 +1559,7 @@ fn doRelocs(self: *Zld) !void {...@@ -1518,7 +1559,7 @@ fn doRelocs(self: *Zld) !void {
1518 };1559 };
1519 const ta = if (addend) |a| target_addr + a else target_addr;1560 const ta = if (addend) |a| target_addr + a else target_addr;
1520 const narrowed = @truncate(u12, ta);1561 const narrowed = @truncate(u12, ta);
1521 log.debug(" | rewriting TLV access to ADD opcode", .{});1562 log.warn(" | rewriting TLV access to ADD opcode", .{});
1522 // For TLV, we always generate an add instruction.1563 // For TLV, we always generate an add instruction.
1523 mem.writeIntLittle(u32, inst, Arm64.add(parsed.rt, parsed.rn, narrowed, parsed.size).toU32());1564 mem.writeIntLittle(u32, inst, Arm64.add(parsed.rt, parsed.rn, narrowed, parsed.size).toU32());
1524 },1565 },
...@@ -1530,7 +1571,7 @@ fn doRelocs(self: *Zld) !void {...@@ -1530,7 +1571,7 @@ fn doRelocs(self: *Zld) !void {
1530 3 => {1571 3 => {
1531 const inst = code[off..][0..8];1572 const inst = code[off..][0..8];
1532 const offset = mem.readIntLittle(i64, inst);1573 const offset = mem.readIntLittle(i64, inst);
1533 log.debug(" | calculated addend 0x{x}", .{offset});1574 log.warn(" | calculated addend 0x{x}", .{offset});
1534 const result = if (sub) |s|1575 const result = if (sub) |s|
1535 @intCast(i64, target_addr) - s + offset1576 @intCast(i64, target_addr) - s + offset
1536 else1577 else
...@@ -1561,7 +1602,7 @@ fn doRelocs(self: *Zld) !void {...@@ -1561,7 +1602,7 @@ fn doRelocs(self: *Zld) !void {
1561 2 => {1602 2 => {
1562 const inst = code[off..][0..4];1603 const inst = code[off..][0..4];
1563 const offset = mem.readIntLittle(i32, inst);1604 const offset = mem.readIntLittle(i32, inst);
1564 log.debug(" | calculated addend 0x{x}", .{offset});1605 log.warn(" | calculated addend 0x{x}", .{offset});
1565 const result = if (sub) |s|1606 const result = if (sub) |s|
1566 @intCast(i64, target_addr) - s + offset1607 @intCast(i64, target_addr) - s + offset
1567 else1608 else
...@@ -1583,7 +1624,7 @@ fn doRelocs(self: *Zld) !void {...@@ -1583,7 +1624,7 @@ fn doRelocs(self: *Zld) !void {
1583 }1624 }
1584 }1625 }
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}", .{
1587 segname,1628 segname,
1588 sectname,1629 sectname,
1589 object.name,1630 object.name,
...@@ -1595,7 +1636,7 @@ fn doRelocs(self: *Zld) !void {...@@ -1595,7 +1636,7 @@ fn doRelocs(self: *Zld) !void {
1595 target_sect.flags == macho.S_THREAD_LOCAL_ZEROFILL or1636 target_sect.flags == macho.S_THREAD_LOCAL_ZEROFILL or
1596 target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES)1637 target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES)
1597 {1638 {
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}", .{
1599 parseName(&target_sect.segname),1640 parseName(&target_sect.segname),
1600 parseName(&target_sect.sectname),1641 parseName(&target_sect.sectname),
1601 target_sect_off,1642 target_sect_off,
...@@ -1629,7 +1670,7 @@ fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64...@@ -1629,7 +1670,7 @@ fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64
1629 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;1670 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
1630 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];1671 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
1631 const target_sect_addr = target_sect.addr + target_mapping.offset;1672 const target_sect_addr = target_sect.addr + target_mapping.offset;
1632 log.debug(" | symbol local to object", .{});1673 log.warn(" | symbol local to object", .{});
1633 break :blk target_sect_addr + sym.n_value - source_sect.addr;1674 break :blk target_sect_addr + sym.n_value - source_sect.addr;
1634 } else if (isImport(&sym)) {1675 } else if (isImport(&sym)) {
1635 // Relocate to either the artifact's local symbol, or an import from1676 // Relocate to either the artifact's local symbol, or an import from
...@@ -2059,6 +2100,18 @@ fn populateMetadata(self: *Zld) !void {...@@ -2059,6 +2100,18 @@ fn populateMetadata(self: *Zld) !void {
2059 },2100 },
2060 });2101 });
2061 }2102 }
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 }
2062}2115}
20632116
2064fn flush(self: *Zld) !void {2117fn flush(self: *Zld) !void {
...@@ -2077,6 +2130,9 @@ fn flush(self: *Zld) !void {...@@ -2077,6 +2130,9 @@ fn flush(self: *Zld) !void {
2077 try self.writeBindInfoTable();2130 try self.writeBindInfoTable();
2078 try self.writeLazyBindInfoTable();2131 try self.writeLazyBindInfoTable();
2079 try self.writeExportInfo();2132 try self.writeExportInfo();
2133 if (self.arch.? == .x86_64) {
2134 try self.writeDataInCode();
2135 }
20802136
2081 {2137 {
2082 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;2138 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
...@@ -2169,12 +2225,42 @@ fn writeRebaseInfoTable(self: *Zld) !void {...@@ -2169,12 +2225,42 @@ fn writeRebaseInfoTable(self: *Zld) !void {
2169 }2225 }
21702226
2171 try pointers.ensureCapacity(pointers.items.len + self.local_rebases.items.len);2227 try pointers.ensureCapacity(pointers.items.len + self.local_rebases.items.len);
21722228 pointers.appendSliceAssumeCapacity(self.local_rebases.items);
2173 const nlocals = self.local_rebases.items.len;2229
2174 var i = nlocals;2230 // const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2175 while (i > 0) : (i -= 1) {2231 // const base_id = text_seg.sections.items.len;
2176 pointers.appendAssumeCapacity(self.local_rebases.items[i - 1]);2232 // for (self.locals.items()) |entry| {
2177 }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
2179 const size = try rebaseInfoSize(pointers.items);2265 const size = try rebaseInfoSize(pointers.items);
2180 var buffer = try self.allocator.alloc(u8, @intCast(usize, size));2266 var buffer = try self.allocator.alloc(u8, @intCast(usize, size));
...@@ -2189,11 +2275,19 @@ fn writeRebaseInfoTable(self: *Zld) !void {...@@ -2189,11 +2275,19 @@ fn writeRebaseInfoTable(self: *Zld) !void {
2189 dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @sizeOf(u64)));2275 dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @sizeOf(u64)));
2190 seg.inner.filesize += dyld_info.rebase_size;2276 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
2194 try self.file.?.pwriteAll(buffer, dyld_info.rebase_off);2280 try self.file.?.pwriteAll(buffer, dyld_info.rebase_off);
2195}2281}
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
2197fn writeBindInfoTable(self: *Zld) !void {2291fn writeBindInfoTable(self: *Zld) !void {
2198 const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;2292 const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
21992293
...@@ -2242,7 +2336,7 @@ fn writeBindInfoTable(self: *Zld) !void {...@@ -2242,7 +2336,7 @@ fn writeBindInfoTable(self: *Zld) !void {
2242 dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));2336 dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
2243 seg.inner.filesize += dyld_info.bind_size;2337 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
2247 try self.file.?.pwriteAll(buffer, dyld_info.bind_off);2341 try self.file.?.pwriteAll(buffer, dyld_info.bind_off);
2248}2342}
...@@ -2281,7 +2375,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void {...@@ -2281,7 +2375,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void {
2281 dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));2375 dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
2282 seg.inner.filesize += dyld_info.lazy_bind_size;2376 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
2286 try self.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);2380 try self.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);
2287 try self.populateLazyBindOffsetsInStubHelper(buffer);2381 try self.populateLazyBindOffsetsInStubHelper(buffer);
...@@ -2383,7 +2477,7 @@ fn writeExportInfo(self: *Zld) !void {...@@ -2383,7 +2477,7 @@ fn writeExportInfo(self: *Zld) !void {
2383 dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));2477 dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
2384 seg.inner.filesize += dyld_info.export_size;2478 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
2388 try self.file.?.pwriteAll(buffer, dyld_info.export_off);2482 try self.file.?.pwriteAll(buffer, dyld_info.export_off);
2389}2483}
...@@ -2517,7 +2611,7 @@ fn writeDebugInfo(self: *Zld) !void {...@@ -2517,7 +2611,7 @@ fn writeDebugInfo(self: *Zld) !void {
25172611
2518 const stabs_off = symtab.symoff;2612 const stabs_off = symtab.symoff;
2519 const stabs_size = symtab.nsyms * @sizeOf(macho.nlist_64);2613 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 });
2521 try self.file.?.pwriteAll(mem.sliceAsBytes(stabs.items), stabs_off);2615 try self.file.?.pwriteAll(mem.sliceAsBytes(stabs.items), stabs_off);
25222616
2523 linkedit.inner.filesize += stabs_size;2617 linkedit.inner.filesize += stabs_size;
...@@ -2535,12 +2629,12 @@ fn writeSymbolTable(self: *Zld) !void {...@@ -2535,12 +2629,12 @@ fn writeSymbolTable(self: *Zld) !void {
2535 defer locals.deinit();2629 defer locals.deinit();
25362630
2537 for (self.locals.items()) |entries| {2631 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 });
2539 // var symbol: ?macho.nlist_64 = null;2633 // var symbol: ?macho.nlist_64 = null;
2540 for (entries.value.items) |entry| {2634 for (entries.value.items) |entry| {
2541 log.debug(" | {}", .{entry.inner});2635 log.warn(" | {}", .{entry.inner});
2542 log.debug(" | {}", .{entry.tt});2636 log.warn(" | {}", .{entry.tt});
2543 log.debug(" | {s}", .{self.objects.items[entry.object_id].name});2637 log.warn(" | {s}", .{self.objects.items[entry.object_id].name});
2544 // switch (entry.tt) {2638 // switch (entry.tt) {
2545 // .Global => {2639 // .Global => {
2546 // symbol = entry.inner;2640 // symbol = entry.inner;
...@@ -2585,17 +2679,17 @@ fn writeSymbolTable(self: *Zld) !void {...@@ -2585,17 +2679,17 @@ fn writeSymbolTable(self: *Zld) !void {
25852679
2586 const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);2680 const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);
2587 const locals_size = nlocals * @sizeOf(macho.nlist_64);2681 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 });
2589 try self.file.?.pwriteAll(mem.sliceAsBytes(locals.items), locals_off);2683 try self.file.?.pwriteAll(mem.sliceAsBytes(locals.items), locals_off);
25902684
2591 const exports_off = locals_off + locals_size;2685 const exports_off = locals_off + locals_size;
2592 const exports_size = nexports * @sizeOf(macho.nlist_64);2686 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 });
2594 try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off);2688 try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off);
25952689
2596 const undefs_off = exports_off + exports_size;2690 const undefs_off = exports_off + exports_size;
2597 const undefs_size = nundefs * @sizeOf(macho.nlist_64);2691 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 });
2599 try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off);2693 try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off);
26002694
2601 symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs);2695 symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs);
...@@ -2626,7 +2720,7 @@ fn writeDynamicSymbolTable(self: *Zld) !void {...@@ -2626,7 +2720,7 @@ fn writeDynamicSymbolTable(self: *Zld) !void {
2626 const needed_size = dysymtab.nindirectsyms * @sizeOf(u32);2720 const needed_size = dysymtab.nindirectsyms * @sizeOf(u32);
2627 seg.inner.filesize += needed_size;2721 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}", .{
2630 dysymtab.indirectsymoff,2724 dysymtab.indirectsymoff,
2631 dysymtab.indirectsymoff + needed_size,2725 dysymtab.indirectsymoff + needed_size,
2632 });2726 });
...@@ -2665,7 +2759,7 @@ fn writeStringTable(self: *Zld) !void {...@@ -2665,7 +2759,7 @@ fn writeStringTable(self: *Zld) !void {
2665 symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64)));2759 symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64)));
2666 seg.inner.filesize += symtab.strsize;2760 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
2670 try self.file.?.pwriteAll(self.strtab.items, symtab.stroff);2764 try self.file.?.pwriteAll(self.strtab.items, symtab.stroff);
26712765
...@@ -2675,6 +2769,48 @@ fn writeStringTable(self: *Zld) !void {...@@ -2675,6 +2769,48 @@ fn writeStringTable(self: *Zld) !void {
2675 }2769 }
2676}2770}
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
2678fn writeCodeSignaturePadding(self: *Zld) !void {2814fn writeCodeSignaturePadding(self: *Zld) !void {
2679 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;2815 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
2680 const code_sig_cmd = &self.load_commands.items[self.code_signature_cmd_index.?].LinkeditData;2816 const code_sig_cmd = &self.load_commands.items[self.code_signature_cmd_index.?].LinkeditData;
...@@ -2691,7 +2827,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void {...@@ -2691,7 +2827,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void {
2691 seg.inner.filesize += needed_size;2827 seg.inner.filesize += needed_size;
2692 seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);2828 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
2696 // Pad out the space. We need to do this to calculate valid hashes for everything in the file2832 // Pad out the space. We need to do this to calculate valid hashes for everything in the file
2697 // except for code signature data.2833 // except for code signature data.
...@@ -2717,7 +2853,7 @@ fn writeCodeSignature(self: *Zld) !void {...@@ -2717,7 +2853,7 @@ fn writeCodeSignature(self: *Zld) !void {
2717 var stream = std.io.fixedBufferStream(buffer);2853 var stream = std.io.fixedBufferStream(buffer);
2718 try code_sig.write(stream.writer());2854 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
2722 try self.file.?.pwriteAll(buffer, code_sig_cmd.dataoff);2858 try self.file.?.pwriteAll(buffer, code_sig_cmd.dataoff);
2723}2859}
...@@ -2736,7 +2872,7 @@ fn writeLoadCommands(self: *Zld) !void {...@@ -2736,7 +2872,7 @@ fn writeLoadCommands(self: *Zld) !void {
2736 }2872 }
27372873
2738 const off = @sizeOf(macho.mach_header_64);2874 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 });
2740 try self.file.?.pwriteAll(buffer, off);2876 try self.file.?.pwriteAll(buffer, off);
2741}2877}
27422878
...@@ -2774,7 +2910,7 @@ fn writeHeader(self: *Zld) !void {...@@ -2774,7 +2910,7 @@ fn writeHeader(self: *Zld) !void {
2774 for (self.load_commands.items) |cmd| {2910 for (self.load_commands.items) |cmd| {
2775 header.sizeofcmds += cmd.cmdsize();2911 header.sizeofcmds += cmd.cmdsize();
2776 }2912 }
2777 log.debug("writing Mach-O header {}", .{header});2913 log.warn("writing Mach-O header {}", .{header});
2778 try self.file.?.pwriteAll(mem.asBytes(&header), 0);2914 try self.file.?.pwriteAll(mem.asBytes(&header), 0);
2779}2915}
27802916
...@@ -2788,7 +2924,7 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 {...@@ -2788,7 +2924,7 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 {
2788fn makeString(self: *Zld, bytes: []const u8) !u32 {2924fn makeString(self: *Zld, bytes: []const u8) !u32 {
2789 try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1);2925 try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1);
2790 const offset = @intCast(u32, self.strtab.items.len);2926 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 });
2792 self.strtab.appendSliceAssumeCapacity(bytes);2928 self.strtab.appendSliceAssumeCapacity(bytes);
2793 self.strtab.appendAssumeCapacity(0);2929 self.strtab.appendAssumeCapacity(0);
2794 return offset;2930 return offset;