| author | |
| committer | |
| log | e17f12dd643e9edd90abb66b183d2a59eddc248c |
| tree | 5d4b233b71c17ada1006ee1c246b07ed20da7f08 |
| parent | de30a704b134d17d61a36d41c058c7b4994cd7f2 |
Also, add a solution to a degenerate case where on x86_64 a relocation
refers to a cell in a section via section start address even though
a symbol exists. In such case, make the section spawned symbol an alias
of the actual symbol.3 files changed, 40 insertions(+), 33 deletions(-)
src/link/MachO/Object.zig+28-18| ... | ... | @@ -431,30 +431,27 @@ const TextBlockParser = struct { |
| 431 | 431 | else |
| 432 | 432 | max_align; |
| 433 | 433 | |
| 434 | const alias_only_indices = if (aliases.items.len > 0) blk: { | |
| 435 | var out = std.ArrayList(u32).init(self.allocator); | |
| 436 | try out.ensureTotalCapacity(aliases.items.len); | |
| 437 | for (aliases.items) |alias| { | |
| 438 | out.appendAssumeCapacity(alias.index); | |
| 439 | ||
| 440 | const sym = self.zld.locals.items[alias.index]; | |
| 441 | const reg = &sym.payload.regular; | |
| 442 | reg.segment_id = self.match.seg; | |
| 443 | reg.section_id = self.match.sect; | |
| 444 | } | |
| 445 | break :blk out.toOwnedSlice(); | |
| 446 | } else null; | |
| 447 | ||
| 448 | 434 | const block = try self.allocator.create(TextBlock); |
| 449 | 435 | errdefer self.allocator.destroy(block); |
| 450 | 436 | |
| 451 | 437 | block.* = TextBlock.init(self.allocator); |
| 452 | 438 | block.local_sym_index = senior_nlist.index; |
| 453 | block.aliases = alias_only_indices; | |
| 454 | 439 | block.code = try self.allocator.dupe(u8, code); |
| 455 | 440 | block.size = size; |
| 456 | 441 | block.alignment = actual_align; |
| 457 | 442 | |
| 443 | if (aliases.items.len > 0) { | |
| 444 | try block.aliases.ensureTotalCapacity(aliases.items.len); | |
| 445 | for (aliases.items) |alias| { | |
| 446 | block.aliases.appendAssumeCapacity(alias.index); | |
| 447 | ||
| 448 | const sym = self.zld.locals.items[alias.index]; | |
| 449 | const reg = &sym.payload.regular; | |
| 450 | reg.segment_id = self.match.seg; | |
| 451 | reg.section_id = self.match.sect; | |
| 452 | } | |
| 453 | } | |
| 454 | ||
| 458 | 455 | const relocs = filterRelocs(self.relocs, start_addr, end_addr); |
| 459 | 456 | if (relocs.len > 0) { |
| 460 | 457 | try self.object.parseRelocs(self.zld, relocs, block, start_addr); |
| ... | ... | @@ -617,7 +614,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { |
| 617 | 614 | const tsect = &tseg.sections.items[match.sect]; |
| 618 | 615 | const new_alignment = math.max(tsect.@"align", block.alignment); |
| 619 | 616 | 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); | |
| 617 | const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + block.size; | |
| 621 | 618 | tsect.size = new_size; |
| 622 | 619 | tsect.@"align" = new_alignment; |
| 623 | 620 | |
| ... | ... | @@ -653,6 +650,19 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { |
| 653 | 650 | } |
| 654 | 651 | } |
| 655 | 652 | |
| 653 | if (reg.address == sect.addr) { | |
| 654 | if (self.sections_as_symbols.get(sect_id)) |alias| { | |
| 655 | // Add alias. | |
| 656 | const local_sym_index = @intCast(u32, zld.locals.items.len); | |
| 657 | const reg_alias = &alias.payload.regular; | |
| 658 | reg_alias.segment_id = match.seg; | |
| 659 | reg_alias.section_id = match.sect; | |
| 660 | reg_alias.local_sym_index = local_sym_index; | |
| 661 | try block.aliases.append(local_sym_index); | |
| 662 | try zld.locals.append(zld.allocator, alias); | |
| 663 | } | |
| 664 | } | |
| 665 | ||
| 656 | 666 | // Update target section's metadata |
| 657 | 667 | // TODO should we update segment's size here too? |
| 658 | 668 | // How does it tie with incremental space allocs? |
| ... | ... | @@ -660,7 +670,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { |
| 660 | 670 | const tsect = &tseg.sections.items[match.sect]; |
| 661 | 671 | const new_alignment = math.max(tsect.@"align", block.alignment); |
| 662 | 672 | const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment); |
| 663 | const new_size = mem.alignForwardGeneric(u64, tsect.size + block.size, new_alignment_pow_2); | |
| 673 | const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + block.size; | |
| 664 | 674 | tsect.size = new_size; |
| 665 | 675 | tsect.@"align" = new_alignment; |
| 666 | 676 | |
| ... | ... | @@ -764,7 +774,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { |
| 764 | 774 | const tsect = &tseg.sections.items[match.sect]; |
| 765 | 775 | const new_alignment = math.max(tsect.@"align", block.alignment); |
| 766 | 776 | const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment); |
| 767 | const new_size = mem.alignForwardGeneric(u64, tsect.size + block.size, new_alignment_pow_2); | |
| 777 | const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + block.size; | |
| 768 | 778 | tsect.size = new_size; |
| 769 | 779 | tsect.@"align" = new_alignment; |
| 770 | 780 |
src/link/MachO/Zld.zig+10-13| ... | ... | @@ -125,7 +125,7 @@ pub const Output = struct { |
| 125 | 125 | pub const TextBlock = struct { |
| 126 | 126 | allocator: *Allocator, |
| 127 | 127 | local_sym_index: u32, |
| 128 | aliases: ?[]u32 = null, | |
| 128 | aliases: std.ArrayList(u32), | |
| 129 | 129 | references: std.AutoArrayHashMap(u32, void), |
| 130 | 130 | contained: ?[]SymbolAtOffset = null, |
| 131 | 131 | code: []u8, |
| ... | ... | @@ -146,6 +146,7 @@ pub const TextBlock = struct { |
| 146 | 146 | return .{ |
| 147 | 147 | .allocator = allocator, |
| 148 | 148 | .local_sym_index = undefined, |
| 149 | .aliases = std.ArrayList(u32).init(allocator), | |
| 149 | 150 | .references = std.AutoArrayHashMap(u32, void).init(allocator), |
| 150 | 151 | .code = undefined, |
| 151 | 152 | .relocs = std.ArrayList(Relocation).init(allocator), |
| ... | ... | @@ -157,9 +158,7 @@ pub const TextBlock = struct { |
| 157 | 158 | } |
| 158 | 159 | |
| 159 | 160 | pub fn deinit(self: *TextBlock) void { |
| 160 | if (self.aliases) |aliases| { | |
| 161 | self.allocator.free(aliases); | |
| 162 | } | |
| 161 | self.aliases.deinit(); | |
| 163 | 162 | self.references.deinit(); |
| 164 | 163 | if (self.contained) |contained| { |
| 165 | 164 | self.allocator.free(contained); |
| ... | ... | @@ -179,9 +178,9 @@ pub const TextBlock = struct { |
| 179 | 178 | pub fn print_this(self: *const TextBlock, zld: *Zld) void { |
| 180 | 179 | log.warn("TextBlock", .{}); |
| 181 | 180 | log.warn(" {}: {}", .{ self.local_sym_index, zld.locals.items[self.local_sym_index] }); |
| 182 | if (self.aliases) |aliases| { | |
| 181 | if (self.aliases.items.len > 0) { | |
| 183 | 182 | log.warn(" aliases:", .{}); |
| 184 | for (aliases) |index| { | |
| 183 | for (self.aliases.items) |index| { | |
| 185 | 184 | log.warn(" {}: {}", .{ index, zld.locals.items[index] }); |
| 186 | 185 | } |
| 187 | 186 | } |
| ... | ... | @@ -1082,12 +1081,10 @@ fn allocateTextBlocks(self: *Zld) !void { |
| 1082 | 1081 | }); |
| 1083 | 1082 | |
| 1084 | 1083 | // Update each alias (if any) |
| 1085 | if (block.aliases) |aliases| { | |
| 1086 | for (aliases) |index| { | |
| 1087 | const alias_sym = self.locals.items[index]; | |
| 1088 | assert(alias_sym.payload == .regular); | |
| 1089 | alias_sym.payload.regular.address = base_addr; | |
| 1090 | } | |
| 1084 | for (block.aliases.items) |index| { | |
| 1085 | const alias_sym = self.locals.items[index]; | |
| 1086 | assert(alias_sym.payload == .regular); | |
| 1087 | alias_sym.payload.regular.address = base_addr; | |
| 1091 | 1088 | } |
| 1092 | 1089 | |
| 1093 | 1090 | // Update each symbol contained within the TextBlock |
| ... | ... | @@ -1623,7 +1620,7 @@ fn resolveSymbols(self: *Zld) !void { |
| 1623 | 1620 | const tsect = &tseg.sections.items[match.sect]; |
| 1624 | 1621 | const new_alignment = math.max(tsect.@"align", block.alignment); |
| 1625 | 1622 | const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment); |
| 1626 | const new_size = mem.alignForwardGeneric(u64, tsect.size + block.size, new_alignment_pow_2); | |
| 1623 | const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + block.size; | |
| 1627 | 1624 | tsect.size = new_size; |
| 1628 | 1625 | tsect.@"align" = new_alignment; |
| 1629 | 1626 |
src/link/MachO/reloc.zig+2-2| ... | ... | @@ -878,9 +878,9 @@ pub const Parser = struct { |
| 878 | 878 | |
| 879 | 879 | if (rel.r_extern == 0) { |
| 880 | 880 | const source_sym = self.zld.locals.items[self.block.local_sym_index].payload.regular; |
| 881 | const source_addr = source_sym.address + parsed.offset + @intCast(u32, addend) + 4; | |
| 881 | const source_addr = source_sym.address + parsed.offset + 4; | |
| 882 | 882 | const target_sym = parsed.target.payload.regular; |
| 883 | addend = @intCast(i64, source_addr) - @intCast(i64, target_sym.address); | |
| 883 | addend = @intCast(i64, source_addr) + addend - @intCast(i64, target_sym.address); | |
| 884 | 884 | } |
| 885 | 885 | |
| 886 | 886 | parsed.payload = .{ |