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