| ... | @@ -300,7 +300,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void { | ... | @@ -300,7 +300,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void { |
| 300 | self.* = .{}; | 300 | self.* = .{}; |
| 301 | } | 301 | } |
| 302 | | 302 | |
| 303 | pub fn relocs(self: Atom, elf_file: *Elf) []align(1) const elf.Elf64_Rela { | 303 | pub fn relocs(self: Atom, elf_file: *Elf) []const elf.Elf64_Rela { |
| 304 | const shndx = self.relocsShndx() orelse return &[0]elf.Elf64_Rela{}; | 304 | const shndx = self.relocsShndx() orelse return &[0]elf.Elf64_Rela{}; |
| 305 | return switch (self.file(elf_file).?) { | 305 | return switch (self.file(elf_file).?) { |
| 306 | .zig_object => |x| x.relocs.items[shndx].items, | 306 | .zig_object => |x| x.relocs.items[shndx].items, |
| ... | @@ -394,11 +394,54 @@ pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) bool { | ... | @@ -394,11 +394,54 @@ pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) bool { |
| 394 | return false; | 394 | return false; |
| 395 | } | 395 | } |
| 396 | | 396 | |
| 397 | pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype) !void { | 397 | pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype) RelocError!void { |
| 398 | switch (elf_file.getTarget().cpu.arch) { | 398 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 399 | .x86_64 => try x86_64.scanRelocs(self, elf_file, code, undefs), | 399 | const file_ptr = self.file(elf_file).?; |
| 400 | else => return error.UnsupportedCpuArch, | 400 | const rels = self.relocs(elf_file); |
| | 401 | |
| | 402 | var has_reloc_errors = false; |
| | 403 | var it = RelocsIterator{ .relocs = rels }; |
| | 404 | while (it.next()) |rel| { |
| | 405 | const r_kind = relocation.decode(rel.r_type(), cpu_arch); |
| | 406 | if (r_kind == .none) continue; |
| | 407 | |
| | 408 | const symbol_index = switch (file_ptr) { |
| | 409 | .zig_object => |x| x.symbol(rel.r_sym()), |
| | 410 | .object => |x| x.symbols.items[rel.r_sym()], |
| | 411 | else => unreachable, |
| | 412 | }; |
| | 413 | const symbol = elf_file.symbol(symbol_index); |
| | 414 | |
| | 415 | // Check for violation of One Definition Rule for COMDATs. |
| | 416 | if (symbol.file(elf_file) == null) { |
| | 417 | // TODO convert into an error |
| | 418 | log.debug("{}: {s}: {s} refers to a discarded COMDAT section", .{ |
| | 419 | file_ptr.fmtPath(), |
| | 420 | self.name(elf_file), |
| | 421 | symbol.name(elf_file), |
| | 422 | }); |
| | 423 | continue; |
| | 424 | } |
| | 425 | |
| | 426 | // Report an undefined symbol. |
| | 427 | if (try self.reportUndefined(elf_file, symbol, symbol_index, rel, undefs)) continue; |
| | 428 | |
| | 429 | if (symbol.isIFunc(elf_file)) { |
| | 430 | symbol.flags.needs_got = true; |
| | 431 | symbol.flags.needs_plt = true; |
| | 432 | } |
| | 433 | |
| | 434 | // While traversing relocations, mark symbols that require special handling such as |
| | 435 | // pointer indirection via GOT, or a stub trampoline via PLT. |
| | 436 | switch (elf_file.getTarget().cpu.arch) { |
| | 437 | .x86_64 => x86_64.scanReloc(self, elf_file, rel, symbol, code, &it) catch |err| switch (err) { |
| | 438 | error.RelocFailure => has_reloc_errors = true, |
| | 439 | else => |e| return e, |
| | 440 | }, |
| | 441 | else => return error.UnsupportedCpuArch, |
| | 442 | } |
| 401 | } | 443 | } |
| | 444 | if (has_reloc_errors) return error.RelocFailure; |
| 402 | } | 445 | } |
| 403 | | 446 | |
| 404 | fn scanReloc( | 447 | fn scanReloc( |
| ... | @@ -407,7 +450,7 @@ fn scanReloc( | ... | @@ -407,7 +450,7 @@ fn scanReloc( |
| 407 | rel: elf.Elf64_Rela, | 450 | rel: elf.Elf64_Rela, |
| 408 | action: RelocAction, | 451 | action: RelocAction, |
| 409 | elf_file: *Elf, | 452 | elf_file: *Elf, |
| 410 | ) error{OutOfMemory}!void { | 453 | ) RelocError!void { |
| 411 | const is_writeable = self.inputShdr(elf_file).sh_flags & elf.SHF_WRITE != 0; | 454 | const is_writeable = self.inputShdr(elf_file).sh_flags & elf.SHF_WRITE != 0; |
| 412 | const num_dynrelocs = switch (self.file(elf_file).?) { | 455 | const num_dynrelocs = switch (self.file(elf_file).?) { |
| 413 | .linker_defined => unreachable, | 456 | .linker_defined => unreachable, |
| ... | @@ -554,7 +597,7 @@ fn dataType(symbol: *const Symbol, elf_file: *Elf) u2 { | ... | @@ -554,7 +597,7 @@ fn dataType(symbol: *const Symbol, elf_file: *Elf) u2 { |
| 554 | return 3; | 597 | return 3; |
| 555 | } | 598 | } |
| 556 | | 599 | |
| 557 | fn reportUnhandledRelocError(self: Atom, rel: elf.Elf64_Rela, elf_file: *Elf) error{OutOfMemory}!void { | 600 | fn reportUnhandledRelocError(self: Atom, rel: elf.Elf64_Rela, elf_file: *Elf) RelocError!void { |
| 558 | var err = try elf_file.addErrorWithNotes(1); | 601 | var err = try elf_file.addErrorWithNotes(1); |
| 559 | try err.addMsg(elf_file, "fatal linker error: unhandled relocation type {} at offset 0x{x}", .{ | 602 | try err.addMsg(elf_file, "fatal linker error: unhandled relocation type {} at offset 0x{x}", .{ |
| 560 | relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch), | 603 | relocation.fmtRelocType(rel.r_type(), elf_file.getTarget().cpu.arch), |
| ... | @@ -564,6 +607,7 @@ fn reportUnhandledRelocError(self: Atom, rel: elf.Elf64_Rela, elf_file: *Elf) er | ... | @@ -564,6 +607,7 @@ fn reportUnhandledRelocError(self: Atom, rel: elf.Elf64_Rela, elf_file: *Elf) er |
| 564 | self.file(elf_file).?.fmtPath(), | 607 | self.file(elf_file).?.fmtPath(), |
| 565 | self.name(elf_file), | 608 | self.name(elf_file), |
| 566 | }); | 609 | }); |
| | 610 | return error.RelocFailure; |
| 567 | } | 611 | } |
| 568 | | 612 | |
| 569 | fn reportTextRelocError( | 613 | fn reportTextRelocError( |
| ... | @@ -571,7 +615,7 @@ fn reportTextRelocError( | ... | @@ -571,7 +615,7 @@ fn reportTextRelocError( |
| 571 | symbol: *const Symbol, | 615 | symbol: *const Symbol, |
| 572 | rel: elf.Elf64_Rela, | 616 | rel: elf.Elf64_Rela, |
| 573 | elf_file: *Elf, | 617 | elf_file: *Elf, |
| 574 | ) error{OutOfMemory}!void { | 618 | ) RelocError!void { |
| 575 | var err = try elf_file.addErrorWithNotes(1); | 619 | var err = try elf_file.addErrorWithNotes(1); |
| 576 | try err.addMsg(elf_file, "relocation at offset 0x{x} against symbol '{s}' cannot be used", .{ | 620 | try err.addMsg(elf_file, "relocation at offset 0x{x} against symbol '{s}' cannot be used", .{ |
| 577 | rel.r_offset, | 621 | rel.r_offset, |
| ... | @@ -581,6 +625,7 @@ fn reportTextRelocError( | ... | @@ -581,6 +625,7 @@ fn reportTextRelocError( |
| 581 | self.file(elf_file).?.fmtPath(), | 625 | self.file(elf_file).?.fmtPath(), |
| 582 | self.name(elf_file), | 626 | self.name(elf_file), |
| 583 | }); | 627 | }); |
| | 628 | return error.RelocFailure; |
| 584 | } | 629 | } |
| 585 | | 630 | |
| 586 | fn reportPicError( | 631 | fn reportPicError( |
| ... | @@ -588,7 +633,7 @@ fn reportPicError( | ... | @@ -588,7 +633,7 @@ fn reportPicError( |
| 588 | symbol: *const Symbol, | 633 | symbol: *const Symbol, |
| 589 | rel: elf.Elf64_Rela, | 634 | rel: elf.Elf64_Rela, |
| 590 | elf_file: *Elf, | 635 | elf_file: *Elf, |
| 591 | ) error{OutOfMemory}!void { | 636 | ) RelocError!void { |
| 592 | var err = try elf_file.addErrorWithNotes(2); | 637 | var err = try elf_file.addErrorWithNotes(2); |
| 593 | try err.addMsg(elf_file, "relocation at offset 0x{x} against symbol '{s}' cannot be used", .{ | 638 | try err.addMsg(elf_file, "relocation at offset 0x{x} against symbol '{s}' cannot be used", .{ |
| 594 | rel.r_offset, | 639 | rel.r_offset, |
| ... | @@ -599,6 +644,7 @@ fn reportPicError( | ... | @@ -599,6 +644,7 @@ fn reportPicError( |
| 599 | self.name(elf_file), | 644 | self.name(elf_file), |
| 600 | }); | 645 | }); |
| 601 | try err.addNote(elf_file, "recompile with -fPIC", .{}); | 646 | try err.addNote(elf_file, "recompile with -fPIC", .{}); |
| | 647 | return error.RelocFailure; |
| 602 | } | 648 | } |
| 603 | | 649 | |
| 604 | fn reportNoPicError( | 650 | fn reportNoPicError( |
| ... | @@ -606,7 +652,7 @@ fn reportNoPicError( | ... | @@ -606,7 +652,7 @@ fn reportNoPicError( |
| 606 | symbol: *const Symbol, | 652 | symbol: *const Symbol, |
| 607 | rel: elf.Elf64_Rela, | 653 | rel: elf.Elf64_Rela, |
| 608 | elf_file: *Elf, | 654 | elf_file: *Elf, |
| 609 | ) error{OutOfMemory}!void { | 655 | ) RelocError!void { |
| 610 | var err = try elf_file.addErrorWithNotes(2); | 656 | var err = try elf_file.addErrorWithNotes(2); |
| 611 | try err.addMsg(elf_file, "relocation at offset 0x{x} against symbol '{s}' cannot be used", .{ | 657 | try err.addMsg(elf_file, "relocation at offset 0x{x} against symbol '{s}' cannot be used", .{ |
| 612 | rel.r_offset, | 658 | rel.r_offset, |
| ... | @@ -617,6 +663,7 @@ fn reportNoPicError( | ... | @@ -617,6 +663,7 @@ fn reportNoPicError( |
| 617 | self.name(elf_file), | 663 | self.name(elf_file), |
| 618 | }); | 664 | }); |
| 619 | try err.addNote(elf_file, "recompile with -fno-PIC", .{}); | 665 | try err.addNote(elf_file, "recompile with -fno-PIC", .{}); |
| | 666 | return error.RelocFailure; |
| 620 | } | 667 | } |
| 621 | | 668 | |
| 622 | // This function will report any undefined non-weak symbols that are not imports. | 669 | // This function will report any undefined non-weak symbols that are not imports. |
| ... | @@ -627,7 +674,7 @@ fn reportUndefined( | ... | @@ -627,7 +674,7 @@ fn reportUndefined( |
| 627 | sym_index: Symbol.Index, | 674 | sym_index: Symbol.Index, |
| 628 | rel: elf.Elf64_Rela, | 675 | rel: elf.Elf64_Rela, |
| 629 | undefs: anytype, | 676 | undefs: anytype, |
| 630 | ) !void { | 677 | ) !bool { |
| 631 | const comp = elf_file.base.comp; | 678 | const comp = elf_file.base.comp; |
| 632 | const gpa = comp.gpa; | 679 | const gpa = comp.gpa; |
| 633 | const rel_esym = switch (self.file(elf_file).?) { | 680 | const rel_esym = switch (self.file(elf_file).?) { |
| ... | @@ -647,7 +694,10 @@ fn reportUndefined( | ... | @@ -647,7 +694,10 @@ fn reportUndefined( |
| 647 | gop.value_ptr.* = std.ArrayList(Atom.Index).init(gpa); | 694 | gop.value_ptr.* = std.ArrayList(Atom.Index).init(gpa); |
| 648 | } | 695 | } |
| 649 | try gop.value_ptr.append(self.atom_index); | 696 | try gop.value_ptr.append(self.atom_index); |
| | 697 | return true; |
| 650 | } | 698 | } |
| | 699 | |
| | 700 | return false; |
| 651 | } | 701 | } |
| 652 | | 702 | |
| 653 | pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void { | 703 | pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void { |
| ... | @@ -831,152 +881,123 @@ pub const Flags = packed struct { | ... | @@ -831,152 +881,123 @@ pub const Flags = packed struct { |
| 831 | }; | 881 | }; |
| 832 | | 882 | |
| 833 | const x86_64 = struct { | 883 | const x86_64 = struct { |
| 834 | fn scanRelocs(atom: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype) !void { | 884 | fn scanReloc( |
| | 885 | atom: Atom, |
| | 886 | elf_file: *Elf, |
| | 887 | rel: elf.Elf64_Rela, |
| | 888 | symbol: *Symbol, |
| | 889 | code: ?[]const u8, |
| | 890 | it: *RelocsIterator, |
| | 891 | ) !void { |
| 835 | const is_static = elf_file.base.isStatic(); | 892 | const is_static = elf_file.base.isStatic(); |
| 836 | const is_dyn_lib = elf_file.base.isDynLib(); | 893 | const is_dyn_lib = elf_file.base.isDynLib(); |
| 837 | const file_ptr = atom.file(elf_file).?; | | |
| 838 | const rels = atom.relocs(elf_file); | | |
| 839 | var i: usize = 0; | | |
| 840 | while (i < rels.len) : (i += 1) { | | |
| 841 | const rel = rels[i]; | | |
| 842 | const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type()); | | |
| 843 | | | |
| 844 | if (r_type == .NONE) continue; | | |
| 845 | | | |
| 846 | const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; | | |
| 847 | | 894 | |
| 848 | const symbol_index = switch (file_ptr) { | 895 | const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type()); |
| 849 | .zig_object => |x| x.symbol(rel.r_sym()), | 896 | const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; |
| 850 | .object => |x| x.symbols.items[rel.r_sym()], | | |
| 851 | else => unreachable, | | |
| 852 | }; | | |
| 853 | const symbol = elf_file.symbol(symbol_index); | | |
| 854 | | 897 | |
| 855 | // Check for violation of One Definition Rule for COMDATs. | 898 | switch (r_type) { |
| 856 | if (symbol.file(elf_file) == null) { | 899 | .@"64" => { |
| 857 | // TODO convert into an error | 900 | try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file); |
| 858 | log.debug("{}: {s}: {s} refers to a discarded COMDAT section", .{ | 901 | }, |
| 859 | file_ptr.fmtPath(), | | |
| 860 | atom.name(elf_file), | | |
| 861 | symbol.name(elf_file), | | |
| 862 | }); | | |
| 863 | continue; | | |
| 864 | } | | |
| 865 | | 902 | |
| 866 | // Report an undefined symbol. | 903 | .@"32", |
| 867 | try atom.reportUndefined(elf_file, symbol, symbol_index, rel, undefs); | 904 | .@"32S", |
| | 905 | => { |
| | 906 | try atom.scanReloc(symbol, rel, absRelocAction(symbol, elf_file), elf_file); |
| | 907 | }, |
| 868 | | 908 | |
| 869 | if (symbol.isIFunc(elf_file)) { | 909 | .GOT32, |
| | 910 | .GOTPC32, |
| | 911 | .GOTPC64, |
| | 912 | .GOTPCREL, |
| | 913 | .GOTPCREL64, |
| | 914 | .GOTPCRELX, |
| | 915 | .REX_GOTPCRELX, |
| | 916 | => { |
| 870 | symbol.flags.needs_got = true; | 917 | symbol.flags.needs_got = true; |
| 871 | symbol.flags.needs_plt = true; | 918 | }, |
| 872 | } | | |
| 873 | | | |
| 874 | // While traversing relocations, mark symbols that require special handling such as | | |
| 875 | // pointer indirection via GOT, or a stub trampoline via PLT. | | |
| 876 | switch (r_type) { | | |
| 877 | .@"64" => { | | |
| 878 | try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file); | | |
| 879 | }, | | |
| 880 | | | |
| 881 | .@"32", | | |
| 882 | .@"32S", | | |
| 883 | => { | | |
| 884 | try atom.scanReloc(symbol, rel, absRelocAction(symbol, elf_file), elf_file); | | |
| 885 | }, | | |
| 886 | | 919 | |
| 887 | .GOT32, | 920 | .PLT32, |
| 888 | .GOTPC32, | 921 | .PLTOFF64, |
| 889 | .GOTPC64, | 922 | => { |
| 890 | .GOTPCREL, | 923 | if (symbol.flags.import) { |
| 891 | .GOTPCREL64, | 924 | symbol.flags.needs_plt = true; |
| 892 | .GOTPCRELX, | 925 | } |
| 893 | .REX_GOTPCRELX, | 926 | }, |
| 894 | => { | | |
| 895 | symbol.flags.needs_got = true; | | |
| 896 | }, | | |
| 897 | | 927 | |
| 898 | .PLT32, | 928 | .PC32 => { |
| 899 | .PLTOFF64, | 929 | try atom.scanReloc(symbol, rel, pcRelocAction(symbol, elf_file), elf_file); |
| 900 | => { | 930 | }, |
| 901 | if (symbol.flags.import) { | | |
| 902 | symbol.flags.needs_plt = true; | | |
| 903 | } | | |
| 904 | }, | | |
| 905 | | 931 | |
| 906 | .PC32 => { | 932 | .TLSGD => { |
| 907 | try atom.scanReloc(symbol, rel, pcRelocAction(symbol, elf_file), elf_file); | 933 | // TODO verify followed by appropriate relocation such as PLT32 __tls_get_addr |
| 908 | }, | | |
| 909 | | 934 | |
| 910 | .TLSGD => { | 935 | if (is_static or (!symbol.flags.import and !is_dyn_lib)) { |
| 911 | // TODO verify followed by appropriate relocation such as PLT32 __tls_get_addr | 936 | // Relax if building with -static flag as __tls_get_addr() will not be present in libc.a |
| | 937 | // We skip the next relocation. |
| | 938 | it.skip(1); |
| | 939 | } else if (!symbol.flags.import and is_dyn_lib) { |
| | 940 | symbol.flags.needs_gottp = true; |
| | 941 | it.skip(1); |
| | 942 | } else { |
| | 943 | symbol.flags.needs_tlsgd = true; |
| | 944 | } |
| | 945 | }, |
| 912 | | 946 | |
| 913 | if (is_static or (!symbol.flags.import and !is_dyn_lib)) { | 947 | .TLSLD => { |
| 914 | // Relax if building with -static flag as __tls_get_addr() will not be present in libc.a | 948 | // TODO verify followed by appropriate relocation such as PLT32 __tls_get_addr |
| 915 | // We skip the next relocation. | | |
| 916 | i += 1; | | |
| 917 | } else if (!symbol.flags.import and is_dyn_lib) { | | |
| 918 | symbol.flags.needs_gottp = true; | | |
| 919 | i += 1; | | |
| 920 | } else { | | |
| 921 | symbol.flags.needs_tlsgd = true; | | |
| 922 | } | | |
| 923 | }, | | |
| 924 | | 949 | |
| 925 | .TLSLD => { | 950 | if (is_static or !is_dyn_lib) { |
| 926 | // TODO verify followed by appropriate relocation such as PLT32 __tls_get_addr | 951 | // Relax if building with -static flag as __tls_get_addr() will not be present in libc.a |
| | 952 | // We skip the next relocation. |
| | 953 | it.skip(1); |
| | 954 | } else { |
| | 955 | elf_file.got.flags.needs_tlsld = true; |
| | 956 | } |
| | 957 | }, |
| 927 | | 958 | |
| 928 | if (is_static or !is_dyn_lib) { | 959 | .GOTTPOFF => { |
| 929 | // Relax if building with -static flag as __tls_get_addr() will not be present in libc.a | 960 | const should_relax = blk: { |
| 930 | // We skip the next relocation. | 961 | if (is_dyn_lib or symbol.flags.import) break :blk false; |
| 931 | i += 1; | 962 | if (!x86_64.canRelaxGotTpOff(code.?[r_offset - 3 ..])) break :blk false; |
| 932 | } else { | 963 | break :blk true; |
| 933 | elf_file.got.flags.needs_tlsld = true; | 964 | }; |
| 934 | } | 965 | if (!should_relax) { |
| 935 | }, | 966 | symbol.flags.needs_gottp = true; |
| | 967 | } |
| | 968 | }, |
| 936 | | 969 | |
| 937 | .GOTTPOFF => { | 970 | .GOTPC32_TLSDESC => { |
| 938 | const should_relax = blk: { | 971 | const should_relax = is_static or (!is_dyn_lib and !symbol.flags.import); |
| 939 | if (is_dyn_lib or symbol.flags.import) break :blk false; | 972 | if (!should_relax) { |
| 940 | if (!x86_64.canRelaxGotTpOff(code.?[r_offset - 3 ..])) break :blk false; | 973 | symbol.flags.needs_tlsdesc = true; |
| 941 | break :blk true; | 974 | } |
| 942 | }; | 975 | }, |
| 943 | if (!should_relax) { | | |
| 944 | symbol.flags.needs_gottp = true; | | |
| 945 | } | | |
| 946 | }, | | |
| 947 | | 976 | |
| 948 | .GOTPC32_TLSDESC => { | 977 | .TPOFF32, |
| 949 | const should_relax = is_static or (!is_dyn_lib and !symbol.flags.import); | 978 | .TPOFF64, |
| 950 | if (!should_relax) { | 979 | => { |
| 951 | symbol.flags.needs_tlsdesc = true; | 980 | if (is_dyn_lib) try atom.reportPicError(symbol, rel, elf_file); |
| 952 | } | 981 | }, |
| 953 | }, | | |
| 954 | | 982 | |
| 955 | .TPOFF32, | 983 | .GOTOFF64, |
| 956 | .TPOFF64, | 984 | .DTPOFF32, |
| | 985 | .DTPOFF64, |
| | 986 | .SIZE32, |
| | 987 | .SIZE64, |
| | 988 | .TLSDESC_CALL, |
| | 989 | => {}, |
| | 990 | |
| | 991 | else => |x| switch (@intFromEnum(x)) { |
| | 992 | // Zig custom relocations |
| | 993 | Elf.R_ZIG_GOT32, |
| | 994 | Elf.R_ZIG_GOTPCREL, |
| 957 | => { | 995 | => { |
| 958 | if (is_dyn_lib) try atom.reportPicError(symbol, rel, elf_file); | 996 | assert(symbol.flags.has_zig_got); |
| 959 | }, | 997 | }, |
| 960 | | 998 | |
| 961 | .GOTOFF64, | 999 | else => try atom.reportUnhandledRelocError(rel, elf_file), |
| 962 | .DTPOFF32, | 1000 | }, |
| 963 | .DTPOFF64, | | |
| 964 | .SIZE32, | | |
| 965 | .SIZE64, | | |
| 966 | .TLSDESC_CALL, | | |
| 967 | => {}, | | |
| 968 | | | |
| 969 | else => |x| switch (@intFromEnum(x)) { | | |
| 970 | // Zig custom relocations | | |
| 971 | Elf.R_ZIG_GOT32, | | |
| 972 | Elf.R_ZIG_GOTPCREL, | | |
| 973 | => { | | |
| 974 | assert(symbol.flags.has_zig_got); | | |
| 975 | }, | | |
| 976 | | | |
| 977 | else => try atom.reportUnhandledRelocError(rel, elf_file), | | |
| 978 | }, | | |
| 979 | } | | |
| 980 | } | 1001 | } |
| 981 | } | 1002 | } |
| 982 | | 1003 | |
| ... | @@ -1195,7 +1216,7 @@ const x86_64 = struct { | ... | @@ -1195,7 +1216,7 @@ const x86_64 = struct { |
| 1195 | } | 1216 | } |
| 1196 | | 1217 | |
| 1197 | // Report an undefined symbol. | 1218 | // Report an undefined symbol. |
| 1198 | try atom.reportUndefined(elf_file, target, target_index, rel, undefs); | 1219 | if (try atom.reportUndefined(elf_file, target, target_index, rel, undefs)) continue; |
| 1199 | | 1220 | |
| 1200 | // We will use equation format to resolve relocations: | 1221 | // We will use equation format to resolve relocations: |
| 1201 | // https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/ | 1222 | // https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/ |
| ... | @@ -1485,6 +1506,36 @@ const x86_64 = struct { | ... | @@ -1485,6 +1506,36 @@ const x86_64 = struct { |
| 1485 | const Instruction = encoder.Instruction; | 1506 | const Instruction = encoder.Instruction; |
| 1486 | }; | 1507 | }; |
| 1487 | | 1508 | |
| | 1509 | const RelocError = error{ |
| | 1510 | Overflow, |
| | 1511 | OutOfMemory, |
| | 1512 | RelocFailure, |
| | 1513 | UnsupportedCpuArch, |
| | 1514 | }; |
| | 1515 | |
| | 1516 | const RelocsIterator = struct { |
| | 1517 | relocs: []const elf.Elf64_Rela, |
| | 1518 | pos: i64 = -1, |
| | 1519 | |
| | 1520 | fn next(it: *RelocsIterator) ?elf.Elf64_Rela { |
| | 1521 | it.pos += 1; |
| | 1522 | if (it.pos >= it.relocs.len) return null; |
| | 1523 | return it.relocs[@intCast(it.pos)]; |
| | 1524 | } |
| | 1525 | |
| | 1526 | fn prev(it: *RelocsIterator) ?elf.Elf64_Rela { |
| | 1527 | if (it.pos == -1) return null; |
| | 1528 | const rel = it.relocs[@intCast(it.pos)]; |
| | 1529 | it.pos -= 1; |
| | 1530 | return rel; |
| | 1531 | } |
| | 1532 | |
| | 1533 | fn skip(it: *RelocsIterator, num: usize) void { |
| | 1534 | assert(num > 0); |
| | 1535 | it.pos += @intCast(num); |
| | 1536 | } |
| | 1537 | }; |
| | 1538 | |
| 1488 | const std = @import("std"); | 1539 | const std = @import("std"); |
| 1489 | const assert = std.debug.assert; | 1540 | const assert = std.debug.assert; |
| 1490 | const elf = std.elf; | 1541 | const elf = std.elf; |