| ... | @@ -40,7 +40,6 @@ const Liveness = @import("../Liveness.zig"); | ... | @@ -40,7 +40,6 @@ const Liveness = @import("../Liveness.zig"); |
| 40 | const LlvmObject = @import("../codegen/llvm.zig").Object; | 40 | const LlvmObject = @import("../codegen/llvm.zig").Object; |
| 41 | const Module = @import("../Module.zig"); | 41 | const Module = @import("../Module.zig"); |
| 42 | const Relocation = @import("MachO/Relocation.zig"); | 42 | const Relocation = @import("MachO/Relocation.zig"); |
| 43 | const RelocationTable = Relocation.Table; | | |
| 44 | const StringTable = @import("strtab.zig").StringTable; | 43 | const StringTable = @import("strtab.zig").StringTable; |
| 45 | const Trie = @import("MachO/Trie.zig"); | 44 | const Trie = @import("MachO/Trie.zig"); |
| 46 | const Type = @import("../type.zig").Type; | 45 | const Type = @import("../type.zig").Type; |
| ... | @@ -196,6 +195,21 @@ unnamed_const_atoms: UnnamedConstTable = .{}, | ... | @@ -196,6 +195,21 @@ unnamed_const_atoms: UnnamedConstTable = .{}, |
| 196 | /// this will be a table indexed by index into the list of Atoms. | 195 | /// this will be a table indexed by index into the list of Atoms. |
| 197 | relocs: RelocationTable = .{}, | 196 | relocs: RelocationTable = .{}, |
| 198 | | 197 | |
| | 198 | /// A table of rebases indexed by the owning them `Atom`. |
| | 199 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, |
| | 200 | /// this will be a table indexed by index into the list of Atoms. |
| | 201 | rebases: RebaseTable = .{}, |
| | 202 | |
| | 203 | /// A table of bindings indexed by the owning them `Atom`. |
| | 204 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, |
| | 205 | /// this will be a table indexed by index into the list of Atoms. |
| | 206 | bindings: BindingTable = .{}, |
| | 207 | |
| | 208 | /// A table of lazy bindings indexed by the owning them `Atom`. |
| | 209 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, |
| | 210 | /// this will be a table indexed by index into the list of Atoms. |
| | 211 | lazy_bindings: BindingTable = .{}, |
| | 212 | |
| 199 | /// Table of Decls that are currently alive. | 213 | /// Table of Decls that are currently alive. |
| 200 | /// We store them here so that we can properly dispose of any allocated | 214 | /// We store them here so that we can properly dispose of any allocated |
| 201 | /// memory within the atom in the incremental linker. | 215 | /// memory within the atom in the incremental linker. |
| ... | @@ -215,8 +229,8 @@ const Entry = struct { | ... | @@ -215,8 +229,8 @@ const Entry = struct { |
| 215 | return macho_file.getSymbolPtr(.{ .sym_index = entry.sym_index, .file = null }); | 229 | return macho_file.getSymbolPtr(.{ .sym_index = entry.sym_index, .file = null }); |
| 216 | } | 230 | } |
| 217 | | 231 | |
| 218 | pub fn getAtom(entry: Entry, macho_file: *MachO) *Atom { | 232 | pub fn getAtom(entry: Entry, macho_file: *MachO) ?*Atom { |
| 219 | return macho_file.getAtomForSymbol(.{ .sym_index = entry.sym_index, .file = null }).?; | 233 | return macho_file.getAtomForSymbol(.{ .sym_index = entry.sym_index, .file = null }); |
| 220 | } | 234 | } |
| 221 | | 235 | |
| 222 | pub fn getName(entry: Entry, macho_file: *MachO) []const u8 { | 236 | pub fn getName(entry: Entry, macho_file: *MachO) []const u8 { |
| ... | @@ -224,7 +238,10 @@ const Entry = struct { | ... | @@ -224,7 +238,10 @@ const Entry = struct { |
| 224 | } | 238 | } |
| 225 | }; | 239 | }; |
| 226 | | 240 | |
| | 241 | const BindingTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Atom.Binding)); |
| 227 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*Atom)); | 242 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*Atom)); |
| | 243 | const RebaseTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(u32)); |
| | 244 | const RelocationTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Relocation)); |
| 228 | | 245 | |
| 229 | const PendingUpdate = union(enum) { | 246 | const PendingUpdate = union(enum) { |
| 230 | resolve_undef: u32, | 247 | resolve_undef: u32, |
| ... | @@ -238,6 +255,16 @@ pub const SymbolWithLoc = struct { | ... | @@ -238,6 +255,16 @@ pub const SymbolWithLoc = struct { |
| 238 | | 255 | |
| 239 | // null means it's a synthetic global. | 256 | // null means it's a synthetic global. |
| 240 | file: ?u32 = null, | 257 | file: ?u32 = null, |
| | 258 | |
| | 259 | pub fn eql(this: SymbolWithLoc, other: SymbolWithLoc) bool { |
| | 260 | if (this.file == null and other.file == null) { |
| | 261 | return this.sym_index == other.sym_index; |
| | 262 | } |
| | 263 | if (this.file != null and other.file != null) { |
| | 264 | return this.sym_index == other.sym_index and this.file.? == other.file.?; |
| | 265 | } |
| | 266 | return false; |
| | 267 | } |
| 241 | }; | 268 | }; |
| 242 | | 269 | |
| 243 | /// When allocating, the ideal_capacity is calculated by | 270 | /// When allocating, the ideal_capacity is calculated by |
| ... | @@ -436,7 +463,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -436,7 +463,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 436 | var libs = std.StringArrayHashMap(link.SystemLib).init(arena); | 463 | var libs = std.StringArrayHashMap(link.SystemLib).init(arena); |
| 437 | try self.resolveLibSystem(arena, comp, &.{}, &libs); | 464 | try self.resolveLibSystem(arena, comp, &.{}, &libs); |
| 438 | | 465 | |
| 439 | const id_symlink_basename = "zld.id"; | 466 | const id_symlink_basename = "link.id"; |
| 440 | | 467 | |
| 441 | const cache_dir_handle = module.zig_cache_artifact_directory.handle; | 468 | const cache_dir_handle = module.zig_cache_artifact_directory.handle; |
| 442 | var man: Cache.Manifest = undefined; | 469 | var man: Cache.Manifest = undefined; |
| ... | @@ -517,14 +544,19 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -517,14 +544,19 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 517 | | 544 | |
| 518 | try self.allocateSpecialSymbols(); | 545 | try self.allocateSpecialSymbols(); |
| 519 | | 546 | |
| | 547 | { |
| | 548 | var it = self.relocs.keyIterator(); |
| | 549 | while (it.next()) |atom| { |
| | 550 | try atom.*.resolveRelocations(self); |
| | 551 | } |
| | 552 | } |
| | 553 | |
| 520 | if (build_options.enable_logging) { | 554 | if (build_options.enable_logging) { |
| 521 | self.logSymtab(); | 555 | self.logSymtab(); |
| 522 | self.logSections(); | 556 | self.logSections(); |
| 523 | self.logAtoms(); | 557 | self.logAtoms(); |
| 524 | } | 558 | } |
| 525 | | 559 | |
| 526 | try self.writeAtoms(); | | |
| 527 | | | |
| 528 | var lc_buffer = std.ArrayList(u8).init(arena); | 560 | var lc_buffer = std.ArrayList(u8).init(arena); |
| 529 | const lc_writer = lc_buffer.writer(); | 561 | const lc_writer = lc_buffer.writer(); |
| 530 | var ncmds: u32 = 0; | 562 | var ncmds: u32 = 0; |
| ... | @@ -1179,84 +1211,49 @@ pub fn createEmptyAtom(gpa: Allocator, sym_index: u32, size: u64, alignment: u32 | ... | @@ -1179,84 +1211,49 @@ pub fn createEmptyAtom(gpa: Allocator, sym_index: u32, size: u64, alignment: u32 |
| 1179 | return atom; | 1211 | return atom; |
| 1180 | } | 1212 | } |
| 1181 | | 1213 | |
| 1182 | pub fn writeAtom(self: *MachO, atom: *Atom) !void { | 1214 | pub fn writeAtom(self: *MachO, atom: *Atom, code: []const u8) !void { |
| | 1215 | // TODO: temporary sanity check |
| | 1216 | assert(atom.code.items.len == 0); |
| | 1217 | assert(atom.relocs.items.len == 0); |
| | 1218 | assert(atom.rebases.items.len == 0); |
| | 1219 | assert(atom.bindings.items.len == 0); |
| | 1220 | assert(atom.lazy_bindings.items.len == 0); |
| | 1221 | |
| 1183 | const sym = atom.getSymbol(self); | 1222 | const sym = atom.getSymbol(self); |
| 1184 | const section = self.sections.get(sym.n_sect - 1); | 1223 | const section = self.sections.get(sym.n_sect - 1); |
| 1185 | const file_offset = section.header.offset + sym.n_value - section.header.addr; | 1224 | const file_offset = section.header.offset + sym.n_value - section.header.addr; |
| 1186 | try atom.resolveRelocs(self); | | |
| 1187 | log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ atom.getName(self), file_offset }); | 1225 | log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ atom.getName(self), file_offset }); |
| 1188 | try self.base.file.?.pwriteAll(atom.code.items, file_offset); | 1226 | try self.base.file.?.pwriteAll(code, file_offset); |
| | 1227 | try atom.resolveRelocations(self); |
| 1189 | } | 1228 | } |
| 1190 | | 1229 | |
| 1191 | // fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void { | 1230 | fn writePtrWidthAtom(self: *MachO, atom: *Atom) !void { |
| 1192 | // // TODO: reverse-lookup might come in handy here | 1231 | var buffer: [@sizeOf(u64)]u8 = [_]u8{0} ** @sizeOf(u64); |
| 1193 | // var it = self.relocs.valueIterator(); | 1232 | try self.writeAtom(atom, &buffer); |
| 1194 | // while (it.next()) |relocs| { | 1233 | } |
| 1195 | // for (relocs.items) |*reloc| { | | |
| 1196 | // if (!reloc.target.eql(target)) continue; | | |
| 1197 | // reloc.dirty = true; | | |
| 1198 | // } | | |
| 1199 | // } | | |
| 1200 | // } | | |
| 1201 | | | |
| 1202 | // fn markRelocsDirtyByAddress(self: *MachO, addr: u32) void { | | |
| 1203 | // var it = self.relocs.valueIterator(); | | |
| 1204 | // while (it.next()) |relocs| { | | |
| 1205 | // for (relocs.items) |*reloc| { | | |
| 1206 | // const target_atom = reloc.getTargetAtom(self) orelse continue; | | |
| 1207 | // const target_sym = target_atom.getSymbol(self); | | |
| 1208 | // if (target_sym.value < addr) continue; | | |
| 1209 | // reloc.dirty = true; | | |
| 1210 | // } | | |
| 1211 | // } | | |
| 1212 | // } | | |
| 1213 | | | |
| 1214 | // fn resolveRelocs(self: *MachO, atom: *Atom) !void { | | |
| 1215 | // const relocs = self.relocs.get(atom) orelse return; | | |
| 1216 | // const source_sym = atom.getSymbol(self); | | |
| 1217 | // const source_section = self.sections.get(@enumToInt(source_sym.section_number) - 1).header; | | |
| 1218 | // const file_offset = section.offset + source_sym.n_value - section.addr; | | |
| 1219 | | | |
| 1220 | // log.debug("relocating '{s}'", .{atom.getName(self)}); | | |
| 1221 | | | |
| 1222 | // for (relocs.items) |*reloc| { | | |
| 1223 | // if (!reloc.dirty) continue; | | |
| 1224 | | | |
| 1225 | // const target_atom = reloc.getTargetAtom(self) orelse continue; | | |
| 1226 | // const target_vaddr = target_atom.getSymbol(self).value; | | |
| 1227 | // const target_vaddr_with_addend = target_vaddr + reloc.addend; | | |
| 1228 | | | |
| 1229 | // log.debug(" ({x}: [() => 0x{x} ({s})) ({s}) (in file at 0x{x})", .{ | | |
| 1230 | // source_sym.value + reloc.offset, | | |
| 1231 | // target_vaddr_with_addend, | | |
| 1232 | // self.getSymbolName(reloc.target), | | |
| 1233 | // @tagName(reloc.@"type"), | | |
| 1234 | // file_offset + reloc.offset, | | |
| 1235 | // }); | | |
| 1236 | | | |
| 1237 | // reloc.dirty = false; | | |
| 1238 | | 1234 | |
| 1239 | // if (reloc.pcrel) { | 1235 | fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void { |
| 1240 | // const source_vaddr = source_sym.value + reloc.offset; | 1236 | // TODO: reverse-lookup might come in handy here |
| 1241 | // const disp = | 1237 | var it = self.relocs.valueIterator(); |
| 1242 | // @intCast(i32, target_vaddr_with_addend) - @intCast(i32, source_vaddr) - 4; | 1238 | while (it.next()) |relocs| { |
| 1243 | // try self.base.file.?.pwriteAll(mem.asBytes(&disp), file_offset + reloc.offset); | 1239 | for (relocs.items) |*reloc| { |
| 1244 | // continue; | 1240 | if (!reloc.target.eql(target)) continue; |
| 1245 | // } | 1241 | reloc.dirty = true; |
| | 1242 | } |
| | 1243 | } |
| | 1244 | } |
| 1246 | | 1245 | |
| 1247 | // switch (reloc.length) { | 1246 | fn markRelocsDirtyByAddress(self: *MachO, addr: u64) void { |
| 1248 | // 2 => try self.base.file.?.pwriteAll( | 1247 | var it = self.relocs.valueIterator(); |
| 1249 | // mem.asBytes(&@truncate(u32, target_vaddr_with_addend)), | 1248 | while (it.next()) |relocs| { |
| 1250 | // file_offset + reloc.offset, | 1249 | for (relocs.items) |*reloc| { |
| 1251 | // ), | 1250 | const target_atom = reloc.getTargetAtom(self) orelse continue; |
| 1252 | // 3 => try self.base.file.?.pwriteAll( | 1251 | const target_sym = target_atom.getSymbol(self); |
| 1253 | // mem.asBytes(&(target_vaddr_with_addend)), | 1252 | if (target_sym.n_value < addr) continue; |
| 1254 | // file_offset + reloc.offset, | 1253 | reloc.dirty = true; |
| 1255 | // ), | 1254 | } |
| 1256 | // else => unreachable, | 1255 | } |
| 1257 | // } | 1256 | } |
| 1258 | // } | | |
| 1259 | // } | | |
| 1260 | | 1257 | |
| 1261 | pub fn allocateSpecialSymbols(self: *MachO) !void { | 1258 | pub fn allocateSpecialSymbols(self: *MachO) !void { |
| 1262 | for (&[_][]const u8{ | 1259 | for (&[_][]const u8{ |
| ... | @@ -1277,74 +1274,92 @@ pub fn allocateSpecialSymbols(self: *MachO) !void { | ... | @@ -1277,74 +1274,92 @@ pub fn allocateSpecialSymbols(self: *MachO) !void { |
| 1277 | } | 1274 | } |
| 1278 | } | 1275 | } |
| 1279 | | 1276 | |
| 1280 | fn writeAtoms(self: *MachO) !void { | | |
| 1281 | assert(self.mode == .incremental); | | |
| 1282 | | | |
| 1283 | const slice = self.sections.slice(); | | |
| 1284 | for (slice.items(.last_atom)) |last, i| { | | |
| 1285 | var atom: *Atom = last orelse continue; | | |
| 1286 | const sect_i = @intCast(u8, i); | | |
| 1287 | const header = slice.items(.header)[sect_i]; | | |
| 1288 | | | |
| 1289 | if (header.isZerofill()) continue; | | |
| 1290 | | | |
| 1291 | log.debug("writing atoms in {s},{s}", .{ header.segName(), header.sectName() }); | | |
| 1292 | | | |
| 1293 | while (true) { | | |
| 1294 | if (atom.dirty) { | | |
| 1295 | try self.writeAtom(atom); | | |
| 1296 | atom.dirty = false; | | |
| 1297 | } | | |
| 1298 | | | |
| 1299 | if (atom.prev) |prev| { | | |
| 1300 | atom = prev; | | |
| 1301 | } else break; | | |
| 1302 | } | | |
| 1303 | } | | |
| 1304 | } | | |
| 1305 | | | |
| 1306 | pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom { | 1277 | pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom { |
| 1307 | const gpa = self.base.allocator; | 1278 | const gpa = self.base.allocator; |
| | 1279 | |
| 1308 | const sym_index = try self.allocateSymbol(); | 1280 | const sym_index = try self.allocateSymbol(); |
| 1309 | const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3); | 1281 | const atom = switch (self.mode) { |
| | 1282 | .incremental => blk: { |
| | 1283 | const atom = try gpa.create(Atom); |
| | 1284 | atom.* = Atom.empty; |
| | 1285 | atom.sym_index = sym_index; |
| | 1286 | atom.size = @sizeOf(u64); |
| | 1287 | atom.alignment = 3; |
| | 1288 | break :blk atom; |
| | 1289 | }, |
| | 1290 | .one_shot => try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3), |
| | 1291 | }; |
| | 1292 | errdefer gpa.destroy(atom); |
| | 1293 | |
| | 1294 | try self.managed_atoms.append(gpa, atom); |
| | 1295 | try self.atom_by_index_table.putNoClobber(gpa, atom.sym_index, atom); |
| | 1296 | |
| 1310 | const sym = atom.getSymbolPtr(self); | 1297 | const sym = atom.getSymbolPtr(self); |
| 1311 | sym.n_type = macho.N_SECT; | 1298 | sym.n_type = macho.N_SECT; |
| 1312 | sym.n_sect = self.got_section_index.? + 1; | 1299 | sym.n_sect = self.got_section_index.? + 1; |
| 1313 | | 1300 | |
| 1314 | try atom.relocs.append(gpa, .{ | 1301 | if (self.mode == .incremental) { |
| 1315 | .offset = 0, | 1302 | sym.n_value = try self.allocateAtom(atom, atom.size, @alignOf(u64)); |
| 1316 | .target = target, | | |
| 1317 | .addend = 0, | | |
| 1318 | .subtractor = null, | | |
| 1319 | .pcrel = false, | | |
| 1320 | .length = 3, | | |
| 1321 | .@"type" = switch (self.base.options.target.cpu.arch) { | | |
| 1322 | .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED), | | |
| 1323 | .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED), | | |
| 1324 | else => unreachable, | | |
| 1325 | }, | | |
| 1326 | }); | | |
| 1327 | | 1303 | |
| 1328 | const target_sym = self.getSymbol(target); | 1304 | log.debug("allocated GOT atom at 0x{x}", .{sym.n_value}); |
| 1329 | if (target_sym.undf()) { | 1305 | |
| 1330 | const global = self.getGlobal(self.getSymbolName(target)).?; | 1306 | try atom.addRelocation(self, .{ |
| 1331 | try atom.bindings.append(gpa, .{ | 1307 | .@"type" = switch (self.base.options.target.cpu.arch) { |
| 1332 | .target = global, | 1308 | .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED), |
| | 1309 | .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED), |
| | 1310 | else => unreachable, |
| | 1311 | }, |
| | 1312 | .target = target, |
| 1333 | .offset = 0, | 1313 | .offset = 0, |
| | 1314 | .addend = 0, |
| | 1315 | .pcrel = false, |
| | 1316 | .length = 3, |
| 1334 | }); | 1317 | }); |
| | 1318 | |
| | 1319 | const target_sym = self.getSymbol(target); |
| | 1320 | if (target_sym.undf()) { |
| | 1321 | try atom.addBinding(self, .{ |
| | 1322 | .target = self.getGlobal(self.getSymbolName(target)).?, |
| | 1323 | .offset = 0, |
| | 1324 | }); |
| | 1325 | } else { |
| | 1326 | try atom.addRebase(self, 0); |
| | 1327 | } |
| 1335 | } else { | 1328 | } else { |
| 1336 | try atom.rebases.append(gpa, 0); | 1329 | try atom.relocs.append(gpa, .{ |
| 1337 | } | 1330 | .offset = 0, |
| | 1331 | .target = target, |
| | 1332 | .addend = 0, |
| | 1333 | .subtractor = null, |
| | 1334 | .pcrel = false, |
| | 1335 | .length = 3, |
| | 1336 | .@"type" = switch (self.base.options.target.cpu.arch) { |
| | 1337 | .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED), |
| | 1338 | .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED), |
| | 1339 | else => unreachable, |
| | 1340 | }, |
| | 1341 | }); |
| 1338 | | 1342 | |
| 1339 | try self.managed_atoms.append(gpa, atom); | 1343 | const target_sym = self.getSymbol(target); |
| 1340 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); | 1344 | if (target_sym.undf()) { |
| | 1345 | const global = self.getGlobal(self.getSymbolName(target)).?; |
| | 1346 | try atom.bindings.append(gpa, .{ |
| | 1347 | .target = global, |
| | 1348 | .offset = 0, |
| | 1349 | }); |
| | 1350 | } else { |
| | 1351 | try atom.rebases.append(gpa, 0); |
| | 1352 | } |
| 1341 | | 1353 | |
| 1342 | try self.allocateAtomCommon(atom); | 1354 | try self.addAtomToSection(atom); |
| | 1355 | } |
| 1343 | | 1356 | |
| 1344 | return atom; | 1357 | return atom; |
| 1345 | } | 1358 | } |
| 1346 | | 1359 | |
| 1347 | pub fn createTlvPtrAtom(self: *MachO, target: SymbolWithLoc) !*Atom { | 1360 | pub fn createTlvPtrAtom(self: *MachO, target: SymbolWithLoc) !*Atom { |
| | 1361 | assert(self.mode == .one_shot); |
| | 1362 | |
| 1348 | const gpa = self.base.allocator; | 1363 | const gpa = self.base.allocator; |
| 1349 | const sym_index = try self.allocateSymbol(); | 1364 | const sym_index = try self.allocateSymbol(); |
| 1350 | const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3); | 1365 | const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3); |
| ... | @@ -1368,14 +1383,9 @@ pub fn createTlvPtrAtom(self: *MachO, target: SymbolWithLoc) !*Atom { | ... | @@ -1368,14 +1383,9 @@ pub fn createTlvPtrAtom(self: *MachO, target: SymbolWithLoc) !*Atom { |
| 1368 | .sectname = makeStaticString("__thread_ptrs"), | 1383 | .sectname = makeStaticString("__thread_ptrs"), |
| 1369 | .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS, | 1384 | .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS, |
| 1370 | })).?; | 1385 | })).?; |
| 1371 | if (self.mode == .incremental and !gop.found_existing) { | | |
| 1372 | // TODO allocate section | | |
| 1373 | const needed_size: u64 = self.page_size; | | |
| 1374 | try self.allocateSection(gop.sect_id, needed_size, @alignOf(u64)); | | |
| 1375 | } | | |
| 1376 | sym.n_sect = gop.sect_id + 1; | 1386 | sym.n_sect = gop.sect_id + 1; |
| 1377 | | 1387 | |
| 1378 | try self.allocateAtomCommon(atom); | 1388 | try self.addAtomToSection(atom); |
| 1379 | | 1389 | |
| 1380 | return atom; | 1390 | return atom; |
| 1381 | } | 1391 | } |
| ... | @@ -1385,17 +1395,36 @@ pub fn createDyldPrivateAtom(self: *MachO) !void { | ... | @@ -1385,17 +1395,36 @@ pub fn createDyldPrivateAtom(self: *MachO) !void { |
| 1385 | if (self.dyld_private_atom != null) return; | 1395 | if (self.dyld_private_atom != null) return; |
| 1386 | | 1396 | |
| 1387 | const gpa = self.base.allocator; | 1397 | const gpa = self.base.allocator; |
| | 1398 | |
| 1388 | const sym_index = try self.allocateSymbol(); | 1399 | const sym_index = try self.allocateSymbol(); |
| 1389 | const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3); | 1400 | const atom = switch (self.mode) { |
| | 1401 | .incremental => blk: { |
| | 1402 | const atom = try gpa.create(Atom); |
| | 1403 | atom.* = Atom.empty; |
| | 1404 | atom.sym_index = sym_index; |
| | 1405 | atom.size = @sizeOf(u64); |
| | 1406 | atom.alignment = 3; |
| | 1407 | break :blk atom; |
| | 1408 | }, |
| | 1409 | .one_shot => try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3), |
| | 1410 | }; |
| | 1411 | errdefer gpa.destroy(atom); |
| | 1412 | |
| 1390 | const sym = atom.getSymbolPtr(self); | 1413 | const sym = atom.getSymbolPtr(self); |
| 1391 | sym.n_type = macho.N_SECT; | 1414 | sym.n_type = macho.N_SECT; |
| 1392 | sym.n_sect = self.data_section_index.? + 1; | 1415 | sym.n_sect = self.data_section_index.? + 1; |
| 1393 | self.dyld_private_atom = atom; | 1416 | self.dyld_private_atom = atom; |
| 1394 | | 1417 | |
| 1395 | try self.allocateAtomCommon(atom); | | |
| 1396 | | | |
| 1397 | try self.managed_atoms.append(gpa, atom); | 1418 | try self.managed_atoms.append(gpa, atom); |
| 1398 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); | 1419 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); |
| | 1420 | |
| | 1421 | if (self.mode == .incremental) { |
| | 1422 | sym.n_value = try self.allocateAtom(atom, atom.size, @alignOf(u64)); |
| | 1423 | log.debug("allocated dyld_private atom at 0x{x}", .{sym.n_value}); |
| | 1424 | try self.writePtrWidthAtom(atom); |
| | 1425 | } else { |
| | 1426 | try self.addAtomToSection(atom); |
| | 1427 | } |
| 1399 | } | 1428 | } |
| 1400 | | 1429 | |
| 1401 | pub fn createStubHelperPreambleAtom(self: *MachO) !void { | 1430 | pub fn createStubHelperPreambleAtom(self: *MachO) !void { |
| ... | @@ -1415,118 +1444,196 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void { | ... | @@ -1415,118 +1444,196 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void { |
| 1415 | else => unreachable, | 1444 | else => unreachable, |
| 1416 | }; | 1445 | }; |
| 1417 | const sym_index = try self.allocateSymbol(); | 1446 | const sym_index = try self.allocateSymbol(); |
| 1418 | const atom = try MachO.createEmptyAtom(gpa, sym_index, size, alignment); | 1447 | const atom = switch (self.mode) { |
| | 1448 | .incremental => blk: { |
| | 1449 | const atom = try gpa.create(Atom); |
| | 1450 | atom.* = Atom.empty; |
| | 1451 | atom.sym_index = sym_index; |
| | 1452 | atom.size = size; |
| | 1453 | atom.alignment = alignment; |
| | 1454 | break :blk atom; |
| | 1455 | }, |
| | 1456 | .one_shot => try MachO.createEmptyAtom(gpa, sym_index, size, alignment), |
| | 1457 | }; |
| | 1458 | errdefer gpa.destroy(atom); |
| | 1459 | |
| 1419 | const sym = atom.getSymbolPtr(self); | 1460 | const sym = atom.getSymbolPtr(self); |
| 1420 | sym.n_type = macho.N_SECT; | 1461 | sym.n_type = macho.N_SECT; |
| 1421 | sym.n_sect = self.stub_helper_section_index.? + 1; | 1462 | sym.n_sect = self.stub_helper_section_index.? + 1; |
| 1422 | | 1463 | |
| 1423 | const dyld_private_sym_index = self.dyld_private_atom.?.sym_index; | 1464 | const dyld_private_sym_index = self.dyld_private_atom.?.sym_index; |
| | 1465 | |
| | 1466 | const code = try gpa.alloc(u8, size); |
| | 1467 | defer gpa.free(code); |
| | 1468 | mem.set(u8, code, 0); |
| | 1469 | |
| 1424 | switch (arch) { | 1470 | switch (arch) { |
| 1425 | .x86_64 => { | 1471 | .x86_64 => { |
| 1426 | try atom.relocs.ensureUnusedCapacity(self.base.allocator, 2); | | |
| 1427 | // lea %r11, [rip + disp] | 1472 | // lea %r11, [rip + disp] |
| 1428 | atom.code.items[0] = 0x4c; | 1473 | code[0] = 0x4c; |
| 1429 | atom.code.items[1] = 0x8d; | 1474 | code[1] = 0x8d; |
| 1430 | atom.code.items[2] = 0x1d; | 1475 | code[2] = 0x1d; |
| 1431 | atom.relocs.appendAssumeCapacity(.{ | | |
| 1432 | .offset = 3, | | |
| 1433 | .target = .{ .sym_index = dyld_private_sym_index, .file = null }, | | |
| 1434 | .addend = 0, | | |
| 1435 | .subtractor = null, | | |
| 1436 | .pcrel = true, | | |
| 1437 | .length = 2, | | |
| 1438 | .@"type" = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_SIGNED), | | |
| 1439 | }); | | |
| 1440 | // push %r11 | 1476 | // push %r11 |
| 1441 | atom.code.items[7] = 0x41; | 1477 | code[7] = 0x41; |
| 1442 | atom.code.items[8] = 0x53; | 1478 | code[8] = 0x53; |
| 1443 | // jmp [rip + disp] | 1479 | // jmp [rip + disp] |
| 1444 | atom.code.items[9] = 0xff; | 1480 | code[9] = 0xff; |
| 1445 | atom.code.items[10] = 0x25; | 1481 | code[10] = 0x25; |
| 1446 | atom.relocs.appendAssumeCapacity(.{ | 1482 | |
| 1447 | .offset = 11, | 1483 | if (self.mode == .incremental) { |
| 1448 | .target = .{ .sym_index = self.dyld_stub_binder_index.?, .file = null }, | 1484 | try atom.addRelocations(self, 2, .{ .{ |
| 1449 | .addend = 0, | 1485 | .@"type" = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_SIGNED), |
| 1450 | .subtractor = null, | 1486 | .target = .{ .sym_index = dyld_private_sym_index, .file = null }, |
| 1451 | .pcrel = true, | 1487 | .offset = 3, |
| 1452 | .length = 2, | 1488 | .addend = 0, |
| 1453 | .@"type" = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_GOT), | 1489 | .pcrel = true, |
| 1454 | }); | 1490 | .length = 2, |
| | 1491 | }, .{ |
| | 1492 | .@"type" = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_GOT), |
| | 1493 | .target = .{ .sym_index = self.dyld_stub_binder_index.?, .file = null }, |
| | 1494 | .offset = 11, |
| | 1495 | .addend = 0, |
| | 1496 | .pcrel = true, |
| | 1497 | .length = 2, |
| | 1498 | } }); |
| | 1499 | } else { |
| | 1500 | try atom.relocs.ensureUnusedCapacity(self.base.allocator, 2); |
| | 1501 | atom.relocs.appendAssumeCapacity(.{ |
| | 1502 | .offset = 3, |
| | 1503 | .target = .{ .sym_index = dyld_private_sym_index, .file = null }, |
| | 1504 | .addend = 0, |
| | 1505 | .subtractor = null, |
| | 1506 | .pcrel = true, |
| | 1507 | .length = 2, |
| | 1508 | .@"type" = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_SIGNED), |
| | 1509 | }); |
| | 1510 | atom.relocs.appendAssumeCapacity(.{ |
| | 1511 | .offset = 11, |
| | 1512 | .target = .{ .sym_index = self.dyld_stub_binder_index.?, .file = null }, |
| | 1513 | .addend = 0, |
| | 1514 | .subtractor = null, |
| | 1515 | .pcrel = true, |
| | 1516 | .length = 2, |
| | 1517 | .@"type" = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_GOT), |
| | 1518 | }); |
| | 1519 | } |
| 1455 | }, | 1520 | }, |
| | 1521 | |
| 1456 | .aarch64 => { | 1522 | .aarch64 => { |
| 1457 | try atom.relocs.ensureUnusedCapacity(self.base.allocator, 4); | | |
| 1458 | // adrp x17, 0 | 1523 | // adrp x17, 0 |
| 1459 | mem.writeIntLittle(u32, atom.code.items[0..][0..4], aarch64.Instruction.adrp(.x17, 0).toU32()); | 1524 | mem.writeIntLittle(u32, code[0..][0..4], aarch64.Instruction.adrp(.x17, 0).toU32()); |
| 1460 | atom.relocs.appendAssumeCapacity(.{ | | |
| 1461 | .offset = 0, | | |
| 1462 | .target = .{ .sym_index = dyld_private_sym_index, .file = null }, | | |
| 1463 | .addend = 0, | | |
| 1464 | .subtractor = null, | | |
| 1465 | .pcrel = true, | | |
| 1466 | .length = 2, | | |
| 1467 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21), | | |
| 1468 | }); | | |
| 1469 | // add x17, x17, 0 | 1525 | // add x17, x17, 0 |
| 1470 | mem.writeIntLittle(u32, atom.code.items[4..][0..4], aarch64.Instruction.add(.x17, .x17, 0, false).toU32()); | 1526 | mem.writeIntLittle(u32, code[4..][0..4], aarch64.Instruction.add(.x17, .x17, 0, false).toU32()); |
| 1471 | atom.relocs.appendAssumeCapacity(.{ | | |
| 1472 | .offset = 4, | | |
| 1473 | .target = .{ .sym_index = dyld_private_sym_index, .file = null }, | | |
| 1474 | .addend = 0, | | |
| 1475 | .subtractor = null, | | |
| 1476 | .pcrel = false, | | |
| 1477 | .length = 2, | | |
| 1478 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGEOFF12), | | |
| 1479 | }); | | |
| 1480 | // stp x16, x17, [sp, #-16]! | 1527 | // stp x16, x17, [sp, #-16]! |
| 1481 | mem.writeIntLittle(u32, atom.code.items[8..][0..4], aarch64.Instruction.stp( | 1528 | mem.writeIntLittle(u32, code[8..][0..4], aarch64.Instruction.stp( |
| 1482 | .x16, | 1529 | .x16, |
| 1483 | .x17, | 1530 | .x17, |
| 1484 | aarch64.Register.sp, | 1531 | aarch64.Register.sp, |
| 1485 | aarch64.Instruction.LoadStorePairOffset.pre_index(-16), | 1532 | aarch64.Instruction.LoadStorePairOffset.pre_index(-16), |
| 1486 | ).toU32()); | 1533 | ).toU32()); |
| 1487 | // adrp x16, 0 | 1534 | // adrp x16, 0 |
| 1488 | mem.writeIntLittle(u32, atom.code.items[12..][0..4], aarch64.Instruction.adrp(.x16, 0).toU32()); | 1535 | mem.writeIntLittle(u32, code[12..][0..4], aarch64.Instruction.adrp(.x16, 0).toU32()); |
| 1489 | atom.relocs.appendAssumeCapacity(.{ | | |
| 1490 | .offset = 12, | | |
| 1491 | .target = .{ .sym_index = self.dyld_stub_binder_index.?, .file = null }, | | |
| 1492 | .addend = 0, | | |
| 1493 | .subtractor = null, | | |
| 1494 | .pcrel = true, | | |
| 1495 | .length = 2, | | |
| 1496 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21), | | |
| 1497 | }); | | |
| 1498 | // ldr x16, [x16, 0] | 1536 | // ldr x16, [x16, 0] |
| 1499 | mem.writeIntLittle(u32, atom.code.items[16..][0..4], aarch64.Instruction.ldr( | 1537 | mem.writeIntLittle(u32, code[16..][0..4], aarch64.Instruction.ldr( |
| 1500 | .x16, | 1538 | .x16, |
| 1501 | .x16, | 1539 | .x16, |
| 1502 | aarch64.Instruction.LoadStoreOffset.imm(0), | 1540 | aarch64.Instruction.LoadStoreOffset.imm(0), |
| 1503 | ).toU32()); | 1541 | ).toU32()); |
| 1504 | atom.relocs.appendAssumeCapacity(.{ | | |
| 1505 | .offset = 16, | | |
| 1506 | .target = .{ .sym_index = self.dyld_stub_binder_index.?, .file = null }, | | |
| 1507 | .addend = 0, | | |
| 1508 | .subtractor = null, | | |
| 1509 | .pcrel = false, | | |
| 1510 | .length = 2, | | |
| 1511 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGEOFF12), | | |
| 1512 | }); | | |
| 1513 | // br x16 | 1542 | // br x16 |
| 1514 | mem.writeIntLittle(u32, atom.code.items[20..][0..4], aarch64.Instruction.br(.x16).toU32()); | 1543 | mem.writeIntLittle(u32, code[20..][0..4], aarch64.Instruction.br(.x16).toU32()); |
| | 1544 | |
| | 1545 | if (self.mode == .incremental) { |
| | 1546 | try atom.addRelocations(self, 4, .{ .{ |
| | 1547 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21), |
| | 1548 | .target = .{ .sym_index = dyld_private_sym_index, .file = null }, |
| | 1549 | .offset = 0, |
| | 1550 | .addend = 0, |
| | 1551 | .pcrel = true, |
| | 1552 | .length = 2, |
| | 1553 | }, .{ |
| | 1554 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGEOFF12), |
| | 1555 | .target = .{ .sym_index = dyld_private_sym_index, .file = null }, |
| | 1556 | .offset = 4, |
| | 1557 | .addend = 0, |
| | 1558 | .pcrel = false, |
| | 1559 | .length = 2, |
| | 1560 | }, .{ |
| | 1561 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21), |
| | 1562 | .target = .{ .sym_index = self.dyld_stub_binder_index.?, .file = null }, |
| | 1563 | .offset = 12, |
| | 1564 | .addend = 0, |
| | 1565 | .pcrel = true, |
| | 1566 | .length = 2, |
| | 1567 | }, .{ |
| | 1568 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGEOFF12), |
| | 1569 | .target = .{ .sym_index = self.dyld_stub_binder_index.?, .file = null }, |
| | 1570 | .offset = 16, |
| | 1571 | .addend = 0, |
| | 1572 | .pcrel = false, |
| | 1573 | .length = 2, |
| | 1574 | } }); |
| | 1575 | } else { |
| | 1576 | try atom.relocs.ensureUnusedCapacity(gpa, 4); |
| | 1577 | atom.relocs.appendAssumeCapacity(.{ |
| | 1578 | .offset = 0, |
| | 1579 | .target = .{ .sym_index = dyld_private_sym_index, .file = null }, |
| | 1580 | .addend = 0, |
| | 1581 | .subtractor = null, |
| | 1582 | .pcrel = true, |
| | 1583 | .length = 2, |
| | 1584 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21), |
| | 1585 | }); |
| | 1586 | atom.relocs.appendAssumeCapacity(.{ |
| | 1587 | .offset = 4, |
| | 1588 | .target = .{ .sym_index = dyld_private_sym_index, .file = null }, |
| | 1589 | .addend = 0, |
| | 1590 | .subtractor = null, |
| | 1591 | .pcrel = false, |
| | 1592 | .length = 2, |
| | 1593 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGEOFF12), |
| | 1594 | }); |
| | 1595 | atom.relocs.appendAssumeCapacity(.{ |
| | 1596 | .offset = 12, |
| | 1597 | .target = .{ .sym_index = self.dyld_stub_binder_index.?, .file = null }, |
| | 1598 | .addend = 0, |
| | 1599 | .subtractor = null, |
| | 1600 | .pcrel = true, |
| | 1601 | .length = 2, |
| | 1602 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21), |
| | 1603 | }); |
| | 1604 | atom.relocs.appendAssumeCapacity(.{ |
| | 1605 | .offset = 16, |
| | 1606 | .target = .{ .sym_index = self.dyld_stub_binder_index.?, .file = null }, |
| | 1607 | .addend = 0, |
| | 1608 | .subtractor = null, |
| | 1609 | .pcrel = false, |
| | 1610 | .length = 2, |
| | 1611 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGEOFF12), |
| | 1612 | }); |
| | 1613 | } |
| 1515 | }, | 1614 | }, |
| | 1615 | |
| 1516 | else => unreachable, | 1616 | else => unreachable, |
| 1517 | } | 1617 | } |
| 1518 | self.stub_helper_preamble_atom = atom; | 1618 | self.stub_helper_preamble_atom = atom; |
| 1519 | | 1619 | |
| 1520 | try self.allocateAtomCommon(atom); | | |
| 1521 | | | |
| 1522 | try self.managed_atoms.append(gpa, atom); | 1620 | try self.managed_atoms.append(gpa, atom); |
| 1523 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); | 1621 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); |
| | 1622 | |
| | 1623 | if (self.mode == .incremental) { |
| | 1624 | sym.n_value = try self.allocateAtom(atom, size, math.powi(u32, 2, alignment) catch unreachable); |
| | 1625 | log.debug("allocated stub preamble atom at 0x{x}", .{sym.n_value}); |
| | 1626 | try self.writeAtom(atom, code); |
| | 1627 | } else { |
| | 1628 | mem.copy(u8, atom.code.items, code); |
| | 1629 | try self.addAtomToSection(atom); |
| | 1630 | } |
| 1524 | } | 1631 | } |
| 1525 | | 1632 | |
| 1526 | pub fn createStubHelperAtom(self: *MachO) !*Atom { | 1633 | pub fn createStubHelperAtom(self: *MachO) !*Atom { |
| 1527 | const gpa = self.base.allocator; | 1634 | const gpa = self.base.allocator; |
| 1528 | const arch = self.base.options.target.cpu.arch; | 1635 | const arch = self.base.options.target.cpu.arch; |
| 1529 | const stub_size: u4 = switch (arch) { | 1636 | const size: u4 = switch (arch) { |
| 1530 | .x86_64 => 10, | 1637 | .x86_64 => 10, |
| 1531 | .aarch64 => 3 * @sizeOf(u32), | 1638 | .aarch64 => 3 * @sizeOf(u32), |
| 1532 | else => unreachable, | 1639 | else => unreachable, |
| ... | @@ -1537,52 +1644,92 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { | ... | @@ -1537,52 +1644,92 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { |
| 1537 | else => unreachable, | 1644 | else => unreachable, |
| 1538 | }; | 1645 | }; |
| 1539 | const sym_index = try self.allocateSymbol(); | 1646 | const sym_index = try self.allocateSymbol(); |
| 1540 | const atom = try MachO.createEmptyAtom(gpa, sym_index, stub_size, alignment); | 1647 | const atom = switch (self.mode) { |
| | 1648 | .incremental => blk: { |
| | 1649 | const atom = try gpa.create(Atom); |
| | 1650 | atom.* = Atom.empty; |
| | 1651 | atom.sym_index = sym_index; |
| | 1652 | atom.size = size; |
| | 1653 | atom.alignment = alignment; |
| | 1654 | break :blk atom; |
| | 1655 | }, |
| | 1656 | .one_shot => try MachO.createEmptyAtom(gpa, sym_index, size, alignment), |
| | 1657 | }; |
| | 1658 | errdefer gpa.destroy(atom); |
| | 1659 | |
| 1541 | const sym = atom.getSymbolPtr(self); | 1660 | const sym = atom.getSymbolPtr(self); |
| 1542 | sym.n_type = macho.N_SECT; | 1661 | sym.n_type = macho.N_SECT; |
| 1543 | sym.n_sect = self.stub_helper_section_index.? + 1; | 1662 | sym.n_sect = self.stub_helper_section_index.? + 1; |
| 1544 | | 1663 | |
| 1545 | try atom.relocs.ensureTotalCapacity(gpa, 1); | 1664 | const code = try gpa.alloc(u8, size); |
| | 1665 | defer gpa.free(code); |
| | 1666 | mem.set(u8, code, 0); |
| 1546 | | 1667 | |
| 1547 | switch (arch) { | 1668 | switch (arch) { |
| 1548 | .x86_64 => { | 1669 | .x86_64 => { |
| 1549 | // pushq | 1670 | // pushq |
| 1550 | atom.code.items[0] = 0x68; | 1671 | code[0] = 0x68; |
| 1551 | // Next 4 bytes 1..4 are just a placeholder populated in `populateLazyBindOffsetsInStubHelper`. | 1672 | // Next 4 bytes 1..4 are just a placeholder populated in `populateLazyBindOffsetsInStubHelper`. |
| 1552 | // jmpq | 1673 | // jmpq |
| 1553 | atom.code.items[5] = 0xe9; | 1674 | code[5] = 0xe9; |
| 1554 | atom.relocs.appendAssumeCapacity(.{ | 1675 | |
| 1555 | .offset = 6, | 1676 | if (self.mode == .incremental) { |
| 1556 | .target = .{ .sym_index = self.stub_helper_preamble_atom.?.sym_index, .file = null }, | 1677 | try atom.addRelocation(self, .{ |
| 1557 | .addend = 0, | 1678 | .@"type" = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_BRANCH), |
| 1558 | .subtractor = null, | 1679 | .target = .{ .sym_index = self.stub_helper_preamble_atom.?.sym_index, .file = null }, |
| 1559 | .pcrel = true, | 1680 | .offset = 6, |
| 1560 | .length = 2, | 1681 | .addend = 0, |
| 1561 | .@"type" = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_BRANCH), | 1682 | .pcrel = true, |
| 1562 | }); | 1683 | .length = 2, |
| | 1684 | }); |
| | 1685 | } else { |
| | 1686 | try atom.relocs.ensureTotalCapacity(gpa, 1); |
| | 1687 | atom.relocs.appendAssumeCapacity(.{ |
| | 1688 | .offset = 6, |
| | 1689 | .target = .{ .sym_index = self.stub_helper_preamble_atom.?.sym_index, .file = null }, |
| | 1690 | .addend = 0, |
| | 1691 | .subtractor = null, |
| | 1692 | .pcrel = true, |
| | 1693 | .length = 2, |
| | 1694 | .@"type" = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_BRANCH), |
| | 1695 | }); |
| | 1696 | } |
| 1563 | }, | 1697 | }, |
| 1564 | .aarch64 => { | 1698 | .aarch64 => { |
| 1565 | const literal = blk: { | 1699 | const literal = blk: { |
| 1566 | const div_res = try math.divExact(u64, stub_size - @sizeOf(u32), 4); | 1700 | const div_res = try math.divExact(u64, size - @sizeOf(u32), 4); |
| 1567 | break :blk math.cast(u18, div_res) orelse return error.Overflow; | 1701 | break :blk math.cast(u18, div_res) orelse return error.Overflow; |
| 1568 | }; | 1702 | }; |
| 1569 | // ldr w16, literal | 1703 | // ldr w16, literal |
| 1570 | mem.writeIntLittle(u32, atom.code.items[0..4], aarch64.Instruction.ldrLiteral( | 1704 | mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.ldrLiteral( |
| 1571 | .w16, | 1705 | .w16, |
| 1572 | literal, | 1706 | literal, |
| 1573 | ).toU32()); | 1707 | ).toU32()); |
| 1574 | // b disp | 1708 | // b disp |
| 1575 | mem.writeIntLittle(u32, atom.code.items[4..8], aarch64.Instruction.b(0).toU32()); | 1709 | mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.b(0).toU32()); |
| 1576 | atom.relocs.appendAssumeCapacity(.{ | | |
| 1577 | .offset = 4, | | |
| 1578 | .target = .{ .sym_index = self.stub_helper_preamble_atom.?.sym_index, .file = null }, | | |
| 1579 | .addend = 0, | | |
| 1580 | .subtractor = null, | | |
| 1581 | .pcrel = true, | | |
| 1582 | .length = 2, | | |
| 1583 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_BRANCH26), | | |
| 1584 | }); | | |
| 1585 | // Next 4 bytes 8..12 are just a placeholder populated in `populateLazyBindOffsetsInStubHelper`. | 1710 | // Next 4 bytes 8..12 are just a placeholder populated in `populateLazyBindOffsetsInStubHelper`. |
| | 1711 | |
| | 1712 | if (self.mode == .incremental) { |
| | 1713 | try atom.addRelocation(self, .{ |
| | 1714 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_BRANCH26), |
| | 1715 | .target = .{ .sym_index = self.stub_helper_preamble_atom.?.sym_index, .file = null }, |
| | 1716 | .offset = 4, |
| | 1717 | .addend = 0, |
| | 1718 | .pcrel = true, |
| | 1719 | .length = 2, |
| | 1720 | }); |
| | 1721 | } else { |
| | 1722 | try atom.relocs.ensureTotalCapacity(gpa, 1); |
| | 1723 | atom.relocs.appendAssumeCapacity(.{ |
| | 1724 | .offset = 4, |
| | 1725 | .target = .{ .sym_index = self.stub_helper_preamble_atom.?.sym_index, .file = null }, |
| | 1726 | .addend = 0, |
| | 1727 | .subtractor = null, |
| | 1728 | .pcrel = true, |
| | 1729 | .length = 2, |
| | 1730 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_BRANCH26), |
| | 1731 | }); |
| | 1732 | } |
| 1586 | }, | 1733 | }, |
| 1587 | else => unreachable, | 1734 | else => unreachable, |
| 1588 | } | 1735 | } |
| ... | @@ -1590,7 +1737,14 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { | ... | @@ -1590,7 +1737,14 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { |
| 1590 | try self.managed_atoms.append(gpa, atom); | 1737 | try self.managed_atoms.append(gpa, atom); |
| 1591 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); | 1738 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); |
| 1592 | | 1739 | |
| 1593 | try self.allocateAtomCommon(atom); | 1740 | if (self.mode == .incremental) { |
| | 1741 | sym.n_value = try self.allocateAtom(atom, size, math.powi(u32, 2, alignment) catch unreachable); |
| | 1742 | log.debug("allocated stub helper atom at 0x{x}", .{sym.n_value}); |
| | 1743 | try self.writeAtom(atom, code); |
| | 1744 | } else { |
| | 1745 | mem.copy(u8, atom.code.items, code); |
| | 1746 | try self.addAtomToSection(atom); |
| | 1747 | } |
| 1594 | | 1748 | |
| 1595 | return atom; | 1749 | return atom; |
| 1596 | } | 1750 | } |
| ... | @@ -1598,36 +1752,73 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { | ... | @@ -1598,36 +1752,73 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { |
| 1598 | pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWithLoc) !*Atom { | 1752 | pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWithLoc) !*Atom { |
| 1599 | const gpa = self.base.allocator; | 1753 | const gpa = self.base.allocator; |
| 1600 | const sym_index = try self.allocateSymbol(); | 1754 | const sym_index = try self.allocateSymbol(); |
| 1601 | const atom = try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3); | 1755 | const atom = switch (self.mode) { |
| | 1756 | .incremental => blk: { |
| | 1757 | const atom = try gpa.create(Atom); |
| | 1758 | atom.* = Atom.empty; |
| | 1759 | atom.sym_index = sym_index; |
| | 1760 | atom.size = @sizeOf(u64); |
| | 1761 | atom.alignment = 3; |
| | 1762 | break :blk atom; |
| | 1763 | }, |
| | 1764 | .one_shot => try MachO.createEmptyAtom(gpa, sym_index, @sizeOf(u64), 3), |
| | 1765 | }; |
| | 1766 | errdefer gpa.destroy(atom); |
| | 1767 | |
| 1602 | const sym = atom.getSymbolPtr(self); | 1768 | const sym = atom.getSymbolPtr(self); |
| 1603 | sym.n_type = macho.N_SECT; | 1769 | sym.n_type = macho.N_SECT; |
| 1604 | sym.n_sect = self.la_symbol_ptr_section_index.? + 1; | 1770 | sym.n_sect = self.la_symbol_ptr_section_index.? + 1; |
| 1605 | | 1771 | |
| 1606 | try atom.relocs.append(gpa, .{ | 1772 | if (self.mode == .incremental) { |
| 1607 | .offset = 0, | 1773 | try atom.addRelocation(self, .{ |
| 1608 | .target = .{ .sym_index = stub_sym_index, .file = null }, | 1774 | .@"type" = switch (self.base.options.target.cpu.arch) { |
| 1609 | .addend = 0, | 1775 | .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED), |
| 1610 | .subtractor = null, | 1776 | .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED), |
| 1611 | .pcrel = false, | 1777 | else => unreachable, |
| 1612 | .length = 3, | 1778 | }, |
| 1613 | .@"type" = switch (self.base.options.target.cpu.arch) { | 1779 | .target = .{ .sym_index = stub_sym_index, .file = null }, |
| 1614 | .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED), | 1780 | .offset = 0, |
| 1615 | .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED), | 1781 | .addend = 0, |
| 1616 | else => unreachable, | 1782 | .pcrel = false, |
| 1617 | }, | 1783 | .length = 3, |
| 1618 | }); | 1784 | }); |
| 1619 | try atom.rebases.append(gpa, 0); | 1785 | try atom.addRebase(self, 0); |
| 1620 | | 1786 | try atom.addLazyBinding(self, .{ |
| 1621 | const global = self.getGlobal(self.getSymbolName(target)).?; | 1787 | .target = self.getGlobal(self.getSymbolName(target)).?, |
| 1622 | try atom.lazy_bindings.append(gpa, .{ | 1788 | .offset = 0, |
| 1623 | .target = global, | 1789 | }); |
| 1624 | .offset = 0, | 1790 | } else { |
| 1625 | }); | 1791 | try atom.relocs.append(gpa, .{ |
| | 1792 | .offset = 0, |
| | 1793 | .target = .{ .sym_index = stub_sym_index, .file = null }, |
| | 1794 | .addend = 0, |
| | 1795 | .subtractor = null, |
| | 1796 | .pcrel = false, |
| | 1797 | .length = 3, |
| | 1798 | .@"type" = switch (self.base.options.target.cpu.arch) { |
| | 1799 | .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED), |
| | 1800 | .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED), |
| | 1801 | else => unreachable, |
| | 1802 | }, |
| | 1803 | }); |
| | 1804 | try atom.rebases.append(gpa, 0); |
| | 1805 | const global = self.getGlobal(self.getSymbolName(target)).?; |
| | 1806 | try atom.lazy_bindings.append(gpa, .{ |
| | 1807 | .target = global, |
| | 1808 | .offset = 0, |
| | 1809 | }); |
| | 1810 | } |
| 1626 | | 1811 | |
| 1627 | try self.managed_atoms.append(gpa, atom); | 1812 | try self.managed_atoms.append(gpa, atom); |
| 1628 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); | 1813 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); |
| 1629 | | 1814 | |
| 1630 | try self.allocateAtomCommon(atom); | 1815 | if (self.mode == .incremental) { |
| | 1816 | sym.n_value = try self.allocateAtom(atom, atom.size, @alignOf(u64)); |
| | 1817 | log.debug("allocated lazy pointer atom at 0x{x}", .{sym.n_value}); |
| | 1818 | try self.writePtrWidthAtom(atom); |
| | 1819 | } else { |
| | 1820 | try self.addAtomToSection(atom); |
| | 1821 | } |
| 1631 | | 1822 | |
| 1632 | return atom; | 1823 | return atom; |
| 1633 | } | 1824 | } |
| ... | @@ -1640,62 +1831,112 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom { | ... | @@ -1640,62 +1831,112 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom { |
| 1640 | .aarch64 => 2, | 1831 | .aarch64 => 2, |
| 1641 | else => unreachable, // unhandled architecture type | 1832 | else => unreachable, // unhandled architecture type |
| 1642 | }; | 1833 | }; |
| 1643 | const stub_size: u4 = switch (arch) { | 1834 | const size: u4 = switch (arch) { |
| 1644 | .x86_64 => 6, | 1835 | .x86_64 => 6, |
| 1645 | .aarch64 => 3 * @sizeOf(u32), | 1836 | .aarch64 => 3 * @sizeOf(u32), |
| 1646 | else => unreachable, // unhandled architecture type | 1837 | else => unreachable, // unhandled architecture type |
| 1647 | }; | 1838 | }; |
| 1648 | const sym_index = try self.allocateSymbol(); | 1839 | const sym_index = try self.allocateSymbol(); |
| 1649 | const atom = try MachO.createEmptyAtom(gpa, sym_index, stub_size, alignment); | 1840 | const atom = switch (self.mode) { |
| | 1841 | .incremental => blk: { |
| | 1842 | const atom = try gpa.create(Atom); |
| | 1843 | atom.* = Atom.empty; |
| | 1844 | atom.sym_index = sym_index; |
| | 1845 | atom.size = size; |
| | 1846 | atom.alignment = alignment; |
| | 1847 | break :blk atom; |
| | 1848 | }, |
| | 1849 | .one_shot => try MachO.createEmptyAtom(gpa, sym_index, size, alignment), |
| | 1850 | }; |
| | 1851 | errdefer gpa.destroy(atom); |
| | 1852 | |
| 1650 | const sym = atom.getSymbolPtr(self); | 1853 | const sym = atom.getSymbolPtr(self); |
| 1651 | sym.n_type = macho.N_SECT; | 1854 | sym.n_type = macho.N_SECT; |
| 1652 | sym.n_sect = self.stubs_section_index.? + 1; | 1855 | sym.n_sect = self.stubs_section_index.? + 1; |
| 1653 | | 1856 | |
| | 1857 | const code = try gpa.alloc(u8, size); |
| | 1858 | defer gpa.free(code); |
| | 1859 | mem.set(u8, code, 0); |
| | 1860 | |
| 1654 | switch (arch) { | 1861 | switch (arch) { |
| 1655 | .x86_64 => { | 1862 | .x86_64 => { |
| 1656 | // jmp | 1863 | // jmp |
| 1657 | atom.code.items[0] = 0xff; | 1864 | code[0] = 0xff; |
| 1658 | atom.code.items[1] = 0x25; | 1865 | code[1] = 0x25; |
| 1659 | try atom.relocs.append(gpa, .{ | 1866 | |
| 1660 | .offset = 2, | 1867 | if (self.mode == .incremental) { |
| 1661 | .target = .{ .sym_index = laptr_sym_index, .file = null }, | 1868 | try atom.addRelocation(self, .{ |
| 1662 | .addend = 0, | 1869 | .@"type" = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_BRANCH), |
| 1663 | .subtractor = null, | 1870 | .target = .{ .sym_index = laptr_sym_index, .file = null }, |
| 1664 | .pcrel = true, | 1871 | .offset = 2, |
| 1665 | .length = 2, | 1872 | .addend = 0, |
| 1666 | .@"type" = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_BRANCH), | 1873 | .pcrel = true, |
| 1667 | }); | 1874 | .length = 2, |
| | 1875 | }); |
| | 1876 | } else { |
| | 1877 | try atom.relocs.append(gpa, .{ |
| | 1878 | .offset = 2, |
| | 1879 | .target = .{ .sym_index = laptr_sym_index, .file = null }, |
| | 1880 | .addend = 0, |
| | 1881 | .subtractor = null, |
| | 1882 | .pcrel = true, |
| | 1883 | .length = 2, |
| | 1884 | .@"type" = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_BRANCH), |
| | 1885 | }); |
| | 1886 | } |
| 1668 | }, | 1887 | }, |
| 1669 | .aarch64 => { | 1888 | .aarch64 => { |
| 1670 | try atom.relocs.ensureTotalCapacity(gpa, 2); | | |
| 1671 | // adrp x16, pages | 1889 | // adrp x16, pages |
| 1672 | mem.writeIntLittle(u32, atom.code.items[0..4], aarch64.Instruction.adrp(.x16, 0).toU32()); | 1890 | mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adrp(.x16, 0).toU32()); |
| 1673 | atom.relocs.appendAssumeCapacity(.{ | | |
| 1674 | .offset = 0, | | |
| 1675 | .target = .{ .sym_index = laptr_sym_index, .file = null }, | | |
| 1676 | .addend = 0, | | |
| 1677 | .subtractor = null, | | |
| 1678 | .pcrel = true, | | |
| 1679 | .length = 2, | | |
| 1680 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21), | | |
| 1681 | }); | | |
| 1682 | // ldr x16, x16, offset | 1891 | // ldr x16, x16, offset |
| 1683 | mem.writeIntLittle(u32, atom.code.items[4..8], aarch64.Instruction.ldr( | 1892 | mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.ldr( |
| 1684 | .x16, | 1893 | .x16, |
| 1685 | .x16, | 1894 | .x16, |
| 1686 | aarch64.Instruction.LoadStoreOffset.imm(0), | 1895 | aarch64.Instruction.LoadStoreOffset.imm(0), |
| 1687 | ).toU32()); | 1896 | ).toU32()); |
| 1688 | atom.relocs.appendAssumeCapacity(.{ | | |
| 1689 | .offset = 4, | | |
| 1690 | .target = .{ .sym_index = laptr_sym_index, .file = null }, | | |
| 1691 | .addend = 0, | | |
| 1692 | .subtractor = null, | | |
| 1693 | .pcrel = false, | | |
| 1694 | .length = 2, | | |
| 1695 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGEOFF12), | | |
| 1696 | }); | | |
| 1697 | // br x16 | 1897 | // br x16 |
| 1698 | mem.writeIntLittle(u32, atom.code.items[8..12], aarch64.Instruction.br(.x16).toU32()); | 1898 | mem.writeIntLittle(u32, code[8..12], aarch64.Instruction.br(.x16).toU32()); |
| | 1899 | |
| | 1900 | if (self.mode == .incremental) { |
| | 1901 | try atom.addRelocations(self, 2, .{ |
| | 1902 | .{ |
| | 1903 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21), |
| | 1904 | .target = .{ .sym_index = laptr_sym_index, .file = null }, |
| | 1905 | .offset = 0, |
| | 1906 | .addend = 0, |
| | 1907 | .pcrel = true, |
| | 1908 | .length = 2, |
| | 1909 | }, |
| | 1910 | .{ |
| | 1911 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGEOFF12), |
| | 1912 | .target = .{ .sym_index = laptr_sym_index, .file = null }, |
| | 1913 | .offset = 4, |
| | 1914 | .addend = 0, |
| | 1915 | .pcrel = false, |
| | 1916 | .length = 2, |
| | 1917 | }, |
| | 1918 | }); |
| | 1919 | } else { |
| | 1920 | try atom.relocs.ensureTotalCapacity(gpa, 2); |
| | 1921 | atom.relocs.appendAssumeCapacity(.{ |
| | 1922 | .offset = 0, |
| | 1923 | .target = .{ .sym_index = laptr_sym_index, .file = null }, |
| | 1924 | .addend = 0, |
| | 1925 | .subtractor = null, |
| | 1926 | .pcrel = true, |
| | 1927 | .length = 2, |
| | 1928 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21), |
| | 1929 | }); |
| | 1930 | atom.relocs.appendAssumeCapacity(.{ |
| | 1931 | .offset = 4, |
| | 1932 | .target = .{ .sym_index = laptr_sym_index, .file = null }, |
| | 1933 | .addend = 0, |
| | 1934 | .subtractor = null, |
| | 1935 | .pcrel = false, |
| | 1936 | .length = 2, |
| | 1937 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGEOFF12), |
| | 1938 | }); |
| | 1939 | } |
| 1699 | }, | 1940 | }, |
| 1700 | else => unreachable, | 1941 | else => unreachable, |
| 1701 | } | 1942 | } |
| ... | @@ -1703,7 +1944,14 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom { | ... | @@ -1703,7 +1944,14 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom { |
| 1703 | try self.managed_atoms.append(gpa, atom); | 1944 | try self.managed_atoms.append(gpa, atom); |
| 1704 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); | 1945 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); |
| 1705 | | 1946 | |
| 1706 | try self.allocateAtomCommon(atom); | 1947 | if (self.mode == .incremental) { |
| | 1948 | sym.n_value = try self.allocateAtom(atom, size, math.powi(u32, 2, alignment) catch unreachable); |
| | 1949 | log.debug("allocated stub atom at 0x{x}", .{sym.n_value}); |
| | 1950 | try self.writeAtom(atom, code); |
| | 1951 | } else { |
| | 1952 | mem.copy(u8, atom.code.items, code); |
| | 1953 | try self.addAtomToSection(atom); |
| | 1954 | } |
| 1707 | | 1955 | |
| 1708 | return atom; | 1956 | return atom; |
| 1709 | } | 1957 | } |
| ... | @@ -1976,6 +2224,7 @@ pub fn resolveSymbolsInDylibs(self: *MachO) !void { | ... | @@ -1976,6 +2224,7 @@ pub fn resolveSymbolsInDylibs(self: *MachO) !void { |
| 1976 | const laptr_atom = try self.createLazyPointerAtom(stub_helper_atom.sym_index, global); | 2224 | const laptr_atom = try self.createLazyPointerAtom(stub_helper_atom.sym_index, global); |
| 1977 | const stub_atom = try self.createStubAtom(laptr_atom.sym_index); | 2225 | const stub_atom = try self.createStubAtom(laptr_atom.sym_index); |
| 1978 | self.stubs.items[stub_index].sym_index = stub_atom.sym_index; | 2226 | self.stubs.items[stub_index].sym_index = stub_atom.sym_index; |
| | 2227 | self.markRelocsDirtyByTarget(global); |
| 1979 | } | 2228 | } |
| 1980 | | 2229 | |
| 1981 | continue :loop; | 2230 | continue :loop; |
| ... | @@ -2073,6 +2322,10 @@ pub fn resolveDyldStubBinder(self: *MachO) !void { | ... | @@ -2073,6 +2322,10 @@ pub fn resolveDyldStubBinder(self: *MachO) !void { |
| 2073 | const got_index = try self.allocateGotEntry(global); | 2322 | const got_index = try self.allocateGotEntry(global); |
| 2074 | const got_atom = try self.createGotAtom(global); | 2323 | const got_atom = try self.createGotAtom(global); |
| 2075 | self.got_entries.items[got_index].sym_index = got_atom.sym_index; | 2324 | self.got_entries.items[got_index].sym_index = got_atom.sym_index; |
| | 2325 | |
| | 2326 | if (self.mode == .incremental) { |
| | 2327 | try self.writePtrWidthAtom(got_atom); |
| | 2328 | } |
| 2076 | } | 2329 | } |
| 2077 | | 2330 | |
| 2078 | pub fn writeDylinkerLC(ncmds: *u32, lc_writer: anytype) !void { | 2331 | pub fn writeDylinkerLC(ncmds: *u32, lc_writer: anytype) !void { |
| ... | @@ -2356,6 +2609,30 @@ pub fn deinit(self: *MachO) void { | ... | @@ -2356,6 +2609,30 @@ pub fn deinit(self: *MachO) void { |
| 2356 | } | 2609 | } |
| 2357 | self.relocs.deinit(gpa); | 2610 | self.relocs.deinit(gpa); |
| 2358 | } | 2611 | } |
| | 2612 | |
| | 2613 | { |
| | 2614 | var it = self.rebases.valueIterator(); |
| | 2615 | while (it.next()) |rebases| { |
| | 2616 | rebases.deinit(gpa); |
| | 2617 | } |
| | 2618 | self.rebases.deinit(gpa); |
| | 2619 | } |
| | 2620 | |
| | 2621 | { |
| | 2622 | var it = self.bindings.valueIterator(); |
| | 2623 | while (it.next()) |bindings| { |
| | 2624 | bindings.deinit(gpa); |
| | 2625 | } |
| | 2626 | self.bindings.deinit(gpa); |
| | 2627 | } |
| | 2628 | |
| | 2629 | { |
| | 2630 | var it = self.lazy_bindings.valueIterator(); |
| | 2631 | while (it.next()) |bindings| { |
| | 2632 | bindings.deinit(gpa); |
| | 2633 | } |
| | 2634 | self.lazy_bindings.deinit(gpa); |
| | 2635 | } |
| 2359 | } | 2636 | } |
| 2360 | | 2637 | |
| 2361 | fn freeAtom(self: *MachO, atom: *Atom, owns_atom: bool) void { | 2638 | fn freeAtom(self: *MachO, atom: *Atom, owns_atom: bool) void { |
| ... | @@ -2363,6 +2640,8 @@ fn freeAtom(self: *MachO, atom: *Atom, owns_atom: bool) void { | ... | @@ -2363,6 +2640,8 @@ fn freeAtom(self: *MachO, atom: *Atom, owns_atom: bool) void { |
| 2363 | if (!owns_atom) { | 2640 | if (!owns_atom) { |
| 2364 | atom.deinit(self.base.allocator); | 2641 | atom.deinit(self.base.allocator); |
| 2365 | } | 2642 | } |
| | 2643 | // Remove any relocs and base relocs associated with this Atom |
| | 2644 | self.freeRelocationsForAtom(atom); |
| 2366 | | 2645 | |
| 2367 | const sect_id = atom.getSymbol(self).n_sect - 1; | 2646 | const sect_id = atom.getSymbol(self).n_sect - 1; |
| 2368 | const free_list = &self.sections.items(.free_list)[sect_id]; | 2647 | const free_list = &self.sections.items(.free_list)[sect_id]; |
| ... | @@ -2569,13 +2848,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv | ... | @@ -2569,13 +2848,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv |
| 2569 | const decl_index = func.owner_decl; | 2848 | const decl_index = func.owner_decl; |
| 2570 | const decl = module.declPtr(decl_index); | 2849 | const decl = module.declPtr(decl_index); |
| 2571 | self.freeUnnamedConsts(decl_index); | 2850 | self.freeUnnamedConsts(decl_index); |
| 2572 | | 2851 | self.freeRelocationsForAtom(&decl.link.macho); |
| 2573 | // TODO clearing the code and relocs buffer should probably be orchestrated | | |
| 2574 | // in a different, smarter, more automatic way somewhere else, in a more centralised | | |
| 2575 | // way than this. | | |
| 2576 | // If we don't clear the buffers here, we are up for some nasty surprises when | | |
| 2577 | // this atom is reused later on and was not freed by freeAtom(). | | |
| 2578 | decl.link.macho.clearRetainingCapacity(); | | |
| 2579 | | 2852 | |
| 2580 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | 2853 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 2581 | defer code_buffer.deinit(); | 2854 | defer code_buffer.deinit(); |
| ... | @@ -2593,18 +2866,16 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv | ... | @@ -2593,18 +2866,16 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv |
| 2593 | else | 2866 | else |
| 2594 | try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none); | 2867 | try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none); |
| 2595 | | 2868 | |
| 2596 | switch (res) { | 2869 | const code = switch (res) { |
| 2597 | .appended => { | 2870 | .appended => code_buffer.items, |
| 2598 | try decl.link.macho.code.appendSlice(self.base.allocator, code_buffer.items); | | |
| 2599 | }, | | |
| 2600 | .fail => |em| { | 2871 | .fail => |em| { |
| 2601 | decl.analysis = .codegen_failure; | 2872 | decl.analysis = .codegen_failure; |
| 2602 | try module.failed_decls.put(module.gpa, decl_index, em); | 2873 | try module.failed_decls.put(module.gpa, decl_index, em); |
| 2603 | return; | 2874 | return; |
| 2604 | }, | 2875 | }, |
| 2605 | } | 2876 | }; |
| 2606 | | 2877 | |
| 2607 | const addr = try self.placeDecl(decl_index, decl.link.macho.code.items.len); | 2878 | const addr = try self.updateDeclCode(decl_index, code); |
| 2608 | | 2879 | |
| 2609 | if (decl_state) |*ds| { | 2880 | if (decl_state) |*ds| { |
| 2610 | try self.d_sym.?.dwarf.commitDeclState( | 2881 | try self.d_sym.?.dwarf.commitDeclState( |
| ... | @@ -2650,20 +2921,17 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu | ... | @@ -2650,20 +2921,17 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu |
| 2650 | | 2921 | |
| 2651 | log.debug("allocating symbol indexes for {?s}", .{name}); | 2922 | log.debug("allocating symbol indexes for {?s}", .{name}); |
| 2652 | | 2923 | |
| 2653 | const required_alignment = typed_value.ty.abiAlignment(self.base.options.target); | 2924 | const atom = try gpa.create(Atom); |
| 2654 | const sym_index = try self.allocateSymbol(); | 2925 | errdefer gpa.destroy(atom); |
| 2655 | const atom = try MachO.createEmptyAtom( | 2926 | atom.* = Atom.empty; |
| 2656 | gpa, | 2927 | |
| 2657 | sym_index, | 2928 | atom.sym_index = try self.allocateSymbol(); |
| 2658 | @sizeOf(u64), | | |
| 2659 | math.log2(required_alignment), | | |
| 2660 | ); | | |
| 2661 | | 2929 | |
| 2662 | try self.managed_atoms.append(gpa, atom); | 2930 | try self.managed_atoms.append(gpa, atom); |
| 2663 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); | 2931 | try self.atom_by_index_table.putNoClobber(gpa, atom.sym_index, atom); |
| 2664 | | 2932 | |
| 2665 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .none, .{ | 2933 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .none, .{ |
| 2666 | .parent_atom_index = sym_index, | 2934 | .parent_atom_index = atom.sym_index, |
| 2667 | }); | 2935 | }); |
| 2668 | const code = switch (res) { | 2936 | const code = switch (res) { |
| 2669 | .externally_managed => |x| x, | 2937 | .externally_managed => |x| x, |
| ... | @@ -2676,9 +2944,9 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu | ... | @@ -2676,9 +2944,9 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu |
| 2676 | }, | 2944 | }, |
| 2677 | }; | 2945 | }; |
| 2678 | | 2946 | |
| 2679 | atom.code.clearRetainingCapacity(); | 2947 | const required_alignment = typed_value.ty.abiAlignment(self.base.options.target); |
| 2680 | try atom.code.appendSlice(gpa, code); | 2948 | atom.size = code.len; |
| 2681 | | 2949 | atom.alignment = math.log2(required_alignment); |
| 2682 | const sect_id = try self.getOutputSectionAtom( | 2950 | const sect_id = try self.getOutputSectionAtom( |
| 2683 | atom, | 2951 | atom, |
| 2684 | decl_name, | 2952 | decl_name, |
| ... | @@ -2691,13 +2959,14 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu | ... | @@ -2691,13 +2959,14 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu |
| 2691 | symbol.n_type = macho.N_SECT; | 2959 | symbol.n_type = macho.N_SECT; |
| 2692 | symbol.n_sect = sect_id + 1; | 2960 | symbol.n_sect = sect_id + 1; |
| 2693 | symbol.n_value = try self.allocateAtom(atom, code.len, required_alignment); | 2961 | symbol.n_value = try self.allocateAtom(atom, code.len, required_alignment); |
| | 2962 | errdefer self.freeAtom(atom, true); |
| | 2963 | |
| | 2964 | try unnamed_consts.append(gpa, atom); |
| 2694 | | 2965 | |
| 2695 | log.debug("allocated atom for {?s} at 0x{x}", .{ name, symbol.n_value }); | 2966 | log.debug("allocated atom for {?s} at 0x{x}", .{ name, symbol.n_value }); |
| 2696 | log.debug(" (required alignment 0x{x})", .{required_alignment}); | 2967 | log.debug(" (required alignment 0x{x})", .{required_alignment}); |
| 2697 | | 2968 | |
| 2698 | errdefer self.freeAtom(atom, true); | 2969 | try self.writeAtom(atom, code); |
| 2699 | | | |
| 2700 | try unnamed_consts.append(gpa, atom); | | |
| 2701 | | 2970 | |
| 2702 | return atom.sym_index; | 2971 | return atom.sym_index; |
| 2703 | } | 2972 | } |
| ... | @@ -2724,6 +2993,8 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index) | ... | @@ -2724,6 +2993,8 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index) |
| 2724 | } | 2993 | } |
| 2725 | } | 2994 | } |
| 2726 | | 2995 | |
| | 2996 | self.freeRelocationsForAtom(&decl.link.macho); |
| | 2997 | |
| 2727 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | 2998 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 2728 | defer code_buffer.deinit(); | 2999 | defer code_buffer.deinit(); |
| 2729 | | 3000 | |
| ... | @@ -2751,27 +3022,16 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index) | ... | @@ -2751,27 +3022,16 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index) |
| 2751 | .parent_atom_index = decl.link.macho.sym_index, | 3022 | .parent_atom_index = decl.link.macho.sym_index, |
| 2752 | }); | 3023 | }); |
| 2753 | | 3024 | |
| 2754 | const code = blk: { | 3025 | const code = switch (res) { |
| 2755 | switch (res) { | 3026 | .externally_managed => |x| x, |
| 2756 | .externally_managed => |x| break :blk x, | 3027 | .appended => code_buffer.items, |
| 2757 | .appended => { | 3028 | .fail => |em| { |
| 2758 | // TODO clearing the code and relocs buffer should probably be orchestrated | 3029 | decl.analysis = .codegen_failure; |
| 2759 | // in a different, smarter, more automatic way somewhere else, in a more centralised | 3030 | try module.failed_decls.put(module.gpa, decl_index, em); |
| 2760 | // way than this. | 3031 | return; |
| 2761 | // If we don't clear the buffers here, we are up for some nasty surprises when | 3032 | }, |
| 2762 | // this atom is reused later on and was not freed by freeAtom(). | | |
| 2763 | decl.link.macho.code.clearAndFree(self.base.allocator); | | |
| 2764 | try decl.link.macho.code.appendSlice(self.base.allocator, code_buffer.items); | | |
| 2765 | break :blk decl.link.macho.code.items; | | |
| 2766 | }, | | |
| 2767 | .fail => |em| { | | |
| 2768 | decl.analysis = .codegen_failure; | | |
| 2769 | try module.failed_decls.put(module.gpa, decl_index, em); | | |
| 2770 | return; | | |
| 2771 | }, | | |
| 2772 | } | | |
| 2773 | }; | 3033 | }; |
| 2774 | const addr = try self.placeDecl(decl_index, code.len); | 3034 | const addr = try self.updateDeclCode(decl_index, code); |
| 2775 | | 3035 | |
| 2776 | if (decl_state) |*ds| { | 3036 | if (decl_state) |*ds| { |
| 2777 | try self.d_sym.?.dwarf.commitDeclState( | 3037 | try self.d_sym.?.dwarf.commitDeclState( |
| ... | @@ -2936,19 +3196,22 @@ fn getOutputSectionAtom( | ... | @@ -2936,19 +3196,22 @@ fn getOutputSectionAtom( |
| 2936 | return sect_id; | 3196 | return sect_id; |
| 2937 | } | 3197 | } |
| 2938 | | 3198 | |
| 2939 | fn placeDecl(self: *MachO, decl_index: Module.Decl.Index, code_len: usize) !u64 { | 3199 | fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8) !u64 { |
| 2940 | const module = self.base.options.module.?; | 3200 | const gpa = self.base.allocator; |
| 2941 | const decl = module.declPtr(decl_index); | 3201 | const mod = self.base.options.module.?; |
| | 3202 | const decl = mod.declPtr(decl_index); |
| | 3203 | |
| 2942 | const required_alignment = decl.getAlignment(self.base.options.target); | 3204 | const required_alignment = decl.getAlignment(self.base.options.target); |
| 2943 | assert(decl.link.macho.sym_index != 0); // Caller forgot to call allocateDeclIndexes() | 3205 | assert(decl.link.macho.sym_index != 0); // Caller forgot to call allocateDeclIndexes() |
| 2944 | | 3206 | |
| 2945 | const sym_name = try decl.getFullyQualifiedName(module); | 3207 | const sym_name = try decl.getFullyQualifiedName(mod); |
| 2946 | defer self.base.allocator.free(sym_name); | 3208 | defer self.base.allocator.free(sym_name); |
| 2947 | | 3209 | |
| | 3210 | const atom = &decl.link.macho; |
| 2948 | const decl_ptr = self.decls.getPtr(decl_index).?; | 3211 | const decl_ptr = self.decls.getPtr(decl_index).?; |
| 2949 | if (decl_ptr.* == null) { | 3212 | if (decl_ptr.* == null) { |
| 2950 | decl_ptr.* = try self.getOutputSectionAtom( | 3213 | decl_ptr.* = try self.getOutputSectionAtom( |
| 2951 | &decl.link.macho, | 3214 | atom, |
| 2952 | sym_name, | 3215 | sym_name, |
| 2953 | decl.ty, | 3216 | decl.ty, |
| 2954 | decl.val, | 3217 | decl.val, |
| ... | @@ -2956,55 +3219,63 @@ fn placeDecl(self: *MachO, decl_index: Module.Decl.Index, code_len: usize) !u64 | ... | @@ -2956,55 +3219,63 @@ fn placeDecl(self: *MachO, decl_index: Module.Decl.Index, code_len: usize) !u64 |
| 2956 | ); | 3219 | ); |
| 2957 | } | 3220 | } |
| 2958 | const sect_id = decl_ptr.*.?; | 3221 | const sect_id = decl_ptr.*.?; |
| | 3222 | const code_len = code.len; |
| 2959 | | 3223 | |
| 2960 | if (decl.link.macho.size != 0) { | 3224 | if (atom.size != 0) { |
| 2961 | const symbol = decl.link.macho.getSymbolPtr(self); | 3225 | const sym = atom.getSymbolPtr(self); |
| 2962 | symbol.n_strx = try self.strtab.insert(self.base.allocator, sym_name); | 3226 | sym.n_strx = try self.strtab.insert(gpa, sym_name); |
| 2963 | symbol.n_type = macho.N_SECT; | 3227 | sym.n_type = macho.N_SECT; |
| 2964 | symbol.n_sect = sect_id + 1; | 3228 | sym.n_sect = sect_id + 1; |
| 2965 | symbol.n_desc = 0; | 3229 | sym.n_desc = 0; |
| 2966 | | 3230 | |
| 2967 | const capacity = decl.link.macho.capacity(self); | 3231 | const capacity = decl.link.macho.capacity(self); |
| 2968 | const need_realloc = code_len > capacity or !mem.isAlignedGeneric(u64, symbol.n_value, required_alignment); | 3232 | const need_realloc = code_len > capacity or !mem.isAlignedGeneric(u64, sym.n_value, required_alignment); |
| 2969 | | 3233 | |
| 2970 | if (need_realloc) { | 3234 | if (need_realloc) { |
| 2971 | const vaddr = try self.growAtom(&decl.link.macho, code_len, required_alignment); | 3235 | const vaddr = try self.growAtom(atom, code_len, required_alignment); |
| 2972 | log.debug("growing {s} and moving from 0x{x} to 0x{x}", .{ sym_name, symbol.n_value, vaddr }); | 3236 | log.debug("growing {s} and moving from 0x{x} to 0x{x}", .{ sym_name, sym.n_value, vaddr }); |
| 2973 | log.debug(" (required alignment 0x{x})", .{required_alignment}); | 3237 | log.debug(" (required alignment 0x{x})", .{required_alignment}); |
| 2974 | symbol.n_value = vaddr; | | |
| 2975 | | | |
| 2976 | const got_atom = self.getGotAtomForSymbol(.{ | | |
| 2977 | .sym_index = decl.link.macho.sym_index, | | |
| 2978 | .file = null, | | |
| 2979 | }).?; | | |
| 2980 | got_atom.dirty = true; | | |
| 2981 | } else if (code_len < decl.link.macho.size) { | | |
| 2982 | self.shrinkAtom(&decl.link.macho, code_len); | | |
| 2983 | } | | |
| 2984 | | 3238 | |
| 2985 | decl.link.macho.size = code_len; | 3239 | if (vaddr != sym.n_value) { |
| 2986 | decl.link.macho.dirty = true; | 3240 | sym.n_value = vaddr; |
| | 3241 | log.debug(" (updating GOT entry)", .{}); |
| | 3242 | const got_target = SymbolWithLoc{ .sym_index = atom.sym_index, .file = null }; |
| | 3243 | const got_atom = self.getGotAtomForSymbol(got_target).?; |
| | 3244 | self.markRelocsDirtyByTarget(got_target); |
| | 3245 | try self.writePtrWidthAtom(got_atom); |
| | 3246 | } |
| | 3247 | } else if (code_len < atom.size) { |
| | 3248 | self.shrinkAtom(atom, code_len); |
| | 3249 | } |
| | 3250 | atom.size = code_len; |
| 2987 | } else { | 3251 | } else { |
| 2988 | const name_str_index = try self.strtab.insert(self.base.allocator, sym_name); | 3252 | const name_str_index = try self.strtab.insert(gpa, sym_name); |
| 2989 | const symbol = decl.link.macho.getSymbolPtr(self); | 3253 | const sym = atom.getSymbolPtr(self); |
| 2990 | symbol.n_strx = name_str_index; | 3254 | sym.n_strx = name_str_index; |
| 2991 | symbol.n_type = macho.N_SECT; | 3255 | sym.n_type = macho.N_SECT; |
| 2992 | symbol.n_sect = sect_id + 1; | 3256 | sym.n_sect = sect_id + 1; |
| 2993 | symbol.n_desc = 0; | 3257 | sym.n_desc = 0; |
| 2994 | symbol.n_value = try self.allocateAtom(&decl.link.macho, code_len, required_alignment); | 3258 | |
| 2995 | | 3259 | const vaddr = try self.allocateAtom(atom, code_len, required_alignment); |
| 2996 | log.debug("allocated atom for {s} at 0x{x}", .{ sym_name, symbol.n_value }); | 3260 | errdefer self.freeAtom(atom, false); |
| | 3261 | |
| | 3262 | log.debug("allocated atom for {s} at 0x{x}", .{ sym_name, vaddr }); |
| 2997 | log.debug(" (required alignment 0x{x})", .{required_alignment}); | 3263 | log.debug(" (required alignment 0x{x})", .{required_alignment}); |
| 2998 | | 3264 | |
| 2999 | errdefer self.freeAtom(&decl.link.macho, false); | 3265 | atom.size = code_len; |
| | 3266 | sym.n_value = vaddr; |
| 3000 | | 3267 | |
| 3001 | const got_target = SymbolWithLoc{ .sym_index = decl.link.macho.sym_index, .file = null }; | 3268 | const got_target = SymbolWithLoc{ .sym_index = atom.sym_index, .file = null }; |
| 3002 | const got_index = try self.allocateGotEntry(got_target); | 3269 | const got_index = try self.allocateGotEntry(got_target); |
| 3003 | const got_atom = try self.createGotAtom(got_target); | 3270 | const got_atom = try self.createGotAtom(got_target); |
| 3004 | self.got_entries.items[got_index].sym_index = got_atom.sym_index; | 3271 | self.got_entries.items[got_index].sym_index = got_atom.sym_index; |
| | 3272 | try self.writePtrWidthAtom(got_atom); |
| 3005 | } | 3273 | } |
| 3006 | | 3274 | |
| 3007 | return decl.link.macho.getSymbol(self).n_value; | 3275 | self.markRelocsDirtyByTarget(atom.getSymbolWithLoc()); |
| | 3276 | try self.writeAtom(atom, code); |
| | 3277 | |
| | 3278 | return atom.getSymbol(self).n_value; |
| 3008 | } | 3279 | } |
| 3009 | | 3280 | |
| 3010 | pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void { | 3281 | pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void { |
| ... | @@ -3152,17 +3423,25 @@ pub fn deleteExport(self: *MachO, exp: Export) void { | ... | @@ -3152,17 +3423,25 @@ pub fn deleteExport(self: *MachO, exp: Export) void { |
| 3152 | } | 3423 | } |
| 3153 | } | 3424 | } |
| 3154 | | 3425 | |
| | 3426 | fn freeRelocationsForAtom(self: *MachO, atom: *Atom) void { |
| | 3427 | _ = self.relocs.remove(atom); |
| | 3428 | _ = self.rebases.remove(atom); |
| | 3429 | _ = self.bindings.remove(atom); |
| | 3430 | _ = self.lazy_bindings.remove(atom); |
| | 3431 | } |
| | 3432 | |
| 3155 | fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void { | 3433 | fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void { |
| | 3434 | const gpa = self.base.allocator; |
| 3156 | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; | 3435 | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; |
| 3157 | for (unnamed_consts.items) |atom| { | 3436 | for (unnamed_consts.items) |atom| { |
| 3158 | self.freeAtom(atom, true); | 3437 | self.freeAtom(atom, true); |
| 3159 | self.locals_free_list.append(self.base.allocator, atom.sym_index) catch {}; | 3438 | self.locals_free_list.append(gpa, atom.sym_index) catch {}; |
| 3160 | self.locals.items[atom.sym_index].n_type = 0; | 3439 | self.locals.items[atom.sym_index].n_type = 0; |
| 3161 | _ = self.atom_by_index_table.remove(atom.sym_index); | 3440 | _ = self.atom_by_index_table.remove(atom.sym_index); |
| 3162 | log.debug(" adding local symbol index {d} to free list", .{atom.sym_index}); | 3441 | log.debug(" adding local symbol index {d} to free list", .{atom.sym_index}); |
| 3163 | atom.sym_index = 0; | 3442 | atom.sym_index = 0; |
| 3164 | } | 3443 | } |
| 3165 | unnamed_consts.clearAndFree(self.base.allocator); | 3444 | unnamed_consts.clearAndFree(gpa); |
| 3166 | } | 3445 | } |
| 3167 | | 3446 | |
| 3168 | pub fn freeDecl(self: *MachO, decl_index: Module.Decl.Index) void { | 3447 | pub fn freeDecl(self: *MachO, decl_index: Module.Decl.Index) void { |
| ... | @@ -3171,20 +3450,25 @@ pub fn freeDecl(self: *MachO, decl_index: Module.Decl.Index) void { | ... | @@ -3171,20 +3450,25 @@ pub fn freeDecl(self: *MachO, decl_index: Module.Decl.Index) void { |
| 3171 | } | 3450 | } |
| 3172 | const mod = self.base.options.module.?; | 3451 | const mod = self.base.options.module.?; |
| 3173 | const decl = mod.declPtr(decl_index); | 3452 | const decl = mod.declPtr(decl_index); |
| | 3453 | |
| 3174 | log.debug("freeDecl {*}", .{decl}); | 3454 | log.debug("freeDecl {*}", .{decl}); |
| | 3455 | |
| 3175 | const kv = self.decls.fetchSwapRemove(decl_index); | 3456 | const kv = self.decls.fetchSwapRemove(decl_index); |
| 3176 | if (kv.?.value) |_| { | 3457 | if (kv.?.value) |_| { |
| 3177 | self.freeAtom(&decl.link.macho, false); | 3458 | self.freeAtom(&decl.link.macho, false); |
| 3178 | self.freeUnnamedConsts(decl_index); | 3459 | self.freeUnnamedConsts(decl_index); |
| 3179 | } | 3460 | } |
| | 3461 | |
| 3180 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | 3462 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. |
| 3181 | if (decl.link.macho.sym_index != 0) { | 3463 | const gpa = self.base.allocator; |
| 3182 | self.locals_free_list.append(self.base.allocator, decl.link.macho.sym_index) catch {}; | 3464 | const sym_index = decl.link.macho.sym_index; |
| | 3465 | if (sym_index != 0) { |
| | 3466 | self.locals_free_list.append(gpa, sym_index) catch {}; |
| 3183 | | 3467 | |
| 3184 | // Try freeing GOT atom if this decl had one | 3468 | // Try freeing GOT atom if this decl had one |
| 3185 | const got_target = SymbolWithLoc{ .sym_index = decl.link.macho.sym_index, .file = null }; | 3469 | const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null }; |
| 3186 | if (self.got_entries_table.get(got_target)) |got_index| { | 3470 | if (self.got_entries_table.get(got_target)) |got_index| { |
| 3187 | self.got_entries_free_list.append(self.base.allocator, @intCast(u32, got_index)) catch {}; | 3471 | self.got_entries_free_list.append(gpa, @intCast(u32, got_index)) catch {}; |
| 3188 | self.got_entries.items[got_index] = .{ | 3472 | self.got_entries.items[got_index] = .{ |
| 3189 | .target = .{ .sym_index = 0, .file = null }, | 3473 | .target = .{ .sym_index = 0, .file = null }, |
| 3190 | .sym_index = 0, | 3474 | .sym_index = 0, |
| ... | @@ -3192,20 +3476,18 @@ pub fn freeDecl(self: *MachO, decl_index: Module.Decl.Index) void { | ... | @@ -3192,20 +3476,18 @@ pub fn freeDecl(self: *MachO, decl_index: Module.Decl.Index) void { |
| 3192 | _ = self.got_entries_table.remove(got_target); | 3476 | _ = self.got_entries_table.remove(got_target); |
| 3193 | | 3477 | |
| 3194 | if (self.d_sym) |*d_sym| { | 3478 | if (self.d_sym) |*d_sym| { |
| 3195 | d_sym.swapRemoveRelocs(decl.link.macho.sym_index); | 3479 | d_sym.swapRemoveRelocs(sym_index); |
| 3196 | } | 3480 | } |
| 3197 | | 3481 | |
| 3198 | log.debug(" adding GOT index {d} to free list (target local@{d})", .{ | 3482 | log.debug(" adding GOT index {d} to free list (target local@{d})", .{ got_index, sym_index }); |
| 3199 | got_index, | | |
| 3200 | decl.link.macho.sym_index, | | |
| 3201 | }); | | |
| 3202 | } | 3483 | } |
| 3203 | | 3484 | |
| 3204 | self.locals.items[decl.link.macho.sym_index].n_type = 0; | 3485 | self.locals.items[sym_index].n_type = 0; |
| 3205 | _ = self.atom_by_index_table.remove(decl.link.macho.sym_index); | 3486 | _ = self.atom_by_index_table.remove(sym_index); |
| 3206 | log.debug(" adding local symbol index {d} to free list", .{decl.link.macho.sym_index}); | 3487 | log.debug(" adding local symbol index {d} to free list", .{sym_index}); |
| 3207 | decl.link.macho.sym_index = 0; | 3488 | decl.link.macho.sym_index = 0; |
| 3208 | } | 3489 | } |
| | 3490 | |
| 3209 | if (self.d_sym) |*d_sym| { | 3491 | if (self.d_sym) |*d_sym| { |
| 3210 | d_sym.dwarf.freeDecl(decl); | 3492 | d_sym.dwarf.freeDecl(decl); |
| 3211 | } | 3493 | } |
| ... | @@ -3218,21 +3500,20 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil | ... | @@ -3218,21 +3500,20 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil |
| 3218 | assert(self.llvm_object == null); | 3500 | assert(self.llvm_object == null); |
| 3219 | assert(decl.link.macho.sym_index != 0); | 3501 | assert(decl.link.macho.sym_index != 0); |
| 3220 | | 3502 | |
| 3221 | const atom = self.atom_by_index_table.get(reloc_info.parent_atom_index).?; | 3503 | const atom = self.getAtomForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?; |
| 3222 | try atom.relocs.append(self.base.allocator, .{ | 3504 | try atom.addRelocation(self, .{ |
| 3223 | .offset = @intCast(u32, reloc_info.offset), | | |
| 3224 | .target = .{ .sym_index = decl.link.macho.sym_index, .file = null }, | | |
| 3225 | .addend = reloc_info.addend, | | |
| 3226 | .subtractor = null, | | |
| 3227 | .pcrel = false, | | |
| 3228 | .length = 3, | | |
| 3229 | .@"type" = switch (self.base.options.target.cpu.arch) { | 3505 | .@"type" = switch (self.base.options.target.cpu.arch) { |
| 3230 | .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED), | 3506 | .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED), |
| 3231 | .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED), | 3507 | .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED), |
| 3232 | else => unreachable, | 3508 | else => unreachable, |
| 3233 | }, | 3509 | }, |
| | 3510 | .target = .{ .sym_index = decl.link.macho.sym_index, .file = null }, |
| | 3511 | .offset = @intCast(u32, reloc_info.offset), |
| | 3512 | .addend = reloc_info.addend, |
| | 3513 | .pcrel = false, |
| | 3514 | .length = 3, |
| 3234 | }); | 3515 | }); |
| 3235 | try atom.rebases.append(self.base.allocator, reloc_info.offset); | 3516 | try atom.addRebase(self, @intCast(u32, reloc_info.offset)); |
| 3236 | | 3517 | |
| 3237 | return 0; | 3518 | return 0; |
| 3238 | } | 3519 | } |
| ... | @@ -3575,6 +3856,7 @@ fn allocateSection(self: *MachO, sect_id: u8, size: u64, alignment: u32) !void { | ... | @@ -3575,6 +3856,7 @@ fn allocateSection(self: *MachO, sect_id: u8, size: u64, alignment: u32) !void { |
| 3575 | | 3856 | |
| 3576 | if (size > max_size) { | 3857 | if (size > max_size) { |
| 3577 | try self.growSection(sect_id, @intCast(u32, size)); | 3858 | try self.growSection(sect_id, @intCast(u32, size)); |
| | 3859 | self.markRelocsDirtyByAddress(header.addr + size); |
| 3578 | } | 3860 | } |
| 3579 | | 3861 | |
| 3580 | log.debug("allocating {s},{s} section at 0x{x}", .{ header.segName(), header.sectName(), off }); | 3862 | log.debug("allocating {s},{s} section at 0x{x}", .{ header.segName(), header.sectName(), off }); |
| ... | @@ -3885,7 +4167,13 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) ! | ... | @@ -3885,7 +4167,13 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) ! |
| 3885 | const header = &self.sections.items(.header)[sect_id]; | 4167 | const header = &self.sections.items(.header)[sect_id]; |
| 3886 | const free_list = &self.sections.items(.free_list)[sect_id]; | 4168 | const free_list = &self.sections.items(.free_list)[sect_id]; |
| 3887 | const maybe_last_atom = &self.sections.items(.last_atom)[sect_id]; | 4169 | const maybe_last_atom = &self.sections.items(.last_atom)[sect_id]; |
| 3888 | const new_atom_ideal_capacity = if (header.isCode()) padToIdeal(new_atom_size) else new_atom_size; | 4170 | const requires_padding = blk: { |
| | 4171 | if (!header.isCode()) break :blk false; |
| | 4172 | if (mem.eql(u8, "__stubs", header.sectName())) break :blk false; |
| | 4173 | if (mem.eql(u8, "__stub_helper", header.sectName())) break :blk false; |
| | 4174 | break :blk true; |
| | 4175 | }; |
| | 4176 | const new_atom_ideal_capacity = if (requires_padding) padToIdeal(new_atom_size) else new_atom_size; |
| 3889 | | 4177 | |
| 3890 | // We use these to indicate our intention to update metadata, placing the new atom, | 4178 | // We use these to indicate our intention to update metadata, placing the new atom, |
| 3891 | // and possibly removing a free list node. | 4179 | // and possibly removing a free list node. |
| ... | @@ -3905,7 +4193,7 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) ! | ... | @@ -3905,7 +4193,7 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) ! |
| 3905 | // Is it enough that we could fit this new atom? | 4193 | // Is it enough that we could fit this new atom? |
| 3906 | const sym = big_atom.getSymbol(self); | 4194 | const sym = big_atom.getSymbol(self); |
| 3907 | const capacity = big_atom.capacity(self); | 4195 | const capacity = big_atom.capacity(self); |
| 3908 | const ideal_capacity = if (header.isCode()) padToIdeal(capacity) else capacity; | 4196 | const ideal_capacity = if (requires_padding) padToIdeal(capacity) else capacity; |
| 3909 | const ideal_capacity_end_vaddr = math.add(u64, sym.n_value, ideal_capacity) catch ideal_capacity; | 4197 | const ideal_capacity_end_vaddr = math.add(u64, sym.n_value, ideal_capacity) catch ideal_capacity; |
| 3910 | const capacity_end_vaddr = sym.n_value + capacity; | 4198 | const capacity_end_vaddr = sym.n_value + capacity; |
| 3911 | const new_start_vaddr_unaligned = capacity_end_vaddr - new_atom_ideal_capacity; | 4199 | const new_start_vaddr_unaligned = capacity_end_vaddr - new_atom_ideal_capacity; |
| ... | @@ -3935,7 +4223,7 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) ! | ... | @@ -3935,7 +4223,7 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) ! |
| 3935 | break :blk new_start_vaddr; | 4223 | break :blk new_start_vaddr; |
| 3936 | } else if (maybe_last_atom.*) |last| { | 4224 | } else if (maybe_last_atom.*) |last| { |
| 3937 | const last_symbol = last.getSymbol(self); | 4225 | const last_symbol = last.getSymbol(self); |
| 3938 | const ideal_capacity = if (header.isCode()) padToIdeal(last.size) else last.size; | 4226 | const ideal_capacity = if (requires_padding) padToIdeal(last.size) else last.size; |
| 3939 | const ideal_capacity_end_vaddr = last_symbol.n_value + ideal_capacity; | 4227 | const ideal_capacity_end_vaddr = last_symbol.n_value + ideal_capacity; |
| 3940 | const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, alignment); | 4228 | const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, alignment); |
| 3941 | atom_placement = last; | 4229 | atom_placement = last; |
| ... | @@ -3949,6 +4237,7 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) ! | ... | @@ -3949,6 +4237,7 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) ! |
| 3949 | if (expand_section) { | 4237 | if (expand_section) { |
| 3950 | const needed_size = @intCast(u32, (vaddr + new_atom_size) - header.addr); | 4238 | const needed_size = @intCast(u32, (vaddr + new_atom_size) - header.addr); |
| 3951 | try self.growSection(sect_id, needed_size); | 4239 | try self.growSection(sect_id, needed_size); |
| | 4240 | self.markRelocsDirtyByAddress(header.addr + needed_size); |
| 3952 | maybe_last_atom.* = atom; | 4241 | maybe_last_atom.* = atom; |
| 3953 | header.size = needed_size; | 4242 | header.size = needed_size; |
| 3954 | } | 4243 | } |
| ... | @@ -4105,64 +4394,70 @@ pub fn writeDyldInfoData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { | ... | @@ -4105,64 +4394,70 @@ pub fn writeDyldInfoData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 4105 | const sym = atom.getSymbol(self); | 4394 | const sym = atom.getSymbol(self); |
| 4106 | const base_offset = sym.n_value - seg.vmaddr; | 4395 | const base_offset = sym.n_value - seg.vmaddr; |
| 4107 | | 4396 | |
| 4108 | for (atom.rebases.items) |offset| { | 4397 | if (self.rebases.get(atom)) |rebases| { |
| 4109 | log.debug(" | rebase at {x}", .{base_offset + offset}); | 4398 | for (rebases.items) |offset| { |
| 4110 | try rebase_pointers.append(.{ | 4399 | log.debug(" | rebase at {x}", .{base_offset + offset}); |
| 4111 | .offset = base_offset + offset, | 4400 | try rebase_pointers.append(.{ |
| 4112 | .segment_id = segment_index, | 4401 | .offset = base_offset + offset, |
| 4113 | }); | 4402 | .segment_id = segment_index, |
| | 4403 | }); |
| | 4404 | } |
| 4114 | } | 4405 | } |
| 4115 | | 4406 | |
| 4116 | for (atom.bindings.items) |binding| { | 4407 | if (self.bindings.get(atom)) |bindings| { |
| 4117 | const bind_sym = self.getSymbol(binding.target); | 4408 | for (bindings.items) |binding| { |
| 4118 | const bind_sym_name = self.getSymbolName(binding.target); | 4409 | const bind_sym = self.getSymbol(binding.target); |
| 4119 | const dylib_ordinal = @divTrunc( | 4410 | const bind_sym_name = self.getSymbolName(binding.target); |
| 4120 | @bitCast(i16, bind_sym.n_desc), | 4411 | const dylib_ordinal = @divTrunc( |
| 4121 | macho.N_SYMBOL_RESOLVER, | 4412 | @bitCast(i16, bind_sym.n_desc), |
| 4122 | ); | 4413 | macho.N_SYMBOL_RESOLVER, |
| 4123 | var flags: u4 = 0; | 4414 | ); |
| 4124 | log.debug(" | bind at {x}, import('{s}') in dylib({d})", .{ | 4415 | var flags: u4 = 0; |
| 4125 | binding.offset + base_offset, | 4416 | log.debug(" | bind at {x}, import('{s}') in dylib({d})", .{ |
| 4126 | bind_sym_name, | 4417 | binding.offset + base_offset, |
| 4127 | dylib_ordinal, | 4418 | bind_sym_name, |
| 4128 | }); | 4419 | dylib_ordinal, |
| 4129 | if (bind_sym.weakRef()) { | 4420 | }); |
| 4130 | log.debug(" | marking as weak ref ", .{}); | 4421 | if (bind_sym.weakRef()) { |
| 4131 | flags |= @truncate(u4, macho.BIND_SYMBOL_FLAGS_WEAK_IMPORT); | 4422 | log.debug(" | marking as weak ref ", .{}); |
| | 4423 | flags |= @truncate(u4, macho.BIND_SYMBOL_FLAGS_WEAK_IMPORT); |
| | 4424 | } |
| | 4425 | try bind_pointers.append(.{ |
| | 4426 | .offset = binding.offset + base_offset, |
| | 4427 | .segment_id = segment_index, |
| | 4428 | .dylib_ordinal = dylib_ordinal, |
| | 4429 | .name = bind_sym_name, |
| | 4430 | .bind_flags = flags, |
| | 4431 | }); |
| 4132 | } | 4432 | } |
| 4133 | try bind_pointers.append(.{ | | |
| 4134 | .offset = binding.offset + base_offset, | | |
| 4135 | .segment_id = segment_index, | | |
| 4136 | .dylib_ordinal = dylib_ordinal, | | |
| 4137 | .name = bind_sym_name, | | |
| 4138 | .bind_flags = flags, | | |
| 4139 | }); | | |
| 4140 | } | 4433 | } |
| 4141 | | 4434 | |
| 4142 | for (atom.lazy_bindings.items) |binding| { | 4435 | if (self.lazy_bindings.get(atom)) |lazy_bindings| { |
| 4143 | const bind_sym = self.getSymbol(binding.target); | 4436 | for (lazy_bindings.items) |binding| { |
| 4144 | const bind_sym_name = self.getSymbolName(binding.target); | 4437 | const bind_sym = self.getSymbol(binding.target); |
| 4145 | const dylib_ordinal = @divTrunc( | 4438 | const bind_sym_name = self.getSymbolName(binding.target); |
| 4146 | @bitCast(i16, bind_sym.n_desc), | 4439 | const dylib_ordinal = @divTrunc( |
| 4147 | macho.N_SYMBOL_RESOLVER, | 4440 | @bitCast(i16, bind_sym.n_desc), |
| 4148 | ); | 4441 | macho.N_SYMBOL_RESOLVER, |
| 4149 | var flags: u4 = 0; | 4442 | ); |
| 4150 | log.debug(" | lazy bind at {x} import('{s}') ord({d})", .{ | 4443 | var flags: u4 = 0; |
| 4151 | binding.offset + base_offset, | 4444 | log.debug(" | lazy bind at {x} import('{s}') ord({d})", .{ |
| 4152 | bind_sym_name, | 4445 | binding.offset + base_offset, |
| 4153 | dylib_ordinal, | 4446 | bind_sym_name, |
| 4154 | }); | 4447 | dylib_ordinal, |
| 4155 | if (bind_sym.weakRef()) { | 4448 | }); |
| 4156 | log.debug(" | marking as weak ref ", .{}); | 4449 | if (bind_sym.weakRef()) { |
| 4157 | flags |= @truncate(u4, macho.BIND_SYMBOL_FLAGS_WEAK_IMPORT); | 4450 | log.debug(" | marking as weak ref ", .{}); |
| | 4451 | flags |= @truncate(u4, macho.BIND_SYMBOL_FLAGS_WEAK_IMPORT); |
| | 4452 | } |
| | 4453 | try lazy_bind_pointers.append(.{ |
| | 4454 | .offset = binding.offset + base_offset, |
| | 4455 | .segment_id = segment_index, |
| | 4456 | .dylib_ordinal = dylib_ordinal, |
| | 4457 | .name = bind_sym_name, |
| | 4458 | .bind_flags = flags, |
| | 4459 | }); |
| 4158 | } | 4460 | } |
| 4159 | try lazy_bind_pointers.append(.{ | | |
| 4160 | .offset = binding.offset + base_offset, | | |
| 4161 | .segment_id = segment_index, | | |
| 4162 | .dylib_ordinal = dylib_ordinal, | | |
| 4163 | .name = bind_sym_name, | | |
| 4164 | .bind_flags = flags, | | |
| 4165 | }); | | |
| 4166 | } | 4461 | } |
| 4167 | | 4462 | |
| 4168 | if (atom.prev) |prev| { | 4463 | if (atom.prev) |prev| { |
| ... | @@ -4387,25 +4682,25 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { | ... | @@ -4387,25 +4682,25 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { |
| 4387 | | 4682 | |
| 4388 | const asc_u64 = std.sort.asc(u64); | 4683 | const asc_u64 = std.sort.asc(u64); |
| 4389 | | 4684 | |
| 4390 | fn writeFunctionStarts(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { | 4685 | pub fn writeFunctionStarts(macho_file: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 4391 | const tracy = trace(@src()); | 4686 | const tracy = trace(@src()); |
| 4392 | defer tracy.end(); | 4687 | defer tracy.end(); |
| 4393 | | 4688 | |
| 4394 | const text_seg_index = self.text_segment_cmd_index orelse return; | 4689 | const text_seg_index = macho_file.text_segment_cmd_index orelse return; |
| 4395 | const text_sect_index = self.text_section_index orelse return; | 4690 | const text_sect_index = macho_file.text_section_index orelse return; |
| 4396 | const text_seg = self.segments.items[text_seg_index]; | 4691 | const text_seg = macho_file.segments.items[text_seg_index]; |
| 4397 | | 4692 | |
| 4398 | const gpa = self.base.allocator; | 4693 | const gpa = macho_file.base.allocator; |
| 4399 | | 4694 | |
| 4400 | // We need to sort by address first | 4695 | // We need to sort by address first |
| 4401 | var addresses = std.ArrayList(u64).init(gpa); | 4696 | var addresses = std.ArrayList(u64).init(gpa); |
| 4402 | defer addresses.deinit(); | 4697 | defer addresses.deinit(); |
| 4403 | try addresses.ensureTotalCapacityPrecise(self.globals.items.len); | 4698 | try addresses.ensureTotalCapacityPrecise(macho_file.globals.items.len); |
| 4404 | | 4699 | |
| 4405 | for (self.globals.items) |global| { | 4700 | for (macho_file.globals.items) |global| { |
| 4406 | const sym = self.getSymbol(global); | 4701 | const sym = macho_file.getSymbol(global); |
| 4407 | if (sym.undf()) continue; | 4702 | if (sym.undf()) continue; |
| 4408 | if (sym.n_desc == N_DESC_GCED) continue; | 4703 | if (sym.n_desc == MachO.N_DESC_GCED) continue; |
| 4409 | const sect_id = sym.n_sect - 1; | 4704 | const sect_id = sym.n_sect - 1; |
| 4410 | if (sect_id != text_sect_index) continue; | 4705 | if (sect_id != text_sect_index) continue; |
| 4411 | | 4706 | |
| ... | @@ -4439,14 +4734,14 @@ fn writeFunctionStarts(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { | ... | @@ -4439,14 +4734,14 @@ fn writeFunctionStarts(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 4439 | try std.leb.writeULEB128(buffer.writer(), offset); | 4734 | try std.leb.writeULEB128(buffer.writer(), offset); |
| 4440 | } | 4735 | } |
| 4441 | | 4736 | |
| 4442 | const link_seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; | 4737 | const link_seg = &macho_file.segments.items[macho_file.linkedit_segment_cmd_index.?]; |
| 4443 | const offset = mem.alignForwardGeneric(u64, link_seg.fileoff + link_seg.filesize, @alignOf(u64)); | 4738 | const offset = mem.alignForwardGeneric(u64, link_seg.fileoff + link_seg.filesize, @alignOf(u64)); |
| 4444 | const needed_size = buffer.items.len; | 4739 | const needed_size = buffer.items.len; |
| 4445 | link_seg.filesize = offset + needed_size - link_seg.fileoff; | 4740 | link_seg.filesize = offset + needed_size - link_seg.fileoff; |
| 4446 | | 4741 | |
| 4447 | log.debug("writing function starts info from 0x{x} to 0x{x}", .{ offset, offset + needed_size }); | 4742 | log.debug("writing function starts info from 0x{x} to 0x{x}", .{ offset, offset + needed_size }); |
| 4448 | | 4743 | |
| 4449 | try self.base.file.?.pwriteAll(buffer.items, offset); | 4744 | try macho_file.base.file.?.pwriteAll(buffer.items, offset); |
| 4450 | | 4745 | |
| 4451 | try lc_writer.writeStruct(macho.linkedit_data_command{ | 4746 | try lc_writer.writeStruct(macho.linkedit_data_command{ |
| 4452 | .cmd = .FUNCTION_STARTS, | 4747 | .cmd = .FUNCTION_STARTS, |
| ... | @@ -4465,8 +4760,8 @@ fn filterDataInCode( | ... | @@ -4465,8 +4760,8 @@ fn filterDataInCode( |
| 4465 | const Predicate = struct { | 4760 | const Predicate = struct { |
| 4466 | addr: u64, | 4761 | addr: u64, |
| 4467 | | 4762 | |
| 4468 | pub fn predicate(self: @This(), dice: macho.data_in_code_entry) bool { | 4763 | pub fn predicate(macho_file: @This(), dice: macho.data_in_code_entry) bool { |
| 4469 | return dice.offset >= self.addr; | 4764 | return dice.offset >= macho_file.addr; |
| 4470 | } | 4765 | } |
| 4471 | }; | 4766 | }; |
| 4472 | | 4767 | |
| ... | @@ -4476,26 +4771,26 @@ fn filterDataInCode( | ... | @@ -4476,26 +4771,26 @@ fn filterDataInCode( |
| 4476 | return dices[start..end]; | 4771 | return dices[start..end]; |
| 4477 | } | 4772 | } |
| 4478 | | 4773 | |
| 4479 | fn writeDataInCode(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { | 4774 | pub fn writeDataInCode(macho_file: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 4480 | const tracy = trace(@src()); | 4775 | const tracy = trace(@src()); |
| 4481 | defer tracy.end(); | 4776 | defer tracy.end(); |
| 4482 | | 4777 | |
| 4483 | var out_dice = std.ArrayList(macho.data_in_code_entry).init(self.base.allocator); | 4778 | var out_dice = std.ArrayList(macho.data_in_code_entry).init(macho_file.base.allocator); |
| 4484 | defer out_dice.deinit(); | 4779 | defer out_dice.deinit(); |
| 4485 | | 4780 | |
| 4486 | const text_sect_id = self.text_section_index orelse return; | 4781 | const text_sect_id = macho_file.text_section_index orelse return; |
| 4487 | const text_sect_header = self.sections.items(.header)[text_sect_id]; | 4782 | const text_sect_header = macho_file.sections.items(.header)[text_sect_id]; |
| 4488 | | 4783 | |
| 4489 | for (self.objects.items) |object| { | 4784 | for (macho_file.objects.items) |object| { |
| 4490 | const dice = object.parseDataInCode() orelse continue; | 4785 | const dice = object.parseDataInCode() orelse continue; |
| 4491 | try out_dice.ensureUnusedCapacity(dice.len); | 4786 | try out_dice.ensureUnusedCapacity(dice.len); |
| 4492 | | 4787 | |
| 4493 | for (object.managed_atoms.items) |atom| { | 4788 | for (object.managed_atoms.items) |atom| { |
| 4494 | const sym = atom.getSymbol(self); | 4789 | const sym = atom.getSymbol(macho_file); |
| 4495 | if (sym.n_desc == N_DESC_GCED) continue; | 4790 | if (sym.n_desc == MachO.N_DESC_GCED) continue; |
| 4496 | | 4791 | |
| 4497 | const sect_id = sym.n_sect - 1; | 4792 | const sect_id = sym.n_sect - 1; |
| 4498 | if (sect_id != self.text_section_index.?) { | 4793 | if (sect_id != macho_file.text_section_index.?) { |
| 4499 | continue; | 4794 | continue; |
| 4500 | } | 4795 | } |
| 4501 | | 4796 | |
| ... | @@ -4516,14 +4811,14 @@ fn writeDataInCode(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { | ... | @@ -4516,14 +4811,14 @@ fn writeDataInCode(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 4516 | } | 4811 | } |
| 4517 | } | 4812 | } |
| 4518 | | 4813 | |
| 4519 | const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; | 4814 | const seg = &macho_file.segments.items[macho_file.linkedit_segment_cmd_index.?]; |
| 4520 | const offset = mem.alignForwardGeneric(u64, seg.fileoff + seg.filesize, @alignOf(u64)); | 4815 | const offset = mem.alignForwardGeneric(u64, seg.fileoff + seg.filesize, @alignOf(u64)); |
| 4521 | const needed_size = out_dice.items.len * @sizeOf(macho.data_in_code_entry); | 4816 | const needed_size = out_dice.items.len * @sizeOf(macho.data_in_code_entry); |
| 4522 | seg.filesize = offset + needed_size - seg.fileoff; | 4817 | seg.filesize = offset + needed_size - seg.fileoff; |
| 4523 | | 4818 | |
| 4524 | log.debug("writing data-in-code from 0x{x} to 0x{x}", .{ offset, offset + needed_size }); | 4819 | log.debug("writing data-in-code from 0x{x} to 0x{x}", .{ offset, offset + needed_size }); |
| 4525 | | 4820 | |
| 4526 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(out_dice.items), offset); | 4821 | try macho_file.base.file.?.pwriteAll(mem.sliceAsBytes(out_dice.items), offset); |
| 4527 | try lc_writer.writeStruct(macho.linkedit_data_command{ | 4822 | try lc_writer.writeStruct(macho.linkedit_data_command{ |
| 4528 | .cmd = .DATA_IN_CODE, | 4823 | .cmd = .DATA_IN_CODE, |
| 4529 | .cmdsize = @sizeOf(macho.linkedit_data_command), | 4824 | .cmdsize = @sizeOf(macho.linkedit_data_command), |
| ... | @@ -4533,7 +4828,7 @@ fn writeDataInCode(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { | ... | @@ -4533,7 +4828,7 @@ fn writeDataInCode(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 4533 | ncmds.* += 1; | 4828 | ncmds.* += 1; |
| 4534 | } | 4829 | } |
| 4535 | | 4830 | |
| 4536 | fn writeSymtabs(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { | 4831 | pub fn writeSymtabs(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 4537 | var symtab_cmd = macho.symtab_command{ | 4832 | var symtab_cmd = macho.symtab_command{ |
| 4538 | .cmdsize = @sizeOf(macho.symtab_command), | 4833 | .cmdsize = @sizeOf(macho.symtab_command), |
| 4539 | .symoff = 0, | 4834 | .symoff = 0, |
| ... | @@ -4571,7 +4866,7 @@ fn writeSymtabs(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { | ... | @@ -4571,7 +4866,7 @@ fn writeSymtabs(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 4571 | ncmds.* += 2; | 4866 | ncmds.* += 2; |
| 4572 | } | 4867 | } |
| 4573 | | 4868 | |
| 4574 | fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx { | 4869 | pub fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx { |
| 4575 | const gpa = self.base.allocator; | 4870 | const gpa = self.base.allocator; |
| 4576 | | 4871 | |
| 4577 | var locals = std.ArrayList(macho.nlist_64).init(gpa); | 4872 | var locals = std.ArrayList(macho.nlist_64).init(gpa); |
| ... | @@ -5485,7 +5780,7 @@ pub fn logSymtab(self: *MachO) void { | ... | @@ -5485,7 +5780,7 @@ pub fn logSymtab(self: *MachO) void { |
| 5485 | const def_index = if (sym.undf() and !sym.tentative()) | 5780 | const def_index = if (sym.undf() and !sym.tentative()) |
| 5486 | @divTrunc(sym.n_desc, macho.N_SYMBOL_RESOLVER) | 5781 | @divTrunc(sym.n_desc, macho.N_SYMBOL_RESOLVER) |
| 5487 | else | 5782 | else |
| 5488 | sym.n_sect; | 5783 | sym.n_sect + 1; |
| 5489 | log.debug(" %{d}: {s} @{x} in {s}({d}), {s}", .{ | 5784 | log.debug(" %{d}: {s} @{x} in {s}({d}), {s}", .{ |
| 5490 | sym_id, | 5785 | sym_id, |
| 5491 | object.getString(sym.n_strx), | 5786 | object.getString(sym.n_strx), |
| ... | @@ -5502,7 +5797,7 @@ pub fn logSymtab(self: *MachO) void { | ... | @@ -5502,7 +5797,7 @@ pub fn logSymtab(self: *MachO) void { |
| 5502 | const def_index = if (sym.undf() and !sym.tentative()) | 5797 | const def_index = if (sym.undf() and !sym.tentative()) |
| 5503 | @divTrunc(sym.n_desc, macho.N_SYMBOL_RESOLVER) | 5798 | @divTrunc(sym.n_desc, macho.N_SYMBOL_RESOLVER) |
| 5504 | else | 5799 | else |
| 5505 | sym.n_sect; | 5800 | sym.n_sect + 1; |
| 5506 | log.debug(" %{d}: {?s} @{x} in {s}({d}), {s}", .{ | 5801 | log.debug(" %{d}: {?s} @{x} in {s}({d}), {s}", .{ |
| 5507 | sym_id, | 5802 | sym_id, |
| 5508 | self.strtab.get(sym.n_strx), | 5803 | self.strtab.get(sym.n_strx), |
| ... | @@ -5633,6 +5928,6 @@ pub fn copyRangeAllOverlappingAlloc( | ... | @@ -5633,6 +5928,6 @@ pub fn copyRangeAllOverlappingAlloc( |
| 5633 | ) !void { | 5928 | ) !void { |
| 5634 | const buf = try allocator.alloc(u8, len); | 5929 | const buf = try allocator.alloc(u8, len); |
| 5635 | defer allocator.free(buf); | 5930 | defer allocator.free(buf); |
| 5636 | _ = try file.preadAll(buf, in_offset); | 5931 | const amt = try file.preadAll(buf, in_offset); |
| 5637 | try file.pwriteAll(buf, out_offset); | 5932 | try file.pwriteAll(buf[0..amt], out_offset); |
| 5638 | } | 5933 | } |