| ... | @@ -384,7 +384,10 @@ pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) bool { | ... | @@ -384,7 +384,10 @@ pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) bool { |
| 384 | const cpu_arch = elf_file.getTarget().cpu.arch; | 384 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 385 | for (self.relocs(elf_file)) |rel| { | 385 | for (self.relocs(elf_file)) |rel| { |
| 386 | switch (cpu_arch) { | 386 | switch (cpu_arch) { |
| 387 | .x86_64 => if (rel.r_type() == elf.R_X86_64_GOTTPOFF) return true, | 387 | .x86_64 => { |
| | 388 | const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type()); |
| | 389 | if (r_type == .R_X86_64_GOTTPOFF) return true; |
| | 390 | }, |
| 388 | else => {}, | 391 | else => {}, |
| 389 | } | 392 | } |
| 390 | } | 393 | } |
| ... | @@ -836,8 +839,9 @@ const x86_64 = struct { | ... | @@ -836,8 +839,9 @@ const x86_64 = struct { |
| 836 | var i: usize = 0; | 839 | var i: usize = 0; |
| 837 | while (i < rels.len) : (i += 1) { | 840 | while (i < rels.len) : (i += 1) { |
| 838 | const rel = rels[i]; | 841 | const rel = rels[i]; |
| | 842 | const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type()); |
| 839 | | 843 | |
| 840 | if (rel.r_type() == elf.R_X86_64_NONE) continue; | 844 | if (r_type == .R_X86_64_NONE) continue; |
| 841 | | 845 | |
| 842 | const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; | 846 | const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; |
| 843 | | 847 | |
| ... | @@ -869,41 +873,41 @@ const x86_64 = struct { | ... | @@ -869,41 +873,41 @@ const x86_64 = struct { |
| 869 | | 873 | |
| 870 | // While traversing relocations, mark symbols that require special handling such as | 874 | // While traversing relocations, mark symbols that require special handling such as |
| 871 | // pointer indirection via GOT, or a stub trampoline via PLT. | 875 | // pointer indirection via GOT, or a stub trampoline via PLT. |
| 872 | switch (rel.r_type()) { | 876 | switch (r_type) { |
| 873 | elf.R_X86_64_64 => { | 877 | .R_X86_64_64 => { |
| 874 | try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file); | 878 | try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file); |
| 875 | }, | 879 | }, |
| 876 | | 880 | |
| 877 | elf.R_X86_64_32, | 881 | .R_X86_64_32, |
| 878 | elf.R_X86_64_32S, | 882 | .R_X86_64_32S, |
| 879 | => { | 883 | => { |
| 880 | try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file); | 884 | try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file); |
| 881 | }, | 885 | }, |
| 882 | | 886 | |
| 883 | elf.R_X86_64_GOT32, | 887 | .R_X86_64_GOT32, |
| 884 | elf.R_X86_64_GOTPC32, | 888 | .R_X86_64_GOTPC32, |
| 885 | elf.R_X86_64_GOTPC64, | 889 | .R_X86_64_GOTPC64, |
| 886 | elf.R_X86_64_GOTPCREL, | 890 | .R_X86_64_GOTPCREL, |
| 887 | elf.R_X86_64_GOTPCREL64, | 891 | .R_X86_64_GOTPCREL64, |
| 888 | elf.R_X86_64_GOTPCRELX, | 892 | .R_X86_64_GOTPCRELX, |
| 889 | elf.R_X86_64_REX_GOTPCRELX, | 893 | .R_X86_64_REX_GOTPCRELX, |
| 890 | => { | 894 | => { |
| 891 | symbol.flags.needs_got = true; | 895 | symbol.flags.needs_got = true; |
| 892 | }, | 896 | }, |
| 893 | | 897 | |
| 894 | elf.R_X86_64_PLT32, | 898 | .R_X86_64_PLT32, |
| 895 | elf.R_X86_64_PLTOFF64, | 899 | .R_X86_64_PLTOFF64, |
| 896 | => { | 900 | => { |
| 897 | if (symbol.flags.import) { | 901 | if (symbol.flags.import) { |
| 898 | symbol.flags.needs_plt = true; | 902 | symbol.flags.needs_plt = true; |
| 899 | } | 903 | } |
| 900 | }, | 904 | }, |
| 901 | | 905 | |
| 902 | elf.R_X86_64_PC32 => { | 906 | .R_X86_64_PC32 => { |
| 903 | try atom.scanReloc(symbol, rel, pcRelocAction(symbol, elf_file), elf_file); | 907 | try atom.scanReloc(symbol, rel, pcRelocAction(symbol, elf_file), elf_file); |
| 904 | }, | 908 | }, |
| 905 | | 909 | |
| 906 | elf.R_X86_64_TLSGD => { | 910 | .R_X86_64_TLSGD => { |
| 907 | // TODO verify followed by appropriate relocation such as PLT32 __tls_get_addr | 911 | // TODO verify followed by appropriate relocation such as PLT32 __tls_get_addr |
| 908 | | 912 | |
| 909 | if (is_static or (!symbol.flags.import and !is_dyn_lib)) { | 913 | if (is_static or (!symbol.flags.import and !is_dyn_lib)) { |
| ... | @@ -918,7 +922,7 @@ const x86_64 = struct { | ... | @@ -918,7 +922,7 @@ const x86_64 = struct { |
| 918 | } | 922 | } |
| 919 | }, | 923 | }, |
| 920 | | 924 | |
| 921 | elf.R_X86_64_TLSLD => { | 925 | .R_X86_64_TLSLD => { |
| 922 | // TODO verify followed by appropriate relocation such as PLT32 __tls_get_addr | 926 | // TODO verify followed by appropriate relocation such as PLT32 __tls_get_addr |
| 923 | | 927 | |
| 924 | if (is_static or !is_dyn_lib) { | 928 | if (is_static or !is_dyn_lib) { |
| ... | @@ -930,7 +934,7 @@ const x86_64 = struct { | ... | @@ -930,7 +934,7 @@ const x86_64 = struct { |
| 930 | } | 934 | } |
| 931 | }, | 935 | }, |
| 932 | | 936 | |
| 933 | elf.R_X86_64_GOTTPOFF => { | 937 | .R_X86_64_GOTTPOFF => { |
| 934 | const should_relax = blk: { | 938 | const should_relax = blk: { |
| 935 | if (is_dyn_lib or symbol.flags.import) break :blk false; | 939 | if (is_dyn_lib or symbol.flags.import) break :blk false; |
| 936 | if (!x86_64.canRelaxGotTpOff(code.?[r_offset - 3 ..])) break :blk false; | 940 | if (!x86_64.canRelaxGotTpOff(code.?[r_offset - 3 ..])) break :blk false; |
| ... | @@ -941,35 +945,37 @@ const x86_64 = struct { | ... | @@ -941,35 +945,37 @@ const x86_64 = struct { |
| 941 | } | 945 | } |
| 942 | }, | 946 | }, |
| 943 | | 947 | |
| 944 | elf.R_X86_64_GOTPC32_TLSDESC => { | 948 | .R_X86_64_GOTPC32_TLSDESC => { |
| 945 | const should_relax = is_static or (!is_dyn_lib and !symbol.flags.import); | 949 | const should_relax = is_static or (!is_dyn_lib and !symbol.flags.import); |
| 946 | if (!should_relax) { | 950 | if (!should_relax) { |
| 947 | symbol.flags.needs_tlsdesc = true; | 951 | symbol.flags.needs_tlsdesc = true; |
| 948 | } | 952 | } |
| 949 | }, | 953 | }, |
| 950 | | 954 | |
| 951 | elf.R_X86_64_TPOFF32, | 955 | .R_X86_64_TPOFF32, |
| 952 | elf.R_X86_64_TPOFF64, | 956 | .R_X86_64_TPOFF64, |
| 953 | => { | 957 | => { |
| 954 | if (is_dyn_lib) try atom.reportPicError(symbol, rel, elf_file); | 958 | if (is_dyn_lib) try atom.reportPicError(symbol, rel, elf_file); |
| 955 | }, | 959 | }, |
| 956 | | 960 | |
| 957 | elf.R_X86_64_GOTOFF64, | 961 | .R_X86_64_GOTOFF64, |
| 958 | elf.R_X86_64_DTPOFF32, | 962 | .R_X86_64_DTPOFF32, |
| 959 | elf.R_X86_64_DTPOFF64, | 963 | .R_X86_64_DTPOFF64, |
| 960 | elf.R_X86_64_SIZE32, | 964 | .R_X86_64_SIZE32, |
| 961 | elf.R_X86_64_SIZE64, | 965 | .R_X86_64_SIZE64, |
| 962 | elf.R_X86_64_TLSDESC_CALL, | 966 | .R_X86_64_TLSDESC_CALL, |
| 963 | => {}, | 967 | => {}, |
| 964 | | 968 | |
| 965 | // Zig custom relocations | 969 | else => |x| switch (@intFromEnum(x)) { |
| 966 | Elf.R_X86_64_ZIG_GOT32, | 970 | // Zig custom relocations |
| 967 | Elf.R_X86_64_ZIG_GOTPCREL, | 971 | Elf.R_X86_64_ZIG_GOT32, |
| 968 | => { | 972 | Elf.R_X86_64_ZIG_GOTPCREL, |
| 969 | assert(symbol.flags.has_zig_got); | 973 | => { |
| 970 | }, | 974 | assert(symbol.flags.has_zig_got); |
| | 975 | }, |
| 971 | | 976 | |
| 972 | else => try atom.reportUnhandledRelocError(rel, elf_file), | 977 | else => try atom.reportUnhandledRelocError(rel, elf_file), |
| | 978 | }, |
| 973 | } | 979 | } |
| 974 | } | 980 | } |
| 975 | } | 981 | } |
| ... | @@ -983,8 +989,8 @@ const x86_64 = struct { | ... | @@ -983,8 +989,8 @@ const x86_64 = struct { |
| 983 | var i: usize = 0; | 989 | var i: usize = 0; |
| 984 | while (i < rels.len) : (i += 1) { | 990 | while (i < rels.len) : (i += 1) { |
| 985 | const rel = rels[i]; | 991 | const rel = rels[i]; |
| 986 | const r_type = rel.r_type(); | 992 | const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type()); |
| 987 | if (r_type == elf.R_X86_64_NONE) continue; | 993 | if (r_type == .R_X86_64_NONE) continue; |
| 988 | | 994 | |
| 989 | const target = switch (file_ptr) { | 995 | const target = switch (file_ptr) { |
| 990 | .zig_object => |x| elf_file.symbol(x.symbol(rel.r_sym())), | 996 | .zig_object => |x| elf_file.symbol(x.symbol(rel.r_sym())), |
| ... | @@ -1022,7 +1028,7 @@ const x86_64 = struct { | ... | @@ -1022,7 +1028,7 @@ const x86_64 = struct { |
| 1022 | const DTP = @as(i64, @intCast(elf_file.dtpAddress())); | 1028 | const DTP = @as(i64, @intCast(elf_file.dtpAddress())); |
| 1023 | | 1029 | |
| 1024 | relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ZG({x}) ({s})", .{ | 1030 | relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ZG({x}) ({s})", .{ |
| 1025 | relocation.fmtRelocType(r_type, .x86_64), | 1031 | @tagName(r_type), |
| 1026 | r_offset, | 1032 | r_offset, |
| 1027 | P, | 1033 | P, |
| 1028 | S + A, | 1034 | S + A, |
| ... | @@ -1033,10 +1039,10 @@ const x86_64 = struct { | ... | @@ -1033,10 +1039,10 @@ const x86_64 = struct { |
| 1033 | | 1039 | |
| 1034 | try stream.seekTo(r_offset); | 1040 | try stream.seekTo(r_offset); |
| 1035 | | 1041 | |
| 1036 | switch (rel.r_type()) { | 1042 | switch (r_type) { |
| 1037 | elf.R_X86_64_NONE => unreachable, | 1043 | .R_X86_64_NONE => unreachable, |
| 1038 | | 1044 | |
| 1039 | elf.R_X86_64_64 => { | 1045 | .R_X86_64_64 => { |
| 1040 | try atom.resolveDynAbsReloc( | 1046 | try atom.resolveDynAbsReloc( |
| 1041 | target, | 1047 | target, |
| 1042 | rel, | 1048 | rel, |
| ... | @@ -1046,15 +1052,15 @@ const x86_64 = struct { | ... | @@ -1046,15 +1052,15 @@ const x86_64 = struct { |
| 1046 | ); | 1052 | ); |
| 1047 | }, | 1053 | }, |
| 1048 | | 1054 | |
| 1049 | elf.R_X86_64_PLT32, | 1055 | .R_X86_64_PLT32, |
| 1050 | elf.R_X86_64_PC32, | 1056 | .R_X86_64_PC32, |
| 1051 | => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little), | 1057 | => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little), |
| 1052 | | 1058 | |
| 1053 | elf.R_X86_64_GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little), | 1059 | .R_X86_64_GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little), |
| 1054 | elf.R_X86_64_GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little), | 1060 | .R_X86_64_GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little), |
| 1055 | elf.R_X86_64_GOTPC64 => try cwriter.writeInt(i64, GOT + A - P, .little), | 1061 | .R_X86_64_GOTPC64 => try cwriter.writeInt(i64, GOT + A - P, .little), |
| 1056 | | 1062 | |
| 1057 | elf.R_X86_64_GOTPCRELX => { | 1063 | .R_X86_64_GOTPCRELX => { |
| 1058 | if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: { | 1064 | if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: { |
| 1059 | x86_64.relaxGotpcrelx(code[r_offset - 2 ..]) catch break :blk; | 1065 | x86_64.relaxGotpcrelx(code[r_offset - 2 ..]) catch break :blk; |
| 1060 | try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little); | 1066 | try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little); |
| ... | @@ -1063,7 +1069,7 @@ const x86_64 = struct { | ... | @@ -1063,7 +1069,7 @@ const x86_64 = struct { |
| 1063 | try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little); | 1069 | try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little); |
| 1064 | }, | 1070 | }, |
| 1065 | | 1071 | |
| 1066 | elf.R_X86_64_REX_GOTPCRELX => { | 1072 | .R_X86_64_REX_GOTPCRELX => { |
| 1067 | if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: { | 1073 | if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: { |
| 1068 | x86_64.relaxRexGotpcrelx(code[r_offset - 3 ..]) catch break :blk; | 1074 | x86_64.relaxRexGotpcrelx(code[r_offset - 3 ..]) catch break :blk; |
| 1069 | try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little); | 1075 | try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little); |
| ... | @@ -1072,16 +1078,16 @@ const x86_64 = struct { | ... | @@ -1072,16 +1078,16 @@ const x86_64 = struct { |
| 1072 | try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little); | 1078 | try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little); |
| 1073 | }, | 1079 | }, |
| 1074 | | 1080 | |
| 1075 | elf.R_X86_64_32 => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little), | 1081 | .R_X86_64_32 => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little), |
| 1076 | elf.R_X86_64_32S => try cwriter.writeInt(i32, @as(i32, @truncate(S + A)), .little), | 1082 | .R_X86_64_32S => try cwriter.writeInt(i32, @as(i32, @truncate(S + A)), .little), |
| 1077 | | 1083 | |
| 1078 | elf.R_X86_64_TPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - TP)), .little), | 1084 | .R_X86_64_TPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - TP)), .little), |
| 1079 | elf.R_X86_64_TPOFF64 => try cwriter.writeInt(i64, S + A - TP, .little), | 1085 | .R_X86_64_TPOFF64 => try cwriter.writeInt(i64, S + A - TP, .little), |
| 1080 | | 1086 | |
| 1081 | elf.R_X86_64_DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - DTP)), .little), | 1087 | .R_X86_64_DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - DTP)), .little), |
| 1082 | elf.R_X86_64_DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little), | 1088 | .R_X86_64_DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little), |
| 1083 | | 1089 | |
| 1084 | elf.R_X86_64_TLSGD => { | 1090 | .R_X86_64_TLSGD => { |
| 1085 | if (target.flags.has_tlsgd) { | 1091 | if (target.flags.has_tlsgd) { |
| 1086 | const S_ = @as(i64, @intCast(target.tlsGdAddress(elf_file))); | 1092 | const S_ = @as(i64, @intCast(target.tlsGdAddress(elf_file))); |
| 1087 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); | 1093 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); |
| ... | @@ -1101,7 +1107,7 @@ const x86_64 = struct { | ... | @@ -1101,7 +1107,7 @@ const x86_64 = struct { |
| 1101 | } | 1107 | } |
| 1102 | }, | 1108 | }, |
| 1103 | | 1109 | |
| 1104 | elf.R_X86_64_TLSLD => { | 1110 | .R_X86_64_TLSLD => { |
| 1105 | if (elf_file.got.tlsld_index) |entry_index| { | 1111 | if (elf_file.got.tlsld_index) |entry_index| { |
| 1106 | const tlsld_entry = elf_file.got.entries.items[entry_index]; | 1112 | const tlsld_entry = elf_file.got.entries.items[entry_index]; |
| 1107 | const S_ = @as(i64, @intCast(tlsld_entry.address(elf_file))); | 1113 | const S_ = @as(i64, @intCast(tlsld_entry.address(elf_file))); |
| ... | @@ -1118,7 +1124,7 @@ const x86_64 = struct { | ... | @@ -1118,7 +1124,7 @@ const x86_64 = struct { |
| 1118 | } | 1124 | } |
| 1119 | }, | 1125 | }, |
| 1120 | | 1126 | |
| 1121 | elf.R_X86_64_GOTPC32_TLSDESC => { | 1127 | .R_X86_64_GOTPC32_TLSDESC => { |
| 1122 | if (target.flags.has_tlsdesc) { | 1128 | if (target.flags.has_tlsdesc) { |
| 1123 | const S_ = @as(i64, @intCast(target.tlsDescAddress(elf_file))); | 1129 | const S_ = @as(i64, @intCast(target.tlsDescAddress(elf_file))); |
| 1124 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); | 1130 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); |
| ... | @@ -1128,12 +1134,12 @@ const x86_64 = struct { | ... | @@ -1128,12 +1134,12 @@ const x86_64 = struct { |
| 1128 | } | 1134 | } |
| 1129 | }, | 1135 | }, |
| 1130 | | 1136 | |
| 1131 | elf.R_X86_64_TLSDESC_CALL => if (!target.flags.has_tlsdesc) { | 1137 | .R_X86_64_TLSDESC_CALL => if (!target.flags.has_tlsdesc) { |
| 1132 | // call -> nop | 1138 | // call -> nop |
| 1133 | try cwriter.writeAll(&.{ 0x66, 0x90 }); | 1139 | try cwriter.writeAll(&.{ 0x66, 0x90 }); |
| 1134 | }, | 1140 | }, |
| 1135 | | 1141 | |
| 1136 | elf.R_X86_64_GOTTPOFF => { | 1142 | .R_X86_64_GOTTPOFF => { |
| 1137 | if (target.flags.has_gottp) { | 1143 | if (target.flags.has_gottp) { |
| 1138 | const S_ = @as(i64, @intCast(target.gotTpAddress(elf_file))); | 1144 | const S_ = @as(i64, @intCast(target.gotTpAddress(elf_file))); |
| 1139 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); | 1145 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); |
| ... | @@ -1143,13 +1149,15 @@ const x86_64 = struct { | ... | @@ -1143,13 +1149,15 @@ const x86_64 = struct { |
| 1143 | } | 1149 | } |
| 1144 | }, | 1150 | }, |
| 1145 | | 1151 | |
| 1146 | elf.R_X86_64_GOT32 => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A)), .little), | 1152 | .R_X86_64_GOT32 => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A)), .little), |
| 1147 | | 1153 | |
| 1148 | // Zig custom relocations | 1154 | else => |x| switch (@intFromEnum(x)) { |
| 1149 | Elf.R_X86_64_ZIG_GOT32 => try cwriter.writeInt(u32, @as(u32, @intCast(ZIG_GOT + A)), .little), | 1155 | // Zig custom relocations |
| 1150 | Elf.R_X86_64_ZIG_GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(ZIG_GOT + A - P)), .little), | 1156 | Elf.R_X86_64_ZIG_GOT32 => try cwriter.writeInt(u32, @as(u32, @intCast(ZIG_GOT + A)), .little), |
| | 1157 | Elf.R_X86_64_ZIG_GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(ZIG_GOT + A - P)), .little), |
| 1151 | | 1158 | |
| 1152 | else => {}, | 1159 | else => {}, |
| | 1160 | }, |
| 1153 | } | 1161 | } |
| 1154 | } | 1162 | } |
| 1155 | } | 1163 | } |
| ... | @@ -1163,8 +1171,8 @@ const x86_64 = struct { | ... | @@ -1163,8 +1171,8 @@ const x86_64 = struct { |
| 1163 | var i: usize = 0; | 1171 | var i: usize = 0; |
| 1164 | while (i < rels.len) : (i += 1) { | 1172 | while (i < rels.len) : (i += 1) { |
| 1165 | const rel = rels[i]; | 1173 | const rel = rels[i]; |
| 1166 | const r_type = rel.r_type(); | 1174 | const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type()); |
| 1167 | if (r_type == elf.R_X86_64_NONE) continue; | 1175 | if (r_type == .R_X86_64_NONE) continue; |
| 1168 | | 1176 | |
| 1169 | const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; | 1177 | const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; |
| 1170 | | 1178 | |
| ... | @@ -1211,7 +1219,7 @@ const x86_64 = struct { | ... | @@ -1211,7 +1219,7 @@ const x86_64 = struct { |
| 1211 | const DTP = @as(i64, @intCast(elf_file.dtpAddress())); | 1219 | const DTP = @as(i64, @intCast(elf_file.dtpAddress())); |
| 1212 | | 1220 | |
| 1213 | relocs_log.debug(" {s}: {x}: [{x} => {x}] ({s})", .{ | 1221 | relocs_log.debug(" {s}: {x}: [{x} => {x}] ({s})", .{ |
| 1214 | relocation.fmtRelocType(r_type, .x86_64), | 1222 | @tagName(r_type), |
| 1215 | rel.r_offset, | 1223 | rel.r_offset, |
| 1216 | P, | 1224 | P, |
| 1217 | S + A, | 1225 | S + A, |
| ... | @@ -1221,21 +1229,21 @@ const x86_64 = struct { | ... | @@ -1221,21 +1229,21 @@ const x86_64 = struct { |
| 1221 | try stream.seekTo(r_offset); | 1229 | try stream.seekTo(r_offset); |
| 1222 | | 1230 | |
| 1223 | switch (r_type) { | 1231 | switch (r_type) { |
| 1224 | elf.R_X86_64_NONE => unreachable, | 1232 | .R_X86_64_NONE => unreachable, |
| 1225 | elf.R_X86_64_8 => try cwriter.writeInt(u8, @as(u8, @bitCast(@as(i8, @intCast(S + A)))), .little), | 1233 | .R_X86_64_8 => try cwriter.writeInt(u8, @as(u8, @bitCast(@as(i8, @intCast(S + A)))), .little), |
| 1226 | elf.R_X86_64_16 => try cwriter.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little), | 1234 | .R_X86_64_16 => try cwriter.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little), |
| 1227 | elf.R_X86_64_32 => try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little), | 1235 | .R_X86_64_32 => try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little), |
| 1228 | elf.R_X86_64_32S => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), | 1236 | .R_X86_64_32S => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), |
| 1229 | elf.R_X86_64_64 => try cwriter.writeInt(i64, S + A, .little), | 1237 | .R_X86_64_64 => try cwriter.writeInt(i64, S + A, .little), |
| 1230 | elf.R_X86_64_DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little), | 1238 | .R_X86_64_DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little), |
| 1231 | elf.R_X86_64_DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little), | 1239 | .R_X86_64_DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little), |
| 1232 | elf.R_X86_64_GOTOFF64 => try cwriter.writeInt(i64, S + A - GOT, .little), | 1240 | .R_X86_64_GOTOFF64 => try cwriter.writeInt(i64, S + A - GOT, .little), |
| 1233 | elf.R_X86_64_GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little), | 1241 | .R_X86_64_GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little), |
| 1234 | elf.R_X86_64_SIZE32 => { | 1242 | .R_X86_64_SIZE32 => { |
| 1235 | const size = @as(i64, @intCast(target.elfSym(elf_file).st_size)); | 1243 | const size = @as(i64, @intCast(target.elfSym(elf_file).st_size)); |
| 1236 | try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(size + A)))), .little); | 1244 | try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(size + A)))), .little); |
| 1237 | }, | 1245 | }, |
| 1238 | elf.R_X86_64_SIZE64 => { | 1246 | .R_X86_64_SIZE64 => { |
| 1239 | const size = @as(i64, @intCast(target.elfSym(elf_file).st_size)); | 1247 | const size = @as(i64, @intCast(target.elfSym(elf_file).st_size)); |
| 1240 | try cwriter.writeInt(i64, @as(i64, @intCast(size + A)), .little); | 1248 | try cwriter.writeInt(i64, @as(i64, @intCast(size + A)), .little); |
| 1241 | }, | 1249 | }, |
| ... | @@ -1283,9 +1291,11 @@ const x86_64 = struct { | ... | @@ -1283,9 +1291,11 @@ const x86_64 = struct { |
| 1283 | ) !void { | 1291 | ) !void { |
| 1284 | assert(rels.len == 2); | 1292 | assert(rels.len == 2); |
| 1285 | const writer = stream.writer(); | 1293 | const writer = stream.writer(); |
| 1286 | switch (rels[1].r_type()) { | 1294 | const rel_0: elf.R_X86_64 = @enumFromInt(rels[0].r_type()); |
| 1287 | elf.R_X86_64_PC32, | 1295 | const rel_1: elf.R_X86_64 = @enumFromInt(rels[1].r_type()); |
| 1288 | elf.R_X86_64_PLT32, | 1296 | switch (rel_1) { |
| | 1297 | .R_X86_64_PC32, |
| | 1298 | .R_X86_64_PLT32, |
| 1289 | => { | 1299 | => { |
| 1290 | var insts = [_]u8{ | 1300 | var insts = [_]u8{ |
| 1291 | 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0, // movq %fs:0,%rax | 1301 | 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0, // movq %fs:0,%rax |
| ... | @@ -1298,9 +1308,9 @@ const x86_64 = struct { | ... | @@ -1298,9 +1308,9 @@ const x86_64 = struct { |
| 1298 | | 1308 | |
| 1299 | else => { | 1309 | else => { |
| 1300 | var err = try elf_file.addErrorWithNotes(1); | 1310 | var err = try elf_file.addErrorWithNotes(1); |
| 1301 | try err.addMsg(elf_file, "fatal linker error: rewrite {} when followed by {}", .{ | 1311 | try err.addMsg(elf_file, "fatal linker error: rewrite {s} when followed by {s}", .{ |
| 1302 | relocation.fmtRelocType(rels[0].r_type(), .x86_64), | 1312 | @tagName(rel_0), |
| 1303 | relocation.fmtRelocType(rels[1].r_type(), .x86_64), | 1313 | @tagName(rel_1), |
| 1304 | }); | 1314 | }); |
| 1305 | try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{ | 1315 | try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{ |
| 1306 | self.file(elf_file).?.fmtPath(), | 1316 | self.file(elf_file).?.fmtPath(), |
| ... | @@ -1320,9 +1330,11 @@ const x86_64 = struct { | ... | @@ -1320,9 +1330,11 @@ const x86_64 = struct { |
| 1320 | ) !void { | 1330 | ) !void { |
| 1321 | assert(rels.len == 2); | 1331 | assert(rels.len == 2); |
| 1322 | const writer = stream.writer(); | 1332 | const writer = stream.writer(); |
| 1323 | switch (rels[1].r_type()) { | 1333 | const rel_0: elf.R_X86_64 = @enumFromInt(rels[0].r_type()); |
| 1324 | elf.R_X86_64_PC32, | 1334 | const rel_1: elf.R_X86_64 = @enumFromInt(rels[1].r_type()); |
| 1325 | elf.R_X86_64_PLT32, | 1335 | switch (rel_1) { |
| | 1336 | .R_X86_64_PC32, |
| | 1337 | .R_X86_64_PLT32, |
| 1326 | => { | 1338 | => { |
| 1327 | var insts = [_]u8{ | 1339 | var insts = [_]u8{ |
| 1328 | 0x31, 0xc0, // xor %eax, %eax | 1340 | 0x31, 0xc0, // xor %eax, %eax |
| ... | @@ -1334,8 +1346,8 @@ const x86_64 = struct { | ... | @@ -1334,8 +1346,8 @@ const x86_64 = struct { |
| 1334 | try writer.writeAll(&insts); | 1346 | try writer.writeAll(&insts); |
| 1335 | }, | 1347 | }, |
| 1336 | | 1348 | |
| 1337 | elf.R_X86_64_GOTPCREL, | 1349 | .R_X86_64_GOTPCREL, |
| 1338 | elf.R_X86_64_GOTPCRELX, | 1350 | .R_X86_64_GOTPCRELX, |
| 1339 | => { | 1351 | => { |
| 1340 | var insts = [_]u8{ | 1352 | var insts = [_]u8{ |
| 1341 | 0x31, 0xc0, // xor %eax, %eax | 1353 | 0x31, 0xc0, // xor %eax, %eax |
| ... | @@ -1350,9 +1362,9 @@ const x86_64 = struct { | ... | @@ -1350,9 +1362,9 @@ const x86_64 = struct { |
| 1350 | | 1362 | |
| 1351 | else => { | 1363 | else => { |
| 1352 | var err = try elf_file.addErrorWithNotes(1); | 1364 | var err = try elf_file.addErrorWithNotes(1); |
| 1353 | try err.addMsg(elf_file, "fatal linker error: rewrite {} when followed by {}", .{ | 1365 | try err.addMsg(elf_file, "fatal linker error: rewrite {s} when followed by {s}", .{ |
| 1354 | relocation.fmtRelocType(rels[0].r_type(), .x86_64), | 1366 | @tagName(rel_0), |
| 1355 | relocation.fmtRelocType(rels[1].r_type(), .x86_64), | 1367 | @tagName(rel_1), |
| 1356 | }); | 1368 | }); |
| 1357 | try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{ | 1369 | try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{ |
| 1358 | self.file(elf_file).?.fmtPath(), | 1370 | self.file(elf_file).?.fmtPath(), |
| ... | @@ -1419,11 +1431,13 @@ const x86_64 = struct { | ... | @@ -1419,11 +1431,13 @@ const x86_64 = struct { |
| 1419 | ) !void { | 1431 | ) !void { |
| 1420 | assert(rels.len == 2); | 1432 | assert(rels.len == 2); |
| 1421 | const writer = stream.writer(); | 1433 | const writer = stream.writer(); |
| 1422 | switch (rels[1].r_type()) { | 1434 | const rel_0: elf.R_X86_64 = @enumFromInt(rels[0].r_type()); |
| 1423 | elf.R_X86_64_PC32, | 1435 | const rel_1: elf.R_X86_64 = @enumFromInt(rels[1].r_type()); |
| 1424 | elf.R_X86_64_PLT32, | 1436 | switch (rel_1) { |
| 1425 | elf.R_X86_64_GOTPCREL, | 1437 | .R_X86_64_PC32, |
| 1426 | elf.R_X86_64_GOTPCRELX, | 1438 | .R_X86_64_PLT32, |
| | 1439 | .R_X86_64_GOTPCREL, |
| | 1440 | .R_X86_64_GOTPCRELX, |
| 1427 | => { | 1441 | => { |
| 1428 | var insts = [_]u8{ | 1442 | var insts = [_]u8{ |
| 1429 | 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0, // movq %fs:0,%rax | 1443 | 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0, // movq %fs:0,%rax |
| ... | @@ -1432,17 +1446,14 @@ const x86_64 = struct { | ... | @@ -1432,17 +1446,14 @@ const x86_64 = struct { |
| 1432 | std.mem.writeInt(i32, insts[12..][0..4], value, .little); | 1446 | std.mem.writeInt(i32, insts[12..][0..4], value, .little); |
| 1433 | try stream.seekBy(-4); | 1447 | try stream.seekBy(-4); |
| 1434 | try writer.writeAll(&insts); | 1448 | try writer.writeAll(&insts); |
| 1435 | relocs_log.debug(" relaxing {} and {}", .{ | 1449 | relocs_log.debug(" relaxing {s} and {s}", .{ @tagName(rel_0), @tagName(rel_1) }); |
| 1436 | relocation.fmtRelocType(rels[0].r_type(), .x86_64), | | |
| 1437 | relocation.fmtRelocType(rels[1].r_type(), .x86_64), | | |
| 1438 | }); | | |
| 1439 | }, | 1450 | }, |
| 1440 | | 1451 | |
| 1441 | else => { | 1452 | else => { |
| 1442 | var err = try elf_file.addErrorWithNotes(1); | 1453 | var err = try elf_file.addErrorWithNotes(1); |
| 1443 | try err.addMsg(elf_file, "fatal linker error: rewrite {} when followed by {}", .{ | 1454 | try err.addMsg(elf_file, "fatal linker error: rewrite {s} when followed by {s}", .{ |
| 1444 | relocation.fmtRelocType(rels[0].r_type(), .x86_64), | 1455 | @tagName(rel_0), |
| 1445 | relocation.fmtRelocType(rels[1].r_type(), .x86_64), | 1456 | @tagName(rel_1), |
| 1446 | }); | 1457 | }); |
| 1447 | try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{ | 1458 | try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{ |
| 1448 | self.file(elf_file).?.fmtPath(), | 1459 | self.file(elf_file).?.fmtPath(), |