authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-12 23:56:36+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:47+02:00
loge17f12dd643e9edd90abb66b183d2a59eddc248c
tree5d4b233b71c17ada1006ee1c246b07ed20da7f08
parentde30a704b134d17d61a36d41c058c7b4994cd7f2

zld: fix incorrectly worked out section size

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 else431 else
432 max_align;432 max_align;
433433
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);
450436
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;
457442
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;
623620
...@@ -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 }
655652
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 metadata666 // 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;
666676
...@@ -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;
770780
src/link/MachO/Zld.zig+10-13
...@@ -125,7 +125,7 @@ pub const Output = struct {...@@ -125,7 +125,7 @@ pub const Output = struct {
125pub const TextBlock = struct {125pub 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 }
158159
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 });
10831082
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 }
10921089
1093 // Update each symbol contained within the TextBlock1090 // 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;
16291626
src/link/MachO/reloc.zig+2-2
...@@ -878,9 +878,9 @@ pub const Parser = struct {...@@ -878,9 +878,9 @@ pub const Parser = struct {
878878
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 }
885885
886 parsed.payload = .{886 parsed.payload = .{