| 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,30 +431,27 @@ const TextBlockParser = struct { |
| 431 | else | 431 | else |
| 432 | max_align; | 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 | const block = try self.allocator.create(TextBlock); | 434 | const block = try self.allocator.create(TextBlock); |
| 449 | errdefer self.allocator.destroy(block); | 435 | errdefer self.allocator.destroy(block); |
| 450 | 436 | ||
| 451 | block.* = TextBlock.init(self.allocator); | 437 | block.* = TextBlock.init(self.allocator); |
| 452 | block.local_sym_index = senior_nlist.index; | 438 | block.local_sym_index = senior_nlist.index; |
| 453 | block.aliases = alias_only_indices; | ||
| 454 | block.code = try self.allocator.dupe(u8, code); | 439 | block.code = try self.allocator.dupe(u8, code); |
| 455 | block.size = size; | 440 | block.size = size; |
| 456 | block.alignment = actual_align; | 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 | const relocs = filterRelocs(self.relocs, start_addr, end_addr); | 455 | const relocs = filterRelocs(self.relocs, start_addr, end_addr); |
| 459 | if (relocs.len > 0) { | 456 | if (relocs.len > 0) { |
| 460 | try self.object.parseRelocs(self.zld, relocs, block, start_addr); | 457 | try self.object.parseRelocs(self.zld, relocs, block, start_addr); |
| ... | @@ -617,7 +614,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { | ... | @@ -617,7 +614,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { |
| 617 | const tsect = &tseg.sections.items[match.sect]; | 614 | const tsect = &tseg.sections.items[match.sect]; |
| 618 | const new_alignment = math.max(tsect.@"align", block.alignment); | 615 | const new_alignment = math.max(tsect.@"align", block.alignment); |
| 619 | const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment); | 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 | tsect.size = new_size; | 618 | tsect.size = new_size; |
| 622 | tsect.@"align" = new_alignment; | 619 | tsect.@"align" = new_alignment; |
| 623 | 620 | ||
| ... | @@ -653,6 +650,19 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { | ... | @@ -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 | // Update target section's metadata | 666 | // Update target section's metadata |
| 657 | // TODO should we update segment's size here too? | 667 | // TODO should we update segment's size here too? |
| 658 | // How does it tie with incremental space allocs? | 668 | // How does it tie with incremental space allocs? |
| ... | @@ -660,7 +670,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { | ... | @@ -660,7 +670,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { |
| 660 | const tsect = &tseg.sections.items[match.sect]; | 670 | const tsect = &tseg.sections.items[match.sect]; |
| 661 | const new_alignment = math.max(tsect.@"align", block.alignment); | 671 | const new_alignment = math.max(tsect.@"align", block.alignment); |
| 662 | const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment); | 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 | tsect.size = new_size; | 674 | tsect.size = new_size; |
| 665 | tsect.@"align" = new_alignment; | 675 | tsect.@"align" = new_alignment; |
| 666 | 676 | ||
| ... | @@ -764,7 +774,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { | ... | @@ -764,7 +774,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { |
| 764 | const tsect = &tseg.sections.items[match.sect]; | 774 | const tsect = &tseg.sections.items[match.sect]; |
| 765 | const new_alignment = math.max(tsect.@"align", block.alignment); | 775 | const new_alignment = math.max(tsect.@"align", block.alignment); |
| 766 | const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment); | 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 | tsect.size = new_size; | 778 | tsect.size = new_size; |
| 769 | tsect.@"align" = new_alignment; | 779 | tsect.@"align" = new_alignment; |
| 770 | 780 |
src/link/MachO/Zld.zig+10-13| ... | @@ -125,7 +125,7 @@ pub const Output = struct { | ... | @@ -125,7 +125,7 @@ pub const Output = struct { |
| 125 | pub const TextBlock = struct { | 125 | pub const TextBlock = struct { |
| 126 | allocator: *Allocator, | 126 | allocator: *Allocator, |
| 127 | local_sym_index: u32, | 127 | local_sym_index: u32, |
| 128 | aliases: ?[]u32 = null, | 128 | aliases: std.ArrayList(u32), |
| 129 | references: std.AutoArrayHashMap(u32, void), | 129 | references: std.AutoArrayHashMap(u32, void), |
| 130 | contained: ?[]SymbolAtOffset = null, | 130 | contained: ?[]SymbolAtOffset = null, |
| 131 | code: []u8, | 131 | code: []u8, |
| ... | @@ -146,6 +146,7 @@ pub const TextBlock = struct { | ... | @@ -146,6 +146,7 @@ pub const TextBlock = struct { |
| 146 | return .{ | 146 | return .{ |
| 147 | .allocator = allocator, | 147 | .allocator = allocator, |
| 148 | .local_sym_index = undefined, | 148 | .local_sym_index = undefined, |
| 149 | .aliases = std.ArrayList(u32).init(allocator), | ||
| 149 | .references = std.AutoArrayHashMap(u32, void).init(allocator), | 150 | .references = std.AutoArrayHashMap(u32, void).init(allocator), |
| 150 | .code = undefined, | 151 | .code = undefined, |
| 151 | .relocs = std.ArrayList(Relocation).init(allocator), | 152 | .relocs = std.ArrayList(Relocation).init(allocator), |
| ... | @@ -157,9 +158,7 @@ pub const TextBlock = struct { | ... | @@ -157,9 +158,7 @@ pub const TextBlock = struct { |
| 157 | } | 158 | } |
| 158 | 159 | ||
| 159 | pub fn deinit(self: *TextBlock) void { | 160 | pub fn deinit(self: *TextBlock) void { |
| 160 | if (self.aliases) |aliases| { | 161 | self.aliases.deinit(); |
| 161 | self.allocator.free(aliases); | ||
| 162 | } | ||
| 163 | self.references.deinit(); | 162 | self.references.deinit(); |
| 164 | if (self.contained) |contained| { | 163 | if (self.contained) |contained| { |
| 165 | self.allocator.free(contained); | 164 | self.allocator.free(contained); |
| ... | @@ -179,9 +178,9 @@ pub const TextBlock = struct { | ... | @@ -179,9 +178,9 @@ pub const TextBlock = struct { |
| 179 | pub fn print_this(self: *const TextBlock, zld: *Zld) void { | 178 | pub fn print_this(self: *const TextBlock, zld: *Zld) void { |
| 180 | log.warn("TextBlock", .{}); | 179 | log.warn("TextBlock", .{}); |
| 181 | log.warn(" {}: {}", .{ self.local_sym_index, zld.locals.items[self.local_sym_index] }); | 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 | log.warn(" aliases:", .{}); | 182 | log.warn(" aliases:", .{}); |
| 184 | for (aliases) |index| { | 183 | for (self.aliases.items) |index| { |
| 185 | log.warn(" {}: {}", .{ index, zld.locals.items[index] }); | 184 | log.warn(" {}: {}", .{ index, zld.locals.items[index] }); |
| 186 | } | 185 | } |
| 187 | } | 186 | } |
| ... | @@ -1082,12 +1081,10 @@ fn allocateTextBlocks(self: *Zld) !void { | ... | @@ -1082,12 +1081,10 @@ fn allocateTextBlocks(self: *Zld) !void { |
| 1082 | }); | 1081 | }); |
| 1083 | 1082 | ||
| 1084 | // Update each alias (if any) | 1083 | // Update each alias (if any) |
| 1085 | if (block.aliases) |aliases| { | 1084 | for (block.aliases.items) |index| { |
| 1086 | for (aliases) |index| { | 1085 | const alias_sym = self.locals.items[index]; |
| 1087 | const alias_sym = self.locals.items[index]; | 1086 | assert(alias_sym.payload == .regular); |
| 1088 | assert(alias_sym.payload == .regular); | 1087 | alias_sym.payload.regular.address = base_addr; |
| 1089 | alias_sym.payload.regular.address = base_addr; | ||
| 1090 | } | ||
| 1091 | } | 1088 | } |
| 1092 | 1089 | ||
| 1093 | // Update each symbol contained within the TextBlock | 1090 | // Update each symbol contained within the TextBlock |
| ... | @@ -1623,7 +1620,7 @@ fn resolveSymbols(self: *Zld) !void { | ... | @@ -1623,7 +1620,7 @@ fn resolveSymbols(self: *Zld) !void { |
| 1623 | const tsect = &tseg.sections.items[match.sect]; | 1620 | const tsect = &tseg.sections.items[match.sect]; |
| 1624 | const new_alignment = math.max(tsect.@"align", block.alignment); | 1621 | const new_alignment = math.max(tsect.@"align", block.alignment); |
| 1625 | const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment); | 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 | tsect.size = new_size; | 1624 | tsect.size = new_size; |
| 1628 | tsect.@"align" = new_alignment; | 1625 | tsect.@"align" = new_alignment; |
| 1629 | 1626 |
src/link/MachO/reloc.zig+2-2| ... | @@ -878,9 +878,9 @@ pub const Parser = struct { | ... | @@ -878,9 +878,9 @@ pub const Parser = struct { |
| 878 | 878 | ||
| 879 | if (rel.r_extern == 0) { | 879 | if (rel.r_extern == 0) { |
| 880 | const source_sym = self.zld.locals.items[self.block.local_sym_index].payload.regular; | 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 | const target_sym = parsed.target.payload.regular; | 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 | parsed.payload = .{ | 886 | parsed.payload = .{ |