| ... | @@ -15,6 +15,7 @@ const Allocator = mem.Allocator; | ... | @@ -15,6 +15,7 @@ const Allocator = mem.Allocator; |
| 15 | const Arch = std.Target.Cpu.Arch; | 15 | const Arch = std.Target.Cpu.Arch; |
| 16 | const Relocation = reloc.Relocation; | 16 | const Relocation = reloc.Relocation; |
| 17 | const Symbol = @import("Symbol.zig"); | 17 | const Symbol = @import("Symbol.zig"); |
| | 18 | const TextBlock = @import("Zld.zig").TextBlock; |
| 18 | | 19 | |
| 19 | usingnamespace @import("commands.zig"); | 20 | usingnamespace @import("commands.zig"); |
| 20 | | 21 | |
| ... | @@ -271,6 +272,7 @@ pub fn parse(self: *Object) !void { | ... | @@ -271,6 +272,7 @@ pub fn parse(self: *Object) !void { |
| 271 | try self.parseSymtab(); | 272 | try self.parseSymtab(); |
| 272 | try self.parseDataInCode(); | 273 | try self.parseDataInCode(); |
| 273 | try self.parseInitializers(); | 274 | try self.parseInitializers(); |
| | 275 | try self.parseDummy(); |
| 274 | } | 276 | } |
| 275 | | 277 | |
| 276 | pub fn readLoadCommands(self: *Object, reader: anytype) !void { | 278 | pub fn readLoadCommands(self: *Object, reader: anytype) !void { |
| ... | @@ -379,6 +381,110 @@ pub fn parseSections(self: *Object) !void { | ... | @@ -379,6 +381,110 @@ pub fn parseSections(self: *Object) !void { |
| 379 | } | 381 | } |
| 380 | } | 382 | } |
| 381 | | 383 | |
| | 384 | fn cmpNlist(_: void, lhs: macho.nlist_64, rhs: macho.nlist_64) bool { |
| | 385 | return lhs.n_value < rhs.n_value; |
| | 386 | } |
| | 387 | |
| | 388 | fn filterSymsInSection(symbols: []macho.nlist_64, sect_id: u8) []macho.nlist_64 { |
| | 389 | var start: usize = 0; |
| | 390 | var end: usize = symbols.len; |
| | 391 | |
| | 392 | while (true) { |
| | 393 | var change = false; |
| | 394 | if (symbols[start].n_sect != sect_id) { |
| | 395 | start += 1; |
| | 396 | change = true; |
| | 397 | } |
| | 398 | if (symbols[end - 1].n_sect != sect_id) { |
| | 399 | end -= 1; |
| | 400 | change = true; |
| | 401 | } |
| | 402 | |
| | 403 | if (start == end) break; |
| | 404 | if (!change) break; |
| | 405 | } |
| | 406 | |
| | 407 | return symbols[start..end]; |
| | 408 | } |
| | 409 | |
| | 410 | pub fn parseDummy(self: *Object) !void { |
| | 411 | const seg = self.load_commands.items[self.segment_cmd_index.?].Segment; |
| | 412 | |
| | 413 | log.warn("analysing {s}", .{self.name.?}); |
| | 414 | |
| | 415 | const dysymtab = self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab; |
| | 416 | |
| | 417 | var sorted_syms = std.ArrayList(macho.nlist_64).init(self.allocator); |
| | 418 | defer sorted_syms.deinit(); |
| | 419 | try sorted_syms.appendSlice(self.symtab.items[dysymtab.ilocalsym..dysymtab.iundefsym]); |
| | 420 | |
| | 421 | std.sort.sort(macho.nlist_64, sorted_syms.items, {}, cmpNlist); |
| | 422 | |
| | 423 | for (seg.sections.items) |sect, sect_id| { |
| | 424 | log.warn("section {s},{s}", .{ parseName(&sect.segname), parseName(&sect.sectname) }); |
| | 425 | // Read code |
| | 426 | var code = try self.allocator.alloc(u8, @intCast(usize, sect.size)); |
| | 427 | defer self.allocator.free(code); |
| | 428 | _ = try self.file.?.preadAll(code, sect.offset); |
| | 429 | |
| | 430 | // Read and parse relocs |
| | 431 | const raw_relocs = try self.allocator.alloc(u8, @sizeOf(macho.relocation_info) * sect.nreloc); |
| | 432 | defer self.allocator.free(raw_relocs); |
| | 433 | _ = try self.file.?.preadAll(raw_relocs, sect.reloff); |
| | 434 | |
| | 435 | const relocs = try reloc.parse( |
| | 436 | self.allocator, |
| | 437 | self.arch.?, |
| | 438 | code, |
| | 439 | mem.bytesAsSlice(macho.relocation_info, raw_relocs), |
| | 440 | ); |
| | 441 | |
| | 442 | if (self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0) { |
| | 443 | const syms = filterSymsInSection(sorted_syms.items, @intCast(u8, sect_id + 1)); |
| | 444 | |
| | 445 | var indices = std.ArrayList(u32).init(self.allocator); |
| | 446 | defer indices.deinit(); |
| | 447 | |
| | 448 | var i: u32 = 0; |
| | 449 | while (i < syms.len) : (i += 1) { |
| | 450 | const curr = syms[i]; |
| | 451 | try indices.append(i); |
| | 452 | |
| | 453 | const next: ?macho.nlist_64 = if (i + 1 < syms.len) |
| | 454 | syms[i + 1] |
| | 455 | else |
| | 456 | null; |
| | 457 | |
| | 458 | if (next) |n| { |
| | 459 | if (curr.n_value == n.n_value) { |
| | 460 | continue; |
| | 461 | } |
| | 462 | } |
| | 463 | |
| | 464 | const start_addr = curr.n_value - sect.addr; |
| | 465 | const end_addr = if (next) |n| n.n_value - sect.addr else sect.size; |
| | 466 | const alignment = sect.@"align"; |
| | 467 | |
| | 468 | const tb_code = code[start_addr..end_addr]; |
| | 469 | const size = tb_code.len; |
| | 470 | |
| | 471 | log.warn("TextBlock", .{}); |
| | 472 | for (indices.items) |id| { |
| | 473 | log.warn(" | symbol {s}", .{self.getString(syms[id].n_strx)}); |
| | 474 | } |
| | 475 | log.warn(" | start_addr = 0x{x}", .{start_addr}); |
| | 476 | log.warn(" | end_addr = 0x{x}", .{end_addr}); |
| | 477 | log.warn(" | size = {}", .{size}); |
| | 478 | log.warn(" | alignment = 0x{x}", .{alignment}); |
| | 479 | |
| | 480 | indices.clearRetainingCapacity(); |
| | 481 | } |
| | 482 | } else { |
| | 483 | return error.TODOOneLargeTextBlock; |
| | 484 | } |
| | 485 | } |
| | 486 | } |
| | 487 | |
| 382 | pub fn parseInitializers(self: *Object) !void { | 488 | pub fn parseInitializers(self: *Object) !void { |
| 383 | const index = self.mod_init_func_section_index orelse return; | 489 | const index = self.mod_init_func_section_index orelse return; |
| 384 | const section = self.sections.items[index]; | 490 | const section = self.sections.items[index]; |