| ... | @@ -55,7 +55,11 @@ mtime: ?u64 = null, | ... | @@ -55,7 +55,11 @@ mtime: ?u64 = null, |
| 55 | | 55 | |
| 56 | text_blocks: std.ArrayListUnmanaged(*TextBlock) = .{}, | 56 | text_blocks: std.ArrayListUnmanaged(*TextBlock) = .{}, |
| 57 | sections_as_symbols: std.AutoHashMapUnmanaged(u16, u32) = .{}, | 57 | sections_as_symbols: std.AutoHashMapUnmanaged(u16, u32) = .{}, |
| | 58 | |
| | 59 | // TODO symbol mapping and its inverse can probably be simple arrays |
| | 60 | // instead of hash maps. |
| 58 | symbol_mapping: std.AutoHashMapUnmanaged(u32, u32) = .{}, | 61 | symbol_mapping: std.AutoHashMapUnmanaged(u32, u32) = .{}, |
| | 62 | reverse_symbol_mapping: std.AutoHashMapUnmanaged(u32, u32) = .{}, |
| 59 | | 63 | |
| 60 | const DebugInfo = struct { | 64 | const DebugInfo = struct { |
| 61 | inner: dwarf.DwarfInfo, | 65 | inner: dwarf.DwarfInfo, |
| ... | @@ -164,6 +168,7 @@ pub fn deinit(self: *Object) void { | ... | @@ -164,6 +168,7 @@ pub fn deinit(self: *Object) void { |
| 164 | self.text_blocks.deinit(self.allocator); | 168 | self.text_blocks.deinit(self.allocator); |
| 165 | self.sections_as_symbols.deinit(self.allocator); | 169 | self.sections_as_symbols.deinit(self.allocator); |
| 166 | self.symbol_mapping.deinit(self.allocator); | 170 | self.symbol_mapping.deinit(self.allocator); |
| | 171 | self.reverse_symbol_mapping.deinit(self.allocator); |
| 167 | | 172 | |
| 168 | if (self.debug_info) |*db| { | 173 | if (self.debug_info) |*db| { |
| 169 | db.deinit(self.allocator); | 174 | db.deinit(self.allocator); |
| ... | @@ -367,7 +372,7 @@ const TextBlockParser = struct { | ... | @@ -367,7 +372,7 @@ const TextBlockParser = struct { |
| 367 | } else if (MachO.symbolIsPext(rhs.nlist) or MachO.symbolIsWeakDef(rhs.nlist)) { | 372 | } else if (MachO.symbolIsPext(rhs.nlist) or MachO.symbolIsWeakDef(rhs.nlist)) { |
| 368 | return !MachO.symbolIsExt(lhs.nlist); | 373 | return !MachO.symbolIsExt(lhs.nlist); |
| 369 | } else { | 374 | } else { |
| 370 | return true; | 375 | return false; |
| 371 | } | 376 | } |
| 372 | } | 377 | } |
| 373 | | 378 | |
| ... | @@ -392,15 +397,7 @@ const TextBlockParser = struct { | ... | @@ -392,15 +397,7 @@ const TextBlockParser = struct { |
| 392 | } else null; | 397 | } else null; |
| 393 | | 398 | |
| 394 | for (aliases.items) |*nlist_with_index| { | 399 | for (aliases.items) |*nlist_with_index| { |
| 395 | nlist_with_index.index = self.symbol_mapping.get(nlist_with_index.index); | 400 | nlist_with_index.index = self.object.symbol_mapping.get(nlist_with_index.index) orelse unreachable; |
| 396 | const sym = self.object.symbols.items[nlist_with_index.index]; | | |
| 397 | if (sym.payload != .regular) { | | |
| 398 | log.err("expected a regular symbol, found {s}", .{sym.payload}); | | |
| 399 | log.err(" when remapping {s}", .{self.macho_file.getString(sym.strx)}); | | |
| 400 | return error.SymbolIsNotRegular; | | |
| 401 | } | | |
| 402 | assert(sym.payload.regular.local_sym_index != 0); // This means the symbol has not been properly resolved. | | |
| 403 | nlist_with_index.index = sym.payload.regular.local_sym_index; | | |
| 404 | } | 401 | } |
| 405 | | 402 | |
| 406 | if (aliases.items.len > 1) { | 403 | if (aliases.items.len > 1) { |
| ... | @@ -409,15 +406,13 @@ const TextBlockParser = struct { | ... | @@ -409,15 +406,13 @@ const TextBlockParser = struct { |
| 409 | NlistWithIndex, | 406 | NlistWithIndex, |
| 410 | aliases.items, | 407 | aliases.items, |
| 411 | SeniorityContext{ .object = self.object }, | 408 | SeniorityContext{ .object = self.object }, |
| 412 | @This().lessThanBySeniority, | 409 | TextBlockParser.lessThanBySeniority, |
| 413 | ); | 410 | ); |
| 414 | } | 411 | } |
| 415 | | 412 | |
| 416 | const senior_nlist = aliases.pop(); | 413 | const senior_nlist = aliases.pop(); |
| 417 | const senior_sym = self.macho_file.locals.items[senior_nlist.index]; | 414 | const senior_sym = &self.macho_file.locals.items[senior_nlist.index]; |
| 418 | assert(senior_sym.payload == .regular); | 415 | senior_sym.n_sect = self.macho_file.section_to_ordinal.get(self.match) orelse unreachable; |
| 419 | senior_sym.payload.regular.segment_id = self.match.seg; | | |
| 420 | senior_sym.payload.regular.section_id = self.match.sect; | | |
| 421 | | 416 | |
| 422 | const start_addr = senior_nlist.nlist.n_value - self.section.addr; | 417 | const start_addr = senior_nlist.nlist.n_value - self.section.addr; |
| 423 | const end_addr = if (next_nlist) |n| n.nlist.n_value - self.section.addr else self.section.size; | 418 | const end_addr = if (next_nlist) |n| n.nlist.n_value - self.section.addr else self.section.size; |
| ... | @@ -442,33 +437,29 @@ const TextBlockParser = struct { | ... | @@ -442,33 +437,29 @@ const TextBlockParser = struct { |
| 442 | } | 437 | } |
| 443 | } | 438 | } |
| 444 | } | 439 | } |
| 445 | if (self.macho_file.globals.contains(self.macho_file.getString(senior_sym.strx))) break :blk .global; | 440 | // TODO |
| | 441 | // if (self.macho_file.globals.contains(self.macho_file.getString(senior_sym.strx))) break :blk .global; |
| 446 | break :blk .static; | 442 | break :blk .static; |
| 447 | } else null; | 443 | } else null; |
| 448 | | 444 | |
| 449 | const block = try self.allocator.create(TextBlock); | 445 | const block = try self.macho_file.base.allocator.create(TextBlock); |
| 450 | errdefer self.allocator.destroy(block); | 446 | block.* = TextBlock.empty; |
| 451 | | | |
| 452 | block.* = TextBlock.init(self.allocator); | | |
| 453 | block.local_sym_index = senior_nlist.index; | 447 | block.local_sym_index = senior_nlist.index; |
| 454 | block.stab = stab; | 448 | block.stab = stab; |
| 455 | block.code = try self.allocator.dupe(u8, code); | | |
| 456 | block.size = size; | 449 | block.size = size; |
| 457 | block.alignment = actual_align; | 450 | block.alignment = actual_align; |
| | 451 | try self.macho_file.managed_blocks.append(self.macho_file.base.allocator, block); |
| 458 | | 452 | |
| 459 | if (aliases.items.len > 0) { | 453 | try block.code.appendSlice(self.macho_file.base.allocator, code); |
| 460 | try block.aliases.ensureTotalCapacity(aliases.items.len); | | |
| 461 | for (aliases.items) |alias| { | | |
| 462 | block.aliases.appendAssumeCapacity(alias.index); | | |
| 463 | | 454 | |
| 464 | const sym = self.macho_file.locals.items[alias.index]; | 455 | try block.aliases.ensureTotalCapacity(self.macho_file.base.allocator, aliases.items.len); |
| 465 | const reg = &sym.payload.regular; | 456 | for (aliases.items) |alias| { |
| 466 | reg.segment_id = self.match.seg; | 457 | block.aliases.appendAssumeCapacity(alias.index); |
| 467 | reg.section_id = self.match.sect; | 458 | const sym = &self.macho_file.locals.items[alias.index]; |
| 468 | } | 459 | sym.n_sect = self.macho_file.section_to_ordinal.get(self.match) orelse unreachable; |
| 469 | } | 460 | } |
| 470 | | 461 | |
| 471 | try block.parseRelocsFromObject(self.allocator, relocs, object, .{ | 462 | try block.parseRelocsFromObject(self.macho_file.base.allocator, self.relocs, self.object, .{ |
| 472 | .base_addr = start_addr, | 463 | .base_addr = start_addr, |
| 473 | .macho_file = self.macho_file, | 464 | .macho_file = self.macho_file, |
| 474 | }); | 465 | }); |
| ... | @@ -479,7 +470,7 @@ const TextBlockParser = struct { | ... | @@ -479,7 +470,7 @@ const TextBlockParser = struct { |
| 479 | senior_nlist.nlist.n_value, | 470 | senior_nlist.nlist.n_value, |
| 480 | senior_nlist.nlist.n_value + size, | 471 | senior_nlist.nlist.n_value + size, |
| 481 | ); | 472 | ); |
| 482 | try block.dices.ensureTotalCapacity(dices.len); | 473 | try block.dices.ensureTotalCapacity(self.macho_file.base.allocator, dices.len); |
| 483 | | 474 | |
| 484 | for (dices) |dice| { | 475 | for (dices) |dice| { |
| 485 | block.dices.appendAssumeCapacity(.{ | 476 | block.dices.appendAssumeCapacity(.{ |
| ... | @@ -518,10 +509,22 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void { | ... | @@ -518,10 +509,22 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void { |
| 518 | | 509 | |
| 519 | sort.sort(NlistWithIndex, sorted_all_nlists.items, {}, NlistWithIndex.lessThan); | 510 | sort.sort(NlistWithIndex, sorted_all_nlists.items, {}, NlistWithIndex.lessThan); |
| 520 | | 511 | |
| 521 | const dysymtab = self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab; | 512 | // Well, shit, sometimes compilers skip the dysymtab load command altogether, meaning we |
| | 513 | // have to infer the start of undef section in the symtab ourselves. |
| | 514 | const iundefsym = if (self.dysymtab_cmd_index) |cmd_index| blk: { |
| | 515 | const dysymtab = self.load_commands.items[cmd_index].Dysymtab; |
| | 516 | break :blk dysymtab.iundefsym; |
| | 517 | } else blk: { |
| | 518 | var iundefsym: usize = sorted_all_nlists.items.len; |
| | 519 | while (iundefsym > 0) : (iundefsym -= 1) { |
| | 520 | const nlist = sorted_all_nlists.items[iundefsym]; |
| | 521 | if (MachO.symbolIsSect(nlist.nlist)) break; |
| | 522 | } |
| | 523 | break :blk iundefsym; |
| | 524 | }; |
| 522 | | 525 | |
| 523 | // We only care about defined symbols, so filter every other out. | 526 | // We only care about defined symbols, so filter every other out. |
| 524 | const sorted_nlists = sorted_all_nlists.items[dysymtab.ilocalsym..dysymtab.iundefsym]; | 527 | const sorted_nlists = sorted_all_nlists.items[0..iundefsym]; |
| 525 | | 528 | |
| 526 | for (seg.sections.items) |sect, id| { | 529 | for (seg.sections.items) |sect, id| { |
| 527 | const sect_id = @intCast(u8, id); | 530 | const sect_id = @intCast(u8, id); |
| ... | @@ -550,11 +553,12 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void { | ... | @@ -550,11 +553,12 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void { |
| 550 | // Symbols within this section only. | 553 | // Symbols within this section only. |
| 551 | const filtered_nlists = NlistWithIndex.filterInSection(sorted_nlists, sect); | 554 | const filtered_nlists = NlistWithIndex.filterInSection(sorted_nlists, sect); |
| 552 | | 555 | |
| 553 | // Is there any padding between symbols within the section? | 556 | // In release mode, if the object file was generated with dead code stripping optimisations, |
| 554 | // const is_splittable = self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0; | 557 | // note it now and parse sections as atoms. |
| 555 | // TODO is it perhaps worth skip parsing subsections in Debug mode and not worry about | 558 | const is_splittable = blk: { |
| 556 | // duplicates at all? Need some benchmarks! | 559 | if (macho_file.base.options.optimize_mode == .Debug) break :blk false; |
| 557 | // const is_splittable = false; | 560 | break :blk self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0; |
| | 561 | }; |
| 558 | | 562 | |
| 559 | macho_file.has_dices = blk: { | 563 | macho_file.has_dices = blk: { |
| 560 | if (self.text_section_index) |index| { | 564 | if (self.text_section_index) |index| { |
| ... | @@ -566,157 +570,152 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void { | ... | @@ -566,157 +570,152 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void { |
| 566 | }; | 570 | }; |
| 567 | macho_file.has_stabs = macho_file.has_stabs or self.debug_info != null; | 571 | macho_file.has_stabs = macho_file.has_stabs or self.debug_info != null; |
| 568 | | 572 | |
| 569 | { | 573 | next: { |
| 570 | // next: { | 574 | if (is_splittable) blocks: { |
| 571 | // if (is_splittable) blocks: { | 575 | if (filtered_nlists.len == 0) break :blocks; |
| 572 | // if (filtered_nlists.len == 0) break :blocks; | 576 | |
| 573 | | 577 | // If the first nlist does not match the start of the section, |
| 574 | // // If the first nlist does not match the start of the section, | 578 | // then we need to encapsulate the memory range [section start, first symbol) |
| 575 | // // then we need encapsulate the memory range [section start, first symbol) | 579 | // as a temporary symbol and insert the matching TextBlock. |
| 576 | // // as a temporary symbol and insert the matching TextBlock. | 580 | const first_nlist = filtered_nlists[0].nlist; |
| 577 | // const first_nlist = filtered_nlists[0].nlist; | 581 | if (first_nlist.n_value > sect.addr) { |
| 578 | // if (first_nlist.n_value > sect.addr) { | 582 | const sym_name = try std.fmt.allocPrint(self.allocator, "l_{s}_{s}_{s}", .{ |
| 579 | // const symbol = self.sections_as_symbols.get(sect_id) orelse symbol: { | 583 | self.name.?, |
| 580 | // const name = try std.fmt.allocPrint(self.allocator, "l_{s}_{s}_{s}", .{ | 584 | segmentName(sect), |
| 581 | // self.name.?, | 585 | sectionName(sect), |
| 582 | // segmentName(sect), | 586 | }); |
| 583 | // sectionName(sect), | 587 | defer self.allocator.free(sym_name); |
| 584 | // }); | 588 | |
| 585 | // defer self.allocator.free(name); | 589 | const block_local_sym_index = self.sections_as_symbols.get(sect_id) orelse blk: { |
| 586 | // const symbol = try zld.allocator.create(Symbol); | 590 | const block_local_sym_index = @intCast(u32, macho_file.locals.items.len); |
| 587 | // symbol.* = .{ | 591 | try macho_file.locals.append(macho_file.base.allocator, .{ |
| 588 | // .strx = try zld.makeString(name), | 592 | .n_strx = try macho_file.makeString(sym_name), |
| 589 | // .payload = .{ .undef = .{} }, | 593 | .n_type = macho.N_SECT, |
| 590 | // }; | 594 | .n_sect = macho_file.section_to_ordinal.get(match) orelse unreachable, |
| 591 | // try self.sections_as_symbols.putNoClobber(self.allocator, sect_id, symbol); | 595 | .n_desc = 0, |
| 592 | // break :symbol symbol; | 596 | .n_value = sect.addr, |
| 593 | // }; | 597 | }); |
| 594 | | 598 | try self.sections_as_symbols.putNoClobber(self.allocator, sect_id, block_local_sym_index); |
| 595 | // const local_sym_index = @intCast(u32, zld.locals.items.len); | 599 | break :blk block_local_sym_index; |
| 596 | // symbol.payload = .{ | 600 | }; |
| 597 | // .regular = .{ | 601 | |
| 598 | // .linkage = .translation_unit, | 602 | const block_code = code[0 .. first_nlist.n_value - sect.addr]; |
| 599 | // .address = sect.addr, | 603 | const block_size = block_code.len; |
| 600 | // .segment_id = match.seg, | 604 | |
| 601 | // .section_id = match.sect, | 605 | const block = try macho_file.base.allocator.create(TextBlock); |
| 602 | // .file = self, | 606 | block.* = TextBlock.empty; |
| 603 | // .local_sym_index = local_sym_index, | 607 | block.local_sym_index = block_local_sym_index; |
| 604 | // }, | 608 | block.size = block_size; |
| 605 | // }; | 609 | block.alignment = sect.@"align"; |
| 606 | // try zld.locals.append(zld.allocator, symbol); | 610 | try macho_file.managed_blocks.append(macho_file.base.allocator, block); |
| 607 | | 611 | |
| 608 | // const block_code = code[0 .. first_nlist.n_value - sect.addr]; | 612 | try block.code.appendSlice(macho_file.base.allocator, block_code); |
| 609 | // const block_size = block_code.len; | 613 | |
| 610 | | 614 | try block.parseRelocsFromObject(self.allocator, relocs, self, .{ |
| 611 | // const block = try self.allocator.create(TextBlock); | 615 | .base_addr = 0, |
| 612 | // errdefer self.allocator.destroy(block); | 616 | .macho_file = macho_file, |
| 613 | | 617 | }); |
| 614 | // block.* = TextBlock.init(self.allocator); | 618 | |
| 615 | // block.local_sym_index = local_sym_index; | 619 | if (macho_file.has_dices) { |
| 616 | // block.code = try self.allocator.dupe(u8, block_code); | 620 | const dices = filterDice(self.data_in_code_entries.items, sect.addr, sect.addr + block_size); |
| 617 | // block.size = block_size; | 621 | try block.dices.ensureTotalCapacity(macho_file.base.allocator, dices.len); |
| 618 | // block.alignment = sect.@"align"; | 622 | |
| 619 | | 623 | for (dices) |dice| { |
| 620 | // const block_relocs = filterRelocs(relocs, 0, block_size); | 624 | block.dices.appendAssumeCapacity(.{ |
| 621 | // if (block_relocs.len > 0) { | 625 | .offset = dice.offset - try math.cast(u32, sect.addr), |
| 622 | // try self.parseRelocs(zld, block_relocs, block, 0); | 626 | .length = dice.length, |
| 623 | // } | 627 | .kind = dice.kind, |
| 624 | | 628 | }); |
| 625 | // if (zld.has_dices) { | 629 | } |
| 626 | // const dices = filterDice(self.data_in_code_entries.items, sect.addr, sect.addr + block_size); | 630 | } |
| 627 | // try block.dices.ensureTotalCapacity(dices.len); | 631 | |
| 628 | | 632 | // Update target section's metadata |
| 629 | // for (dices) |dice| { | 633 | // TODO should we update segment's size here too? |
| 630 | // block.dices.appendAssumeCapacity(.{ | 634 | // How does it tie with incremental space allocs? |
| 631 | // .offset = dice.offset - try math.cast(u32, sect.addr), | 635 | const tseg = &macho_file.load_commands.items[match.seg].Segment; |
| 632 | // .length = dice.length, | 636 | const tsect = &tseg.sections.items[match.sect]; |
| 633 | // .kind = dice.kind, | 637 | const new_alignment = math.max(tsect.@"align", block.alignment); |
| 634 | // }); | 638 | const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment); |
| 635 | // } | 639 | const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + block.size; |
| 636 | // } | 640 | tsect.size = new_size; |
| 637 | | 641 | tsect.@"align" = new_alignment; |
| 638 | // // Update target section's metadata | 642 | |
| 639 | // // TODO should we update segment's size here too? | 643 | if (macho_file.blocks.getPtr(match)) |last| { |
| 640 | // // How does it tie with incremental space allocs? | 644 | last.*.next = block; |
| 641 | // const tseg = &zld.load_commands.items[match.seg].Segment; | 645 | block.prev = last.*; |
| 642 | // const tsect = &tseg.sections.items[match.sect]; | 646 | last.* = block; |
| 643 | // const new_alignment = math.max(tsect.@"align", block.alignment); | 647 | } else { |
| 644 | // const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment); | 648 | try macho_file.blocks.putNoClobber(macho_file.base.allocator, match, block); |
| 645 | // const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + block.size; | 649 | } |
| 646 | // tsect.size = new_size; | 650 | |
| 647 | // tsect.@"align" = new_alignment; | 651 | try self.text_blocks.append(self.allocator, block); |
| 648 | | 652 | } |
| 649 | // if (zld.blocks.getPtr(match)) |last| { | 653 | |
| 650 | // last.*.next = block; | 654 | var parser = TextBlockParser{ |
| 651 | // block.prev = last.*; | 655 | .allocator = self.allocator, |
| 652 | // last.* = block; | 656 | .section = sect, |
| 653 | // } else { | 657 | .code = code, |
| 654 | // try zld.blocks.putNoClobber(zld.allocator, match, block); | 658 | .relocs = relocs, |
| 655 | // } | 659 | .object = self, |
| 656 | | 660 | .macho_file = macho_file, |
| 657 | // try self.text_blocks.append(self.allocator, block); | 661 | .nlists = filtered_nlists, |
| 658 | // } | 662 | .match = match, |
| 659 | | 663 | }; |
| 660 | // var parser = TextBlockParser{ | 664 | |
| 661 | // .allocator = self.allocator, | 665 | while (try parser.next()) |block| { |
| 662 | // .section = sect, | 666 | const sym = macho_file.locals.items[block.local_sym_index]; |
| 663 | // .code = code, | 667 | const is_ext = blk: { |
| 664 | // .relocs = relocs, | 668 | const orig_sym_id = self.reverse_symbol_mapping.get(block.local_sym_index) orelse unreachable; |
| 665 | // .object = self, | 669 | break :blk MachO.symbolIsExt(self.symtab.items[orig_sym_id]); |
| 666 | // .zld = zld, | 670 | }; |
| 667 | // .nlists = filtered_nlists, | 671 | if (is_ext) { |
| 668 | // .match = match, | 672 | if (macho_file.symbol_resolver.get(sym.n_strx)) |resolv| { |
| 669 | // }; | 673 | assert(resolv.where == .global); |
| 670 | | 674 | const global_object = macho_file.objects.items[resolv.file]; |
| 671 | // while (try parser.next()) |block| { | 675 | if (global_object != self) { |
| 672 | // const sym = zld.locals.items[block.local_sym_index]; | 676 | log.debug("deduping definition of {s} in {s}", .{ |
| 673 | // const reg = &sym.payload.regular; | 677 | macho_file.getString(sym.n_strx), |
| 674 | // if (reg.file) |file| { | 678 | self.name.?, |
| 675 | // if (file != self) { | 679 | }); |
| 676 | // log.debug("deduping definition of {s} in {s}", .{ zld.getString(sym.strx), self.name.? }); | 680 | log.debug(" already defined in {s}", .{global_object.name.?}); |
| 677 | // block.deinit(); | 681 | continue; |
| 678 | // self.allocator.destroy(block); | 682 | } |
| 679 | // continue; | 683 | } |
| 680 | // } | 684 | } |
| 681 | // } | 685 | |
| 682 | | 686 | if (sym.n_value == sect.addr) { |
| 683 | // if (reg.address == sect.addr) { | 687 | if (self.sections_as_symbols.get(sect_id)) |alias| { |
| 684 | // if (self.sections_as_symbols.get(sect_id)) |alias| { | 688 | // In x86_64 relocs, it can so happen that the compiler refers to the same |
| 685 | // // Add alias. | 689 | // atom by both the actual assigned symbol and the start of the section. In this |
| 686 | // const local_sym_index = @intCast(u32, zld.locals.items.len); | 690 | // case, we need to link the two together so add an alias. |
| 687 | // const reg_alias = &alias.payload.regular; | 691 | try block.aliases.append(macho_file.base.allocator, alias); |
| 688 | // reg_alias.segment_id = match.seg; | 692 | } |
| 689 | // reg_alias.section_id = match.sect; | 693 | } |
| 690 | // reg_alias.local_sym_index = local_sym_index; | 694 | |
| 691 | // try block.aliases.append(local_sym_index); | 695 | // Update target section's metadata |
| 692 | // try zld.locals.append(zld.allocator, alias); | 696 | // TODO should we update segment's size here too? |
| 693 | // } | 697 | // How does it tie with incremental space allocs? |
| 694 | // } | 698 | const tseg = &macho_file.load_commands.items[match.seg].Segment; |
| 695 | | 699 | const tsect = &tseg.sections.items[match.sect]; |
| 696 | // // Update target section's metadata | 700 | const new_alignment = math.max(tsect.@"align", block.alignment); |
| 697 | // // TODO should we update segment's size here too? | 701 | const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment); |
| 698 | // // How does it tie with incremental space allocs? | 702 | const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + block.size; |
| 699 | // const tseg = &zld.load_commands.items[match.seg].Segment; | 703 | tsect.size = new_size; |
| 700 | // const tsect = &tseg.sections.items[match.sect]; | 704 | tsect.@"align" = new_alignment; |
| 701 | // const new_alignment = math.max(tsect.@"align", block.alignment); | 705 | |
| 702 | // const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment); | 706 | if (macho_file.blocks.getPtr(match)) |last| { |
| 703 | // const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + block.size; | 707 | last.*.next = block; |
| 704 | // tsect.size = new_size; | 708 | block.prev = last.*; |
| 705 | // tsect.@"align" = new_alignment; | 709 | last.* = block; |
| 706 | | 710 | } else { |
| 707 | // if (zld.blocks.getPtr(match)) |last| { | 711 | try macho_file.blocks.putNoClobber(macho_file.base.allocator, match, block); |
| 708 | // last.*.next = block; | 712 | } |
| 709 | // block.prev = last.*; | 713 | |
| 710 | // last.* = block; | 714 | try self.text_blocks.append(self.allocator, block); |
| 711 | // } else { | 715 | } |
| 712 | // try zld.blocks.putNoClobber(zld.allocator, match, block); | 716 | |
| 713 | // } | 717 | break :next; |
| 714 | | 718 | } |
| 715 | // try self.text_blocks.append(self.allocator, block); | | |
| 716 | // } | | |
| 717 | | | |
| 718 | // break :next; | | |
| 719 | // } | | |
| 720 | | 719 | |
| 721 | // Since there is no symbol to refer to this block, we create | 720 | // Since there is no symbol to refer to this block, we create |
| 722 | // a temp one, unless we already did that when working out the relocations | 721 | // a temp one, unless we already did that when working out the relocations |
| ... | @@ -757,7 +756,7 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void { | ... | @@ -757,7 +756,7 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void { |
| 757 | | 756 | |
| 758 | if (macho_file.has_dices) { | 757 | if (macho_file.has_dices) { |
| 759 | const dices = filterDice(self.data_in_code_entries.items, sect.addr, sect.addr + sect.size); | 758 | const dices = filterDice(self.data_in_code_entries.items, sect.addr, sect.addr + sect.size); |
| 760 | try block.dices.ensureTotalCapacity(self.allocator, dices.len); | 759 | try block.dices.ensureTotalCapacity(macho_file.base.allocator, dices.len); |
| 761 | | 760 | |
| 762 | for (dices) |dice| { | 761 | for (dices) |dice| { |
| 763 | block.dices.appendAssumeCapacity(.{ | 762 | block.dices.appendAssumeCapacity(.{ |
| ... | @@ -820,7 +819,7 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void { | ... | @@ -820,7 +819,7 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void { |
| 820 | block.prev = last.*; | 819 | block.prev = last.*; |
| 821 | last.* = block; | 820 | last.* = block; |
| 822 | } else { | 821 | } else { |
| 823 | try macho_file.blocks.putNoClobber(self.allocator, match, block); | 822 | try macho_file.blocks.putNoClobber(macho_file.base.allocator, match, block); |
| 824 | } | 823 | } |
| 825 | | 824 | |
| 826 | try self.text_blocks.append(self.allocator, block); | 825 | try self.text_blocks.append(self.allocator, block); |