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 {
431431 else
432432 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
448434 const block = try self.allocator.create(TextBlock);
449435 errdefer self.allocator.destroy(block);
450436
451437 block.* = TextBlock.init(self.allocator);
452438 block.local_sym_index = senior_nlist.index;
453 block.aliases = alias_only_indices;
454439 block.code = try self.allocator.dupe(u8, code);
455440 block.size = size;
456441 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
458455 const relocs = filterRelocs(self.relocs, start_addr, end_addr);
459456 if (relocs.len > 0) {
460457 try self.object.parseRelocs(self.zld, relocs, block, start_addr);
......@@ -617,7 +614,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
617614 const tsect = &tseg.sections.items[match.sect];
618615 const new_alignment = math.max(tsect.@"align", block.alignment);
619616 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;
621618 tsect.size = new_size;
622619 tsect.@"align" = new_alignment;
623620
......@@ -653,6 +650,19 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
653650 }
654651 }
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
656666 // Update target section's metadata
657667 // TODO should we update segment's size here too?
658668 // How does it tie with incremental space allocs?
......@@ -660,7 +670,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
660670 const tsect = &tseg.sections.items[match.sect];
661671 const new_alignment = math.max(tsect.@"align", block.alignment);
662672 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;
664674 tsect.size = new_size;
665675 tsect.@"align" = new_alignment;
666676
......@@ -764,7 +774,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
764774 const tsect = &tseg.sections.items[match.sect];
765775 const new_alignment = math.max(tsect.@"align", block.alignment);
766776 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;
768778 tsect.size = new_size;
769779 tsect.@"align" = new_alignment;
770780
src/link/MachO/Zld.zig+10-13
......@@ -125,7 +125,7 @@ pub const Output = struct {
125125pub const TextBlock = struct {
126126 allocator: *Allocator,
127127 local_sym_index: u32,
128 aliases: ?[]u32 = null,
128 aliases: std.ArrayList(u32),
129129 references: std.AutoArrayHashMap(u32, void),
130130 contained: ?[]SymbolAtOffset = null,
131131 code: []u8,
......@@ -146,6 +146,7 @@ pub const TextBlock = struct {
146146 return .{
147147 .allocator = allocator,
148148 .local_sym_index = undefined,
149 .aliases = std.ArrayList(u32).init(allocator),
149150 .references = std.AutoArrayHashMap(u32, void).init(allocator),
150151 .code = undefined,
151152 .relocs = std.ArrayList(Relocation).init(allocator),
......@@ -157,9 +158,7 @@ pub const TextBlock = struct {
157158 }
158159
159160 pub fn deinit(self: *TextBlock) void {
160 if (self.aliases) |aliases| {
161 self.allocator.free(aliases);
162 }
161 self.aliases.deinit();
163162 self.references.deinit();
164163 if (self.contained) |contained| {
165164 self.allocator.free(contained);
......@@ -179,9 +178,9 @@ pub const TextBlock = struct {
179178 pub fn print_this(self: *const TextBlock, zld: *Zld) void {
180179 log.warn("TextBlock", .{});
181180 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) {
183182 log.warn(" aliases:", .{});
184 for (aliases) |index| {
183 for (self.aliases.items) |index| {
185184 log.warn(" {}: {}", .{ index, zld.locals.items[index] });
186185 }
187186 }
......@@ -1082,12 +1081,10 @@ fn allocateTextBlocks(self: *Zld) !void {
10821081 });
10831082
10841083 // 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;
10911088 }
10921089
10931090 // Update each symbol contained within the TextBlock
......@@ -1623,7 +1620,7 @@ fn resolveSymbols(self: *Zld) !void {
16231620 const tsect = &tseg.sections.items[match.sect];
16241621 const new_alignment = math.max(tsect.@"align", block.alignment);
16251622 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;
16271624 tsect.size = new_size;
16281625 tsect.@"align" = new_alignment;
16291626
src/link/MachO/reloc.zig+2-2
......@@ -878,9 +878,9 @@ pub const Parser = struct {
878878
879879 if (rel.r_extern == 0) {
880880 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;
882882 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);
884884 }
885885
886886 parsed.payload = .{