authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-09 14:46:28+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-09 14:46:28+01:00
log1f8dd27e40bb455da85bfb1ae655ad63bc05ea08
tree618b69cfa2785761e3846cad801bb3c31a0068e9
parentb1fcf0ed8f435b834f21a3d57c03f5c0333c6fd9

elf: correctly format output .eh_frame when emitting relocatable


3 files changed, 58 insertions(+), 14 deletions(-)

src/link/Elf.zig+11-8
...@@ -1446,8 +1446,6 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8)...@@ -1446,8 +1446,6 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8)
1446 // Now, we are ready to resolve the symbols across all input files.1446 // Now, we are ready to resolve the symbols across all input files.
1447 // We will first resolve the files in the ZigObject, next in the parsed1447 // We will first resolve the files in the ZigObject, next in the parsed
1448 // input Object files.1448 // input Object files.
1449 // Any qualifing unresolved symbol will be upgraded to an absolute, weak
1450 // symbol for potential resolution at load-time.
1451 self.resolveSymbols();1449 self.resolveSymbols();
1452 self.markEhFrameAtomsDead();1450 self.markEhFrameAtomsDead();
1453 self.claimUnresolvedObject();1451 self.claimUnresolvedObject();
...@@ -4037,11 +4035,10 @@ fn sortShdrs(self: *Elf) !void {...@@ -4037,11 +4035,10 @@ fn sortShdrs(self: *Elf) !void {
4037 shdr.sh_info = self.plt_section_index.?;4035 shdr.sh_info = self.plt_section_index.?;
4038 }4036 }
40394037
4040 for (self.shdrs.items) |*shdr| {4038 if (self.eh_frame_rela_section_index) |index| {
4041 if (shdr.sh_type == elf.SHT_RELA and shdr.sh_flags & elf.SHF_INFO_LINK != 0) {4039 const shdr = &self.shdrs.items[index];
4042 shdr.sh_link = self.symtab_section_index.?;4040 shdr.sh_link = self.symtab_section_index.?;
4043 shdr.sh_info = backlinks[shdr.sh_info];4041 shdr.sh_info = self.eh_frame_section_index.?;
4044 }
4045 }4042 }
40464043
4047 {4044 {
...@@ -4122,6 +4119,12 @@ fn sortShdrs(self: *Elf) !void {...@@ -4122,6 +4119,12 @@ fn sortShdrs(self: *Elf) !void {
4122 global.output_section_index = backlinks[out_shndx];4119 global.output_section_index = backlinks[out_shndx];
4123 }4120 }
4124 }4121 }
4122
4123 for (self.output_rela_sections.keys(), self.output_rela_sections.values()) |shndx, sec| {
4124 const shdr = &self.shdrs.items[sec.shndx];
4125 shdr.sh_link = self.symtab_section_index.?;
4126 shdr.sh_info = shndx;
4127 }
4125}4128}
41264129
4127fn updateSectionSizes(self: *Elf) !void {4130fn updateSectionSizes(self: *Elf) !void {
...@@ -5009,7 +5012,7 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {...@@ -5009,7 +5012,7 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {
5009 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;5012 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
5010 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);5013 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
5011 defer buffer.deinit();5014 defer buffer.deinit();
5012 try eh_frame.writeEhFrame(self, buffer.writer());5015 try eh_frame.writeEhFrameObject(self, buffer.writer());
5013 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);5016 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
5014 }5017 }
5015 if (self.eh_frame_rela_section_index) |shndx| {5018 if (self.eh_frame_rela_section_index) |shndx| {
src/link/Elf/Object.zig+9-5
...@@ -687,7 +687,6 @@ pub fn initRelaSections(self: Object, elf_file: *Elf) !void {...@@ -687,7 +687,6 @@ pub fn initRelaSections(self: Object, elf_file: *Elf) !void {
687 const out_shdr = &elf_file.shdrs.items[out_shndx];687 const out_shdr = &elf_file.shdrs.items[out_shndx];
688 out_shdr.sh_addralign = @alignOf(elf.Elf64_Rela);688 out_shdr.sh_addralign = @alignOf(elf.Elf64_Rela);
689 out_shdr.sh_entsize = @sizeOf(elf.Elf64_Rela);689 out_shdr.sh_entsize = @sizeOf(elf.Elf64_Rela);
690 out_shdr.sh_info = self.initOutputSection(elf_file, atom.inputShdr(elf_file)) catch unreachable;
691 }690 }
692}691}
693692
...@@ -695,13 +694,18 @@ pub fn addAtomsToRelaSections(self: Object, elf_file: *Elf) !void {...@@ -695,13 +694,18 @@ pub fn addAtomsToRelaSections(self: Object, elf_file: *Elf) !void {
695 for (self.atoms.items) |atom_index| {694 for (self.atoms.items) |atom_index| {
696 const atom = elf_file.atom(atom_index) orelse continue;695 const atom = elf_file.atom(atom_index) orelse continue;
697 if (!atom.flags.alive) continue;696 if (!atom.flags.alive) continue;
698 const shndx = atom.relocsShndx() orelse continue;697 const shndx = blk: {
699 const shdr = self.shdrs.items[shndx];698 const shndx = atom.relocsShndx() orelse continue;
700 const out_shndx = self.initOutputSection(elf_file, shdr) catch unreachable;699 const shdr = self.shdrs.items[shndx];
700 break :blk self.initOutputSection(elf_file, shdr) catch unreachable;
701 };
702 const shdr = &elf_file.shdrs.items[shndx];
703 shdr.sh_info = atom.outputShndx().?;
704 shdr.sh_link = elf_file.symtab_section_index.?;
701705
702 const gpa = elf_file.base.allocator;706 const gpa = elf_file.base.allocator;
703 const gop = try elf_file.output_rela_sections.getOrPut(gpa, atom.outputShndx().?);707 const gop = try elf_file.output_rela_sections.getOrPut(gpa, atom.outputShndx().?);
704 if (!gop.found_existing) gop.value_ptr.* = .{ .shndx = out_shndx };708 if (!gop.found_existing) gop.value_ptr.* = .{ .shndx = shndx };
705 try gop.value_ptr.atom_list.append(gpa, atom_index);709 try gop.value_ptr.atom_list.append(gpa, atom_index);
706 }710 }
707}711}
src/link/Elf/eh_frame.zig+38-1
...@@ -268,7 +268,11 @@ pub fn calcEhFrameSize(elf_file: *Elf) !usize {...@@ -268,7 +268,11 @@ pub fn calcEhFrameSize(elf_file: *Elf) !usize {
268 }268 }
269 }269 }
270270
271 return offset + 4; // NULL terminator271 if (!elf_file.isRelocatable()) {
272 offset += 4; // NULL terminator
273 }
274
275 return offset;
272}276}
273277
274pub fn calcEhFrameHdrSize(elf_file: *Elf) usize {278pub fn calcEhFrameHdrSize(elf_file: *Elf) usize {
...@@ -373,6 +377,39 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {...@@ -373,6 +377,39 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
373 try writer.writeInt(u32, 0, .little);377 try writer.writeInt(u32, 0, .little);
374}378}
375379
380pub fn writeEhFrameObject(elf_file: *Elf, writer: anytype) !void {
381 const gpa = elf_file.base.allocator;
382
383 for (elf_file.objects.items) |index| {
384 const object = elf_file.file(index).?.object;
385
386 for (object.cies.items) |cie| {
387 if (!cie.alive) continue;
388 try writer.writeAll(cie.data(elf_file));
389 }
390 }
391
392 for (elf_file.objects.items) |index| {
393 const object = elf_file.file(index).?.object;
394
395 for (object.fdes.items) |fde| {
396 if (!fde.alive) continue;
397
398 const contents = try gpa.dupe(u8, fde.data(elf_file));
399 defer gpa.free(contents);
400
401 std.mem.writeInt(
402 i32,
403 contents[4..8],
404 @truncate(@as(i64, @intCast(fde.out_offset + 4)) - @as(i64, @intCast(fde.cie(elf_file).out_offset))),
405 .little,
406 );
407
408 try writer.writeAll(contents);
409 }
410 }
411}
412
376fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela {413fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela {
377 const r_offset = rec.address(elf_file) + rel.r_offset - rec.offset;414 const r_offset = rec.address(elf_file) + rel.r_offset - rec.offset;
378 const r_type = rel.r_type();415 const r_type = rel.r_type();