| ... | @@ -550,6 +550,86 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { | ... | @@ -550,6 +550,86 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { |
| 550 | if (is_splittable) blocks: { | 550 | if (is_splittable) blocks: { |
| 551 | if (filtered_nlists.len == 0) break :blocks; | 551 | if (filtered_nlists.len == 0) break :blocks; |
| 552 | | 552 | |
| | 553 | // If the first nlist does not match the start of the section, |
| | 554 | // then we need encapsulate the memory range [section start, first symbol) |
| | 555 | // as a temporary symbol and insert the matching TextBlock. |
| | 556 | const first_nlist = filtered_nlists[0].nlist; |
| | 557 | if (first_nlist.n_value > sect.addr) { |
| | 558 | const symbol = self.sections_as_symbols.get(sect_id) orelse symbol: { |
| | 559 | const name = try std.fmt.allocPrint(self.allocator, "l_{s}_{s}_{s}", .{ |
| | 560 | self.name.?, |
| | 561 | segmentName(sect), |
| | 562 | sectionName(sect), |
| | 563 | }); |
| | 564 | defer self.allocator.free(name); |
| | 565 | const symbol = try Symbol.new(self.allocator, name); |
| | 566 | try self.sections_as_symbols.putNoClobber(self.allocator, sect_id, symbol); |
| | 567 | break :symbol symbol; |
| | 568 | }; |
| | 569 | |
| | 570 | const local_sym_index = @intCast(u32, zld.locals.items.len); |
| | 571 | symbol.payload = .{ |
| | 572 | .regular = .{ |
| | 573 | .linkage = .translation_unit, |
| | 574 | .address = sect.addr, |
| | 575 | .segment_id = match.seg, |
| | 576 | .section_id = match.sect, |
| | 577 | .file = self, |
| | 578 | .local_sym_index = local_sym_index, |
| | 579 | }, |
| | 580 | }; |
| | 581 | try zld.locals.append(zld.allocator, symbol); |
| | 582 | |
| | 583 | const block_code = code[0 .. first_nlist.n_value - sect.addr]; |
| | 584 | const block_size = block_code.len; |
| | 585 | |
| | 586 | const block = try self.allocator.create(TextBlock); |
| | 587 | errdefer self.allocator.destroy(block); |
| | 588 | |
| | 589 | block.* = TextBlock.init(self.allocator); |
| | 590 | block.local_sym_index = local_sym_index; |
| | 591 | block.code = try self.allocator.dupe(u8, block_code); |
| | 592 | block.size = block_size; |
| | 593 | block.alignment = sect.@"align"; |
| | 594 | |
| | 595 | const block_relocs = filterRelocs(relocs, 0, block_size); |
| | 596 | if (block_relocs.len > 0) { |
| | 597 | try self.parseRelocs(zld, block_relocs, block, 0); |
| | 598 | } |
| | 599 | |
| | 600 | if (zld.has_dices) { |
| | 601 | const dices = filterDice(self.data_in_code_entries.items, sect.addr, sect.addr + block_size); |
| | 602 | try block.dices.ensureTotalCapacity(dices.len); |
| | 603 | |
| | 604 | for (dices) |dice| { |
| | 605 | block.dices.appendAssumeCapacity(.{ |
| | 606 | .offset = dice.offset - try math.cast(u32, sect.addr), |
| | 607 | .length = dice.length, |
| | 608 | .kind = dice.kind, |
| | 609 | }); |
| | 610 | } |
| | 611 | } |
| | 612 | |
| | 613 | // Update target section's metadata |
| | 614 | // TODO should we update segment's size here too? |
| | 615 | // How does it tie with incremental space allocs? |
| | 616 | const tseg = &zld.load_commands.items[match.seg].Segment; |
| | 617 | const tsect = &tseg.sections.items[match.sect]; |
| | 618 | const new_alignment = math.max(tsect.@"align", block.alignment); |
| | 619 | const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment); |
| | 620 | const new_size = mem.alignForwardGeneric(u64, tsect.size + block.size, new_alignment_pow_2); |
| | 621 | tsect.size = new_size; |
| | 622 | tsect.@"align" = new_alignment; |
| | 623 | |
| | 624 | if (zld.blocks.getPtr(match)) |last| { |
| | 625 | last.*.next = block; |
| | 626 | block.prev = last.*; |
| | 627 | last.* = block; |
| | 628 | } else { |
| | 629 | try zld.blocks.putNoClobber(zld.allocator, match, block); |
| | 630 | } |
| | 631 | } |
| | 632 | |
| 553 | var parser = TextBlockParser{ | 633 | var parser = TextBlockParser{ |
| 554 | .allocator = self.allocator, | 634 | .allocator = self.allocator, |
| 555 | .section = sect, | 635 | .section = sect, |
| ... | @@ -610,6 +690,8 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { | ... | @@ -610,6 +690,8 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { |
| 610 | try self.sections_as_symbols.putNoClobber(self.allocator, sect_id, symbol); | 690 | try self.sections_as_symbols.putNoClobber(self.allocator, sect_id, symbol); |
| 611 | break :symbol symbol; | 691 | break :symbol symbol; |
| 612 | }; | 692 | }; |
| | 693 | |
| | 694 | const local_sym_index = @intCast(u32, zld.locals.items.len); |
| 613 | symbol.payload = .{ | 695 | symbol.payload = .{ |
| 614 | .regular = .{ | 696 | .regular = .{ |
| 615 | .linkage = .translation_unit, | 697 | .linkage = .translation_unit, |
| ... | @@ -617,9 +699,9 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { | ... | @@ -617,9 +699,9 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { |
| 617 | .segment_id = match.seg, | 699 | .segment_id = match.seg, |
| 618 | .section_id = match.sect, | 700 | .section_id = match.sect, |
| 619 | .file = self, | 701 | .file = self, |
| | 702 | .local_sym_index = local_sym_index, |
| 620 | }, | 703 | }, |
| 621 | }; | 704 | }; |
| 622 | const local_sym_index = @intCast(u32, zld.locals.items.len); | | |
| 623 | try zld.locals.append(zld.allocator, symbol); | 705 | try zld.locals.append(zld.allocator, symbol); |
| 624 | | 706 | |
| 625 | const block = try self.allocator.create(TextBlock); | 707 | const block = try self.allocator.create(TextBlock); |