| author | |
| committer | |
| log | 86ab6ca56c4e6d115b017eed40dc62815a6a8e3d |
| tree | 7d429b531800dfe8614ea4789686338d5fd9a5df |
| parent | b6be28ddcc50bd4bf085294ffcb696e31a7a1de5 |
5 files changed, 186 insertions(+), 145 deletions(-)
src/link/MachO/Object.zig+80-98| ... | @@ -43,17 +43,13 @@ dwarf_debug_str_index: ?u16 = null, | ... | @@ -43,17 +43,13 @@ dwarf_debug_str_index: ?u16 = null, |
| 43 | dwarf_debug_line_index: ?u16 = null, | 43 | dwarf_debug_line_index: ?u16 = null, |
| 44 | dwarf_debug_ranges_index: ?u16 = null, | 44 | dwarf_debug_ranges_index: ?u16 = null, |
| 45 | 45 | ||
| 46 | symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | 46 | symbols: std.ArrayListUnmanaged(*Symbol) = .{}, |
| 47 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 47 | initializers: std.ArrayListUnmanaged(*Symbol) = .{}, |
| 48 | data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{}, | ||
| 48 | 49 | ||
| 49 | locals: std.StringArrayHashMapUnmanaged(Symbol) = .{}, | ||
| 50 | stabs: std.ArrayListUnmanaged(Stab) = .{}, | ||
| 51 | tu_path: ?[]const u8 = null, | 50 | tu_path: ?[]const u8 = null, |
| 52 | tu_mtime: ?u64 = null, | 51 | tu_mtime: ?u64 = null, |
| 53 | 52 | ||
| 54 | initializers: std.ArrayListUnmanaged(CppStatic) = .{}, | ||
| 55 | data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{}, | ||
| 56 | |||
| 57 | pub const Section = struct { | 53 | pub const Section = struct { |
| 58 | inner: macho.section_64, | 54 | inner: macho.section_64, |
| 59 | code: []u8, | 55 | code: []u8, |
| ... | @@ -71,23 +67,6 @@ pub const Section = struct { | ... | @@ -71,23 +67,6 @@ pub const Section = struct { |
| 71 | } | 67 | } |
| 72 | }; | 68 | }; |
| 73 | 69 | ||
| 74 | const CppStatic = struct { | ||
| 75 | symbol: u32, | ||
| 76 | target_addr: u64, | ||
| 77 | }; | ||
| 78 | |||
| 79 | const Stab = struct { | ||
| 80 | tag: Tag, | ||
| 81 | symbol: u32, | ||
| 82 | size: ?u64 = null, | ||
| 83 | |||
| 84 | const Tag = enum { | ||
| 85 | function, | ||
| 86 | global, | ||
| 87 | static, | ||
| 88 | }; | ||
| 89 | }; | ||
| 90 | |||
| 91 | const DebugInfo = struct { | 70 | const DebugInfo = struct { |
| 92 | inner: dwarf.DwarfInfo, | 71 | inner: dwarf.DwarfInfo, |
| 93 | debug_info: []u8, | 72 | debug_info: []u8, |
| ... | @@ -169,14 +148,12 @@ pub fn deinit(self: *Object) void { | ... | @@ -169,14 +148,12 @@ pub fn deinit(self: *Object) void { |
| 169 | } | 148 | } |
| 170 | self.sections.deinit(self.allocator); | 149 | self.sections.deinit(self.allocator); |
| 171 | 150 | ||
| 172 | for (self.locals.items()) |*entry| { | 151 | for (self.symbols.items) |sym| { |
| 173 | entry.value.deinit(self.allocator); | 152 | sym.deinit(self.allocator); |
| 153 | self.allocator.destroy(sym); | ||
| 174 | } | 154 | } |
| 175 | self.locals.deinit(self.allocator); | 155 | self.symbols.deinit(self.allocator); |
| 176 | 156 | ||
| 177 | self.symtab.deinit(self.allocator); | ||
| 178 | self.strtab.deinit(self.allocator); | ||
| 179 | self.stabs.deinit(self.allocator); | ||
| 180 | self.data_in_code_entries.deinit(self.allocator); | 157 | self.data_in_code_entries.deinit(self.allocator); |
| 181 | self.initializers.deinit(self.allocator); | 158 | self.initializers.deinit(self.allocator); |
| 182 | 159 | ||
| ... | @@ -222,9 +199,9 @@ pub fn parse(self: *Object) !void { | ... | @@ -222,9 +199,9 @@ pub fn parse(self: *Object) !void { |
| 222 | } | 199 | } |
| 223 | 200 | ||
| 224 | try self.readLoadCommands(reader); | 201 | try self.readLoadCommands(reader); |
| 202 | try self.parseSymbols(); | ||
| 225 | try self.parseSections(); | 203 | try self.parseSections(); |
| 226 | if (self.symtab_cmd_index != null) try self.parseSymtab(); | 204 | try self.parseDataInCode(); |
| 227 | if (self.data_in_code_cmd_index != null) try self.readDataInCode(); | ||
| 228 | try self.parseInitializers(); | 205 | try self.parseInitializers(); |
| 229 | try self.parseDebugInfo(); | 206 | try self.parseDebugInfo(); |
| 230 | } | 207 | } |
| ... | @@ -298,9 +275,10 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void { | ... | @@ -298,9 +275,10 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void { |
| 298 | } | 275 | } |
| 299 | 276 | ||
| 300 | pub fn parseSections(self: *Object) !void { | 277 | pub fn parseSections(self: *Object) !void { |
| 301 | log.debug("parsing sections in {s}", .{self.name.?}); | ||
| 302 | const seg = self.load_commands.items[self.segment_cmd_index.?].Segment; | 278 | const seg = self.load_commands.items[self.segment_cmd_index.?].Segment; |
| 303 | 279 | ||
| 280 | log.debug("parsing sections in {s}", .{self.name.?}); | ||
| 281 | |||
| 304 | try self.sections.ensureCapacity(self.allocator, seg.sections.items.len); | 282 | try self.sections.ensureCapacity(self.allocator, seg.sections.items.len); |
| 305 | 283 | ||
| 306 | for (seg.sections.items) |sect| { | 284 | for (seg.sections.items) |sect| { |
| ... | @@ -327,6 +305,7 @@ pub fn parseSections(self: *Object) !void { | ... | @@ -327,6 +305,7 @@ pub fn parseSections(self: *Object) !void { |
| 327 | self.arch.?, | 305 | self.arch.?, |
| 328 | section.code, | 306 | section.code, |
| 329 | mem.bytesAsSlice(macho.relocation_info, raw_relocs), | 307 | mem.bytesAsSlice(macho.relocation_info, raw_relocs), |
| 308 | self.symbols.items, | ||
| 330 | ); | 309 | ); |
| 331 | } | 310 | } |
| 332 | 311 | ||
| ... | @@ -344,60 +323,70 @@ pub fn parseInitializers(self: *Object) !void { | ... | @@ -344,60 +323,70 @@ pub fn parseInitializers(self: *Object) !void { |
| 344 | const relocs = section.relocs orelse unreachable; | 323 | const relocs = section.relocs orelse unreachable; |
| 345 | try self.initializers.ensureCapacity(self.allocator, relocs.len); | 324 | try self.initializers.ensureCapacity(self.allocator, relocs.len); |
| 346 | for (relocs) |rel| { | 325 | for (relocs) |rel| { |
| 347 | self.initializers.appendAssumeCapacity(.{ | 326 | self.initializers.appendAssumeCapacity(rel.target.symbol); |
| 348 | .symbol = rel.target.symbol, | ||
| 349 | .target_addr = undefined, | ||
| 350 | }); | ||
| 351 | } | 327 | } |
| 352 | 328 | ||
| 353 | mem.reverse(CppStatic, self.initializers.items); | 329 | mem.reverse(*Symbol, self.initializers.items); |
| 354 | |||
| 355 | for (self.initializers.items) |initializer| { | ||
| 356 | const sym = self.symtab.items[initializer.symbol]; | ||
| 357 | const sym_name = self.getString(sym.n_strx); | ||
| 358 | log.debug(" | {s}", .{sym_name}); | ||
| 359 | } | ||
| 360 | } | 330 | } |
| 361 | 331 | ||
| 362 | pub fn parseSymtab(self: *Object) !void { | 332 | pub fn parseSymbols(self: *Object) !void { |
| 363 | const symtab_cmd = self.load_commands.items[self.symtab_cmd_index.?].Symtab; | 333 | const index = self.symtab_cmd_index orelse return; |
| 334 | const symtab_cmd = self.load_commands.items[index].Symtab; | ||
| 364 | 335 | ||
| 365 | var symtab = try self.allocator.alloc(u8, @sizeOf(macho.nlist_64) * symtab_cmd.nsyms); | 336 | var symtab = try self.allocator.alloc(u8, @sizeOf(macho.nlist_64) * symtab_cmd.nsyms); |
| 366 | defer self.allocator.free(symtab); | 337 | defer self.allocator.free(symtab); |
| 367 | |||
| 368 | _ = try self.file.?.preadAll(symtab, symtab_cmd.symoff); | 338 | _ = try self.file.?.preadAll(symtab, symtab_cmd.symoff); |
| 369 | const slice = @alignCast(@alignOf(macho.nlist_64), mem.bytesAsSlice(macho.nlist_64, symtab)); | 339 | const slice = @alignCast(@alignOf(macho.nlist_64), mem.bytesAsSlice(macho.nlist_64, symtab)); |
| 370 | try self.symtab.appendSlice(self.allocator, slice); | ||
| 371 | 340 | ||
| 372 | var strtab = try self.allocator.alloc(u8, symtab_cmd.strsize); | 341 | var strtab = try self.allocator.alloc(u8, symtab_cmd.strsize); |
| 373 | defer self.allocator.free(strtab); | 342 | defer self.allocator.free(strtab); |
| 374 | |||
| 375 | _ = try self.file.?.preadAll(strtab, symtab_cmd.stroff); | 343 | _ = try self.file.?.preadAll(strtab, symtab_cmd.stroff); |
| 376 | try self.strtab.appendSlice(self.allocator, strtab); | ||
| 377 | 344 | ||
| 378 | for (self.symtab.items) |sym, sym_id| { | 345 | for (slice) |sym| { |
| 379 | if (Symbol.isStab(sym) or Symbol.isUndef(sym)) continue; | 346 | if (Symbol.isStab(sym)) { |
| 347 | log.err("TODO handle stabs embedded within object files", .{}); | ||
| 348 | return error.HandleStabsInObjects; | ||
| 349 | } | ||
| 380 | 350 | ||
| 381 | const sym_name = self.getString(sym.n_strx); | 351 | const sym_name = mem.spanZ(@ptrCast([*:0]const u8, strtab.ptr + sym.n_strx)); |
| 382 | const tag: Symbol.Tag = tag: { | 352 | const name = try self.allocator.dupe(u8, sym_name); |
| 383 | if (Symbol.isLocal(sym)) { | 353 | |
| 384 | if (self.arch.? == .aarch64 and mem.startsWith(u8, sym_name, "l")) continue; | 354 | const symbol: *Symbol = symbol: { |
| 385 | break :tag .local; | 355 | if (Symbol.isSect(sym)) { |
| 386 | } | 356 | const linkage: Symbol.Regular.Linkage = linkage: { |
| 387 | if (Symbol.isWeakDef(sym)) { | 357 | if (!Symbol.isExt(sym)) break :linkage .translation_unit; |
| 388 | break :tag .weak; | 358 | if (Symbol.isWeakDef(sym) or Symbol.isPext(sym)) break :linkage .linkage_unit; |
| 359 | break :linkage .global; | ||
| 360 | }; | ||
| 361 | const regular = try self.allocator.create(Symbol.Regular); | ||
| 362 | errdefer self.allocator.destroy(regular); | ||
| 363 | regular.* = .{ | ||
| 364 | .base = .{ | ||
| 365 | .@"type" = .regular, | ||
| 366 | .name = name, | ||
| 367 | }, | ||
| 368 | .linkage = .translation_unit, | ||
| 369 | .address = sym.n_value, | ||
| 370 | .section = sym.n_sect - 1, | ||
| 371 | .weak_ref = Symbol.isWeakRef(sym), | ||
| 372 | .file = self, | ||
| 373 | }; | ||
| 374 | break :symbol &regular.base; | ||
| 389 | } | 375 | } |
| 390 | break :tag .strong; | 376 | |
| 377 | const undef = try self.allocator.create(Symbol.Unresolved); | ||
| 378 | errdefer self.allocator.destroy(undef); | ||
| 379 | undef.* = .{ | ||
| 380 | .base = .{ | ||
| 381 | .@"type" = .unresolved, | ||
| 382 | .name = name, | ||
| 383 | }, | ||
| 384 | .file = self, | ||
| 385 | }; | ||
| 386 | break :symbol &undef.base; | ||
| 391 | }; | 387 | }; |
| 392 | const name = try self.allocator.dupe(u8, sym_name); | ||
| 393 | 388 | ||
| 394 | try self.locals.putNoClobber(self.allocator, name, .{ | 389 | try self.symbols.append(self.allocator, symbol); |
| 395 | .tag = tag, | ||
| 396 | .name = name, | ||
| 397 | .address = 0, | ||
| 398 | .section = 0, | ||
| 399 | .index = @intCast(u32, sym_id), | ||
| 400 | }); | ||
| 401 | } | 390 | } |
| 402 | } | 391 | } |
| 403 | 392 | ||
| ... | @@ -429,38 +418,31 @@ pub fn parseDebugInfo(self: *Object) !void { | ... | @@ -429,38 +418,31 @@ pub fn parseDebugInfo(self: *Object) !void { |
| 429 | break :mtime @intCast(u64, @divFloor(stat.mtime, 1_000_000_000)); | 418 | break :mtime @intCast(u64, @divFloor(stat.mtime, 1_000_000_000)); |
| 430 | }; | 419 | }; |
| 431 | 420 | ||
| 432 | for (self.locals.items()) |entry, index| { | 421 | for (self.symbols.items) |sym| { |
| 433 | const local = entry.value; | 422 | if (sym.cast(Symbol.Regular)) |reg| { |
| 434 | const source_sym = self.symtab.items[local.index.?]; | 423 | const size: u64 = blk: for (debug_info.inner.func_list.items) |func| { |
| 435 | const size = blk: for (debug_info.inner.func_list.items) |func| { | 424 | if (func.pc_range) |range| { |
| 436 | if (func.pc_range) |range| { | 425 | if (reg.address >= range.start and reg.address < range.end) { |
| 437 | if (source_sym.n_value >= range.start and source_sym.n_value < range.end) { | 426 | break :blk range.end - range.start; |
| 438 | break :blk range.end - range.start; | 427 | } |
| 439 | } | 428 | } |
| 440 | } | 429 | } else 0; |
| 441 | } else null; | 430 | |
| 442 | const tag: Stab.Tag = tag: { | 431 | reg.stab = .{ |
| 443 | if (size != null) break :tag .function; | 432 | .kind = kind: { |
| 444 | switch (local.tag) { | 433 | if (size > 0) break :kind .function; |
| 445 | .weak, .strong => break :tag .global, | 434 | switch (reg.linkage) { |
| 446 | else => break :tag .static, | 435 | .translation_unit => break :kind .static, |
| 447 | } | 436 | else => break :kind .global, |
| 448 | }; | 437 | } |
| 449 | 438 | }, | |
| 450 | try self.stabs.append(self.allocator, .{ | 439 | .size = size, |
| 451 | .tag = tag, | 440 | }; |
| 452 | .size = size, | 441 | } |
| 453 | .symbol = @intCast(u32, index), | ||
| 454 | }); | ||
| 455 | } | 442 | } |
| 456 | } | 443 | } |
| 457 | 444 | ||
| 458 | pub fn getString(self: *const Object, str_off: u32) []const u8 { | 445 | fn readSection(self: Object, allocator: *Allocator, index: u16) ![]u8 { |
| 459 | assert(str_off < self.strtab.items.len); | ||
| 460 | return mem.spanZ(@ptrCast([*:0]const u8, self.strtab.items.ptr + str_off)); | ||
| 461 | } | ||
| 462 | |||
| 463 | pub fn readSection(self: Object, allocator: *Allocator, index: u16) ![]u8 { | ||
| 464 | const seg = self.load_commands.items[self.segment_cmd_index.?].Segment; | 446 | const seg = self.load_commands.items[self.segment_cmd_index.?].Segment; |
| 465 | const sect = seg.sections.items[index]; | 447 | const sect = seg.sections.items[index]; |
| 466 | var buffer = try allocator.alloc(u8, sect.size); | 448 | var buffer = try allocator.alloc(u8, sect.size); |
| ... | @@ -468,7 +450,7 @@ pub fn readSection(self: Object, allocator: *Allocator, index: u16) ![]u8 { | ... | @@ -468,7 +450,7 @@ pub fn readSection(self: Object, allocator: *Allocator, index: u16) ![]u8 { |
| 468 | return buffer; | 450 | return buffer; |
| 469 | } | 451 | } |
| 470 | 452 | ||
| 471 | pub fn readDataInCode(self: *Object) !void { | 453 | pub fn parseDataInCode(self: *Object) !void { |
| 472 | const index = self.data_in_code_cmd_index orelse return; | 454 | const index = self.data_in_code_cmd_index orelse return; |
| 473 | const data_in_code = self.load_commands.items[index].LinkeditData; | 455 | const data_in_code = self.load_commands.items[index].LinkeditData; |
| 474 | 456 |
src/link/MachO/Symbol.zig+81-30| ... | @@ -2,31 +2,93 @@ const Symbol = @This(); | ... | @@ -2,31 +2,93 @@ const Symbol = @This(); |
| 2 | 2 | ||
| 3 | const std = @import("std"); | 3 | const std = @import("std"); |
| 4 | const macho = std.macho; | 4 | const macho = std.macho; |
| 5 | const mem = std.mem; | ||
| 5 | 6 | ||
| 6 | const Allocator = std.mem.Allocator; | 7 | const Allocator = mem.Allocator; |
| 8 | const Object = @import("Object.zig"); | ||
| 7 | 9 | ||
| 8 | pub const Tag = enum { | 10 | pub const Type = enum { |
| 9 | local, | 11 | regular, |
| 10 | weak, | 12 | proxy, |
| 11 | strong, | 13 | unresolved, |
| 12 | import, | ||
| 13 | undef, | ||
| 14 | }; | 14 | }; |
| 15 | 15 | ||
| 16 | tag: Tag, | 16 | /// Symbol type. |
| 17 | @"type": Type, | ||
| 18 | |||
| 19 | /// Symbol name. Owned slice. | ||
| 17 | name: []u8, | 20 | name: []u8, |
| 18 | address: u64, | ||
| 19 | section: u8, | ||
| 20 | 21 | ||
| 21 | /// Index of file where to locate this symbol. | 22 | pub const Regular = struct { |
| 22 | /// Depending on context, this is either an object file, or a dylib. | 23 | base: Symbol, |
| 23 | file: ?u16 = null, | 24 | |
| 25 | /// Linkage type. | ||
| 26 | linkage: Linkage, | ||
| 27 | |||
| 28 | /// Symbol address. | ||
| 29 | address: u64, | ||
| 30 | |||
| 31 | /// Section ID where the symbol resides. | ||
| 32 | section: u8, | ||
| 33 | |||
| 34 | /// Whether the symbol is a weak ref. | ||
| 35 | weak_ref: bool, | ||
| 36 | |||
| 37 | /// File where to locate this symbol. | ||
| 38 | file: *Object, | ||
| 39 | |||
| 40 | /// Debug stab if defined. | ||
| 41 | stab: ?struct { | ||
| 42 | /// Stab kind | ||
| 43 | kind: enum { | ||
| 44 | function, | ||
| 45 | global, | ||
| 46 | static, | ||
| 47 | }, | ||
| 24 | 48 | ||
| 25 | /// Index of this symbol within the file's symbol table. | 49 | /// Size of the stab. |
| 26 | index: ?u32 = null, | 50 | size: u64, |
| 51 | } = null, | ||
| 27 | 52 | ||
| 28 | pub fn deinit(self: *Symbol, allocator: *Allocator) void { | 53 | pub const base_type: Symbol.Type = .regular; |
| 29 | allocator.free(self.name); | 54 | |
| 55 | pub const Linkage = enum { | ||
| 56 | translation_unit, | ||
| 57 | linkage_unit, | ||
| 58 | global, | ||
| 59 | }; | ||
| 60 | }; | ||
| 61 | |||
| 62 | pub const Proxy = struct { | ||
| 63 | base: Symbol, | ||
| 64 | |||
| 65 | /// Dylib ordinal. | ||
| 66 | dylib: u16, | ||
| 67 | |||
| 68 | pub const base_type: Symbol.Type = .proxy; | ||
| 69 | }; | ||
| 70 | |||
| 71 | pub const Unresolved = struct { | ||
| 72 | base: Symbol, | ||
| 73 | |||
| 74 | /// Alias of. | ||
| 75 | alias: ?*Symbol = null, | ||
| 76 | |||
| 77 | /// File where this symbol was referenced. | ||
| 78 | file: *Object, | ||
| 79 | |||
| 80 | pub const base_type: Symbol.Type = .unresolved; | ||
| 81 | }; | ||
| 82 | |||
| 83 | pub fn deinit(base: *Symbol, allocator: *Allocator) void { | ||
| 84 | allocator.free(base.name); | ||
| 85 | } | ||
| 86 | |||
| 87 | pub fn cast(base: *Symbol, comptime T: type) ?*T { | ||
| 88 | if (base.@"type" != T.base_type) { | ||
| 89 | return null; | ||
| 90 | } | ||
| 91 | return @fieldParentPtr(T, "base", base); | ||
| 30 | } | 92 | } |
| 31 | 93 | ||
| 32 | pub fn isStab(sym: macho.nlist_64) bool { | 94 | pub fn isStab(sym: macho.nlist_64) bool { |
| ... | @@ -55,17 +117,6 @@ pub fn isWeakDef(sym: macho.nlist_64) bool { | ... | @@ -55,17 +117,6 @@ pub fn isWeakDef(sym: macho.nlist_64) bool { |
| 55 | return (sym.n_desc & macho.N_WEAK_DEF) != 0; | 117 | return (sym.n_desc & macho.N_WEAK_DEF) != 0; |
| 56 | } | 118 | } |
| 57 | 119 | ||
| 58 | /// Symbol is local if it is defined and not an extern. | 120 | pub fn isWeakRef(sym: macho.nlist_64) bool { |
| 59 | pub fn isLocal(sym: macho.nlist_64) bool { | 121 | return (sym.n_desc & macho.N_WEAK_REF) != 0; |
| 60 | return isSect(sym) and !isExt(sym); | ||
| 61 | } | ||
| 62 | |||
| 63 | /// Symbol is global if it is defined and an extern. | ||
| 64 | pub fn isGlobal(sym: macho.nlist_64) bool { | ||
| 65 | return isSect(sym) and isExt(sym); | ||
| 66 | } | ||
| 67 | |||
| 68 | /// Symbol is undefined if it is not defined and an extern. | ||
| 69 | pub fn isUndef(sym: macho.nlist_64) bool { | ||
| 70 | return isUndf(sym) and isExt(sym); | ||
| 71 | } | 122 | } |
src/link/MachO/reloc.zig+7-3| ... | @@ -10,6 +10,7 @@ const aarch64 = @import("reloc/aarch64.zig"); | ... | @@ -10,6 +10,7 @@ const aarch64 = @import("reloc/aarch64.zig"); |
| 10 | const x86_64 = @import("reloc/x86_64.zig"); | 10 | const x86_64 = @import("reloc/x86_64.zig"); |
| 11 | 11 | ||
| 12 | const Allocator = mem.Allocator; | 12 | const Allocator = mem.Allocator; |
| 13 | const Symbol = @import("Symbol.zig"); | ||
| 13 | 14 | ||
| 14 | pub const Relocation = struct { | 15 | pub const Relocation = struct { |
| 15 | @"type": Type, | 16 | @"type": Type, |
| ... | @@ -75,12 +76,12 @@ pub const Relocation = struct { | ... | @@ -75,12 +76,12 @@ pub const Relocation = struct { |
| 75 | }; | 76 | }; |
| 76 | 77 | ||
| 77 | pub const Target = union(enum) { | 78 | pub const Target = union(enum) { |
| 78 | symbol: u32, | 79 | symbol: *Symbol, |
| 79 | section: u16, | 80 | section: u16, |
| 80 | 81 | ||
| 81 | pub fn from_reloc(reloc: macho.relocation_info) Target { | 82 | pub fn from_reloc(reloc: macho.relocation_info, symbols: []*Symbol) Target { |
| 82 | return if (reloc.r_extern == 1) .{ | 83 | return if (reloc.r_extern == 1) .{ |
| 83 | .symbol = reloc.r_symbolnum, | 84 | .symbol = symbols[reloc.r_symbolnum], |
| 84 | } else .{ | 85 | } else .{ |
| 85 | .section = @intCast(u16, reloc.r_symbolnum - 1), | 86 | .section = @intCast(u16, reloc.r_symbolnum - 1), |
| 86 | }; | 87 | }; |
| ... | @@ -136,6 +137,7 @@ pub fn parse( | ... | @@ -136,6 +137,7 @@ pub fn parse( |
| 136 | arch: std.Target.Cpu.Arch, | 137 | arch: std.Target.Cpu.Arch, |
| 137 | code: []u8, | 138 | code: []u8, |
| 138 | relocs: []const macho.relocation_info, | 139 | relocs: []const macho.relocation_info, |
| 140 | symbols: []*Symbol, | ||
| 139 | ) ![]*Relocation { | 141 | ) ![]*Relocation { |
| 140 | var it = RelocIterator{ | 142 | var it = RelocIterator{ |
| 141 | .buffer = relocs, | 143 | .buffer = relocs, |
| ... | @@ -148,6 +150,7 @@ pub fn parse( | ... | @@ -148,6 +150,7 @@ pub fn parse( |
| 148 | .it = &it, | 150 | .it = &it, |
| 149 | .code = code, | 151 | .code = code, |
| 150 | .parsed = std.ArrayList(*Relocation).init(allocator), | 152 | .parsed = std.ArrayList(*Relocation).init(allocator), |
| 153 | .symbols = symbols, | ||
| 151 | }; | 154 | }; |
| 152 | defer parser.deinit(); | 155 | defer parser.deinit(); |
| 153 | try parser.parse(); | 156 | try parser.parse(); |
| ... | @@ -160,6 +163,7 @@ pub fn parse( | ... | @@ -160,6 +163,7 @@ pub fn parse( |
| 160 | .it = &it, | 163 | .it = &it, |
| 161 | .code = code, | 164 | .code = code, |
| 162 | .parsed = std.ArrayList(*Relocation).init(allocator), | 165 | .parsed = std.ArrayList(*Relocation).init(allocator), |
| 166 | .symbols = symbols, | ||
| 163 | }; | 167 | }; |
| 164 | defer parser.deinit(); | 168 | defer parser.deinit(); |
| 165 | try parser.parse(); | 169 | try parser.parse(); |
src/link/MachO/reloc/aarch64.zig+9-7| ... | @@ -10,6 +10,7 @@ const reloc = @import("../reloc.zig"); | ... | @@ -10,6 +10,7 @@ const reloc = @import("../reloc.zig"); |
| 10 | 10 | ||
| 11 | const Allocator = mem.Allocator; | 11 | const Allocator = mem.Allocator; |
| 12 | const Relocation = reloc.Relocation; | 12 | const Relocation = reloc.Relocation; |
| 13 | const Symbol = @import("../Symbol.zig"); | ||
| 13 | 14 | ||
| 14 | pub const Branch = struct { | 15 | pub const Branch = struct { |
| 15 | base: Relocation, | 16 | base: Relocation, |
| ... | @@ -188,6 +189,7 @@ pub const Parser = struct { | ... | @@ -188,6 +189,7 @@ pub const Parser = struct { |
| 188 | it: *reloc.RelocIterator, | 189 | it: *reloc.RelocIterator, |
| 189 | code: []u8, | 190 | code: []u8, |
| 190 | parsed: std.ArrayList(*Relocation), | 191 | parsed: std.ArrayList(*Relocation), |
| 192 | symbols: []*Symbol, | ||
| 191 | addend: ?u32 = null, | 193 | addend: ?u32 = null, |
| 192 | subtractor: ?Relocation.Target = null, | 194 | subtractor: ?Relocation.Target = null, |
| 193 | 195 | ||
| ... | @@ -273,7 +275,7 @@ pub const Parser = struct { | ... | @@ -273,7 +275,7 @@ pub const Parser = struct { |
| 273 | var branch = try parser.allocator.create(Branch); | 275 | var branch = try parser.allocator.create(Branch); |
| 274 | errdefer parser.allocator.destroy(branch); | 276 | errdefer parser.allocator.destroy(branch); |
| 275 | 277 | ||
| 276 | const target = Relocation.Target.from_reloc(rel); | 278 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 277 | 279 | ||
| 278 | branch.* = .{ | 280 | branch.* = .{ |
| 279 | .base = .{ | 281 | .base = .{ |
| ... | @@ -294,7 +296,7 @@ pub const Parser = struct { | ... | @@ -294,7 +296,7 @@ pub const Parser = struct { |
| 294 | assert(rel.r_length == 2); | 296 | assert(rel.r_length == 2); |
| 295 | 297 | ||
| 296 | const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type); | 298 | const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type); |
| 297 | const target = Relocation.Target.from_reloc(rel); | 299 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 298 | 300 | ||
| 299 | const offset = @intCast(u32, rel.r_address); | 301 | const offset = @intCast(u32, rel.r_address); |
| 300 | const inst = parser.code[offset..][0..4]; | 302 | const inst = parser.code[offset..][0..4]; |
| ... | @@ -400,7 +402,7 @@ pub const Parser = struct { | ... | @@ -400,7 +402,7 @@ pub const Parser = struct { |
| 400 | aarch64.Instruction.load_store_register, | 402 | aarch64.Instruction.load_store_register, |
| 401 | ), inst) }; | 403 | ), inst) }; |
| 402 | } | 404 | } |
| 403 | const target = Relocation.Target.from_reloc(rel); | 405 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 404 | 406 | ||
| 405 | var page_off = try parser.allocator.create(PageOff); | 407 | var page_off = try parser.allocator.create(PageOff); |
| 406 | errdefer parser.allocator.destroy(page_off); | 408 | errdefer parser.allocator.destroy(page_off); |
| ... | @@ -437,7 +439,7 @@ pub const Parser = struct { | ... | @@ -437,7 +439,7 @@ pub const Parser = struct { |
| 437 | ), inst); | 439 | ), inst); |
| 438 | assert(parsed_inst.size == 3); | 440 | assert(parsed_inst.size == 3); |
| 439 | 441 | ||
| 440 | const target = Relocation.Target.from_reloc(rel); | 442 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 441 | 443 | ||
| 442 | var page_off = try parser.allocator.create(GotPageOff); | 444 | var page_off = try parser.allocator.create(GotPageOff); |
| 443 | errdefer parser.allocator.destroy(page_off); | 445 | errdefer parser.allocator.destroy(page_off); |
| ... | @@ -496,7 +498,7 @@ pub const Parser = struct { | ... | @@ -496,7 +498,7 @@ pub const Parser = struct { |
| 496 | } | 498 | } |
| 497 | }; | 499 | }; |
| 498 | 500 | ||
| 499 | const target = Relocation.Target.from_reloc(rel); | 501 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 500 | 502 | ||
| 501 | var page_off = try parser.allocator.create(TlvpPageOff); | 503 | var page_off = try parser.allocator.create(TlvpPageOff); |
| 502 | errdefer parser.allocator.destroy(page_off); | 504 | errdefer parser.allocator.destroy(page_off); |
| ... | @@ -531,7 +533,7 @@ pub const Parser = struct { | ... | @@ -531,7 +533,7 @@ pub const Parser = struct { |
| 531 | assert(rel.r_pcrel == 0); | 533 | assert(rel.r_pcrel == 0); |
| 532 | assert(parser.subtractor == null); | 534 | assert(parser.subtractor == null); |
| 533 | 535 | ||
| 534 | parser.subtractor = Relocation.Target.from_reloc(rel); | 536 | parser.subtractor = Relocation.Target.from_reloc(rel, parser.symbols); |
| 535 | 537 | ||
| 536 | // Verify SUBTRACTOR is followed by UNSIGNED. | 538 | // Verify SUBTRACTOR is followed by UNSIGNED. |
| 537 | const next = @intToEnum(macho.reloc_type_arm64, parser.it.peek().r_type); | 539 | const next = @intToEnum(macho.reloc_type_arm64, parser.it.peek().r_type); |
| ... | @@ -554,7 +556,7 @@ pub const Parser = struct { | ... | @@ -554,7 +556,7 @@ pub const Parser = struct { |
| 554 | var unsigned = try parser.allocator.create(reloc.Unsigned); | 556 | var unsigned = try parser.allocator.create(reloc.Unsigned); |
| 555 | errdefer parser.allocator.destroy(unsigned); | 557 | errdefer parser.allocator.destroy(unsigned); |
| 556 | 558 | ||
| 557 | const target = Relocation.Target.from_reloc(rel); | 559 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 558 | const is_64bit: bool = switch (rel.r_length) { | 560 | const is_64bit: bool = switch (rel.r_length) { |
| 559 | 3 => true, | 561 | 3 => true, |
| 560 | 2 => false, | 562 | 2 => false, |
src/link/MachO/reloc/x86_64.zig+9-7| ... | @@ -9,6 +9,7 @@ const reloc = @import("../reloc.zig"); | ... | @@ -9,6 +9,7 @@ const reloc = @import("../reloc.zig"); |
| 9 | 9 | ||
| 10 | const Allocator = mem.Allocator; | 10 | const Allocator = mem.Allocator; |
| 11 | const Relocation = reloc.Relocation; | 11 | const Relocation = reloc.Relocation; |
| 12 | const Symbol = @import("../Symbol.zig"); | ||
| 12 | 13 | ||
| 13 | pub const Branch = struct { | 14 | pub const Branch = struct { |
| 14 | base: Relocation, | 15 | base: Relocation, |
| ... | @@ -95,6 +96,7 @@ pub const Parser = struct { | ... | @@ -95,6 +96,7 @@ pub const Parser = struct { |
| 95 | it: *reloc.RelocIterator, | 96 | it: *reloc.RelocIterator, |
| 96 | code: []u8, | 97 | code: []u8, |
| 97 | parsed: std.ArrayList(*Relocation), | 98 | parsed: std.ArrayList(*Relocation), |
| 99 | symbols: []*Symbol, | ||
| 98 | subtractor: ?Relocation.Target = null, | 100 | subtractor: ?Relocation.Target = null, |
| 99 | 101 | ||
| 100 | pub fn deinit(parser: *Parser) void { | 102 | pub fn deinit(parser: *Parser) void { |
| ... | @@ -145,7 +147,7 @@ pub const Parser = struct { | ... | @@ -145,7 +147,7 @@ pub const Parser = struct { |
| 145 | var branch = try parser.allocator.create(Branch); | 147 | var branch = try parser.allocator.create(Branch); |
| 146 | errdefer parser.allocator.destroy(branch); | 148 | errdefer parser.allocator.destroy(branch); |
| 147 | 149 | ||
| 148 | const target = Relocation.Target.from_reloc(rel); | 150 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 149 | 151 | ||
| 150 | branch.* = .{ | 152 | branch.* = .{ |
| 151 | .base = .{ | 153 | .base = .{ |
| ... | @@ -165,7 +167,7 @@ pub const Parser = struct { | ... | @@ -165,7 +167,7 @@ pub const Parser = struct { |
| 165 | assert(rel.r_length == 2); | 167 | assert(rel.r_length == 2); |
| 166 | 168 | ||
| 167 | const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type); | 169 | const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type); |
| 168 | const target = Relocation.Target.from_reloc(rel); | 170 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 169 | const is_extern = rel.r_extern == 1; | 171 | const is_extern = rel.r_extern == 1; |
| 170 | 172 | ||
| 171 | const offset = @intCast(u32, rel.r_address); | 173 | const offset = @intCast(u32, rel.r_address); |
| ... | @@ -211,7 +213,7 @@ pub const Parser = struct { | ... | @@ -211,7 +213,7 @@ pub const Parser = struct { |
| 211 | 213 | ||
| 212 | const offset = @intCast(u32, rel.r_address); | 214 | const offset = @intCast(u32, rel.r_address); |
| 213 | const inst = parser.code[offset..][0..4]; | 215 | const inst = parser.code[offset..][0..4]; |
| 214 | const target = Relocation.Target.from_reloc(rel); | 216 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 215 | 217 | ||
| 216 | var got_load = try parser.allocator.create(GotLoad); | 218 | var got_load = try parser.allocator.create(GotLoad); |
| 217 | errdefer parser.allocator.destroy(got_load); | 219 | errdefer parser.allocator.destroy(got_load); |
| ... | @@ -237,7 +239,7 @@ pub const Parser = struct { | ... | @@ -237,7 +239,7 @@ pub const Parser = struct { |
| 237 | 239 | ||
| 238 | const offset = @intCast(u32, rel.r_address); | 240 | const offset = @intCast(u32, rel.r_address); |
| 239 | const inst = parser.code[offset..][0..4]; | 241 | const inst = parser.code[offset..][0..4]; |
| 240 | const target = Relocation.Target.from_reloc(rel); | 242 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 241 | 243 | ||
| 242 | var got = try parser.allocator.create(Got); | 244 | var got = try parser.allocator.create(Got); |
| 243 | errdefer parser.allocator.destroy(got); | 245 | errdefer parser.allocator.destroy(got); |
| ... | @@ -263,7 +265,7 @@ pub const Parser = struct { | ... | @@ -263,7 +265,7 @@ pub const Parser = struct { |
| 263 | 265 | ||
| 264 | const offset = @intCast(u32, rel.r_address); | 266 | const offset = @intCast(u32, rel.r_address); |
| 265 | const inst = parser.code[offset..][0..4]; | 267 | const inst = parser.code[offset..][0..4]; |
| 266 | const target = Relocation.Target.from_reloc(rel); | 268 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 267 | 269 | ||
| 268 | var tlv = try parser.allocator.create(Tlv); | 270 | var tlv = try parser.allocator.create(Tlv); |
| 269 | errdefer parser.allocator.destroy(tlv); | 271 | errdefer parser.allocator.destroy(tlv); |
| ... | @@ -288,7 +290,7 @@ pub const Parser = struct { | ... | @@ -288,7 +290,7 @@ pub const Parser = struct { |
| 288 | assert(rel.r_pcrel == 0); | 290 | assert(rel.r_pcrel == 0); |
| 289 | assert(parser.subtractor == null); | 291 | assert(parser.subtractor == null); |
| 290 | 292 | ||
| 291 | parser.subtractor = Relocation.Target.from_reloc(rel); | 293 | parser.subtractor = Relocation.Target.from_reloc(rel, parser.symbols); |
| 292 | 294 | ||
| 293 | // Verify SUBTRACTOR is followed by UNSIGNED. | 295 | // Verify SUBTRACTOR is followed by UNSIGNED. |
| 294 | const next = @intToEnum(macho.reloc_type_x86_64, parser.it.peek().r_type); | 296 | const next = @intToEnum(macho.reloc_type_x86_64, parser.it.peek().r_type); |
| ... | @@ -311,7 +313,7 @@ pub const Parser = struct { | ... | @@ -311,7 +313,7 @@ pub const Parser = struct { |
| 311 | var unsigned = try parser.allocator.create(reloc.Unsigned); | 313 | var unsigned = try parser.allocator.create(reloc.Unsigned); |
| 312 | errdefer parser.allocator.destroy(unsigned); | 314 | errdefer parser.allocator.destroy(unsigned); |
| 313 | 315 | ||
| 314 | const target = Relocation.Target.from_reloc(rel); | 316 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 315 | const is_64bit: bool = switch (rel.r_length) { | 317 | const is_64bit: bool = switch (rel.r_length) { |
| 316 | 3 => true, | 318 | 3 => true, |
| 317 | 2 => false, | 319 | 2 => false, |