authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-12 20:36:01+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:47+02:00
logde30a704b134d17d61a36d41c058c7b4994cd7f2
treec7923df9959defad370c23c63f41284917b84f86
parentda07251000c5247432017535e5cbcae05be6e00a

zld: map [section addr, first symbol) to a tracked TextBlock

which applies exclusively to x86_64-macos.

2 files changed, 84 insertions(+), 1 deletions(-)

src/link/MachO/Object.zig+83-1
...@@ -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;
552552
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);
624706
625 const block = try self.allocator.create(TextBlock);707 const block = try self.allocator.create(TextBlock);
src/link/MachO/Symbol.zig+1
...@@ -79,6 +79,7 @@ pub const Regular = struct {...@@ -79,6 +79,7 @@ pub const Regular = struct {
79 if (self.file) |file| {79 if (self.file) |file| {
80 try std.fmt.format(writer, ".file = {s}, ", .{file.name.?});80 try std.fmt.format(writer, ".file = {s}, ", .{file.name.?});
81 }81 }
82 try std.fmt.format(writer, ".local_sym_index = {}, ", .{self.local_sym_index});
82 try std.fmt.format(writer, "}}", .{});83 try std.fmt.format(writer, "}}", .{});
83 }84 }
8485