| ... | ... | @@ -15,6 +15,7 @@ const Allocator = mem.Allocator; |
| 15 | 15 | const Arch = std.Target.Cpu.Arch; |
| 16 | 16 | const Relocation = reloc.Relocation; |
| 17 | 17 | const Symbol = @import("Symbol.zig"); |
| 18 | const TextBlock = @import("Zld.zig").TextBlock; |
| 18 | 19 | |
| 19 | 20 | usingnamespace @import("commands.zig"); |
| 20 | 21 | |
| ... | ... | @@ -271,6 +272,7 @@ pub fn parse(self: *Object) !void { |
| 271 | 272 | try self.parseSymtab(); |
| 272 | 273 | try self.parseDataInCode(); |
| 273 | 274 | try self.parseInitializers(); |
| 275 | try self.parseDummy(); |
| 274 | 276 | } |
| 275 | 277 | |
| 276 | 278 | pub fn readLoadCommands(self: *Object, reader: anytype) !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 | 488 | pub fn parseInitializers(self: *Object) !void { |
| 383 | 489 | const index = self.mod_init_func_section_index orelse return; |
| 384 | 490 | const section = self.sections.items[index]; |