diff --git a/src/link/Elf.zig b/src/link/Elf.zig index cdc43b2d1a..d660c48b4b 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -3388,34 +3388,36 @@ fn shdrRank(self: *Elf, shndx: u32) u8 { elf.SHT_PREINIT_ARRAY, elf.SHT_INIT_ARRAY, elf.SHT_FINI_ARRAY, - => return 0xf2, + => return 0xf1, - elf.SHT_DYNAMIC => return 0xf3, + elf.SHT_DYNAMIC => return 0xf2, elf.SHT_RELA, elf.SHT_GROUP => return 0xf, elf.SHT_PROGBITS => if (flags & elf.SHF_ALLOC != 0) { if (flags & elf.SHF_EXECINSTR != 0) { - return 0xf1; + return 0xf0; } else if (flags & elf.SHF_WRITE != 0) { - return if (flags & elf.SHF_TLS != 0) 0xf4 else 0xf6; + return if (flags & elf.SHF_TLS != 0) 0xf3 else 0xf5; } else if (mem.eql(u8, name, ".interp")) { return 1; + } else if (mem.startsWith(u8, name, ".eh_frame")) { + return 0xe1; } else { - return 0xf0; + return 0xe0; } } else { if (mem.startsWith(u8, name, ".debug")) { - return 0xf8; + return 0xf7; } else { - return 0xf9; + return 0xf8; } }, - elf.SHT_X86_64_UNWIND => return 0xf0, + elf.SHT_X86_64_UNWIND => return 0xe1, - elf.SHT_NOBITS => return if (flags & elf.SHF_TLS != 0) 0xf5 else 0xf7, - elf.SHT_SYMTAB => return 0xfa, - elf.SHT_STRTAB => return if (mem.eql(u8, name, ".dynstr")) 0x4 else 0xfb, + elf.SHT_NOBITS => return if (flags & elf.SHF_TLS != 0) 0xf4 else 0xf6, + elf.SHT_SYMTAB => return 0xf9, + elf.SHT_STRTAB => return if (mem.eql(u8, name, ".dynstr")) 0x4 else 0xfa, else => return 0xff, } } diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 92c8c1e23f..a72ac697dd 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -391,15 +391,24 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx: .input_section_index = shndx, .file_index = self.index, }), - .fde => try self.fdes.append(allocator, .{ - .offset = data_start + rec.offset, - .size = rec.size, - .cie_index = undefined, - .rel_index = rel_start + @as(u32, @intCast(rel_range.start)), - .rel_num = @as(u32, @intCast(rel_range.len)), - .input_section_index = shndx, - .file_index = self.index, - }), + .fde => { + if (rel_range.len == 0) { + // No relocs for an FDE means we cannot associate this FDE to an Atom + // so we skip it. According to mold source code + // (https://github.com/rui314/mold/blob/a3e69502b0eaf1126d6093e8ea5e6fdb95219811/src/input-files.cc#L525-L528) + // this can happen for object files built with -r flag by the linker. + continue; + } + try self.fdes.append(allocator, .{ + .offset = data_start + rec.offset, + .size = rec.size, + .cie_index = undefined, + .rel_index = rel_start + @as(u32, @intCast(rel_range.start)), + .rel_num = @as(u32, @intCast(rel_range.len)), + .input_section_index = shndx, + .file_index = self.index, + }); + }, } } @@ -1106,6 +1115,7 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void { for (self.atoms_indexes.items) |atom_index| { const atom_ptr = self.atom(atom_index) orelse continue; if (!atom_ptr.alive) continue; + if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue; const shndx = blk: { const shndx = atom_ptr.relocsShndx() orelse continue; const shdr = self.shdrs.items[shndx]; diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index b62c0beae4..6d2325fb7e 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -808,6 +808,7 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void { for (self.atoms_indexes.items) |atom_index| { const atom_ptr = self.atom(atom_index) orelse continue; if (!atom_ptr.alive) continue; + if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue; const rela_shndx = atom_ptr.relocsShndx() orelse continue; // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level if (self.relocs.items[rela_shndx].items.len == 0) continue; diff --git a/src/link/Elf/eh_frame.zig b/src/link/Elf/eh_frame.zig index 8431a9e572..54024fa1bb 100644 --- a/src/link/Elf/eh_frame.zig +++ b/src/link/Elf/eh_frame.zig @@ -288,6 +288,13 @@ pub fn calcEhFrameHdrSize(elf_file: *Elf) usize { pub fn calcEhFrameRelocs(elf_file: *Elf) usize { var count: usize = 0; + if (elf_file.zigObjectPtr()) |zo| zo: { + const sym_index = zo.eh_frame_index orelse break :zo; + const sym = zo.symbol(sym_index); + const atom_ptr = zo.atom(sym.ref.index).?; + if (!atom_ptr.alive) break :zo; + count += atom_ptr.relocs(elf_file).len; + } for (elf_file.objects.items) |index| { const object = elf_file.file(index).?.object; for (object.cies.items) |cie| { @@ -416,9 +423,9 @@ pub fn writeEhFrameRelocatable(elf_file: *Elf, writer: anytype) !void { } } -fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela { +fn emitReloc(elf_file: *Elf, base_offset: u64, sym: *const Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela { const cpu_arch = elf_file.getTarget().cpu.arch; - const r_offset = rec.address(elf_file) + rel.r_offset - rec.offset; + const r_offset = base_offset + rel.r_offset; const r_type = rel.r_type(); var r_addend = rel.r_addend; var r_sym: u32 = 0; @@ -452,6 +459,19 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { elf_file.sections.items(.shdr)[elf_file.eh_frame_section_index.?].sh_addr, }); + if (elf_file.zigObjectPtr()) |zo| zo: { + const sym_index = zo.eh_frame_index orelse break :zo; + const sym = zo.symbol(sym_index); + const atom_ptr = zo.atom(sym.ref.index).?; + if (!atom_ptr.alive) break :zo; + for (atom_ptr.relocs(elf_file)) |rel| { + const ref = zo.resolveSymbol(rel.r_sym(), elf_file); + const target = elf_file.symbol(ref).?; + const out_rel = emitReloc(elf_file, 0, target, rel); + try writer.writeStruct(out_rel); + } + } + for (elf_file.objects.items) |index| { const object = elf_file.file(index).?.object; @@ -460,7 +480,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { for (cie.relocs(elf_file)) |rel| { const ref = object.resolveSymbol(rel.r_sym(), elf_file); const sym = elf_file.symbol(ref).?; - const out_rel = emitReloc(elf_file, cie, sym, rel); + const offset = cie.address(elf_file) - cie.offset; + const out_rel = emitReloc(elf_file, offset, sym, rel); try writer.writeStruct(out_rel); } } @@ -470,7 +491,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { for (fde.relocs(elf_file)) |rel| { const ref = object.resolveSymbol(rel.r_sym(), elf_file); const sym = elf_file.symbol(ref).?; - const out_rel = emitReloc(elf_file, fde, sym, rel); + const offset = fde.address(elf_file) - fde.offset; + const out_rel = emitReloc(elf_file, offset, sym, rel); try writer.writeStruct(out_rel); } } diff --git a/src/link/Elf/relocatable.zig b/src/link/Elf/relocatable.zig index 0ff2943ffa..b4a7f08f6e 100644 --- a/src/link/Elf/relocatable.zig +++ b/src/link/Elf/relocatable.zig @@ -424,8 +424,9 @@ fn writeSyntheticSections(elf_file: *Elf) !void { const gpa = elf_file.base.comp.gpa; const slice = elf_file.sections.slice(); - for (slice.items(.shdr), slice.items(.atom_list)) |shdr, atom_list| { + for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| { if (shdr.sh_type != elf.SHT_RELA) continue; + if (@as(u32, @intCast(shndx)) == elf_file.eh_frame_rela_section_index) continue; if (atom_list.items.len == 0) continue; const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse