| author | |
| committer | |
| log | 2ef3e30e2d04f16510d0953e6d266a97bcb4eb49 |
| tree | 2d4fd8e6fd36449939b254f99408370b3884cc86 |
| parent | 5cb51c10debd3e9542e35e22648bca2a8b59259e |
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, |
| 3392 | 3392 | ||
| 3393 | elf.SHT_DYNAMIC => return 0xf3, | 3393 | elf.SHT_DYNAMIC => return 0xf2, |
| 3394 | 3394 | ||
| 3395 | elf.SHT_RELA, elf.SHT_GROUP => return 0xf, | 3395 | elf.SHT_RELA, elf.SHT_GROUP => return 0xf, |
| 3396 | 3396 | ||
| 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, |
| 3415 | 3417 | ||
| 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 | } |
| 405 | 414 | ||
| ... | @@ -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 level | 813 | // 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 { |
| 288 | 288 | ||
| 289 | pub fn calcEhFrameRelocs(elf_file: *Elf) usize { | 289 | pub 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 | } |
| 418 | 425 | ||
| 419 | fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela { | 426 | fn 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 | }); |
| 454 | 461 | ||
| 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; |
| 457 | 477 | ||
| ... | @@ -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(); |
| 426 | 426 | ||
| 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; |
| 430 | 431 | ||
| 431 | const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse | 432 | const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse |