| ... | @@ -1020,8 +1020,8 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { | ... | @@ -1020,8 +1020,8 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 1020 | const target_addr = rip.address; | 1020 | const target_addr = rip.address; |
| 1021 | // const got_addr = got_section.addr + decl.link.macho.offset_table_index * @sizeOf(u64); | 1021 | // const got_addr = got_section.addr + decl.link.macho.offset_table_index * @sizeOf(u64); |
| 1022 | const this_addr = symbol.n_value + rip.start; | 1022 | const this_addr = symbol.n_value + rip.start; |
| 1023 | std.debug.print("target_addr=0x{x},this_addr=0x{x}\n", .{target_addr, this_addr}); | 1023 | std.debug.print("target_addr=0x{x},this_addr=0x{x}\n", .{ target_addr, this_addr }); |
| 1024 | const displacement = @intCast(u32, target_addr - this_addr + rip.len); | 1024 | const displacement = @intCast(u32, target_addr - this_addr - rip.len); |
| 1025 | std.debug.print("displacement=0x{x}\n", .{displacement}); | 1025 | std.debug.print("displacement=0x{x}\n", .{displacement}); |
| 1026 | var placeholder = code_buffer.items[rip.start + rip.len - @sizeOf(u32) ..][0..@sizeOf(u32)]; | 1026 | var placeholder = code_buffer.items[rip.start + rip.len - @sizeOf(u32) ..][0..@sizeOf(u32)]; |
| 1027 | mem.writeIntSliceLittle(u32, placeholder, displacement); | 1027 | mem.writeIntSliceLittle(u32, placeholder, displacement); |
| ... | @@ -1201,7 +1201,7 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -1201,7 +1201,7 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1201 | .addr = text_segment.vmaddr + off, | 1201 | .addr = text_segment.vmaddr + off, |
| 1202 | .size = file_size, | 1202 | .size = file_size, |
| 1203 | .offset = off, | 1203 | .offset = off, |
| 1204 | .@"align" = if (self.base.options.target.cpu.arch == .aarch64) 2 else 1, // 2^2 for aarch64, 2^1 for x86_64 | 1204 | .@"align" = if (self.base.options.target.cpu.arch == .aarch64) 2 else 0, // 2^2 for aarch64, 2^0 for x86_64 |
| 1205 | .reloff = 0, | 1205 | .reloff = 0, |
| 1206 | .nreloc = 0, | 1206 | .nreloc = 0, |
| 1207 | .flags = flags, | 1207 | .flags = flags, |
| ... | @@ -1214,48 +1214,23 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -1214,48 +1214,23 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1214 | text_segment.filesize = file_size + off; | 1214 | text_segment.filesize = file_size + off; |
| 1215 | self.cmd_table_dirty = true; | 1215 | self.cmd_table_dirty = true; |
| 1216 | } | 1216 | } |
| 1217 | if (self.data_segment_cmd_index == null) { | | |
| 1218 | self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len); | | |
| 1219 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; | | |
| 1220 | const maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE | macho.VM_PROT_EXECUTE; | | |
| 1221 | const initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE; | | |
| 1222 | try self.load_commands.append(self.base.allocator, .{ | | |
| 1223 | .Segment = .{ | | |
| 1224 | .cmd = macho.LC_SEGMENT_64, | | |
| 1225 | .cmdsize = @sizeOf(macho.segment_command_64), | | |
| 1226 | .segname = makeStaticString("__DATA"), | | |
| 1227 | .vmaddr = text_segment.vmaddr + text_segment.vmsize, | | |
| 1228 | .vmsize = 0, | | |
| 1229 | .fileoff = text_segment.fileoff + text_segment.filesize, | | |
| 1230 | .filesize = 0, | | |
| 1231 | .maxprot = maxprot, | | |
| 1232 | .initprot = initprot, | | |
| 1233 | .nsects = 0, | | |
| 1234 | .flags = 0, | | |
| 1235 | }, | | |
| 1236 | }); | | |
| 1237 | self.cmd_table_dirty = true; | | |
| 1238 | } | | |
| 1239 | if (self.got_section_index == null) { | 1217 | if (self.got_section_index == null) { |
| | 1218 | const text_section = &self.sections.items[self.text_section_index.?]; |
| 1240 | self.got_section_index = @intCast(u16, self.sections.items.len); | 1219 | self.got_section_index = @intCast(u16, self.sections.items.len); |
| 1241 | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; | | |
| 1242 | data_segment.cmdsize += @sizeOf(macho.section_64); | | |
| 1243 | data_segment.nsects += 1; | | |
| 1244 | | 1220 | |
| 1245 | const file_size = @sizeOf(u64) * self.base.options.symbol_count_hint; | 1221 | const file_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 1246 | // TODO looking for free space should be done *within* a segment it belongs to | 1222 | // TODO looking for free space should be done *within* a segment it belongs to |
| 1247 | // const off = @intCast(u32, self.findFreeSpace(file_size, self.page_size)); | 1223 | const off = @intCast(u32, text_section.offset + text_section.size); |
| 1248 | const off = @intCast(u32, data_segment.fileoff); | | |
| 1249 | | 1224 | |
| 1250 | log.debug("found __got section free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); | 1225 | log.debug("found __got section free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); |
| 1251 | | 1226 | |
| 1252 | try self.sections.append(self.base.allocator, .{ | 1227 | try self.sections.append(self.base.allocator, .{ |
| 1253 | .sectname = makeStaticString("__got"), | 1228 | .sectname = makeStaticString("__ziggot"), |
| 1254 | .segname = makeStaticString("__DATA"), | 1229 | .segname = makeStaticString("__TEXT"), |
| 1255 | .addr = data_segment.vmaddr, | 1230 | .addr = text_section.addr + text_section.size, |
| 1256 | .size = file_size, | 1231 | .size = file_size, |
| 1257 | .offset = off, | 1232 | .offset = off, |
| 1258 | .@"align" = 3, // 2^3 = 8 | 1233 | .@"align" = if (self.base.options.target.cpu.arch == .aarch64) 2 else 0, |
| 1259 | .reloff = 0, | 1234 | .reloff = 0, |
| 1260 | .nreloc = 0, | 1235 | .nreloc = 0, |
| 1261 | .flags = macho.S_REGULAR, | 1236 | .flags = macho.S_REGULAR, |
| ... | @@ -1264,23 +1239,26 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -1264,23 +1239,26 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1264 | .reserved3 = 0, | 1239 | .reserved3 = 0, |
| 1265 | }); | 1240 | }); |
| 1266 | | 1241 | |
| 1267 | const segment_size = mem.alignForwardGeneric(u64, file_size, self.page_size); | 1242 | const added_size = mem.alignForwardGeneric(u64, file_size, self.page_size); |
| 1268 | data_segment.vmsize = segment_size; | 1243 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 1269 | data_segment.filesize = segment_size; | 1244 | text_segment.vmsize += added_size; |
| | 1245 | text_segment.filesize += added_size; |
| | 1246 | text_segment.cmdsize += @sizeOf(macho.section_64); |
| | 1247 | text_segment.nsects += 1; |
| 1270 | self.cmd_table_dirty = true; | 1248 | self.cmd_table_dirty = true; |
| 1271 | } | 1249 | } |
| 1272 | if (self.linkedit_segment_cmd_index == null) { | 1250 | if (self.linkedit_segment_cmd_index == null) { |
| 1273 | self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len); | 1251 | self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 1274 | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; | 1252 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 1275 | const maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE | macho.VM_PROT_EXECUTE; | 1253 | const maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE | macho.VM_PROT_EXECUTE; |
| 1276 | const initprot = macho.VM_PROT_READ; | 1254 | const initprot = macho.VM_PROT_READ; |
| 1277 | const off = data_segment.fileoff + data_segment.filesize; | 1255 | const off = text_segment.fileoff + text_segment.filesize; |
| 1278 | try self.load_commands.append(self.base.allocator, .{ | 1256 | try self.load_commands.append(self.base.allocator, .{ |
| 1279 | .Segment = .{ | 1257 | .Segment = .{ |
| 1280 | .cmd = macho.LC_SEGMENT_64, | 1258 | .cmd = macho.LC_SEGMENT_64, |
| 1281 | .cmdsize = @sizeOf(macho.segment_command_64), | 1259 | .cmdsize = @sizeOf(macho.segment_command_64), |
| 1282 | .segname = makeStaticString("__LINKEDIT"), | 1260 | .segname = makeStaticString("__LINKEDIT"), |
| 1283 | .vmaddr = data_segment.vmaddr + data_segment.vmsize, | 1261 | .vmaddr = text_segment.vmaddr + text_segment.vmsize, |
| 1284 | .vmsize = 0, | 1262 | .vmsize = 0, |
| 1285 | .fileoff = off, | 1263 | .fileoff = off, |
| 1286 | .filesize = 0, | 1264 | .filesize = 0, |
| ... | @@ -1671,11 +1649,24 @@ fn findFreeSpace(self: *MachO, object_size: u64, min_alignment: u16) u64 { | ... | @@ -1671,11 +1649,24 @@ fn findFreeSpace(self: *MachO, object_size: u64, min_alignment: u16) u64 { |
| 1671 | fn writeOffsetTableEntry(self: *MachO, index: usize) !void { | 1649 | fn writeOffsetTableEntry(self: *MachO, index: usize) !void { |
| 1672 | const sect = &self.sections.items[self.got_section_index.?]; | 1650 | const sect = &self.sections.items[self.got_section_index.?]; |
| 1673 | const endian = self.base.options.target.cpu.arch.endian(); | 1651 | const endian = self.base.options.target.cpu.arch.endian(); |
| 1674 | var buf: [@sizeOf(u64)]u8 = undefined; | 1652 | |
| 1675 | mem.writeInt(u64, &buf, self.offset_table.items[index], endian); | | |
| 1676 | const off = sect.offset + @sizeOf(u64) * index; | 1653 | const off = sect.offset + @sizeOf(u64) * index; |
| | 1654 | const vmaddr = sect.addr + @sizeOf(u64) * index; |
| | 1655 | const pos_symbol_off = @truncate(u31, vmaddr - self.offset_table.items[index] + 7); |
| | 1656 | const symbol_off = @intCast(i32, pos_symbol_off) * -1; |
| | 1657 | std.debug.print("vmaddr=0x{x},item=0x{x}\n", .{vmaddr, self.offset_table.items[index]}); |
| | 1658 | std.debug.print("posSymbolOff=0x{x},symbolOff=0x{x}\n", .{pos_symbol_off, @bitCast(u32, symbol_off)}); |
| | 1659 | |
| | 1660 | var code: [8]u8 = undefined; |
| | 1661 | // lea %rax, [rip - disp] |
| | 1662 | code[0] = 0x48; |
| | 1663 | code[1] = 0x8D; |
| | 1664 | code[2] = 0x5; |
| | 1665 | mem.writeInt(u32, code[3..7], @bitCast(u32, symbol_off), endian); |
| | 1666 | // ret |
| | 1667 | code[7] = 0xC3; |
| 1677 | log.debug("writing offset table entry 0x{x} at 0x{x}\n", .{ self.offset_table.items[index], off }); | 1668 | log.debug("writing offset table entry 0x{x} at 0x{x}\n", .{ self.offset_table.items[index], off }); |
| 1678 | try self.base.file.?.pwriteAll(&buf, off); | 1669 | try self.base.file.?.pwriteAll(&code, off); |
| 1679 | } | 1670 | } |
| 1680 | | 1671 | |
| 1681 | fn writeSymbolTable(self: *MachO) !void { | 1672 | fn writeSymbolTable(self: *MachO) !void { |
| ... | @@ -1791,7 +1782,7 @@ fn writeExportTrie(self: *MachO) !void { | ... | @@ -1791,7 +1782,7 @@ fn writeExportTrie(self: *MachO) !void { |
| 1791 | | 1782 | |
| 1792 | if (export_size > buffer.items.len) { | 1783 | if (export_size > buffer.items.len) { |
| 1793 | // Pad out to align(8). | 1784 | // Pad out to align(8). |
| 1794 | try self.base.file.?.pwriteAll(&[_]u8{ 0 }, dyld_info.export_off + export_size); | 1785 | try self.base.file.?.pwriteAll(&[_]u8{0}, dyld_info.export_off + export_size); |
| 1795 | } | 1786 | } |
| 1796 | try self.base.file.?.pwriteAll(buffer.items, dyld_info.export_off); | 1787 | try self.base.file.?.pwriteAll(buffer.items, dyld_info.export_off); |
| 1797 | | 1788 | |
| ... | @@ -1816,7 +1807,7 @@ fn writeStringTable(self: *MachO) !void { | ... | @@ -1816,7 +1807,7 @@ fn writeStringTable(self: *MachO) !void { |
| 1816 | | 1807 | |
| 1817 | if (symtab.strsize > needed_size) { | 1808 | if (symtab.strsize > needed_size) { |
| 1818 | // Pad out to align(8); | 1809 | // Pad out to align(8); |
| 1819 | try self.base.file.?.pwriteAll(&[_]u8{ 0 }, symtab.stroff + symtab.strsize); | 1810 | try self.base.file.?.pwriteAll(&[_]u8{0}, symtab.stroff + symtab.strsize); |
| 1820 | } | 1811 | } |
| 1821 | try self.base.file.?.pwriteAll(self.string_table.items, symtab.stroff); | 1812 | try self.base.file.?.pwriteAll(self.string_table.items, symtab.stroff); |
| 1822 | | 1813 | |
| ... | @@ -1843,7 +1834,6 @@ fn writeCmdHeaders(self: *MachO) !void { | ... | @@ -1843,7 +1834,6 @@ fn writeCmdHeaders(self: *MachO) !void { |
| 1843 | last_cmd_offset += cmd.cmdsize(); | 1834 | last_cmd_offset += cmd.cmdsize(); |
| 1844 | } | 1835 | } |
| 1845 | { | 1836 | { |
| 1846 | // write __text section header | | |
| 1847 | const off = if (self.text_segment_cmd_index) |text_segment_index| blk: { | 1837 | const off = if (self.text_segment_cmd_index) |text_segment_index| blk: { |
| 1848 | var i: usize = 0; | 1838 | var i: usize = 0; |
| 1849 | var cmdsize: usize = @sizeOf(macho.mach_header_64) + @sizeOf(macho.segment_command_64); | 1839 | var cmdsize: usize = @sizeOf(macho.mach_header_64) + @sizeOf(macho.segment_command_64); |
| ... | @@ -1856,27 +1846,14 @@ fn writeCmdHeaders(self: *MachO) !void { | ... | @@ -1856,27 +1846,14 @@ fn writeCmdHeaders(self: *MachO) !void { |
| 1856 | // only one, noname segment to append this section header to. | 1846 | // only one, noname segment to append this section header to. |
| 1857 | return error.TODOImplementWritingObjFiles; | 1847 | return error.TODOImplementWritingObjFiles; |
| 1858 | }; | 1848 | }; |
| 1859 | const idx = self.text_section_index.?; | 1849 | // write __text section header |
| | 1850 | const id1 = self.text_section_index.?; |
| 1860 | log.debug("writing text section header at 0x{x}\n", .{off}); | 1851 | log.debug("writing text section header at 0x{x}\n", .{off}); |
| 1861 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.sections.items[idx .. idx + 1]), off); | 1852 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.sections.items[id1 .. id1 + 1]), off); |
| 1862 | } | 1853 | // write __ziggot section header |
| 1863 | { | 1854 | const id2 = self.got_section_index.?; |
| 1864 | // write __got section header | 1855 | log.debug("writing got section header at 0x{x}\n", .{off + @sizeOf(macho.section_64)}); |
| 1865 | const off = if (self.data_segment_cmd_index) |data_segment_index| blk: { | 1856 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.sections.items[id2 .. id2 + 1]), off + @sizeOf(macho.section_64)); |
| 1866 | var i: usize = 0; | | |
| 1867 | var cmdsize: usize = @sizeOf(macho.mach_header_64) + @sizeOf(macho.segment_command_64); | | |
| 1868 | while (i < data_segment_index) : (i += 1) { | | |
| 1869 | cmdsize += self.load_commands.items[i].cmdsize(); | | |
| 1870 | } | | |
| 1871 | break :blk cmdsize; | | |
| 1872 | } else { | | |
| 1873 | // If we've landed in here, we are building a MachO object file, so we have | | |
| 1874 | // only one, noname segment to append this section header to. | | |
| 1875 | return error.TODOImplementWritingObjFiles; | | |
| 1876 | }; | | |
| 1877 | const idx = self.got_section_index.?; | | |
| 1878 | log.debug("writing got section header at 0x{x}\n", .{off}); | | |
| 1879 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.sections.items[idx .. idx + 1]), off); | | |
| 1880 | } | 1857 | } |
| 1881 | } | 1858 | } |
| 1882 | | 1859 | |