diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Elf.zig | 19 | ||||
| -rw-r--r-- | src/link/Elf/Object.zig | 14 | ||||
| -rw-r--r-- | src/link/Elf/eh_frame.zig | 39 |
3 files changed, 58 insertions, 14 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index e490e6091e..ce90efbd23 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1446,8 +1446,6 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) // Now, we are ready to resolve the symbols across all input files. // We will first resolve the files in the ZigObject, next in the parsed // input Object files. - // Any qualifing unresolved symbol will be upgraded to an absolute, weak - // symbol for potential resolution at load-time. self.resolveSymbols(); self.markEhFrameAtomsDead(); self.claimUnresolvedObject(); @@ -4037,11 +4035,10 @@ fn sortShdrs(self: *Elf) !void { shdr.sh_info = self.plt_section_index.?; } - for (self.shdrs.items) |*shdr| { - if (shdr.sh_type == elf.SHT_RELA and shdr.sh_flags & elf.SHF_INFO_LINK != 0) { - shdr.sh_link = self.symtab_section_index.?; - shdr.sh_info = backlinks[shdr.sh_info]; - } + if (self.eh_frame_rela_section_index) |index| { + const shdr = &self.shdrs.items[index]; + shdr.sh_link = self.symtab_section_index.?; + shdr.sh_info = self.eh_frame_section_index.?; } { @@ -4122,6 +4119,12 @@ fn sortShdrs(self: *Elf) !void { global.output_section_index = backlinks[out_shndx]; } } + + for (self.output_rela_sections.keys(), self.output_rela_sections.values()) |shndx, sec| { + const shdr = &self.shdrs.items[sec.shndx]; + shdr.sh_link = self.symtab_section_index.?; + shdr.sh_info = shndx; + } } fn updateSectionSizes(self: *Elf) !void { @@ -5009,7 +5012,7 @@ fn writeSyntheticSectionsObject(self: *Elf) !void { const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); defer buffer.deinit(); - try eh_frame.writeEhFrame(self, buffer.writer()); + try eh_frame.writeEhFrameObject(self, buffer.writer()); try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); } if (self.eh_frame_rela_section_index) |shndx| { diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 0a4232d3b1..ce9b83c9bb 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -687,7 +687,6 @@ pub fn initRelaSections(self: Object, elf_file: *Elf) !void { const out_shdr = &elf_file.shdrs.items[out_shndx]; out_shdr.sh_addralign = @alignOf(elf.Elf64_Rela); out_shdr.sh_entsize = @sizeOf(elf.Elf64_Rela); - out_shdr.sh_info = self.initOutputSection(elf_file, atom.inputShdr(elf_file)) catch unreachable; } } @@ -695,13 +694,18 @@ pub fn addAtomsToRelaSections(self: Object, elf_file: *Elf) !void { for (self.atoms.items) |atom_index| { const atom = elf_file.atom(atom_index) orelse continue; if (!atom.flags.alive) continue; - const shndx = atom.relocsShndx() orelse continue; - const shdr = self.shdrs.items[shndx]; - const out_shndx = self.initOutputSection(elf_file, shdr) catch unreachable; + const shndx = blk: { + const shndx = atom.relocsShndx() orelse continue; + const shdr = self.shdrs.items[shndx]; + break :blk self.initOutputSection(elf_file, shdr) catch unreachable; + }; + const shdr = &elf_file.shdrs.items[shndx]; + shdr.sh_info = atom.outputShndx().?; + shdr.sh_link = elf_file.symtab_section_index.?; const gpa = elf_file.base.allocator; const gop = try elf_file.output_rela_sections.getOrPut(gpa, atom.outputShndx().?); - if (!gop.found_existing) gop.value_ptr.* = .{ .shndx = out_shndx }; + if (!gop.found_existing) gop.value_ptr.* = .{ .shndx = shndx }; try gop.value_ptr.atom_list.append(gpa, atom_index); } } diff --git a/src/link/Elf/eh_frame.zig b/src/link/Elf/eh_frame.zig index 3657a3f5b7..73857d03d2 100644 --- a/src/link/Elf/eh_frame.zig +++ b/src/link/Elf/eh_frame.zig @@ -268,7 +268,11 @@ pub fn calcEhFrameSize(elf_file: *Elf) !usize { } } - return offset + 4; // NULL terminator + if (!elf_file.isRelocatable()) { + offset += 4; // NULL terminator + } + + return offset; } pub fn calcEhFrameHdrSize(elf_file: *Elf) usize { @@ -373,6 +377,39 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void { try writer.writeInt(u32, 0, .little); } +pub fn writeEhFrameObject(elf_file: *Elf, writer: anytype) !void { + const gpa = elf_file.base.allocator; + + for (elf_file.objects.items) |index| { + const object = elf_file.file(index).?.object; + + for (object.cies.items) |cie| { + if (!cie.alive) continue; + try writer.writeAll(cie.data(elf_file)); + } + } + + for (elf_file.objects.items) |index| { + const object = elf_file.file(index).?.object; + + for (object.fdes.items) |fde| { + if (!fde.alive) continue; + + const contents = try gpa.dupe(u8, fde.data(elf_file)); + defer gpa.free(contents); + + std.mem.writeInt( + i32, + contents[4..8], + @truncate(@as(i64, @intCast(fde.out_offset + 4)) - @as(i64, @intCast(fde.cie(elf_file).out_offset))), + .little, + ); + + try writer.writeAll(contents); + } + } +} + fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela { const r_offset = rec.address(elf_file) + rel.r_offset - rec.offset; const r_type = rel.r_type(); |
