| ... | @@ -20,9 +20,14 @@ const MachO = @import("../MachO.zig"); | ... | @@ -20,9 +20,14 @@ const MachO = @import("../MachO.zig"); |
| 20 | file: fs.File, | 20 | file: fs.File, |
| 21 | name: []const u8, | 21 | name: []const u8, |
| 22 | | 22 | |
| | 23 | /// Data contents of the file. Includes sections, and data of load commands. |
| | 24 | /// Excludes the backing memory for the header and load commands. |
| | 25 | /// Initialized in `parse`. |
| | 26 | contents: []const u8 = undefined, |
| | 27 | |
| 23 | file_offset: ?u32 = null, | 28 | file_offset: ?u32 = null, |
| 24 | | 29 | |
| 25 | header: ?macho.mach_header_64 = null, | 30 | header: macho.mach_header_64 = undefined, |
| 26 | | 31 | |
| 27 | load_commands: std.ArrayListUnmanaged(macho.LoadCommand) = .{}, | 32 | load_commands: std.ArrayListUnmanaged(macho.LoadCommand) = .{}, |
| 28 | | 33 | |
| ... | @@ -41,9 +46,9 @@ dwarf_debug_line_index: ?u16 = null, | ... | @@ -41,9 +46,9 @@ dwarf_debug_line_index: ?u16 = null, |
| 41 | dwarf_debug_line_str_index: ?u16 = null, | 46 | dwarf_debug_line_str_index: ?u16 = null, |
| 42 | dwarf_debug_ranges_index: ?u16 = null, | 47 | dwarf_debug_ranges_index: ?u16 = null, |
| 43 | | 48 | |
| 44 | symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | 49 | symtab: []const macho.nlist_64 = &.{}, |
| 45 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 50 | strtab: []const u8 = &.{}, |
| 46 | data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{}, | 51 | data_in_code_entries: []const macho.data_in_code_entry = &.{}, |
| 47 | | 52 | |
| 48 | // Debug info | 53 | // Debug info |
| 49 | debug_info: ?DebugInfo = null, | 54 | debug_info: ?DebugInfo = null, |
| ... | @@ -65,41 +70,41 @@ analyzed: bool = false, | ... | @@ -65,41 +70,41 @@ analyzed: bool = false, |
| 65 | | 70 | |
| 66 | const DebugInfo = struct { | 71 | const DebugInfo = struct { |
| 67 | inner: dwarf.DwarfInfo, | 72 | inner: dwarf.DwarfInfo, |
| 68 | debug_info: []u8, | 73 | debug_info: []const u8, |
| 69 | debug_abbrev: []u8, | 74 | debug_abbrev: []const u8, |
| 70 | debug_str: []u8, | 75 | debug_str: []const u8, |
| 71 | debug_line: []u8, | 76 | debug_line: []const u8, |
| 72 | debug_line_str: []u8, | 77 | debug_line_str: []const u8, |
| 73 | debug_ranges: []u8, | 78 | debug_ranges: []const u8, |
| 74 | | 79 | |
| 75 | pub fn parseFromObject(allocator: Allocator, object: *const Object) !?DebugInfo { | 80 | pub fn parseFromObject(allocator: Allocator, object: *const Object) !?DebugInfo { |
| 76 | var debug_info = blk: { | 81 | var debug_info = blk: { |
| 77 | const index = object.dwarf_debug_info_index orelse return null; | 82 | const index = object.dwarf_debug_info_index orelse return null; |
| 78 | break :blk try object.readSection(allocator, index); | 83 | break :blk object.getSectionContents(index); |
| 79 | }; | 84 | }; |
| 80 | var debug_abbrev = blk: { | 85 | var debug_abbrev = blk: { |
| 81 | const index = object.dwarf_debug_abbrev_index orelse return null; | 86 | const index = object.dwarf_debug_abbrev_index orelse return null; |
| 82 | break :blk try object.readSection(allocator, index); | 87 | break :blk object.getSectionContents(index); |
| 83 | }; | 88 | }; |
| 84 | var debug_str = blk: { | 89 | var debug_str = blk: { |
| 85 | const index = object.dwarf_debug_str_index orelse return null; | 90 | const index = object.dwarf_debug_str_index orelse return null; |
| 86 | break :blk try object.readSection(allocator, index); | 91 | break :blk object.getSectionContents(index); |
| 87 | }; | 92 | }; |
| 88 | var debug_line = blk: { | 93 | var debug_line = blk: { |
| 89 | const index = object.dwarf_debug_line_index orelse return null; | 94 | const index = object.dwarf_debug_line_index orelse return null; |
| 90 | break :blk try object.readSection(allocator, index); | 95 | break :blk object.getSectionContents(index); |
| 91 | }; | 96 | }; |
| 92 | var debug_line_str = blk: { | 97 | var debug_line_str = blk: { |
| 93 | if (object.dwarf_debug_line_str_index) |ind| { | 98 | if (object.dwarf_debug_line_str_index) |ind| { |
| 94 | break :blk try object.readSection(allocator, ind); | 99 | break :blk object.getSectionContents(ind); |
| 95 | } | 100 | } |
| 96 | break :blk try allocator.alloc(u8, 0); | 101 | break :blk &[0]u8{}; |
| 97 | }; | 102 | }; |
| 98 | var debug_ranges = blk: { | 103 | var debug_ranges = blk: { |
| 99 | if (object.dwarf_debug_ranges_index) |ind| { | 104 | if (object.dwarf_debug_ranges_index) |ind| { |
| 100 | break :blk try object.readSection(allocator, ind); | 105 | break :blk object.getSectionContents(ind); |
| 101 | } | 106 | } |
| 102 | break :blk try allocator.alloc(u8, 0); | 107 | break :blk &[0]u8{}; |
| 103 | }; | 108 | }; |
| 104 | | 109 | |
| 105 | var inner: dwarf.DwarfInfo = .{ | 110 | var inner: dwarf.DwarfInfo = .{ |
| ... | @@ -125,12 +130,6 @@ const DebugInfo = struct { | ... | @@ -125,12 +130,6 @@ const DebugInfo = struct { |
| 125 | } | 130 | } |
| 126 | | 131 | |
| 127 | pub fn deinit(self: *DebugInfo, allocator: Allocator) void { | 132 | pub fn deinit(self: *DebugInfo, allocator: Allocator) void { |
| 128 | allocator.free(self.debug_info); | | |
| 129 | allocator.free(self.debug_abbrev); | | |
| 130 | allocator.free(self.debug_str); | | |
| 131 | allocator.free(self.debug_line); | | |
| 132 | allocator.free(self.debug_line_str); | | |
| 133 | allocator.free(self.debug_ranges); | | |
| 134 | self.inner.deinit(allocator); | 133 | self.inner.deinit(allocator); |
| 135 | } | 134 | } |
| 136 | }; | 135 | }; |
| ... | @@ -140,9 +139,7 @@ pub fn deinit(self: *Object, allocator: Allocator) void { | ... | @@ -140,9 +139,7 @@ pub fn deinit(self: *Object, allocator: Allocator) void { |
| 140 | lc.deinit(allocator); | 139 | lc.deinit(allocator); |
| 141 | } | 140 | } |
| 142 | self.load_commands.deinit(allocator); | 141 | self.load_commands.deinit(allocator); |
| 143 | self.data_in_code_entries.deinit(allocator); | 142 | allocator.free(self.contents); |
| 144 | self.symtab.deinit(allocator); | | |
| 145 | self.strtab.deinit(allocator); | | |
| 146 | self.sections_as_symbols.deinit(allocator); | 143 | self.sections_as_symbols.deinit(allocator); |
| 147 | self.symbol_mapping.deinit(allocator); | 144 | self.symbol_mapping.deinit(allocator); |
| 148 | self.reverse_symbol_mapping.deinit(allocator); | 145 | self.reverse_symbol_mapping.deinit(allocator); |
| ... | @@ -155,14 +152,6 @@ pub fn deinit(self: *Object, allocator: Allocator) void { | ... | @@ -155,14 +152,6 @@ pub fn deinit(self: *Object, allocator: Allocator) void { |
| 155 | if (self.debug_info) |*db| { | 152 | if (self.debug_info) |*db| { |
| 156 | db.deinit(allocator); | 153 | db.deinit(allocator); |
| 157 | } | 154 | } |
| 158 | | | |
| 159 | if (self.tu_name) |n| { | | |
| 160 | allocator.free(n); | | |
| 161 | } | | |
| 162 | | | |
| 163 | if (self.tu_comp_dir) |n| { | | |
| 164 | allocator.free(n); | | |
| 165 | } | | |
| 166 | } | 155 | } |
| 167 | | 156 | |
| 168 | pub fn free(self: *Object, allocator: Allocator, macho_file: *MachO) void { | 157 | pub fn free(self: *Object, allocator: Allocator, macho_file: *MachO) void { |
| ... | @@ -233,21 +222,28 @@ fn freeAtoms(self: *Object, macho_file: *MachO) void { | ... | @@ -233,21 +222,28 @@ fn freeAtoms(self: *Object, macho_file: *MachO) void { |
| 233 | } | 222 | } |
| 234 | | 223 | |
| 235 | pub fn parse(self: *Object, allocator: Allocator, target: std.Target) !void { | 224 | pub fn parse(self: *Object, allocator: Allocator, target: std.Target) !void { |
| 236 | const reader = self.file.reader(); | 225 | const file_stat = try self.file.stat(); |
| 237 | if (self.file_offset) |offset| { | 226 | const file_size = math.cast(usize, file_stat.size) orelse return error.Overflow; |
| 238 | try reader.context.seekTo(offset); | 227 | self.contents = try self.file.readToEndAlloc(allocator, file_size); |
| | 228 | |
| | 229 | var stream = std.io.fixedBufferStream(self.contents); |
| | 230 | const reader = stream.reader(); |
| | 231 | |
| | 232 | const file_offset = self.file_offset orelse 0; |
| | 233 | if (file_offset > 0) { |
| | 234 | try reader.context.seekTo(file_offset); |
| 239 | } | 235 | } |
| 240 | | 236 | |
| 241 | const header = try reader.readStruct(macho.mach_header_64); | 237 | self.header = try reader.readStruct(macho.mach_header_64); |
| 242 | if (header.filetype != macho.MH_OBJECT) { | 238 | if (self.header.filetype != macho.MH_OBJECT) { |
| 243 | log.debug("invalid filetype: expected 0x{x}, found 0x{x}", .{ | 239 | log.debug("invalid filetype: expected 0x{x}, found 0x{x}", .{ |
| 244 | macho.MH_OBJECT, | 240 | macho.MH_OBJECT, |
| 245 | header.filetype, | 241 | self.header.filetype, |
| 246 | }); | 242 | }); |
| 247 | return error.NotObject; | 243 | return error.NotObject; |
| 248 | } | 244 | } |
| 249 | | 245 | |
| 250 | const this_arch: std.Target.Cpu.Arch = switch (header.cputype) { | 246 | const this_arch: std.Target.Cpu.Arch = switch (self.header.cputype) { |
| 251 | macho.CPU_TYPE_ARM64 => .aarch64, | 247 | macho.CPU_TYPE_ARM64 => .aarch64, |
| 252 | macho.CPU_TYPE_X86_64 => .x86_64, | 248 | macho.CPU_TYPE_X86_64 => .x86_64, |
| 253 | else => |value| { | 249 | else => |value| { |
| ... | @@ -260,22 +256,10 @@ pub fn parse(self: *Object, allocator: Allocator, target: std.Target) !void { | ... | @@ -260,22 +256,10 @@ pub fn parse(self: *Object, allocator: Allocator, target: std.Target) !void { |
| 260 | return error.MismatchedCpuArchitecture; | 256 | return error.MismatchedCpuArchitecture; |
| 261 | } | 257 | } |
| 262 | | 258 | |
| 263 | self.header = header; | 259 | try self.load_commands.ensureUnusedCapacity(allocator, self.header.ncmds); |
| 264 | | | |
| 265 | try self.readLoadCommands(allocator, reader); | | |
| 266 | try self.parseSymtab(allocator); | | |
| 267 | try self.parseDataInCode(allocator); | | |
| 268 | try self.parseDebugInfo(allocator); | | |
| 269 | } | | |
| 270 | | | |
| 271 | pub fn readLoadCommands(self: *Object, allocator: Allocator, reader: anytype) !void { | | |
| 272 | const header = self.header orelse unreachable; // Unreachable here signifies a fatal unexplored condition. | | |
| 273 | const offset = self.file_offset orelse 0; | | |
| 274 | | | |
| 275 | try self.load_commands.ensureUnusedCapacity(allocator, header.ncmds); | | |
| 276 | | 260 | |
| 277 | var i: u16 = 0; | 261 | var i: u16 = 0; |
| 278 | while (i < header.ncmds) : (i += 1) { | 262 | while (i < self.header.ncmds) : (i += 1) { |
| 279 | var cmd = try macho.LoadCommand.read(allocator, reader); | 263 | var cmd = try macho.LoadCommand.read(allocator, reader); |
| 280 | switch (cmd.cmd()) { | 264 | switch (cmd.cmd()) { |
| 281 | .SEGMENT_64 => { | 265 | .SEGMENT_64 => { |
| ... | @@ -305,18 +289,18 @@ pub fn readLoadCommands(self: *Object, allocator: Allocator, reader: anytype) !v | ... | @@ -305,18 +289,18 @@ pub fn readLoadCommands(self: *Object, allocator: Allocator, reader: anytype) !v |
| 305 | } | 289 | } |
| 306 | } | 290 | } |
| 307 | | 291 | |
| 308 | sect.offset += offset; | 292 | sect.offset += file_offset; |
| 309 | if (sect.reloff > 0) { | 293 | if (sect.reloff > 0) { |
| 310 | sect.reloff += offset; | 294 | sect.reloff += file_offset; |
| 311 | } | 295 | } |
| 312 | } | 296 | } |
| 313 | | 297 | |
| 314 | seg.inner.fileoff += offset; | 298 | seg.inner.fileoff += file_offset; |
| 315 | }, | 299 | }, |
| 316 | .SYMTAB => { | 300 | .SYMTAB => { |
| 317 | self.symtab_cmd_index = i; | 301 | self.symtab_cmd_index = i; |
| 318 | cmd.symtab.symoff += offset; | 302 | cmd.symtab.symoff += file_offset; |
| 319 | cmd.symtab.stroff += offset; | 303 | cmd.symtab.stroff += file_offset; |
| 320 | }, | 304 | }, |
| 321 | .DYSYMTAB => { | 305 | .DYSYMTAB => { |
| 322 | self.dysymtab_cmd_index = i; | 306 | self.dysymtab_cmd_index = i; |
| ... | @@ -326,7 +310,7 @@ pub fn readLoadCommands(self: *Object, allocator: Allocator, reader: anytype) !v | ... | @@ -326,7 +310,7 @@ pub fn readLoadCommands(self: *Object, allocator: Allocator, reader: anytype) !v |
| 326 | }, | 310 | }, |
| 327 | .DATA_IN_CODE => { | 311 | .DATA_IN_CODE => { |
| 328 | self.data_in_code_cmd_index = i; | 312 | self.data_in_code_cmd_index = i; |
| 329 | cmd.linkedit_data.dataoff += offset; | 313 | cmd.linkedit_data.dataoff += file_offset; |
| 330 | }, | 314 | }, |
| 331 | else => { | 315 | else => { |
| 332 | log.debug("Unknown load command detected: 0x{x}.", .{cmd.cmd()}); | 316 | log.debug("Unknown load command detected: 0x{x}.", .{cmd.cmd()}); |
| ... | @@ -334,6 +318,10 @@ pub fn readLoadCommands(self: *Object, allocator: Allocator, reader: anytype) !v | ... | @@ -334,6 +318,10 @@ pub fn readLoadCommands(self: *Object, allocator: Allocator, reader: anytype) !v |
| 334 | } | 318 | } |
| 335 | self.load_commands.appendAssumeCapacity(cmd); | 319 | self.load_commands.appendAssumeCapacity(cmd); |
| 336 | } | 320 | } |
| | 321 | |
| | 322 | self.parseSymtab(); |
| | 323 | self.parseDataInCode(); |
| | 324 | try self.parseDebugInfo(allocator); |
| 337 | } | 325 | } |
| 338 | | 326 | |
| 339 | const NlistWithIndex = struct { | 327 | const NlistWithIndex = struct { |
| ... | @@ -373,7 +361,11 @@ const NlistWithIndex = struct { | ... | @@ -373,7 +361,11 @@ const NlistWithIndex = struct { |
| 373 | } | 361 | } |
| 374 | }; | 362 | }; |
| 375 | | 363 | |
| 376 | fn filterDice(dices: []macho.data_in_code_entry, start_addr: u64, end_addr: u64) []macho.data_in_code_entry { | 364 | fn filterDice( |
| | 365 | dices: []const macho.data_in_code_entry, |
| | 366 | start_addr: u64, |
| | 367 | end_addr: u64, |
| | 368 | ) []const macho.data_in_code_entry { |
| 377 | const Predicate = struct { | 369 | const Predicate = struct { |
| 378 | addr: u64, | 370 | addr: u64, |
| 379 | | 371 | |
| ... | @@ -400,10 +392,10 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) ! | ... | @@ -400,10 +392,10 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) ! |
| 400 | // local < extern defined < undefined. Unfortunately, this is not guaranteed! For instance, | 392 | // local < extern defined < undefined. Unfortunately, this is not guaranteed! For instance, |
| 401 | // the GO compiler does not necessarily respect that therefore we sort immediately by type | 393 | // the GO compiler does not necessarily respect that therefore we sort immediately by type |
| 402 | // and address within. | 394 | // and address within. |
| 403 | var sorted_all_nlists = try std.ArrayList(NlistWithIndex).initCapacity(allocator, self.symtab.items.len); | 395 | var sorted_all_nlists = try std.ArrayList(NlistWithIndex).initCapacity(allocator, self.symtab.len); |
| 404 | defer sorted_all_nlists.deinit(); | 396 | defer sorted_all_nlists.deinit(); |
| 405 | | 397 | |
| 406 | for (self.symtab.items) |nlist, index| { | 398 | for (self.symtab) |nlist, index| { |
| 407 | sorted_all_nlists.appendAssumeCapacity(.{ | 399 | sorted_all_nlists.appendAssumeCapacity(.{ |
| 408 | .nlist = nlist, | 400 | .nlist = nlist, |
| 409 | .index = @intCast(u32, index), | 401 | .index = @intCast(u32, index), |
| ... | @@ -439,16 +431,20 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) ! | ... | @@ -439,16 +431,20 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) ! |
| 439 | continue; | 431 | continue; |
| 440 | }; | 432 | }; |
| 441 | | 433 | |
| | 434 | const is_zerofill = blk: { |
| | 435 | const section_type = sect.type_(); |
| | 436 | break :blk section_type == macho.S_ZEROFILL or section_type == macho.S_THREAD_LOCAL_ZEROFILL; |
| | 437 | }; |
| | 438 | |
| 442 | // Read section's code | 439 | // Read section's code |
| 443 | var code = try allocator.alloc(u8, @intCast(usize, sect.size)); | 440 | const code: ?[]const u8 = if (!is_zerofill) self.getSectionContents(sect_id) else null; |
| 444 | defer allocator.free(code); | | |
| 445 | _ = try self.file.preadAll(code, sect.offset); | | |
| 446 | | 441 | |
| 447 | // Read section's list of relocations | 442 | // Read section's list of relocations |
| 448 | var raw_relocs = try allocator.alloc(u8, sect.nreloc * @sizeOf(macho.relocation_info)); | 443 | const raw_relocs = self.contents[sect.reloff..][0 .. sect.nreloc * @sizeOf(macho.relocation_info)]; |
| 449 | defer allocator.free(raw_relocs); | 444 | const relocs = mem.bytesAsSlice( |
| 450 | _ = try self.file.preadAll(raw_relocs, sect.reloff); | 445 | macho.relocation_info, |
| 451 | const relocs = mem.bytesAsSlice(macho.relocation_info, raw_relocs); | 446 | @alignCast(@alignOf(macho.relocation_info), raw_relocs), |
| | 447 | ); |
| 452 | | 448 | |
| 453 | // Symbols within this section only. | 449 | // Symbols within this section only. |
| 454 | const filtered_nlists = NlistWithIndex.filterInSection(sorted_nlists, sect); | 450 | const filtered_nlists = NlistWithIndex.filterInSection(sorted_nlists, sect); |
| ... | @@ -456,7 +452,7 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) ! | ... | @@ -456,7 +452,7 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) ! |
| 456 | macho_file.has_dices = macho_file.has_dices or blk: { | 452 | macho_file.has_dices = macho_file.has_dices or blk: { |
| 457 | if (self.text_section_index) |index| { | 453 | if (self.text_section_index) |index| { |
| 458 | if (index != id) break :blk false; | 454 | if (index != id) break :blk false; |
| 459 | if (self.data_in_code_entries.items.len == 0) break :blk false; | 455 | if (self.data_in_code_entries.len == 0) break :blk false; |
| 460 | break :blk true; | 456 | break :blk true; |
| 461 | } | 457 | } |
| 462 | break :blk false; | 458 | break :blk false; |
| ... | @@ -482,16 +478,12 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) ! | ... | @@ -482,16 +478,12 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) ! |
| 482 | const aligned_size = mem.alignForwardGeneric(u64, sect.size, alignment); | 478 | const aligned_size = mem.alignForwardGeneric(u64, sect.size, alignment); |
| 483 | const atom = try macho_file.createEmptyAtom(atom_local_sym_index, aligned_size, sect.@"align"); | 479 | const atom = try macho_file.createEmptyAtom(atom_local_sym_index, aligned_size, sect.@"align"); |
| 484 | | 480 | |
| 485 | const is_zerofill = blk: { | 481 | if (code) |cc| { |
| 486 | const section_type = sect.type_(); | 482 | assert(!is_zerofill); |
| 487 | break :blk section_type == macho.S_ZEROFILL or section_type == macho.S_THREAD_LOCAL_ZEROFILL; | 483 | mem.copy(u8, atom.code.items, cc); |
| 488 | }; | | |
| 489 | if (!is_zerofill) { | | |
| 490 | mem.copy(u8, atom.code.items, code); | | |
| 491 | } | 484 | } |
| 492 | | 485 | |
| 493 | // TODO stage2 bug: @alignCast shouldn't be needed | 486 | try atom.parseRelocs(relocs, .{ |
| 494 | try atom.parseRelocs(@alignCast(@alignOf(macho.relocation_info), relocs), .{ | | |
| 495 | .base_addr = sect.addr, | 487 | .base_addr = sect.addr, |
| 496 | .allocator = allocator, | 488 | .allocator = allocator, |
| 497 | .object = self, | 489 | .object = self, |
| ... | @@ -499,7 +491,7 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) ! | ... | @@ -499,7 +491,7 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) ! |
| 499 | }); | 491 | }); |
| 500 | | 492 | |
| 501 | if (macho_file.has_dices) { | 493 | if (macho_file.has_dices) { |
| 502 | const dices = filterDice(self.data_in_code_entries.items, sect.addr, sect.addr + sect.size); | 494 | const dices = filterDice(self.data_in_code_entries, sect.addr, sect.addr + sect.size); |
| 503 | try atom.dices.ensureTotalCapacity(allocator, dices.len); | 495 | try atom.dices.ensureTotalCapacity(allocator, dices.len); |
| 504 | | 496 | |
| 505 | for (dices) |dice| { | 497 | for (dices) |dice| { |
| ... | @@ -562,20 +554,13 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) ! | ... | @@ -562,20 +554,13 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) ! |
| 562 | } | 554 | } |
| 563 | } | 555 | } |
| 564 | | 556 | |
| 565 | fn parseSymtab(self: *Object, allocator: Allocator) !void { | 557 | fn parseSymtab(self: *Object) void { |
| 566 | const index = self.symtab_cmd_index orelse return; | 558 | const index = self.symtab_cmd_index orelse return; |
| 567 | const symtab_cmd = self.load_commands.items[index].symtab; | 559 | const symtab = self.load_commands.items[index].symtab; |
| 568 | | 560 | const symtab_size = @sizeOf(macho.nlist_64) * symtab.nsyms; |
| 569 | var symtab = try allocator.alloc(u8, @sizeOf(macho.nlist_64) * symtab_cmd.nsyms); | 561 | const raw_symtab = self.contents[symtab.symoff..][0..symtab_size]; |
| 570 | defer allocator.free(symtab); | 562 | self.symtab = mem.bytesAsSlice(macho.nlist_64, @alignCast(@alignOf(macho.nlist_64), raw_symtab)); |
| 571 | _ = try self.file.preadAll(symtab, symtab_cmd.symoff); | 563 | self.strtab = self.contents[symtab.stroff..][0..symtab.strsize]; |
| 572 | const slice = @alignCast(@alignOf(macho.nlist_64), mem.bytesAsSlice(macho.nlist_64, symtab)); | | |
| 573 | try self.symtab.appendSlice(allocator, slice); | | |
| 574 | | | |
| 575 | var strtab = try allocator.alloc(u8, symtab_cmd.strsize); | | |
| 576 | defer allocator.free(strtab); | | |
| 577 | _ = try self.file.preadAll(strtab, symtab_cmd.stroff); | | |
| 578 | try self.strtab.appendSlice(allocator, strtab); | | |
| 579 | } | 564 | } |
| 580 | | 565 | |
| 581 | pub fn parseDebugInfo(self: *Object, allocator: Allocator) !void { | 566 | pub fn parseDebugInfo(self: *Object, allocator: Allocator) !void { |
| ... | @@ -599,8 +584,8 @@ pub fn parseDebugInfo(self: *Object, allocator: Allocator) !void { | ... | @@ -599,8 +584,8 @@ pub fn parseDebugInfo(self: *Object, allocator: Allocator) !void { |
| 599 | const comp_dir = try compile_unit.die.getAttrString(&debug_info.inner, dwarf.AT.comp_dir); | 584 | const comp_dir = try compile_unit.die.getAttrString(&debug_info.inner, dwarf.AT.comp_dir); |
| 600 | | 585 | |
| 601 | self.debug_info = debug_info; | 586 | self.debug_info = debug_info; |
| 602 | self.tu_name = try allocator.dupe(u8, name); | 587 | self.tu_name = name; |
| 603 | self.tu_comp_dir = try allocator.dupe(u8, comp_dir); | 588 | self.tu_comp_dir = comp_dir; |
| 604 | | 589 | |
| 605 | if (self.mtime == null) { | 590 | if (self.mtime == null) { |
| 606 | self.mtime = mtime: { | 591 | self.mtime = mtime: { |
| ... | @@ -610,34 +595,29 @@ pub fn parseDebugInfo(self: *Object, allocator: Allocator) !void { | ... | @@ -610,34 +595,29 @@ pub fn parseDebugInfo(self: *Object, allocator: Allocator) !void { |
| 610 | } | 595 | } |
| 611 | } | 596 | } |
| 612 | | 597 | |
| 613 | pub fn parseDataInCode(self: *Object, allocator: Allocator) !void { | 598 | pub fn parseDataInCode(self: *Object) void { |
| 614 | const index = self.data_in_code_cmd_index orelse return; | 599 | const index = self.data_in_code_cmd_index orelse return; |
| 615 | const data_in_code = self.load_commands.items[index].linkedit_data; | 600 | const data_in_code = self.load_commands.items[index].linkedit_data; |
| 616 | | 601 | const raw_dice = self.contents[data_in_code.dataoff..][0..data_in_code.datasize]; |
| 617 | var buffer = try allocator.alloc(u8, data_in_code.datasize); | 602 | self.data_in_code_entries = mem.bytesAsSlice( |
| 618 | defer allocator.free(buffer); | 603 | macho.data_in_code_entry, |
| 619 | | 604 | @alignCast(@alignOf(macho.data_in_code_entry), raw_dice), |
| 620 | _ = try self.file.preadAll(buffer, data_in_code.dataoff); | 605 | ); |
| 621 | | | |
| 622 | var stream = io.fixedBufferStream(buffer); | | |
| 623 | var reader = stream.reader(); | | |
| 624 | while (true) { | | |
| 625 | const dice = reader.readStruct(macho.data_in_code_entry) catch |err| switch (err) { | | |
| 626 | error.EndOfStream => break, | | |
| 627 | }; | | |
| 628 | try self.data_in_code_entries.append(allocator, dice); | | |
| 629 | } | | |
| 630 | } | 606 | } |
| 631 | | 607 | |
| 632 | fn readSection(self: Object, allocator: Allocator, index: u16) ![]u8 { | 608 | fn getSectionContents(self: Object, sect_id: u16) []const u8 { |
| 633 | const seg = self.load_commands.items[self.segment_cmd_index.?].segment; | 609 | const seg = self.load_commands.items[self.segment_cmd_index.?].segment; |
| 634 | const sect = seg.sections.items[index]; | 610 | const sect = seg.sections.items[sect_id]; |
| 635 | var buffer = try allocator.alloc(u8, @intCast(usize, sect.size)); | 611 | log.debug("getting {s},{s} data at 0x{x} - 0x{x}", .{ |
| 636 | _ = try self.file.preadAll(buffer, sect.offset); | 612 | sect.segName(), |
| 637 | return buffer; | 613 | sect.sectName(), |
| | 614 | sect.offset, |
| | 615 | sect.offset + sect.size, |
| | 616 | }); |
| | 617 | return self.contents[sect.offset..][0..sect.size]; |
| 638 | } | 618 | } |
| 639 | | 619 | |
| 640 | pub fn getString(self: Object, off: u32) []const u8 { | 620 | pub fn getString(self: Object, off: u32) []const u8 { |
| 641 | assert(off < self.strtab.items.len); | 621 | assert(off < self.strtab.len); |
| 642 | return mem.sliceTo(@ptrCast([*:0]const u8, self.strtab.items.ptr + off), 0); | 622 | return mem.sliceTo(@ptrCast([*:0]const u8, self.strtab.ptr + off), 0); |
| 643 | } | 623 | } |