authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-09-03 13:28:01+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-09-04 13:34:26+02:00
log2ef3e30e2d04f16510d0953e6d266a97bcb4eb49
tree2d4fd8e6fd36449939b254f99408370b3884cc86
parent5cb51c10debd3e9542e35e22648bca2a8b59259e

elf: emit relocs for self-hosted generated .eh_frame section


5 files changed, 61 insertions(+), 25 deletions(-)

src/link/Elf.zig+13-11
...@@ -3388,34 +3388,36 @@ fn shdrRank(self: *Elf, shndx: u32) u8 {...@@ -3388,34 +3388,36 @@ fn shdrRank(self: *Elf, shndx: u32) u8 {
3388 elf.SHT_PREINIT_ARRAY,3388 elf.SHT_PREINIT_ARRAY,
3389 elf.SHT_INIT_ARRAY,3389 elf.SHT_INIT_ARRAY,
3390 elf.SHT_FINI_ARRAY,3390 elf.SHT_FINI_ARRAY,
3391 => return 0xf2,3391 => return 0xf1,
33923392
3393 elf.SHT_DYNAMIC => return 0xf3,3393 elf.SHT_DYNAMIC => return 0xf2,
33943394
3395 elf.SHT_RELA, elf.SHT_GROUP => return 0xf,3395 elf.SHT_RELA, elf.SHT_GROUP => return 0xf,
33963396
3397 elf.SHT_PROGBITS => if (flags & elf.SHF_ALLOC != 0) {3397 elf.SHT_PROGBITS => if (flags & elf.SHF_ALLOC != 0) {
3398 if (flags & elf.SHF_EXECINSTR != 0) {3398 if (flags & elf.SHF_EXECINSTR != 0) {
3399 return 0xf1;3399 return 0xf0;
3400 } else if (flags & elf.SHF_WRITE != 0) {3400 } else if (flags & elf.SHF_WRITE != 0) {
3401 return if (flags & elf.SHF_TLS != 0) 0xf4 else 0xf6;3401 return if (flags & elf.SHF_TLS != 0) 0xf3 else 0xf5;
3402 } else if (mem.eql(u8, name, ".interp")) {3402 } else if (mem.eql(u8, name, ".interp")) {
3403 return 1;3403 return 1;
3404 } else if (mem.startsWith(u8, name, ".eh_frame")) {
3405 return 0xe1;
3404 } else {3406 } else {
3405 return 0xf0;3407 return 0xe0;
3406 }3408 }
3407 } else {3409 } else {
3408 if (mem.startsWith(u8, name, ".debug")) {3410 if (mem.startsWith(u8, name, ".debug")) {
3409 return 0xf8;3411 return 0xf7;
3410 } else {3412 } else {
3411 return 0xf9;3413 return 0xf8;
3412 }3414 }
3413 },3415 },
3414 elf.SHT_X86_64_UNWIND => return 0xf0,3416 elf.SHT_X86_64_UNWIND => return 0xe1,
34153417
3416 elf.SHT_NOBITS => return if (flags & elf.SHF_TLS != 0) 0xf5 else 0xf7,3418 elf.SHT_NOBITS => return if (flags & elf.SHF_TLS != 0) 0xf4 else 0xf6,
3417 elf.SHT_SYMTAB => return 0xfa,3419 elf.SHT_SYMTAB => return 0xf9,
3418 elf.SHT_STRTAB => return if (mem.eql(u8, name, ".dynstr")) 0x4 else 0xfb,3420 elf.SHT_STRTAB => return if (mem.eql(u8, name, ".dynstr")) 0x4 else 0xfa,
3419 else => return 0xff,3421 else => return 0xff,
3420 }3422 }
3421}3423}
src/link/Elf/Object.zig+19-9
...@@ -391,15 +391,24 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx:...@@ -391,15 +391,24 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx:
391 .input_section_index = shndx,391 .input_section_index = shndx,
392 .file_index = self.index,392 .file_index = self.index,
393 }),393 }),
394 .fde => try self.fdes.append(allocator, .{394 .fde => {
395 .offset = data_start + rec.offset,395 if (rel_range.len == 0) {
396 .size = rec.size,396 // No relocs for an FDE means we cannot associate this FDE to an Atom
397 .cie_index = undefined,397 // so we skip it. According to mold source code
398 .rel_index = rel_start + @as(u32, @intCast(rel_range.start)),398 // (https://github.com/rui314/mold/blob/a3e69502b0eaf1126d6093e8ea5e6fdb95219811/src/input-files.cc#L525-L528)
399 .rel_num = @as(u32, @intCast(rel_range.len)),399 // this can happen for object files built with -r flag by the linker.
400 .input_section_index = shndx,400 continue;
401 .file_index = self.index,401 }
402 }),402 try self.fdes.append(allocator, .{
403 .offset = data_start + rec.offset,
404 .size = rec.size,
405 .cie_index = undefined,
406 .rel_index = rel_start + @as(u32, @intCast(rel_range.start)),
407 .rel_num = @as(u32, @intCast(rel_range.len)),
408 .input_section_index = shndx,
409 .file_index = self.index,
410 });
411 },
403 }412 }
404 }413 }
405414
...@@ -1106,6 +1115,7 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void {...@@ -1106,6 +1115,7 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void {
1106 for (self.atoms_indexes.items) |atom_index| {1115 for (self.atoms_indexes.items) |atom_index| {
1107 const atom_ptr = self.atom(atom_index) orelse continue;1116 const atom_ptr = self.atom(atom_index) orelse continue;
1108 if (!atom_ptr.alive) continue;1117 if (!atom_ptr.alive) continue;
1118 if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue;
1109 const shndx = blk: {1119 const shndx = blk: {
1110 const shndx = atom_ptr.relocsShndx() orelse continue;1120 const shndx = atom_ptr.relocsShndx() orelse continue;
1111 const shdr = self.shdrs.items[shndx];1121 const shdr = self.shdrs.items[shndx];
src/link/Elf/ZigObject.zig+1
...@@ -808,6 +808,7 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void {...@@ -808,6 +808,7 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void {
808 for (self.atoms_indexes.items) |atom_index| {808 for (self.atoms_indexes.items) |atom_index| {
809 const atom_ptr = self.atom(atom_index) orelse continue;809 const atom_ptr = self.atom(atom_index) orelse continue;
810 if (!atom_ptr.alive) continue;810 if (!atom_ptr.alive) continue;
811 if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue;
811 const rela_shndx = atom_ptr.relocsShndx() orelse continue;812 const rela_shndx = atom_ptr.relocsShndx() orelse continue;
812 // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level813 // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level
813 if (self.relocs.items[rela_shndx].items.len == 0) continue;814 if (self.relocs.items[rela_shndx].items.len == 0) continue;
src/link/Elf/eh_frame.zig+26-4
...@@ -288,6 +288,13 @@ pub fn calcEhFrameHdrSize(elf_file: *Elf) usize {...@@ -288,6 +288,13 @@ pub fn calcEhFrameHdrSize(elf_file: *Elf) usize {
288288
289pub fn calcEhFrameRelocs(elf_file: *Elf) usize {289pub fn calcEhFrameRelocs(elf_file: *Elf) usize {
290 var count: usize = 0;290 var count: usize = 0;
291 if (elf_file.zigObjectPtr()) |zo| zo: {
292 const sym_index = zo.eh_frame_index orelse break :zo;
293 const sym = zo.symbol(sym_index);
294 const atom_ptr = zo.atom(sym.ref.index).?;
295 if (!atom_ptr.alive) break :zo;
296 count += atom_ptr.relocs(elf_file).len;
297 }
291 for (elf_file.objects.items) |index| {298 for (elf_file.objects.items) |index| {
292 const object = elf_file.file(index).?.object;299 const object = elf_file.file(index).?.object;
293 for (object.cies.items) |cie| {300 for (object.cies.items) |cie| {
...@@ -416,9 +423,9 @@ pub fn writeEhFrameRelocatable(elf_file: *Elf, writer: anytype) !void {...@@ -416,9 +423,9 @@ pub fn writeEhFrameRelocatable(elf_file: *Elf, writer: anytype) !void {
416 }423 }
417}424}
418425
419fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela {426fn emitReloc(elf_file: *Elf, base_offset: u64, sym: *const Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela {
420 const cpu_arch = elf_file.getTarget().cpu.arch;427 const cpu_arch = elf_file.getTarget().cpu.arch;
421 const r_offset = rec.address(elf_file) + rel.r_offset - rec.offset;428 const r_offset = base_offset + rel.r_offset;
422 const r_type = rel.r_type();429 const r_type = rel.r_type();
423 var r_addend = rel.r_addend;430 var r_addend = rel.r_addend;
424 var r_sym: u32 = 0;431 var r_sym: u32 = 0;
...@@ -452,6 +459,19 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {...@@ -452,6 +459,19 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
452 elf_file.sections.items(.shdr)[elf_file.eh_frame_section_index.?].sh_addr,459 elf_file.sections.items(.shdr)[elf_file.eh_frame_section_index.?].sh_addr,
453 });460 });
454461
462 if (elf_file.zigObjectPtr()) |zo| zo: {
463 const sym_index = zo.eh_frame_index orelse break :zo;
464 const sym = zo.symbol(sym_index);
465 const atom_ptr = zo.atom(sym.ref.index).?;
466 if (!atom_ptr.alive) break :zo;
467 for (atom_ptr.relocs(elf_file)) |rel| {
468 const ref = zo.resolveSymbol(rel.r_sym(), elf_file);
469 const target = elf_file.symbol(ref).?;
470 const out_rel = emitReloc(elf_file, 0, target, rel);
471 try writer.writeStruct(out_rel);
472 }
473 }
474
455 for (elf_file.objects.items) |index| {475 for (elf_file.objects.items) |index| {
456 const object = elf_file.file(index).?.object;476 const object = elf_file.file(index).?.object;
457477
...@@ -460,7 +480,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {...@@ -460,7 +480,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
460 for (cie.relocs(elf_file)) |rel| {480 for (cie.relocs(elf_file)) |rel| {
461 const ref = object.resolveSymbol(rel.r_sym(), elf_file);481 const ref = object.resolveSymbol(rel.r_sym(), elf_file);
462 const sym = elf_file.symbol(ref).?;482 const sym = elf_file.symbol(ref).?;
463 const out_rel = emitReloc(elf_file, cie, sym, rel);483 const offset = cie.address(elf_file) - cie.offset;
484 const out_rel = emitReloc(elf_file, offset, sym, rel);
464 try writer.writeStruct(out_rel);485 try writer.writeStruct(out_rel);
465 }486 }
466 }487 }
...@@ -470,7 +491,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {...@@ -470,7 +491,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
470 for (fde.relocs(elf_file)) |rel| {491 for (fde.relocs(elf_file)) |rel| {
471 const ref = object.resolveSymbol(rel.r_sym(), elf_file);492 const ref = object.resolveSymbol(rel.r_sym(), elf_file);
472 const sym = elf_file.symbol(ref).?;493 const sym = elf_file.symbol(ref).?;
473 const out_rel = emitReloc(elf_file, fde, sym, rel);494 const offset = fde.address(elf_file) - fde.offset;
495 const out_rel = emitReloc(elf_file, offset, sym, rel);
474 try writer.writeStruct(out_rel);496 try writer.writeStruct(out_rel);
475 }497 }
476 }498 }
src/link/Elf/relocatable.zig+2-1
...@@ -424,8 +424,9 @@ fn writeSyntheticSections(elf_file: *Elf) !void {...@@ -424,8 +424,9 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
424 const gpa = elf_file.base.comp.gpa;424 const gpa = elf_file.base.comp.gpa;
425 const slice = elf_file.sections.slice();425 const slice = elf_file.sections.slice();
426426
427 for (slice.items(.shdr), slice.items(.atom_list)) |shdr, atom_list| {427 for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| {
428 if (shdr.sh_type != elf.SHT_RELA) continue;428 if (shdr.sh_type != elf.SHT_RELA) continue;
429 if (@as(u32, @intCast(shndx)) == elf_file.eh_frame_rela_section_index) continue;
429 if (atom_list.items.len == 0) continue;430 if (atom_list.items.len == 0) continue;
430431
431 const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse432 const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse