| author | |
| committer | |
| log | dd5c7588d105c544289b6344b652133538e7e898 |
| tree | 5201e724d6a742c08871015301294894d08febf6 |
| parent | 322be2698d78836e94b54da959eb28476530b822 |
2 files changed, 37 insertions(+), 63 deletions(-)
src/link/MachO/Zld.zig+1-50| ... | ... | @@ -131,7 +131,6 @@ pub const TextBlock = struct { |
| 131 | 131 | size: u64, |
| 132 | 132 | alignment: u32, |
| 133 | 133 | rebases: std.ArrayList(u64), |
| 134 | tlv_offsets: std.ArrayList(TlvOffset), | |
| 135 | 134 | next: ?*TextBlock = null, |
| 136 | 135 | prev: ?*TextBlock = null, |
| 137 | 136 | |
| ... | ... | @@ -140,11 +139,6 @@ pub const TextBlock = struct { |
| 140 | 139 | offset: u64, |
| 141 | 140 | }; |
| 142 | 141 | |
| 143 | pub const TlvOffset = struct { | |
| 144 | local_sym_index: u32, | |
| 145 | offset: u64, | |
| 146 | }; | |
| 147 | ||
| 148 | 142 | pub fn init(allocator: *Allocator) TextBlock { |
| 149 | 143 | return .{ |
| 150 | 144 | .allocator = allocator, |
| ... | ... | @@ -155,7 +149,6 @@ pub const TextBlock = struct { |
| 155 | 149 | .size = undefined, |
| 156 | 150 | .alignment = undefined, |
| 157 | 151 | .rebases = std.ArrayList(u64).init(allocator), |
| 158 | .tlv_offsets = std.ArrayList(TextBlock.TlvOffset).init(allocator), | |
| 159 | 152 | }; |
| 160 | 153 | } |
| 161 | 154 | |
| ... | ... | @@ -170,7 +163,6 @@ pub const TextBlock = struct { |
| 170 | 163 | self.allocator.free(self.code); |
| 171 | 164 | self.relocs.deinit(); |
| 172 | 165 | self.rebases.deinit(); |
| 173 | self.tlv_offsets.deinit(); | |
| 174 | 166 | } |
| 175 | 167 | |
| 176 | 168 | pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void { |
| ... | ... | @@ -210,9 +202,6 @@ pub const TextBlock = struct { |
| 210 | 202 | if (self.rebases.items.len > 0) { |
| 211 | 203 | log.warn(" | rebases: {any}", .{self.rebases.items}); |
| 212 | 204 | } |
| 213 | if (self.tlv_offsets.items.len > 0) { | |
| 214 | log.warn(" | TLV offsets: {any}", .{self.tlv_offsets.items}); | |
| 215 | } | |
| 216 | 205 | log.warn(" | size = {}", .{self.size}); |
| 217 | 206 | log.warn(" | align = {}", .{self.alignment}); |
| 218 | 207 | } |
| ... | ... | @@ -1120,10 +1109,7 @@ fn writeTextBlocks(self: *Zld) !void { |
| 1120 | 1109 | var code = try self.allocator.alloc(u8, sect.size); |
| 1121 | 1110 | defer self.allocator.free(code); |
| 1122 | 1111 | |
| 1123 | if (sect_type == macho.S_ZEROFILL or | |
| 1124 | sect_type == macho.S_THREAD_LOCAL_ZEROFILL or | |
| 1125 | sect_type == macho.S_THREAD_LOCAL_VARIABLES) | |
| 1126 | { | |
| 1112 | if (sect_type == macho.S_ZEROFILL or sect_type == macho.S_THREAD_LOCAL_ZEROFILL) { | |
| 1127 | 1113 | mem.set(u8, code, 0); |
| 1128 | 1114 | } else { |
| 1129 | 1115 | var base_off: u64 = sect.size; |
| ... | ... | @@ -2051,41 +2037,6 @@ fn flush(self: *Zld) !void { |
| 2051 | 2037 | sect.offset = 0; |
| 2052 | 2038 | } |
| 2053 | 2039 | |
| 2054 | if (self.tlv_section_index) |index| { | |
| 2055 | // TODO this should be part of relocation resolution routine. | |
| 2056 | const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; | |
| 2057 | const sect = &seg.sections.items[index]; | |
| 2058 | ||
| 2059 | const base_addr = if (self.tlv_data_section_index) |i| | |
| 2060 | seg.sections.items[i].addr | |
| 2061 | else | |
| 2062 | seg.sections.items[self.tlv_bss_section_index.?].addr; | |
| 2063 | ||
| 2064 | var block: *TextBlock = self.blocks.get(.{ | |
| 2065 | .seg = self.data_segment_cmd_index.?, | |
| 2066 | .sect = index, | |
| 2067 | }) orelse unreachable; | |
| 2068 | ||
| 2069 | var buffer = try self.allocator.alloc(u8, @intCast(usize, sect.size)); | |
| 2070 | defer self.allocator.free(buffer); | |
| 2071 | _ = try self.file.?.preadAll(buffer, sect.offset); | |
| 2072 | ||
| 2073 | while (true) { | |
| 2074 | for (block.tlv_offsets.items) |tlv_offset| { | |
| 2075 | const sym = self.locals.items[tlv_offset.local_sym_index]; | |
| 2076 | assert(sym.payload == .regular); | |
| 2077 | const offset = sym.payload.regular.address - base_addr; | |
| 2078 | mem.writeIntLittle(u64, buffer[tlv_offset.offset..][0..@sizeOf(u64)], offset); | |
| 2079 | } | |
| 2080 | ||
| 2081 | if (block.prev) |prev| { | |
| 2082 | block = prev; | |
| 2083 | } else break; | |
| 2084 | } | |
| 2085 | ||
| 2086 | try self.file.?.pwriteAll(buffer, sect.offset); | |
| 2087 | } | |
| 2088 | ||
| 2089 | 2040 | try self.writeGotEntries(); |
| 2090 | 2041 | try self.setEntryPoint(); |
| 2091 | 2042 | try self.writeRebaseInfoTable(); |
src/link/MachO/reloc.zig+36-13| ... | ... | @@ -50,7 +50,7 @@ pub const Relocation = struct { |
| 50 | 50 | |
| 51 | 51 | source_sect_addr: ?u64 = null, |
| 52 | 52 | |
| 53 | pub fn resolve(self: Unsigned, base: Relocation, source_addr: u64, target_addr: u64) !void { | |
| 53 | pub fn resolve(self: Unsigned, base: Relocation, _: u64, target_addr: u64) !void { | |
| 54 | 54 | const addend = if (self.source_sect_addr) |addr| |
| 55 | 55 | self.addend - @intCast(i64, addr) |
| 56 | 56 | else |
| ... | ... | @@ -430,12 +430,43 @@ pub const Relocation = struct { |
| 430 | 430 | } |
| 431 | 431 | |
| 432 | 432 | switch (self.target.payload) { |
| 433 | .regular => |reg| break :blk reg.address, | |
| 433 | .regular => |reg| { | |
| 434 | const is_tlv = is_tlv: { | |
| 435 | const sym = zld.locals.items[self.block.local_sym_index]; | |
| 436 | const seg = zld.load_commands.items[sym.payload.regular.segment_id].Segment; | |
| 437 | const sect = seg.sections.items[sym.payload.regular.section_id]; | |
| 438 | break :is_tlv commands.sectionType(sect) == macho.S_THREAD_LOCAL_VARIABLES; | |
| 439 | }; | |
| 440 | if (is_tlv) { | |
| 441 | // For TLV relocations, the value specified as a relocation is the displacement from the | |
| 442 | // TLV initializer (either value in __thread_data or zero-init in __thread_bss) to the first | |
| 443 | // defined TLV template init section in the following order: | |
| 444 | // * wrt to __thread_data if defined, then | |
| 445 | // * wrt to __thread_bss | |
| 446 | const seg = zld.load_commands.items[zld.data_segment_cmd_index.?].Segment; | |
| 447 | const base_address = inner: { | |
| 448 | if (zld.tlv_data_section_index) |i| { | |
| 449 | break :inner seg.sections.items[i].addr; | |
| 450 | } else if (zld.tlv_bss_section_index) |i| { | |
| 451 | break :inner seg.sections.items[i].addr; | |
| 452 | } else { | |
| 453 | log.err("threadlocal variables present but no initializer sections found", .{}); | |
| 454 | log.err(" __thread_data not found", .{}); | |
| 455 | log.err(" __thread_bss not found", .{}); | |
| 456 | return error.FailedToResolveRelocationTarget; | |
| 457 | } | |
| 458 | }; | |
| 459 | break :blk reg.address - base_address; | |
| 460 | } | |
| 461 | ||
| 462 | break :blk reg.address; | |
| 463 | }, | |
| 434 | 464 | .proxy => |proxy| { |
| 435 | 465 | if (mem.eql(u8, self.target.name, "__tlv_bootstrap")) { |
| 436 | const segment = zld.load_commands.items[zld.data_segment_cmd_index.?].Segment; | |
| 437 | const tlv = segment.sections.items[zld.tlv_section_index.?]; | |
| 438 | break :blk tlv.addr; | |
| 466 | break :blk 0; // Dynamically bound by dyld. | |
| 467 | // const segment = zld.load_commands.items[zld.data_segment_cmd_index.?].Segment; | |
| 468 | // const tlv = segment.sections.items[zld.tlv_section_index.?]; | |
| 469 | // break :blk tlv.addr; | |
| 439 | 470 | } |
| 440 | 471 | |
| 441 | 472 | const segment = zld.load_commands.items[zld.text_segment_cmd_index.?].Segment; |
| ... | ... | @@ -677,14 +708,6 @@ pub const Parser = struct { |
| 677 | 708 | if (should_rebase) { |
| 678 | 709 | try self.block.rebases.append(out_rel.offset); |
| 679 | 710 | } |
| 680 | ||
| 681 | // TLV is handled via a separate offset mechanism. | |
| 682 | if (sect_type == macho.S_THREAD_LOCAL_VARIABLES) { | |
| 683 | try self.block.tlv_offsets.append(.{ | |
| 684 | .local_sym_index = out_rel.target.payload.regular.local_sym_index, | |
| 685 | .offset = out_rel.offset, | |
| 686 | }); | |
| 687 | } | |
| 688 | 711 | }, |
| 689 | 712 | } |
| 690 | 713 | } else if (out_rel.payload == .branch) blk: { |