elf: emit relocs for self-hosted generated .eh_frame section
This commit is contained in:
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user