| ... | @@ -28,8 +28,10 @@ shdrs: std.ArrayList(Section), | ... | @@ -28,8 +28,10 @@ shdrs: std.ArrayList(Section), |
| 28 | phdrs: std.ArrayList(MappedFile.Node.Index), | 28 | phdrs: std.ArrayList(MappedFile.Node.Index), |
| 29 | shndx: struct { | 29 | shndx: struct { |
| 30 | got: Section.Index, | 30 | got: Section.Index, |
| | 31 | /// Always `.UNDEF` on some targets (e.g. SPARC). |
| 31 | got_plt: Section.Index, | 32 | got_plt: Section.Index, |
| 32 | plt: Section.Index, | 33 | plt: Section.Index, |
| | 34 | /// Only created for x86 targets; `.UNDEF` everywhere else. |
| 33 | plt_sec: Section.Index, | 35 | plt_sec: Section.Index, |
| 34 | dynsym: Section.Index, | 36 | dynsym: Section.Index, |
| 35 | dynstr: Section.Index, | 37 | dynstr: Section.Index, |
| ... | @@ -777,18 +779,26 @@ const GotReloc = struct { | ... | @@ -777,18 +779,26 @@ const GotReloc = struct { |
| 777 | }; | 779 | }; |
| 778 | | 780 | |
| 779 | const Type = enum(u8) { | 781 | const Type = enum(u8) { |
| 780 | offset64, | | |
| 781 | offset32, | 782 | offset32, |
| 782 | rel64, | 783 | offset64, |
| 783 | rel32, | 784 | rel32, |
| | 785 | rel64, |
| 784 | | 786 | |
| 785 | rel32_hi20, | 787 | larch_rel32_hi20, |
| 786 | rel64_lo20, | 788 | larch_rel64_lo20, |
| 787 | rel64_hi12, | 789 | larch_rel64_hi12, |
| 788 | abs32_lo12, | 790 | larch_abs32_lo12, |
| 789 | abs32_hi20, | 791 | larch_abs32_hi20, |
| 790 | abs64_lo20, | 792 | larch_abs64_lo20, |
| 791 | abs64_hi12, | 793 | larch_abs64_hi12, |
| | 794 | |
| | 795 | sparc_10, |
| | 796 | sparc_13, |
| | 797 | sparc_22, |
| | 798 | sparc_ldm_hi22, |
| | 799 | sparc_ldm_lo10, |
| | 800 | sparc_op_hix22, |
| | 801 | sparc_op_lox10, |
| 792 | }; | 802 | }; |
| 793 | | 803 | |
| 794 | const Index = enum(u32) { | 804 | const Index = enum(u32) { |
| ... | @@ -857,51 +867,96 @@ const GotReloc = struct { | ... | @@ -857,51 +867,96 @@ const GotReloc = struct { |
| 857 | @intCast(@as(i64, @bitCast(got_vaddr +% got_offset +% addend -% dest_vaddr))), | 867 | @intCast(@as(i64, @bitCast(got_vaddr +% got_offset +% addend -% dest_vaddr))), |
| 858 | target_endian, | 868 | target_endian, |
| 859 | ), | 869 | ), |
| 860 | .rel32_hi20 => { | 870 | |
| | 871 | .larch_rel32_hi20 => { |
| 861 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 872 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 862 | const target_value = got_vaddr +% got_offset +% addend; | 873 | const target_value = got_vaddr +% got_offset +% addend; |
| 863 | link.loongarch.writeJ20(dest_slice[0..4], link.loongarch.toPcalaHi20(target_value, dest_vaddr)); | 874 | link.loongarch.writeJ20(dest_slice[0..4], link.loongarch.toPcalaHi20(target_value, dest_vaddr)); |
| 864 | }, | 875 | }, |
| 865 | .rel64_lo20 => { | 876 | .larch_rel64_lo20 => { |
| 866 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 877 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 867 | const target_value = got_vaddr +% got_offset +% addend; | 878 | const target_value = got_vaddr +% got_offset +% addend; |
| 868 | link.loongarch.writeJ20(dest_slice[0..4], link.loongarch.toPcala64Lo20(target_value, dest_vaddr)); | 879 | link.loongarch.writeJ20(dest_slice[0..4], link.loongarch.toPcala64Lo20(target_value, dest_vaddr)); |
| 869 | }, | 880 | }, |
| 870 | .rel64_hi12 => { | 881 | .larch_rel64_hi12 => { |
| 871 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 882 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 872 | const target_value = got_vaddr +% got_offset +% addend; | 883 | const target_value = got_vaddr +% got_offset +% addend; |
| 873 | link.loongarch.writeK12(dest_slice[0..4], link.loongarch.toPcala64Hi12(target_value, dest_vaddr)); | 884 | link.loongarch.writeK12(dest_slice[0..4], link.loongarch.toPcala64Hi12(target_value, dest_vaddr)); |
| 874 | }, | 885 | }, |
| 875 | .abs32_lo12 => { | 886 | .larch_abs32_lo12 => { |
| 876 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 887 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 877 | const target_value = got_vaddr +% got_offset +% addend; | 888 | const target_value = got_vaddr +% got_offset +% addend; |
| 878 | link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value)); | 889 | link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value)); |
| 879 | }, | 890 | }, |
| 880 | .abs32_hi20 => { | 891 | .larch_abs32_hi20 => { |
| 881 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 892 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 882 | const target_value = got_vaddr +% got_offset +% addend; | 893 | const target_value = got_vaddr +% got_offset +% addend; |
| 883 | link.loongarch.writeJ20(dest_slice[0..4], @truncate(target_value >> 12)); | 894 | link.loongarch.writeJ20(dest_slice[0..4], @truncate(target_value >> 12)); |
| 884 | }, | 895 | }, |
| 885 | .abs64_lo20 => { | 896 | .larch_abs64_lo20 => { |
| 886 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 897 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 887 | const target_value = got_vaddr +% got_offset +% addend; | 898 | const target_value = got_vaddr +% got_offset +% addend; |
| 888 | link.loongarch.writeJ20(dest_slice[0..4], @truncate(target_value >> 32)); | 899 | link.loongarch.writeJ20(dest_slice[0..4], @truncate(target_value >> 32)); |
| 889 | }, | 900 | }, |
| 890 | .abs64_hi12 => { | 901 | .larch_abs64_hi12 => { |
| 891 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 902 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 892 | const target_value = got_vaddr +% got_offset +% addend; | 903 | const target_value = got_vaddr +% got_offset +% addend; |
| 893 | link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value >> 52)); | 904 | link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value >> 52)); |
| 894 | }, | 905 | }, |
| | 906 | |
| | 907 | .sparc_10 => { |
| | 908 | const dest_ptr: *link.sparc.reloc.Simm13 = @ptrCast(@alignCast(dest_slice)); |
| | 909 | var result = elf.targetLoad(dest_ptr); |
| | 910 | result.simm13 = @as(u10, @truncate(got_offset)); |
| | 911 | elf.targetStore(dest_ptr, result); |
| | 912 | }, |
| | 913 | .sparc_13 => { |
| | 914 | const dest_ptr: *link.sparc.reloc.Simm13 = @ptrCast(@alignCast(dest_slice)); |
| | 915 | var result = elf.targetLoad(dest_ptr); |
| | 916 | result.simm13 = @truncate(got_offset); |
| | 917 | elf.targetStore(dest_ptr, result); |
| | 918 | }, |
| | 919 | .sparc_22 => { |
| | 920 | const dest_ptr: *link.sparc.reloc.Simm22 = @ptrCast(@alignCast(dest_slice)); |
| | 921 | var result = elf.targetLoad(dest_ptr); |
| | 922 | result.simm22 = @truncate(got_offset >> 10); |
| | 923 | elf.targetStore(dest_ptr, result); |
| | 924 | }, |
| | 925 | .sparc_ldm_hi22 => { |
| | 926 | const dest_ptr: *link.sparc.reloc.Simm22 = @ptrCast(@alignCast(dest_slice)); |
| | 927 | var result = elf.targetLoad(dest_ptr); |
| | 928 | result.simm22 = @truncate((got_offset +% addend) >> 10); |
| | 929 | elf.targetStore(dest_ptr, result); |
| | 930 | }, |
| | 931 | .sparc_ldm_lo10 => { |
| | 932 | const dest_ptr: *link.sparc.reloc.Simm13 = @ptrCast(@alignCast(dest_slice)); |
| | 933 | var result = elf.targetLoad(dest_ptr); |
| | 934 | result.simm13 = @as(u10, @truncate(got_offset +% addend)); |
| | 935 | elf.targetStore(dest_ptr, result); |
| | 936 | }, |
| | 937 | .sparc_op_hix22 => { |
| | 938 | const dest_ptr: *link.sparc.reloc.Imm22 = @ptrCast(@alignCast(dest_slice)); |
| | 939 | var result = elf.targetLoad(dest_ptr); |
| | 940 | result.imm22 = @truncate(got_offset >> 10); |
| | 941 | elf.targetStore(dest_ptr, result); |
| | 942 | }, |
| | 943 | .sparc_op_lox10 => { |
| | 944 | const dest_ptr: *link.sparc.reloc.Imm13 = @ptrCast(@alignCast(dest_slice)); |
| | 945 | var result = elf.targetLoad(dest_ptr); |
| | 946 | result.imm13 = @as(u10, @truncate(got_offset)); |
| | 947 | elf.targetStore(dest_ptr, result); |
| | 948 | }, |
| 895 | } | 949 | } |
| 896 | } | 950 | } |
| 897 | }; | 951 | }; |
| 898 | | 952 | |
| 899 | pub const MachineRelocType = union { | 953 | pub const MachineRelocType = union { |
| 900 | X86_64: std.elf.R_X86_64, | | |
| 901 | AARCH64: std.elf.R_AARCH64, | 954 | AARCH64: std.elf.R_AARCH64, |
| 902 | LOONGARCH: std.elf.R_LARCH, | 955 | LOONGARCH: std.elf.R_LARCH, |
| 903 | RISCV: std.elf.R_RISCV, | | |
| 904 | PPC64: std.elf.R_PPC64, | 956 | PPC64: std.elf.R_PPC64, |
| | 957 | RISCV: std.elf.R_RISCV, |
| | 958 | SPARC: std.elf.R_SPARC, |
| | 959 | X86_64: std.elf.R_X86_64, |
| 905 | | 960 | |
| 906 | pub fn none(elf: *Elf) MachineRelocType { | 961 | pub fn none(elf: *Elf) MachineRelocType { |
| 907 | return switch (elf.ehdrField(.machine)) { | 962 | return switch (elf.ehdrField(.machine)) { |
| ... | @@ -910,6 +965,7 @@ pub const MachineRelocType = union { | ... | @@ -910,6 +965,7 @@ pub const MachineRelocType = union { |
| 910 | .LOONGARCH => .{ .LOONGARCH = .NONE }, | 965 | .LOONGARCH => .{ .LOONGARCH = .NONE }, |
| 911 | .PPC64 => .{ .PPC64 = .NONE }, | 966 | .PPC64 => .{ .PPC64 = .NONE }, |
| 912 | .RISCV => .{ .RISCV = .NONE }, | 967 | .RISCV => .{ .RISCV = .NONE }, |
| | 968 | .SPARCV9 => .{ .SPARC = .NONE }, |
| 913 | .X86_64 => .{ .X86_64 = .NONE }, | 969 | .X86_64 => .{ .X86_64 = .NONE }, |
| 914 | }; | 970 | }; |
| 915 | } | 971 | } |
| ... | @@ -920,6 +976,7 @@ pub const MachineRelocType = union { | ... | @@ -920,6 +976,7 @@ pub const MachineRelocType = union { |
| 920 | .LOONGARCH => .{ .LOONGARCH = .COPY }, | 976 | .LOONGARCH => .{ .LOONGARCH = .COPY }, |
| 921 | .PPC64 => .{ .PPC64 = .COPY }, | 977 | .PPC64 => .{ .PPC64 = .COPY }, |
| 922 | .RISCV => .{ .RISCV = .COPY }, | 978 | .RISCV => .{ .RISCV = .COPY }, |
| | 979 | .SPARCV9 => .{ .SPARC = .COPY }, |
| 923 | .X86_64 => .{ .X86_64 = .COPY }, | 980 | .X86_64 => .{ .X86_64 = .COPY }, |
| 924 | }; | 981 | }; |
| 925 | } | 982 | } |
| ... | @@ -930,43 +987,57 @@ pub const MachineRelocType = union { | ... | @@ -930,43 +987,57 @@ pub const MachineRelocType = union { |
| 930 | .LOONGARCH => .{ .LOONGARCH = .RELATIVE }, | 987 | .LOONGARCH => .{ .LOONGARCH = .RELATIVE }, |
| 931 | .PPC64 => .{ .PPC64 = .RELATIVE }, | 988 | .PPC64 => .{ .PPC64 = .RELATIVE }, |
| 932 | .RISCV => .{ .RISCV = .RELATIVE }, | 989 | .RISCV => .{ .RISCV = .RELATIVE }, |
| | 990 | .SPARCV9 => .{ .SPARC = .RELATIVE }, |
| 933 | .X86_64 => .{ .X86_64 = .RELATIVE }, | 991 | .X86_64 => .{ .X86_64 = .RELATIVE }, |
| 934 | }; | 992 | }; |
| 935 | } | 993 | } |
| 936 | pub fn jumpSlot(elf: *Elf) MachineRelocType { | 994 | pub fn jumpSlot(elf: *Elf) MachineRelocType { |
| 937 | return switch (elf.ehdrField(.machine)) { | 995 | return switch (elf.ehdrField(.machine)) { |
| 938 | else => unreachable, | 996 | else => unreachable, |
| 939 | .X86_64 => .{ .X86_64 = .JUMP_SLOT }, | 997 | .AARCH64 => .{ .AARCH64 = .JUMP_SLOT }, |
| 940 | .LOONGARCH => .{ .LOONGARCH = .JUMP_SLOT }, | 998 | .LOONGARCH => .{ .LOONGARCH = .JUMP_SLOT }, |
| | 999 | .PPC64 => .{ .PPC64 = .JMP_SLOT }, |
| | 1000 | .RISCV => .{ .RISCV = .JUMP_SLOT }, |
| | 1001 | .SPARCV9 => .{ .SPARC = .JMP_SLOT }, |
| | 1002 | .X86_64 => .{ .X86_64 = .JUMP_SLOT }, |
| 941 | }; | 1003 | }; |
| 942 | } | 1004 | } |
| 943 | pub fn globDat(elf: *Elf) MachineRelocType { | 1005 | pub fn globDat(elf: *Elf) MachineRelocType { |
| 944 | return switch (elf.ehdrField(.machine)) { | 1006 | return switch (elf.ehdrField(.machine)) { |
| 945 | else => unreachable, | 1007 | else => unreachable, |
| 946 | .X86_64 => .{ .X86_64 = .GLOB_DAT }, | 1008 | .AARCH64 => .{ .AARCH64 = .GLOB_DAT }, |
| 947 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .@"64" else .@"32" }, | 1009 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| | 1010 | .PPC64 => .{ .PPC64 = .GLOB_DAT }, |
| | 1011 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| | 1012 | .SPARCV9 => .{ .SPARC = .GLOB_DAT }, |
| | 1013 | .X86_64 => .{ .X86_64 = .GLOB_DAT }, |
| 948 | }; | 1014 | }; |
| 949 | } | 1015 | } |
| 950 | pub fn dtpOffAddr(elf: *Elf) MachineRelocType { | 1016 | pub fn dtpOffAddr(elf: *Elf) MachineRelocType { |
| 951 | return switch (elf.ehdrField(.machine)) { | 1017 | return switch (elf.ehdrField(.machine)) { |
| 952 | else => unreachable, | 1018 | else => unreachable, |
| 953 | .X86_64 => .{ .X86_64 = .DTPOFF64 }, | | |
| 954 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_DTPREL64 else .TLS_DTPREL32 }, | 1019 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_DTPREL64 else .TLS_DTPREL32 }, |
| | 1020 | .PPC64 => .{ .PPC64 = .DTPREL64 }, |
| | 1021 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .TLS_DTPREL64 else .TLS_DTPREL32 }, |
| | 1022 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .TLS_DTPOFF64 else .TLS_DTPOFF32 }, |
| | 1023 | .X86_64 => .{ .X86_64 = if (elf.identClass() == .@"64") .DTPOFF64 else .DTPOFF32 }, |
| 955 | }; | 1024 | }; |
| 956 | } | 1025 | } |
| 957 | pub fn absAddr(elf: *Elf) MachineRelocType { | 1026 | pub fn absAddr(elf: *Elf) MachineRelocType { |
| 958 | return switch (elf.ehdrField(.machine)) { | 1027 | return switch (elf.ehdrField(.machine)) { |
| 959 | else => unreachable, | 1028 | else => unreachable, |
| 960 | .AARCH64 => .{ .AARCH64 = .ABS64 }, | 1029 | .AARCH64 => .{ .AARCH64 = if (elf.identClass() == .@"64") .ABS64 else .P32_ABS32 }, |
| 961 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .@"64" else .@"32" }, | 1030 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| 962 | .PPC64 => .{ .PPC64 = .ADDR64 }, | 1031 | .PPC64 => .{ .PPC64 = .ADDR64 }, |
| 963 | .RISCV => .{ .RISCV = .@"64" }, | 1032 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| 964 | .X86_64 => .{ .X86_64 = .@"64" }, | 1033 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| | 1034 | .X86_64 => .{ .X86_64 = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| 965 | }; | 1035 | }; |
| 966 | } | 1036 | } |
| 967 | pub fn sizeAddr(elf: *Elf) MachineRelocType { | 1037 | pub fn sizeAddr(elf: *Elf) MachineRelocType { |
| 968 | return switch (elf.ehdrField(.machine)) { | 1038 | return switch (elf.ehdrField(.machine)) { |
| 969 | else => unreachable, | 1039 | else => unreachable, |
| | 1040 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .SIZE64 else .SIZE32 }, |
| 970 | .X86_64 => .{ .X86_64 = .SIZE64 }, | 1041 | .X86_64 => .{ .X86_64 = .SIZE64 }, |
| 971 | }; | 1042 | }; |
| 972 | } | 1043 | } |
| ... | @@ -974,6 +1045,7 @@ pub const MachineRelocType = union { | ... | @@ -974,6 +1045,7 @@ pub const MachineRelocType = union { |
| 974 | pub fn wrap(int: u32, elf: *Elf) MachineRelocType { | 1045 | pub fn wrap(int: u32, elf: *Elf) MachineRelocType { |
| 975 | return switch (elf.ehdrField(.machine)) { | 1046 | return switch (elf.ehdrField(.machine)) { |
| 976 | else => unreachable, | 1047 | else => unreachable, |
| | 1048 | .SPARCV9 => .{ .SPARC = @enumFromInt(int) }, |
| 977 | inline .AARCH64, | 1049 | inline .AARCH64, |
| 978 | .LOONGARCH, | 1050 | .LOONGARCH, |
| 979 | .PPC64, | 1051 | .PPC64, |
| ... | @@ -985,6 +1057,7 @@ pub const MachineRelocType = union { | ... | @@ -985,6 +1057,7 @@ pub const MachineRelocType = union { |
| 985 | pub fn unwrap(rt: MachineRelocType, elf: *Elf) u32 { | 1057 | pub fn unwrap(rt: MachineRelocType, elf: *Elf) u32 { |
| 986 | return switch (elf.ehdrField(.machine)) { | 1058 | return switch (elf.ehdrField(.machine)) { |
| 987 | else => unreachable, | 1059 | else => unreachable, |
| | 1060 | .SPARCV9 => @intFromEnum(rt.SPARC), |
| 988 | inline .AARCH64, | 1061 | inline .AARCH64, |
| 989 | .LOONGARCH, | 1062 | .LOONGARCH, |
| 990 | .PPC64, | 1063 | .PPC64, |
| ... | @@ -1073,37 +1146,67 @@ const SymbolReloc = struct { | ... | @@ -1073,37 +1146,67 @@ const SymbolReloc = struct { |
| 1073 | /// This is only used targeting local symbols so can always be statically resolved. | 1146 | /// This is only used targeting local symbols so can always be statically resolved. |
| 1074 | dsorel32, | 1147 | dsorel32, |
| 1075 | | 1148 | |
| 1076 | abs64, | 1149 | abs8, |
| | 1150 | abs16, |
| 1077 | abs32, | 1151 | abs32, |
| 1078 | abs32s, | 1152 | abs32s, |
| 1079 | rel64, | 1153 | abs64, |
| | 1154 | rel8, |
| | 1155 | rel16, |
| 1080 | rel32, | 1156 | rel32, |
| 1081 | pltrel64, | 1157 | rel64, |
| | 1158 | pltabs32, |
| | 1159 | pltabs64, |
| 1082 | pltrel32, | 1160 | pltrel32, |
| 1083 | dtpoff64, | 1161 | pltrel64, |
| 1084 | dtpoff32, | 1162 | dtpoff32, |
| 1085 | tpoff64, | 1163 | dtpoff64, |
| 1086 | tpoff32, | 1164 | tpoff32, |
| 1087 | size64, | 1165 | tpoff64, |
| 1088 | size32, | 1166 | size32, |
| | 1167 | size64, |
| 1089 | | 1168 | |
| 1090 | abs32_lo12, | 1169 | larch_abs32_lo12, |
| 1091 | rel32_hi20, | 1170 | larch_rel32_hi20, |
| 1092 | rel64_lo20, | 1171 | larch_rel64_lo20, |
| 1093 | rel64_hi12, | 1172 | larch_rel64_hi12, |
| 1094 | branch_rel18, | 1173 | larch_branch_rel18, |
| 1095 | branch_rel23, | 1174 | larch_branch_rel23, |
| 1096 | branch_rel28, | 1175 | larch_branch_rel28, |
| 1097 | call_rel38, | 1176 | larch_call_rel38, |
| 1098 | tpoff32_lo12, | 1177 | larch_tpoff32_lo12, |
| 1099 | tpoff32_hi20, | 1178 | larch_tpoff32_hi20, |
| 1100 | tpoff64_lo20, | 1179 | larch_tpoff64_lo20, |
| 1101 | tpoff64_hi12, | 1180 | larch_tpoff64_hi12, |
| | 1181 | |
| | 1182 | sparc_wdisp30, |
| | 1183 | sparc_pc10, |
| | 1184 | sparc_pc22, |
| | 1185 | sparc_wplt30, |
| | 1186 | sparc_h44, |
| | 1187 | sparc_m44, |
| | 1188 | sparc_l44, |
| | 1189 | sparc_ldo_hix22, |
| | 1190 | sparc_ldo_lox10, |
| | 1191 | sparc_le_hix22, |
| | 1192 | sparc_le_lox10, |
| 1102 | | 1193 | |
| 1103 | fn dependsOnTlsSize(t: SymbolReloc.Type) bool { | 1194 | fn dependsOnTlsSize(t: SymbolReloc.Type) bool { |
| 1104 | return switch (t) { | 1195 | return switch (t) { |
| 1105 | .tpoff32, .tpoff64 => true, | 1196 | .tpoff32, |
| 1106 | .tpoff32_lo12, .tpoff32_hi20, .tpoff64_lo20, .tpoff64_hi12 => true, | 1197 | .tpoff64, |
| | 1198 | => true, |
| | 1199 | |
| | 1200 | .larch_tpoff32_lo12, |
| | 1201 | .larch_tpoff32_hi20, |
| | 1202 | .larch_tpoff64_lo20, |
| | 1203 | .larch_tpoff64_hi12, |
| | 1204 | => true, |
| | 1205 | |
| | 1206 | .sparc_le_hix22, |
| | 1207 | .sparc_le_lox10, |
| | 1208 | => true, |
| | 1209 | |
| 1107 | else => false, | 1210 | else => false, |
| 1108 | }; | 1211 | }; |
| 1109 | } | 1212 | } |
| ... | @@ -1111,8 +1214,18 @@ const SymbolReloc = struct { | ... | @@ -1111,8 +1214,18 @@ const SymbolReloc = struct { |
| 1111 | fn isAbsAddr(t: SymbolReloc.Type, elf: *const Elf) bool { | 1214 | fn isAbsAddr(t: SymbolReloc.Type, elf: *const Elf) bool { |
| 1112 | return switch (elf.identClass()) { | 1215 | return switch (elf.identClass()) { |
| 1113 | .NONE, _ => unreachable, | 1216 | .NONE, _ => unreachable, |
| 1114 | .@"32" => t == .abs32, | 1217 | .@"32" => switch (t) { |
| 1115 | .@"64" => t == .abs64, | 1218 | .abs32, |
| | 1219 | .pltabs32, |
| | 1220 | => true, |
| | 1221 | else => false, |
| | 1222 | }, |
| | 1223 | .@"64" => switch (t) { |
| | 1224 | .abs64, |
| | 1225 | .pltabs64, |
| | 1226 | => true, |
| | 1227 | else => false, |
| | 1228 | }, |
| 1116 | }; | 1229 | }; |
| 1117 | } | 1230 | } |
| 1118 | }; | 1231 | }; |
| ... | @@ -1131,11 +1244,31 @@ const SymbolReloc = struct { | ... | @@ -1131,11 +1244,31 @@ const SymbolReloc = struct { |
| 1131 | .static => unreachable, | 1244 | .static => unreachable, |
| 1132 | .dynamic => return, // the relocation happens at runtime | 1245 | .dynamic => return, // the relocation happens at runtime |
| 1133 | .static_relative => { | 1246 | .static_relative => { |
| 1134 | assert(reloc.type.isAbsAddr(elf)); | | |
| 1135 | // We have emitted an R_*_RELATIVE relocation to help lower an abs32/abs64 reloc. | 1247 | // We have emitted an R_*_RELATIVE relocation to help lower an abs32/abs64 reloc. |
| 1136 | // This is a simplified version of the general relocation handling logic, where we | 1248 | // This is a simplified version of the general relocation handling logic, where we |
| 1137 | // know we're using '.abs64' or '.abs32' (matching the ELF ident class). | 1249 | // know we're using '.abs64' or '.abs32' (matching the ELF ident class). |
| 1138 | const value = reloc.target.value(elf) +% @as(u64, @bitCast(reloc.addend)); | 1250 | const value = type: switch (reloc.type) { |
| | 1251 | .abs32, |
| | 1252 | .abs64, |
| | 1253 | => reloc.target.value(elf) +% @as(u64, @bitCast(reloc.addend)), |
| | 1254 | .pltabs32, |
| | 1255 | .pltabs64, |
| | 1256 | => value: { |
| | 1257 | const plt_index = switch (reloc.target.unwrap()) { |
| | 1258 | .local => continue :type .abs32, |
| | 1259 | .global => |name| elf.plt.getIndex(name) orelse continue :type .abs32, |
| | 1260 | }; |
| | 1261 | if (elf.pltEntryIsDead(plt_index)) continue :type .abs32; |
| | 1262 | const plt_shndx: Section.Index, const plt_header_entries: u64, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { |
| | 1263 | else => |machine| @panic(@tagName(machine)), |
| | 1264 | .SPARCV9 => .{ elf.shndx.plt, 4, 32 }, |
| | 1265 | .X86_64 => .{ elf.shndx.plt_sec, 0, 16 }, |
| | 1266 | }; |
| | 1267 | const plt_entry = plt_shndx.vaddr(elf) +% (plt_header_entries + plt_index) * plt_entry_size; |
| | 1268 | break :value plt_entry +% @as(u64, @bitCast(reloc.addend)); |
| | 1269 | }, |
| | 1270 | else => unreachable, |
| | 1271 | }; |
| 1139 | elf.shndx.rela_dyn.relaSetRelativeOffset(elf, rela_index, value); | 1272 | elf.shndx.rela_dyn.relaSetRelativeOffset(elf, rela_index, value); |
| 1140 | return; | 1273 | return; |
| 1141 | }, | 1274 | }, |
| ... | @@ -1182,6 +1315,13 @@ const SymbolReloc = struct { | ... | @@ -1182,6 +1315,13 @@ const SymbolReloc = struct { |
| 1182 | @intCast(@as(i64, @bitCast(target_value))), | 1315 | @intCast(@as(i64, @bitCast(target_value))), |
| 1183 | target_endian, | 1316 | target_endian, |
| 1184 | ), | 1317 | ), |
| | 1318 | .abs16 => std.mem.writeInt( |
| | 1319 | u16, |
| | 1320 | dest_slice[0..2], |
| | 1321 | @intCast(target_value), |
| | 1322 | target_endian, |
| | 1323 | ), |
| | 1324 | .abs8 => dest_slice[0] = @intCast(target_value), |
| 1185 | .rel64 => std.mem.writeInt( | 1325 | .rel64 => std.mem.writeInt( |
| 1186 | i64, | 1326 | i64, |
| 1187 | dest_slice[0..8], | 1327 | dest_slice[0..8], |
| ... | @@ -1194,17 +1334,65 @@ const SymbolReloc = struct { | ... | @@ -1194,17 +1334,65 @@ const SymbolReloc = struct { |
| 1194 | @intCast(@as(i64, @bitCast(target_value -% dest_vaddr))), | 1334 | @intCast(@as(i64, @bitCast(target_value -% dest_vaddr))), |
| 1195 | target_endian, | 1335 | target_endian, |
| 1196 | ), | 1336 | ), |
| | 1337 | .rel16 => std.mem.writeInt( |
| | 1338 | i16, |
| | 1339 | dest_slice[0..2], |
| | 1340 | @intCast(@as(i64, @bitCast(target_value -% dest_vaddr))), |
| | 1341 | target_endian, |
| | 1342 | ), |
| | 1343 | .rel8 => dest_slice[0] = @bitCast(@as(i8, @intCast(@as(i64, @bitCast(target_value -% dest_vaddr))))), |
| | 1344 | .pltabs64 => { |
| | 1345 | const plt_index = switch (reloc.target.unwrap()) { |
| | 1346 | .local => continue :type .abs64, |
| | 1347 | .global => |name| elf.plt.getIndex(name) orelse continue :type .abs64, |
| | 1348 | }; |
| | 1349 | if (elf.pltEntryIsDead(plt_index)) continue :type .abs64; |
| | 1350 | const plt_shndx: Section.Index, const plt_header_entries: u64, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { |
| | 1351 | else => |machine| @panic(@tagName(machine)), |
| | 1352 | .SPARCV9 => .{ elf.shndx.plt, 4, 32 }, |
| | 1353 | .X86_64 => .{ elf.shndx.plt_sec, 0, 16 }, |
| | 1354 | }; |
| | 1355 | const plt_entry = plt_shndx.vaddr(elf) +% (plt_header_entries + plt_index) * plt_entry_size; |
| | 1356 | std.mem.writeInt( |
| | 1357 | i64, |
| | 1358 | dest_slice[0..8], |
| | 1359 | @bitCast(plt_entry +% @as(u64, @bitCast(reloc.addend))), |
| | 1360 | target_endian, |
| | 1361 | ); |
| | 1362 | }, |
| | 1363 | .pltabs32 => { |
| | 1364 | const plt_index = switch (reloc.target.unwrap()) { |
| | 1365 | .local => continue :type .abs32, |
| | 1366 | .global => |name| elf.plt.getIndex(name) orelse continue :type .abs32, |
| | 1367 | }; |
| | 1368 | if (elf.pltEntryIsDead(plt_index)) continue :type .abs32; |
| | 1369 | const plt_shndx: Section.Index, const plt_header_entries: u64, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { |
| | 1370 | else => |machine| @panic(@tagName(machine)), |
| | 1371 | .SPARCV9 => .{ elf.shndx.plt, 4, 32 }, |
| | 1372 | .X86_64 => .{ elf.shndx.plt_sec, 0, 16 }, |
| | 1373 | }; |
| | 1374 | const plt_entry = plt_shndx.vaddr(elf) +% (plt_header_entries + plt_index) * plt_entry_size; |
| | 1375 | std.mem.writeInt( |
| | 1376 | i32, |
| | 1377 | dest_slice[0..4], |
| | 1378 | @intCast(@as(i64, @bitCast( |
| | 1379 | plt_entry +% @as(u64, @bitCast(reloc.addend)), |
| | 1380 | ))), |
| | 1381 | target_endian, |
| | 1382 | ); |
| | 1383 | }, |
| 1197 | .pltrel64 => { | 1384 | .pltrel64 => { |
| 1198 | const plt_index = switch (reloc.target.unwrap()) { | 1385 | const plt_index = switch (reloc.target.unwrap()) { |
| 1199 | .local => continue :type .rel64, | 1386 | .local => continue :type .rel64, |
| 1200 | .global => |name| elf.plt.getIndex(name) orelse continue :type .rel64, | 1387 | .global => |name| elf.plt.getIndex(name) orelse continue :type .rel64, |
| 1201 | }; | 1388 | }; |
| 1202 | if (elf.pltEntryIsDead(plt_index)) continue :type .rel64; | 1389 | if (elf.pltEntryIsDead(plt_index)) continue :type .rel64; |
| 1203 | const plt_shndx: Section.Index, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { | 1390 | const plt_shndx: Section.Index, const plt_header_entries: u64, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { |
| 1204 | else => |machine| @panic(@tagName(machine)), | 1391 | else => |machine| @panic(@tagName(machine)), |
| 1205 | .X86_64 => .{ elf.shndx.plt_sec, 16 }, | 1392 | .SPARCV9 => .{ elf.shndx.plt, 4, 32 }, |
| | 1393 | .X86_64 => .{ elf.shndx.plt_sec, 0, 16 }, |
| 1206 | }; | 1394 | }; |
| 1207 | const plt_entry = plt_shndx.vaddr(elf) +% plt_index * plt_entry_size; | 1395 | const plt_entry = plt_shndx.vaddr(elf) +% (plt_header_entries + plt_index) * plt_entry_size; |
| 1208 | std.mem.writeInt( | 1396 | std.mem.writeInt( |
| 1209 | i64, | 1397 | i64, |
| 1210 | dest_slice[0..8], | 1398 | dest_slice[0..8], |
| ... | @@ -1218,11 +1406,12 @@ const SymbolReloc = struct { | ... | @@ -1218,11 +1406,12 @@ const SymbolReloc = struct { |
| 1218 | .global => |name| elf.plt.getIndex(name) orelse continue :type .rel32, | 1406 | .global => |name| elf.plt.getIndex(name) orelse continue :type .rel32, |
| 1219 | }; | 1407 | }; |
| 1220 | if (elf.pltEntryIsDead(plt_index)) continue :type .rel32; | 1408 | if (elf.pltEntryIsDead(plt_index)) continue :type .rel32; |
| 1221 | const plt_shndx: Section.Index, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { | 1409 | const plt_shndx: Section.Index, const plt_header_entries: u64, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { |
| 1222 | else => |machine| @panic(@tagName(machine)), | 1410 | else => |machine| @panic(@tagName(machine)), |
| 1223 | .X86_64 => .{ elf.shndx.plt_sec, 16 }, | 1411 | .SPARCV9 => .{ elf.shndx.plt, 4, 32 }, |
| | 1412 | .X86_64 => .{ elf.shndx.plt_sec, 0, 16 }, |
| 1224 | }; | 1413 | }; |
| 1225 | const plt_entry = plt_shndx.vaddr(elf) +% plt_index * plt_entry_size; | 1414 | const plt_entry = plt_shndx.vaddr(elf) +% (plt_header_entries + plt_index) * plt_entry_size; |
| 1226 | std.mem.writeInt( | 1415 | std.mem.writeInt( |
| 1227 | i32, | 1416 | i32, |
| 1228 | dest_slice[0..4], | 1417 | dest_slice[0..4], |
| ... | @@ -1286,42 +1475,43 @@ const SymbolReloc = struct { | ... | @@ -1286,42 +1475,43 @@ const SymbolReloc = struct { |
| 1286 | target_endian, | 1475 | target_endian, |
| 1287 | ); | 1476 | ); |
| 1288 | }, | 1477 | }, |
| 1289 | .abs32_lo12 => { | 1478 | |
| | 1479 | .larch_abs32_lo12 => { |
| 1290 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 1480 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1291 | link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value)); | 1481 | link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value)); |
| 1292 | }, | 1482 | }, |
| 1293 | .rel32_hi20 => { | 1483 | .larch_rel32_hi20 => { |
| 1294 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 1484 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1295 | link.loongarch.writeJ20(dest_slice[0..4], link.loongarch.toPcalaHi20(target_value, dest_vaddr)); | 1485 | link.loongarch.writeJ20(dest_slice[0..4], link.loongarch.toPcalaHi20(target_value, dest_vaddr)); |
| 1296 | }, | 1486 | }, |
| 1297 | .rel64_lo20 => { | 1487 | .larch_rel64_lo20 => { |
| 1298 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 1488 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1299 | link.loongarch.writeJ20(dest_slice[0..4], link.loongarch.toPcala64Lo20(target_value, dest_vaddr)); | 1489 | link.loongarch.writeJ20(dest_slice[0..4], link.loongarch.toPcala64Lo20(target_value, dest_vaddr)); |
| 1300 | }, | 1490 | }, |
| 1301 | .rel64_hi12 => { | 1491 | .larch_rel64_hi12 => { |
| 1302 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 1492 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1303 | link.loongarch.writeK12(dest_slice[0..4], link.loongarch.toPcala64Hi12(target_value, dest_vaddr)); | 1493 | link.loongarch.writeK12(dest_slice[0..4], link.loongarch.toPcala64Hi12(target_value, dest_vaddr)); |
| 1304 | }, | 1494 | }, |
| 1305 | // TODO: handle bad alignment and overflow gracefully | 1495 | // TODO: handle bad alignment and overflow gracefully |
| 1306 | .branch_rel18 => { | 1496 | .larch_branch_rel18 => { |
| 1307 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 1497 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1308 | const target_rel: i64 = @bitCast(target_value -% dest_vaddr); | 1498 | const target_rel: i64 = @bitCast(target_value -% dest_vaddr); |
| 1309 | const slot_target: i16 = @intCast(@shrExact(target_rel, 2)); | 1499 | const slot_target: i16 = @intCast(@shrExact(target_rel, 2)); |
| 1310 | link.loongarch.writeK16(dest_slice[0..4], @bitCast(slot_target)); | 1500 | link.loongarch.writeK16(dest_slice[0..4], @bitCast(slot_target)); |
| 1311 | }, | 1501 | }, |
| 1312 | .branch_rel23 => { | 1502 | .larch_branch_rel23 => { |
| 1313 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 1503 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1314 | const target_rel: i64 = @bitCast(target_value -% dest_vaddr); | 1504 | const target_rel: i64 = @bitCast(target_value -% dest_vaddr); |
| 1315 | const slot_target: i21 = @intCast(@shrExact(target_rel, 2)); | 1505 | const slot_target: i21 = @intCast(@shrExact(target_rel, 2)); |
| 1316 | link.loongarch.writeD5K16(dest_slice[0..4], @bitCast(slot_target)); | 1506 | link.loongarch.writeD5K16(dest_slice[0..4], @bitCast(slot_target)); |
| 1317 | }, | 1507 | }, |
| 1318 | .branch_rel28 => { | 1508 | .larch_branch_rel28 => { |
| 1319 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 1509 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1320 | const target_rel: i64 = @bitCast(target_value -% dest_vaddr); | 1510 | const target_rel: i64 = @bitCast(target_value -% dest_vaddr); |
| 1321 | const slot_target: i26 = @intCast(@shrExact(target_rel, 2)); | 1511 | const slot_target: i26 = @intCast(@shrExact(target_rel, 2)); |
| 1322 | link.loongarch.writeD10K16(dest_slice[0..4], @bitCast(slot_target)); | 1512 | link.loongarch.writeD10K16(dest_slice[0..4], @bitCast(slot_target)); |
| 1323 | }, | 1513 | }, |
| 1324 | .call_rel38 => { | 1514 | .larch_call_rel38 => { |
| 1325 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 1515 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1326 | const target_rel: i64 = @bitCast(target_value -% dest_vaddr); | 1516 | const target_rel: i64 = @bitCast(target_value -% dest_vaddr); |
| 1327 | // We use i64 instead of i36 here because the allowed range is | 1517 | // We use i64 instead of i36 here because the allowed range is |
| ... | @@ -1331,22 +1521,109 @@ const SymbolReloc = struct { | ... | @@ -1331,22 +1521,109 @@ const SymbolReloc = struct { |
| 1331 | link.loongarch.writeJ20(dest_slice[0..4], @bitCast(@as(i20, @intCast((slot_target +% 0x8000) >> 16)))); | 1521 | link.loongarch.writeJ20(dest_slice[0..4], @bitCast(@as(i20, @intCast((slot_target +% 0x8000) >> 16)))); |
| 1332 | link.loongarch.writeK16(dest_slice[4..8], @bitCast(@as(i16, @truncate(slot_target)))); | 1522 | link.loongarch.writeK16(dest_slice[4..8], @bitCast(@as(i16, @truncate(slot_target)))); |
| 1333 | }, | 1523 | }, |
| 1334 | .tpoff32_lo12 => { | 1524 | .larch_tpoff32_lo12 => { |
| 1335 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 1525 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1336 | link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value)); | 1526 | link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value)); |
| 1337 | }, | 1527 | }, |
| 1338 | .tpoff32_hi20 => { | 1528 | .larch_tpoff32_hi20 => { |
| 1339 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 1529 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1340 | link.loongarch.writeJ20(dest_slice[0..4], @truncate(target_value >> 12)); | 1530 | link.loongarch.writeJ20(dest_slice[0..4], @truncate(target_value >> 12)); |
| 1341 | }, | 1531 | }, |
| 1342 | .tpoff64_lo20 => { | 1532 | .larch_tpoff64_lo20 => { |
| 1343 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 1533 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1344 | link.loongarch.writeJ20(dest_slice[0..4], @truncate(target_value >> 32)); | 1534 | link.loongarch.writeJ20(dest_slice[0..4], @truncate(target_value >> 32)); |
| 1345 | }, | 1535 | }, |
| 1346 | .tpoff64_hi12 => { | 1536 | .larch_tpoff64_hi12 => { |
| 1347 | assert(elf.ehdrField(.machine) == .LOONGARCH); | 1537 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1348 | link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value >> 52)); | 1538 | link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value >> 52)); |
| 1349 | }, | 1539 | }, |
| | 1540 | |
| | 1541 | .sparc_wdisp30 => { |
| | 1542 | const dest_ptr: *link.sparc.reloc.Disp30 = @ptrCast(@alignCast(dest_slice)); |
| | 1543 | var result = elf.targetLoad(dest_ptr); |
| | 1544 | result.disp30 = @truncate((target_value -% dest_vaddr) >> 2); |
| | 1545 | elf.targetStore(dest_ptr, result); |
| | 1546 | }, |
| | 1547 | .sparc_pc10 => { |
| | 1548 | const dest_ptr: *link.sparc.reloc.Simm13 = @ptrCast(@alignCast(dest_slice)); |
| | 1549 | var result = elf.targetLoad(dest_ptr); |
| | 1550 | result.simm13 = @as(u10, @truncate(target_value -% dest_vaddr)); |
| | 1551 | elf.targetStore(dest_ptr, result); |
| | 1552 | }, |
| | 1553 | .sparc_pc22 => { |
| | 1554 | const dest_ptr: *link.sparc.reloc.Disp22 = @ptrCast(@alignCast(dest_slice)); |
| | 1555 | var result = elf.targetLoad(dest_ptr); |
| | 1556 | result.disp22 = @truncate((target_value -% dest_vaddr) >> 10); |
| | 1557 | elf.targetStore(dest_ptr, result); |
| | 1558 | }, |
| | 1559 | .sparc_wplt30 => { |
| | 1560 | const plt_index = switch (reloc.target.unwrap()) { |
| | 1561 | .local => continue :type .sparc_wdisp30, |
| | 1562 | .global => |name| elf.plt.getIndex(name) orelse continue :type .sparc_wdisp30, |
| | 1563 | }; |
| | 1564 | if (elf.pltEntryIsDead(plt_index)) continue :type .sparc_wdisp30; |
| | 1565 | const plt_entry = elf.shndx.plt.vaddr(elf) +% (4 + plt_index) * 32; |
| | 1566 | const dest_ptr: *link.sparc.reloc.Disp30 = @ptrCast(@alignCast(dest_slice)); |
| | 1567 | var result = elf.targetLoad(dest_ptr); |
| | 1568 | result.disp30 = @truncate((plt_entry +% @as(u64, @bitCast(reloc.addend)) -% dest_vaddr) >> 2); |
| | 1569 | elf.targetStore(dest_ptr, result); |
| | 1570 | }, |
| | 1571 | .sparc_h44 => { |
| | 1572 | const dest_ptr: *link.sparc.reloc.Imm22 = @ptrCast(@alignCast(dest_slice)); |
| | 1573 | var result = elf.targetLoad(dest_ptr); |
| | 1574 | result.imm22 = @truncate(target_value >> 22); |
| | 1575 | elf.targetStore(dest_ptr, result); |
| | 1576 | }, |
| | 1577 | .sparc_m44 => { |
| | 1578 | const dest_ptr: *link.sparc.reloc.Imm10 = @ptrCast(@alignCast(dest_slice)); |
| | 1579 | var result = elf.targetLoad(dest_ptr); |
| | 1580 | result.imm10 = @truncate(target_value >> 12); |
| | 1581 | elf.targetStore(dest_ptr, result); |
| | 1582 | }, |
| | 1583 | .sparc_l44 => { |
| | 1584 | const dest_ptr: *link.sparc.reloc.Imm13 = @ptrCast(@alignCast(dest_slice)); |
| | 1585 | var result = elf.targetLoad(dest_ptr); |
| | 1586 | result.imm13 = @as(u12, @truncate(target_value)); |
| | 1587 | elf.targetStore(dest_ptr, result); |
| | 1588 | }, |
| | 1589 | .sparc_ldo_hix22 => { |
| | 1590 | const dest_ptr: *link.sparc.reloc.Simm22 = @ptrCast(@alignCast(dest_slice)); |
| | 1591 | var result = elf.targetLoad(dest_ptr); |
| | 1592 | result.simm22 = @truncate(target_value >> 10); |
| | 1593 | elf.targetStore(dest_ptr, result); |
| | 1594 | }, |
| | 1595 | .sparc_ldo_lox10 => { |
| | 1596 | const dest_ptr: *link.sparc.reloc.Simm13 = @ptrCast(@alignCast(dest_slice)); |
| | 1597 | var result = elf.targetLoad(dest_ptr); |
| | 1598 | result.simm13 = @as(u10, @truncate(target_value)); |
| | 1599 | elf.targetStore(dest_ptr, result); |
| | 1600 | }, |
| | 1601 | .sparc_le_hix22 => { |
| | 1602 | const tls_phndx = elf.getNode(elf.ni.tls).segment; |
| | 1603 | const tls_size: u64 = switch (elf.phdrSlice()) { |
| | 1604 | inline else => |phdr| tls_size: { |
| | 1605 | assert(elf.targetLoad(&phdr[tls_phndx].type) == .TLS); |
| | 1606 | break :tls_size elf.targetLoad(&phdr[tls_phndx].memsz); |
| | 1607 | }, |
| | 1608 | }; |
| | 1609 | const dest_ptr: *link.sparc.reloc.Imm22 = @ptrCast(@alignCast(dest_slice)); |
| | 1610 | var result = elf.targetLoad(dest_ptr); |
| | 1611 | result.imm22 = @truncate(~(target_value -% tls_size) >> 10); |
| | 1612 | elf.targetStore(dest_ptr, result); |
| | 1613 | }, |
| | 1614 | .sparc_le_lox10 => { |
| | 1615 | const tls_phndx = elf.getNode(elf.ni.tls).segment; |
| | 1616 | const tls_size: u64 = switch (elf.phdrSlice()) { |
| | 1617 | inline else => |phdr| tls_size: { |
| | 1618 | assert(elf.targetLoad(&phdr[tls_phndx].type) == .TLS); |
| | 1619 | break :tls_size elf.targetLoad(&phdr[tls_phndx].memsz); |
| | 1620 | }, |
| | 1621 | }; |
| | 1622 | const dest_ptr: *link.sparc.reloc.Simm13 = @ptrCast(@alignCast(dest_slice)); |
| | 1623 | var result = elf.targetLoad(dest_ptr); |
| | 1624 | result.simm13 = @as(u13, 0b1110000000000) | @as(u10, @truncate(target_value -% tls_size)); |
| | 1625 | elf.targetStore(dest_ptr, result); |
| | 1626 | }, |
| 1350 | } | 1627 | } |
| 1351 | } | 1628 | } |
| 1352 | | 1629 | |
| ... | @@ -1448,10 +1725,7 @@ fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void { | ... | @@ -1448,10 +1725,7 @@ fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void { |
| 1448 | try elf.ensureNodeSize(elf.shndx.plt.get(elf).ni, plt_need_size); | 1725 | try elf.ensureNodeSize(elf.shndx.plt.get(elf).ni, plt_need_size); |
| 1449 | | 1726 | |
| 1450 | // Ensure the `.got.plt` section's node is big enough | 1727 | // Ensure the `.got.plt` section's node is big enough |
| 1451 | const got_plt_need_size: usize = switch (elf.identClass()) { | 1728 | const got_plt_need_size: usize = elf.targetPtrSize() * (3 + need_plt_capacity); |
| 1452 | .NONE, _ => unreachable, | | |
| 1453 | inline else => |class| @sizeOf(class.ElfN().Addr) * (3 + need_plt_capacity), | | |
| 1454 | }; | | |
| 1455 | try elf.ensureNodeSize(elf.shndx.got_plt.get(elf).ni, got_plt_need_size); | 1729 | try elf.ensureNodeSize(elf.shndx.got_plt.get(elf).ni, got_plt_need_size); |
| 1456 | | 1730 | |
| 1457 | // Ensure the `.plt.sec` section's node is big enough | 1731 | // Ensure the `.plt.sec` section's node is big enough |
| ... | @@ -1460,16 +1734,18 @@ fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void { | ... | @@ -1460,16 +1734,18 @@ fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void { |
| 1460 | }, | 1734 | }, |
| 1461 | .LOONGARCH => { | 1735 | .LOONGARCH => { |
| 1462 | // Ensure the `.plt` section's node is big enough | 1736 | // Ensure the `.plt` section's node is big enough |
| 1463 | const plt_need_size: usize = 32 + 16 * need_plt_capacity; | 1737 | const plt_need_size: usize = 16 * (2 + need_plt_capacity); |
| 1464 | try elf.ensureNodeSize(elf.shndx.plt.get(elf).ni, plt_need_size); | 1738 | try elf.ensureNodeSize(elf.shndx.plt.get(elf).ni, plt_need_size); |
| 1465 | | 1739 | |
| 1466 | // Ensure the `.got.plt` section's node is big enough | 1740 | // Ensure the `.got.plt` section's node is big enough |
| 1467 | const got_plt_need_size: usize = switch (elf.identClass()) { | 1741 | const got_plt_need_size: usize = elf.targetPtrSize() * (2 + need_plt_capacity); |
| 1468 | .NONE, _ => unreachable, | | |
| 1469 | inline else => |class| @sizeOf(class.ElfN().Addr) * (2 + need_plt_capacity), | | |
| 1470 | }; | | |
| 1471 | try elf.ensureNodeSize(elf.shndx.got_plt.get(elf).ni, got_plt_need_size); | 1742 | try elf.ensureNodeSize(elf.shndx.got_plt.get(elf).ni, got_plt_need_size); |
| 1472 | }, | 1743 | }, |
| | 1744 | .SPARCV9 => { |
| | 1745 | // Ensure the `.plt` section's node is big enough |
| | 1746 | const plt_need_size: usize = 32 * (4 + need_plt_capacity); |
| | 1747 | try elf.ensureNodeSize(elf.shndx.plt.get(elf).ni, plt_need_size); |
| | 1748 | }, |
| 1473 | } | 1749 | } |
| 1474 | } | 1750 | } |
| 1475 | /// Given an index into the PLT, returns whether that PLT entry is dead, meaning it may be reused at | 1751 | /// Given an index into the PLT, returns whether that PLT entry is dead, meaning it may be reused at |
| ... | @@ -2090,23 +2366,17 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void | ... | @@ -2090,23 +2366,17 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void |
| 2090 | .addend = 0, | 2366 | .addend = 0, |
| 2091 | })); | 2367 | })); |
| 2092 | | 2368 | |
| 2093 | const reserved_got_plt_entries: u32 = switch (elf.ehdrField(.machine)) { | 2369 | // Note that some architectures don't have .got.plt (e.g. SPARC), and so |
| | 2370 | // these values actually refer to .plt. |
| | 2371 | const got_plt_section, const got_plt_offset = switch (elf.ehdrField(.machine)) { |
| 2094 | else => |machine| @panic(@tagName(machine)), | 2372 | else => |machine| @panic(@tagName(machine)), |
| 2095 | .X86_64 => 3, | 2373 | .LOONGARCH => .{ elf.shndx.got_plt, elf.targetPtrSize() * (2 + plt_index) }, |
| 2096 | .LOONGARCH => 2, | 2374 | .SPARCV9 => .{ elf.shndx.plt, 32 * (4 + plt_index) }, |
| | 2375 | .X86_64 => .{ elf.shndx.got_plt, elf.targetPtrSize() * (3 + plt_index) }, |
| 2097 | }; | 2376 | }; |
| 2098 | | 2377 | |
| 2099 | // Now that we know the index, we can set the relocation's offset. | 2378 | // Now that we know the index, we can set the relocation's offset. |
| 2100 | const got_plt_addr = switch (elf.shdrPtr(elf.shndx.got_plt)) { | 2379 | elf.shndx.rela_plt.relaSetOffset(elf, @enumFromInt(plt_index), got_plt_section.vaddr(elf) + got_plt_offset); |
| 2101 | inline else => |shdr, class| got_plt_addr: { | | |
| 2102 | const ent_size = @sizeOf(class.ElfN().Addr); | | |
| 2103 | assert(elf.targetLoad(&shdr.entsize) == ent_size); | | |
| 2104 | const offset = ent_size * @as(u64, reserved_got_plt_entries + plt_index); | | |
| 2105 | assert(offset <= elf.targetLoad(&shdr.size)); | | |
| 2106 | break :got_plt_addr elf.targetLoad(&shdr.addr) + offset; | | |
| 2107 | }, | | |
| 2108 | }; | | |
| 2109 | elf.shndx.rela_plt.relaSetOffset(elf, @enumFromInt(plt_index), got_plt_addr); | | |
| 2110 | | 2380 | |
| 2111 | if (plt_index < elf.plt.count()) { | 2381 | if (plt_index < elf.plt.count()) { |
| 2112 | // We reused a free entry, so we're already done! | 2382 | // We reused a free entry, so we're already done! |
| ... | @@ -2148,13 +2418,11 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void | ... | @@ -2148,13 +2418,11 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void |
| 2148 | const got_plt_ni = elf.shndx.got_plt.get(elf).ni; | 2418 | const got_plt_ni = elf.shndx.got_plt.get(elf).ni; |
| 2149 | switch (elf.shdrPtr(elf.shndx.got_plt)) { | 2419 | switch (elf.shdrPtr(elf.shndx.got_plt)) { |
| 2150 | inline else => |shdr, class| { | 2420 | inline else => |shdr, class| { |
| 2151 | const ent_size = @sizeOf(class.ElfN().Addr); | 2421 | assert(elf.targetLoad(&shdr.size) == got_plt_offset); |
| 2152 | const old_size = ent_size * (3 + plt_index); | 2422 | elf.targetStore(&shdr.size, got_plt_offset + @sizeOf(class.ElfN().Addr)); |
| 2153 | assert(elf.targetLoad(&shdr.size) == old_size); | | |
| 2154 | elf.targetStore(&shdr.size, old_size + ent_size); | | |
| 2155 | std.mem.writeInt( | 2423 | std.mem.writeInt( |
| 2156 | class.ElfN().Addr, | 2424 | class.ElfN().Addr, |
| 2157 | got_plt_ni.slice(&elf.mf)[old_size..][0..ent_size], | 2425 | got_plt_ni.slice(&elf.mf)[got_plt_offset..][0..@sizeOf(class.ElfN().Addr)], |
| 2158 | @intCast(plt_addr), | 2426 | @intCast(plt_addr), |
| 2159 | target_endian, | 2427 | target_endian, |
| 2160 | ); | 2428 | ); |
| ... | @@ -2176,7 +2444,7 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void | ... | @@ -2176,7 +2444,7 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void |
| 2176 | i32, | 2444 | i32, |
| 2177 | plt_sec_slice[6..][0..4], | 2445 | plt_sec_slice[6..][0..4], |
| 2178 | @intCast(@as(i64, @bitCast( | 2446 | @intCast(@as(i64, @bitCast( |
| 2179 | got_plt_addr -% (elf.targetLoad(&shdr.addr) + old_size + 10), | 2447 | (got_plt_section.vaddr(elf) + got_plt_offset) -% (elf.targetLoad(&shdr.addr) + old_size + 10), |
| 2180 | ))), | 2448 | ))), |
| 2181 | target_endian, | 2449 | target_endian, |
| 2182 | ); | 2450 | ); |
| ... | @@ -2212,26 +2480,54 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void | ... | @@ -2212,26 +2480,54 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void |
| 2212 | const got_plt_ni = elf.shndx.got_plt.get(elf).ni; | 2480 | const got_plt_ni = elf.shndx.got_plt.get(elf).ni; |
| 2213 | switch (elf.shdrPtr(elf.shndx.got_plt)) { | 2481 | switch (elf.shdrPtr(elf.shndx.got_plt)) { |
| 2214 | inline else => |shdr, class| { | 2482 | inline else => |shdr, class| { |
| 2215 | const ent_size = @sizeOf(class.ElfN().Addr); | 2483 | assert(elf.targetLoad(&shdr.size) == got_plt_offset); |
| 2216 | const old_size = ent_size * (2 + plt_index); | 2484 | elf.targetStore(&shdr.size, got_plt_offset + @sizeOf(class.ElfN().Addr)); |
| 2217 | assert(elf.targetLoad(&shdr.size) == old_size); | | |
| 2218 | elf.targetStore(&shdr.size, old_size + ent_size); | | |
| 2219 | std.mem.writeInt( | 2485 | std.mem.writeInt( |
| 2220 | class.ElfN().Addr, | 2486 | class.ElfN().Addr, |
| 2221 | got_plt_ni.slice(&elf.mf)[old_size..][0..ent_size], | 2487 | got_plt_ni.slice(&elf.mf)[got_plt_offset..][0..@sizeOf(class.ElfN().Addr)], |
| 2222 | @intCast(plt_addr), | 2488 | @intCast(plt_addr), |
| 2223 | target_endian, | 2489 | target_endian, |
| 2224 | ); | 2490 | ); |
| 2225 | assert(got_plt_addr == (elf.targetLoad(&shdr.addr) + old_size)); | | |
| 2226 | }, | 2491 | }, |
| 2227 | } | 2492 | } |
| 2228 | | 2493 | |
| 2229 | // relocate the PLT entry to point to the .GOT.PLT entry | 2494 | // relocate the PLT entry to point to the .GOT.PLT entry |
| 2230 | const got_plt_abs: u64 = @as(u64, got_plt_addr); | 2495 | const got_plt_abs = got_plt_section.vaddr(elf) + got_plt_offset; |
| 2231 | // TODO: handle overflow gracefully | 2496 | // TODO: handle overflow gracefully |
| 2232 | link.loongarch.writeJ20(plt_slice[0..4], link.loongarch.toPcalaHi20(got_plt_abs, plt_addr)); | 2497 | link.loongarch.writeJ20(plt_slice[0..4], link.loongarch.toPcalaHi20(got_plt_abs, plt_addr)); |
| 2233 | link.loongarch.writeK12(plt_slice[4..8], @truncate(got_plt_abs)); | 2498 | link.loongarch.writeK12(plt_slice[4..8], @truncate(got_plt_abs)); |
| 2234 | }, | 2499 | }, |
| | 2500 | .SPARCV9 => { |
| | 2501 | // add a .PLT entry, writing the template |
| | 2502 | const plt_ni = elf.shndx.plt.get(elf).ni; |
| | 2503 | switch (elf.shdrPtr(elf.shndx.plt)) { |
| | 2504 | inline else => |shdr| { |
| | 2505 | assert(elf.targetLoad(&shdr.size) == got_plt_offset); |
| | 2506 | elf.targetStore(&shdr.size, got_plt_offset + 32); |
| | 2507 | const plt_slice: []u32 = @ptrCast(@alignCast(plt_ni.slice(&elf.mf)[got_plt_offset..][0..32])); |
| | 2508 | // sethi (. - .plt[0]), %g1 |
| | 2509 | // ba,a %xcc, .plt[1] |
| | 2510 | // nop |
| | 2511 | // nop |
| | 2512 | // nop |
| | 2513 | // nop |
| | 2514 | // nop |
| | 2515 | // nop |
| | 2516 | @memcpy(plt_slice, &([2]u32{ |
| | 2517 | // TODO: handle overflow gracefully |
| | 2518 | @bitCast(link.sparc.reloc.Imm22{ |
| | 2519 | .imm22 = @truncate(got_plt_offset), |
| | 2520 | .b22_31 = 0b0000000011, |
| | 2521 | }), |
| | 2522 | @bitCast(link.sparc.reloc.Disp19{ |
| | 2523 | .disp19 = @truncate((got_plt_offset + 4 - 32) >> 2), |
| | 2524 | .b19_31 = 0b1100001101000, |
| | 2525 | }), |
| | 2526 | } ++ @as([6]u32, @splat(0x01000000)))); |
| | 2527 | if (elf.targetEndian() != native_endian) std.mem.byteSwapAllElements(u32, plt_slice); |
| | 2528 | }, |
| | 2529 | } |
| | 2530 | }, |
| 2235 | } | 2531 | } |
| 2236 | } | 2532 | } |
| 2237 | | 2533 | |
| ... | @@ -2622,12 +2918,12 @@ pub const ExternSymbolOpts = struct { | ... | @@ -2622,12 +2918,12 @@ pub const ExternSymbolOpts = struct { |
| 2622 | }; | 2918 | }; |
| 2623 | pub fn externSymbol(elf: *Elf, opts: ExternSymbolOpts) link.Error!link.File.SymbolId { | 2919 | pub fn externSymbol(elf: *Elf, opts: ExternSymbolOpts) link.Error!link.File.SymbolId { |
| 2624 | const diags = &elf.base.comp.link_diags; | 2920 | const diags = &elf.base.comp.link_diags; |
| 2625 | return elf.externSymbolInner(opts) catch |err| switch (err) { | 2921 | return (elf.externSymbolInner(opts) catch |err| switch (err) { |
| 2626 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | 2922 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), |
| 2627 | else => |e| return e, | 2923 | else => |e| return e, |
| 2628 | }; | 2924 | }).toTypeErased(); |
| 2629 | } | 2925 | } |
| 2630 | fn externSymbolInner(elf: *Elf, opts: ExternSymbolOpts) Error!link.File.SymbolId { | 2926 | fn externSymbolInner(elf: *Elf, opts: ExternSymbolOpts) Error!Symbol.Id { |
| 2631 | try elf.ensureUnusedSymbolCapacity(1, .maybe_global); | 2927 | try elf.ensureUnusedSymbolCapacity(1, .maybe_global); |
| 2632 | const symbol = elf.addGlobalSymbolAssumeCapacity(.{ | 2928 | const symbol = elf.addGlobalSymbolAssumeCapacity(.{ |
| 2633 | .node = .none, | 2929 | .node = .none, |
| ... | @@ -2651,7 +2947,7 @@ fn externSymbolInner(elf: *Elf, opts: ExternSymbolOpts) Error!link.File.SymbolId | ... | @@ -2651,7 +2947,7 @@ fn externSymbolInner(elf: *Elf, opts: ExternSymbolOpts) Error!link.File.SymbolId |
| 2651 | }) catch |err| switch (err) { | 2947 | }) catch |err| switch (err) { |
| 2652 | error.MultipleDefinitions => unreachable, // shndx is undef | 2948 | error.MultipleDefinitions => unreachable, // shndx is undef |
| 2653 | }; | 2949 | }; |
| 2654 | return symbol.toTypeErased(); | 2950 | return symbol; |
| 2655 | } | 2951 | } |
| 2656 | pub fn addReloc( | 2952 | pub fn addReloc( |
| 2657 | elf: *Elf, | 2953 | elf: *Elf, |
| ... | @@ -3084,11 +3380,12 @@ fn initHeaders( | ... | @@ -3084,11 +3380,12 @@ fn initHeaders( |
| 3084 | .@"64" => .@"8", | 3380 | .@"64" => .@"8", |
| 3085 | }; | 3381 | }; |
| 3086 | | 3382 | |
| 3087 | const init_plt_size: std.elf.Xword, const plt_align: std.mem.Alignment, const plt_sec = | 3383 | const init_plt_size: std.elf.Xword, const plt_align: std.mem.Alignment, const got_plt, const plt_sec = |
| 3088 | switch (machine) { | 3384 | switch (machine) { |
| 3089 | else => @panic(@tagName(machine)), | 3385 | else => @panic(@tagName(machine)), |
| 3090 | .X86_64 => .{ 16, .@"16", true }, | 3386 | .LOONGARCH => .{ 16 * 2, .@"4", true, false }, |
| 3091 | .LOONGARCH => .{ 32, .@"4", false }, | 3387 | .SPARCV9 => .{ 32 * 4, .fromByteUnits(256), false, false }, |
| | 3388 | .X86_64 => .{ 16, .@"16", true, true }, |
| 3092 | }; | 3389 | }; |
| 3093 | | 3390 | |
| 3094 | const shnum: u32 = shnum: { | 3391 | const shnum: u32 = shnum: { |
| ... | @@ -3111,7 +3408,7 @@ fn initHeaders( | ... | @@ -3111,7 +3408,7 @@ fn initHeaders( |
| 3111 | } | 3408 | } |
| 3112 | if (@"type" != .REL) { | 3409 | if (@"type" != .REL) { |
| 3113 | shnum += 1; // .got | 3410 | shnum += 1; // .got |
| 3114 | shnum += 1; // .got.plt | 3411 | shnum += @intFromBool(got_plt); // .got.plt |
| 3115 | shnum += 1; // .plt | 3412 | shnum += 1; // .plt |
| 3116 | shnum += @intFromBool(plt_sec); // .plt_sec | 3413 | shnum += @intFromBool(plt_sec); // .plt_sec |
| 3117 | } | 3414 | } |
| ... | @@ -3212,7 +3509,6 @@ fn initHeaders( | ... | @@ -3212,7 +3509,6 @@ fn initHeaders( |
| 3212 | ehdr.phoff = 0; | 3509 | ehdr.phoff = 0; |
| 3213 | ehdr.shoff = 0; | 3510 | ehdr.shoff = 0; |
| 3214 | ehdr.flags = switch (machine) { | 3511 | ehdr.flags = switch (machine) { |
| 3215 | .X86_64 => 0, | | |
| 3216 | .LOONGARCH => e_flags: { | 3512 | .LOONGARCH => e_flags: { |
| 3217 | const target_cpu = &elf.base.comp.getTarget().cpu; | 3513 | const target_cpu = &elf.base.comp.getTarget().cpu; |
| 3218 | const e_flags: std.elf.loongarch.EFlags = .{ | 3514 | const e_flags: std.elf.loongarch.EFlags = .{ |
| ... | @@ -3227,6 +3523,20 @@ fn initHeaders( | ... | @@ -3227,6 +3523,20 @@ fn initHeaders( |
| 3227 | }; | 3523 | }; |
| 3228 | break :e_flags @bitCast(e_flags); | 3524 | break :e_flags @bitCast(e_flags); |
| 3229 | }, | 3525 | }, |
| | 3526 | .SPARCV9 => e_flags: { |
| | 3527 | const e_flags: std.elf.sparc.EFlags = .{ |
| | 3528 | .mm = .rmo, |
| | 3529 | .ext = .{ |
| | 3530 | .@"32plus" = false, |
| | 3531 | .sun_us1 = false, |
| | 3532 | .hal_r1 = false, |
| | 3533 | .sun_us3 = false, |
| | 3534 | .le_data = false, |
| | 3535 | }, |
| | 3536 | }; |
| | 3537 | break :e_flags @bitCast(e_flags); |
| | 3538 | }, |
| | 3539 | .X86_64 => 0, |
| 3230 | else => @panic(@tagName(machine)), | 3540 | else => @panic(@tagName(machine)), |
| 3231 | }; | 3541 | }; |
| 3232 | ehdr.ehsize = @sizeOf(ElfN.Ehdr); | 3542 | ehdr.ehsize = @sizeOf(ElfN.Ehdr); |
| ... | @@ -3247,6 +3557,31 @@ fn initHeaders( | ... | @@ -3247,6 +3557,31 @@ fn initHeaders( |
| 3247 | })); | 3557 | })); |
| 3248 | elf.nodes.appendAssumeCapacity(.shdr); | 3558 | elf.nodes.appendAssumeCapacity(.shdr); |
| 3249 | | 3559 | |
| | 3560 | const page_align: std.mem.Alignment = .fromByteUnits(switch (machine) { |
| | 3561 | .BPF, |
| | 3562 | .SPARCV9, |
| | 3563 | => 0x100000, |
| | 3564 | .AARCH64, |
| | 3565 | .AMDGPU, |
| | 3566 | .QDSP6, |
| | 3567 | .MIPS, |
| | 3568 | .PPC, |
| | 3569 | .PPC64, |
| | 3570 | .SPARC, |
| | 3571 | .SPARC32PLUS, |
| | 3572 | => 0x10000, |
| | 3573 | .LOONGARCH, |
| | 3574 | => 0x4000, |
| | 3575 | .ARC_COMPACT2, |
| | 3576 | .@"68K", |
| | 3577 | => 0x2000, |
| | 3578 | .MSP430, |
| | 3579 | => 0x4, |
| | 3580 | .AVR, |
| | 3581 | => 0x1, |
| | 3582 | else => 0x1000, |
| | 3583 | }); |
| | 3584 | |
| 3250 | var ph_vaddr: u32 = if (@"type" != .REL) ph_vaddr: { | 3585 | var ph_vaddr: u32 = if (@"type" != .REL) ph_vaddr: { |
| 3251 | assert(elf.ni.rodata == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{ | 3586 | assert(elf.ni.rodata == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{ |
| 3252 | .alignment = elf.mf.flags.block_size, | 3587 | .alignment = elf.mf.flags.block_size, |
| ... | @@ -3299,8 +3634,8 @@ fn initHeaders( | ... | @@ -3299,8 +3634,8 @@ fn initHeaders( |
| 3299 | .@"386" => 0x400000, | 3634 | .@"386" => 0x400000, |
| 3300 | .AARCH64, .X86_64 => 0x200000, | 3635 | .AARCH64, .X86_64 => 0x200000, |
| 3301 | .PPC, .PPC64 => 0x10000000, | 3636 | .PPC, .PPC64 => 0x10000000, |
| 3302 | .S390, .S390_OLD => 0x1000000, | 3637 | .S390 => 0x1000000, |
| 3303 | .OLD_SPARCV9, .SPARCV9 => 0x100000, | 3638 | .SPARCV9 => 0x100000, |
| 3304 | else => 0x10000, | 3639 | else => 0x10000, |
| 3305 | }, | 3640 | }, |
| 3306 | }; | 3641 | }; |
| ... | @@ -3351,7 +3686,7 @@ fn initHeaders( | ... | @@ -3351,7 +3686,7 @@ fn initHeaders( |
| 3351 | .filesz = @intCast(rodata_size), | 3686 | .filesz = @intCast(rodata_size), |
| 3352 | .memsz = @intCast(rodata_size), | 3687 | .memsz = @intCast(rodata_size), |
| 3353 | .flags = .{ .R = true }, | 3688 | .flags = .{ .R = true }, |
| 3354 | .@"align" = @intCast(elf.ni.rodata.alignment(&elf.mf).toByteUnits()), | 3689 | .@"align" = @intCast(elf.ni.rodata.alignment(&elf.mf).max(page_align).toByteUnits()), |
| 3355 | }; | 3690 | }; |
| 3356 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_rodata); | 3691 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_rodata); |
| 3357 | ph_vaddr += @intCast(rodata_size); | 3692 | ph_vaddr += @intCast(rodata_size); |
| ... | @@ -3366,7 +3701,7 @@ fn initHeaders( | ... | @@ -3366,7 +3701,7 @@ fn initHeaders( |
| 3366 | .filesz = @intCast(text_size), | 3701 | .filesz = @intCast(text_size), |
| 3367 | .memsz = @intCast(text_size), | 3702 | .memsz = @intCast(text_size), |
| 3368 | .flags = .{ .R = true, .X = true }, | 3703 | .flags = .{ .R = true, .X = true }, |
| 3369 | .@"align" = @intCast(elf.ni.text.alignment(&elf.mf).toByteUnits()), | 3704 | .@"align" = @intCast(elf.ni.text.alignment(&elf.mf).max(page_align).toByteUnits()), |
| 3370 | }; | 3705 | }; |
| 3371 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_text); | 3706 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_text); |
| 3372 | ph_vaddr += @intCast(text_size); | 3707 | ph_vaddr += @intCast(text_size); |
| ... | @@ -3381,7 +3716,7 @@ fn initHeaders( | ... | @@ -3381,7 +3716,7 @@ fn initHeaders( |
| 3381 | .filesz = @intCast(data_size), | 3716 | .filesz = @intCast(data_size), |
| 3382 | .memsz = @intCast(data_size), | 3717 | .memsz = @intCast(data_size), |
| 3383 | .flags = .{ .R = true, .W = true }, | 3718 | .flags = .{ .R = true, .W = true }, |
| 3384 | .@"align" = @intCast(elf.ni.data.alignment(&elf.mf).toByteUnits()), | 3719 | .@"align" = @intCast(elf.ni.data.alignment(&elf.mf).max(page_align).toByteUnits()), |
| 3385 | }; | 3720 | }; |
| 3386 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_data); | 3721 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_data); |
| 3387 | ph_vaddr += @intCast(data_size); | 3722 | ph_vaddr += @intCast(data_size); |
| ... | @@ -3536,14 +3871,16 @@ fn initHeaders( | ... | @@ -3536,14 +3871,16 @@ fn initHeaders( |
| 3536 | // Reserve space for the reserved words, populated later. | 3871 | // Reserve space for the reserved words, populated later. |
| 3537 | .size = switch (machine) { | 3872 | .size = switch (machine) { |
| 3538 | else => @panic(@tagName(machine)), | 3873 | else => @panic(@tagName(machine)), |
| 3539 | .X86_64 => 3 * 8, | 3874 | .X86_64 => 3 * elf.targetPtrSize(), |
| 3540 | .LOONGARCH => if (elf.identClass() == .@"64") 8 else 4, | 3875 | .LOONGARCH, |
| | 3876 | .SPARCV9, |
| | 3877 | => elf.targetPtrSize(), |
| 3541 | }, | 3878 | }, |
| 3542 | .flags = .{ .WRITE = true, .ALLOC = true }, | 3879 | .flags = .{ .WRITE = true, .ALLOC = true }, |
| 3543 | .addralign = addr_align, | 3880 | .addralign = addr_align, |
| 3544 | .entsize = @intCast(addr_align.toByteUnits()), | 3881 | .entsize = @intCast(addr_align.toByteUnits()), |
| 3545 | }); | 3882 | }); |
| 3546 | elf.shndx.got_plt = try elf.addSection( | 3883 | if (got_plt) elf.shndx.got_plt = try elf.addSection( |
| 3547 | if (elf.options.z_now) elf.ni.data_rel_ro else elf.ni.data, | 3884 | if (elf.options.z_now) elf.ni.data_rel_ro else elf.ni.data, |
| 3548 | .{ | 3885 | .{ |
| 3549 | .name = ".got.plt", | 3886 | .name = ".got.plt", |
| ... | @@ -3553,7 +3890,7 @@ fn initHeaders( | ... | @@ -3553,7 +3890,7 @@ fn initHeaders( |
| 3553 | else => @panic(@tagName(machine)), | 3890 | else => @panic(@tagName(machine)), |
| 3554 | .@"386" => 3 * 4, | 3891 | .@"386" => 3 * 4, |
| 3555 | .X86_64 => 3 * 8, | 3892 | .X86_64 => 3 * 8, |
| 3556 | .LOONGARCH => if (elf.identClass() == .@"64") 2 * 8 else 2 * 4, | 3893 | .LOONGARCH => 2 * elf.targetPtrSize(), |
| 3557 | }, | 3894 | }, |
| 3558 | .addralign = addr_align, | 3895 | .addralign = addr_align, |
| 3559 | .entsize = @intCast(addr_align.toByteUnits()), | 3896 | .entsize = @intCast(addr_align.toByteUnits()), |
| ... | @@ -3562,7 +3899,14 @@ fn initHeaders( | ... | @@ -3562,7 +3899,14 @@ fn initHeaders( |
| 3562 | elf.shndx.plt = try elf.addSection(elf.ni.text, .{ | 3899 | elf.shndx.plt = try elf.addSection(elf.ni.text, .{ |
| 3563 | .name = ".plt", | 3900 | .name = ".plt", |
| 3564 | .type = .PROGBITS, | 3901 | .type = .PROGBITS, |
| 3565 | .flags = .{ .ALLOC = true, .EXECINSTR = true }, | 3902 | .flags = .{ |
| | 3903 | .ALLOC = true, |
| | 3904 | .EXECINSTR = true, |
| | 3905 | .WRITE = switch (machine) { |
| | 3906 | .SPARCV9 => true, |
| | 3907 | else => false, |
| | 3908 | }, |
| | 3909 | }, |
| 3566 | .size = init_plt_size, | 3910 | .size = init_plt_size, |
| 3567 | .addralign = plt_align, | 3911 | .addralign = plt_align, |
| 3568 | .node_align = elf.mf.flags.block_size, | 3912 | .node_align = elf.mf.flags.block_size, |
| ... | @@ -3661,7 +4005,7 @@ fn initHeaders( | ... | @@ -3661,7 +4005,7 @@ fn initHeaders( |
| 3661 | .type = .RELA, | 4005 | .type = .RELA, |
| 3662 | .flags = .{ .ALLOC = true, .INFO_LINK = true }, | 4006 | .flags = .{ .ALLOC = true, .INFO_LINK = true }, |
| 3663 | .link = elf.shndx.dynsym.toSection().?, | 4007 | .link = elf.shndx.dynsym.toSection().?, |
| 3664 | .info = elf.shndx.got_plt.toSection().?, | 4008 | .info = (if (got_plt) elf.shndx.got_plt else elf.shndx.plt).toSection().?, |
| 3665 | .addralign = addr_align, | 4009 | .addralign = addr_align, |
| 3666 | .entsize = rela_size, | 4010 | .entsize = rela_size, |
| 3667 | .node_align = elf.mf.flags.block_size, | 4011 | .node_align = elf.mf.flags.block_size, |
| ... | @@ -3729,10 +4073,11 @@ fn initHeaders( | ... | @@ -3729,10 +4073,11 @@ fn initHeaders( |
| 3729 | }); | 4073 | }); |
| 3730 | elf.plt_first_symbol_reloc = @enumFromInt(elf.symbol_relocs.items.len); | 4074 | elf.plt_first_symbol_reloc = @enumFromInt(elf.symbol_relocs.items.len); |
| 3731 | try elf.ensureUnusedRelocCapacity(plt_ni, 3); | 4075 | try elf.ensureUnusedRelocCapacity(plt_ni, 3); |
| 3732 | try elf.addSymbolRelocAssumeCapacity(plt_ni, 0, got_plt_sym, 0, .rel32_hi20); | 4076 | try elf.addSymbolRelocAssumeCapacity(plt_ni, 0, got_plt_sym, 0, .larch_rel32_hi20); |
| 3733 | try elf.addSymbolRelocAssumeCapacity(plt_ni, 8, got_plt_sym, 0, .abs32_lo12); | 4077 | try elf.addSymbolRelocAssumeCapacity(plt_ni, 8, got_plt_sym, 0, .larch_abs32_lo12); |
| 3734 | try elf.addSymbolRelocAssumeCapacity(plt_ni, 16, got_plt_sym, 0, .abs32_lo12); | 4078 | try elf.addSymbolRelocAssumeCapacity(plt_ni, 16, got_plt_sym, 0, .larch_abs32_lo12); |
| 3735 | }, | 4079 | }, |
| | 4080 | .SPARCV9 => {}, |
| 3736 | } | 4081 | } |
| 3737 | } | 4082 | } |
| 3738 | if (comp.config.any_non_single_threaded) { | 4083 | if (comp.config.any_non_single_threaded) { |
| ... | @@ -3757,7 +4102,9 @@ fn initHeaders( | ... | @@ -3757,7 +4102,9 @@ fn initHeaders( |
| 3757 | elf.got.putAssumeCapacityNoClobber(.{ .reserved = 1 }, .none); | 4102 | elf.got.putAssumeCapacityNoClobber(.{ .reserved = 1 }, .none); |
| 3758 | elf.got.putAssumeCapacityNoClobber(.{ .reserved = 2 }, .none); | 4103 | elf.got.putAssumeCapacityNoClobber(.{ .reserved = 2 }, .none); |
| 3759 | }, | 4104 | }, |
| 3760 | .LOONGARCH => { | 4105 | .LOONGARCH, |
| | 4106 | .SPARCV9, |
| | 4107 | => { |
| 3761 | try elf.got.ensureUnusedCapacity(gpa, 1); | 4108 | try elf.got.ensureUnusedCapacity(gpa, 1); |
| 3762 | elf.got.putAssumeCapacityNoClobber(switch (have_dynamic_section) { | 4109 | elf.got.putAssumeCapacityNoClobber(switch (have_dynamic_section) { |
| 3763 | true => .{ .symbol = .local(elf.shndx.dynamic.get(elf).lsi) }, | 4110 | true => .{ .symbol = .local(elf.shndx.dynamic.get(elf).lsi) }, |
| ... | @@ -4075,35 +4422,38 @@ fn identData(elf: *const Elf) std.elf.DATA { | ... | @@ -4075,35 +4422,38 @@ fn identData(elf: *const Elf) std.elf.DATA { |
| 4075 | return @enumFromInt(elf.mf.memory_map.memory[std.elf.EI.DATA]); | 4422 | return @enumFromInt(elf.mf.memory_map.memory[std.elf.EI.DATA]); |
| 4076 | } | 4423 | } |
| 4077 | | 4424 | |
| | 4425 | fn targetPtrSize(elf: *const Elf) u32 { |
| | 4426 | return elf.identClass().size(); |
| | 4427 | } |
| 4078 | fn targetEndian(elf: *const Elf) std.lang.Endian { | 4428 | fn targetEndian(elf: *const Elf) std.lang.Endian { |
| 4079 | return switch (elf.identData()) { | 4429 | return elf.identData().endian(); |
| 4080 | .NONE, _ => unreachable, | | |
| 4081 | .@"2LSB" => .little, | | |
| 4082 | .@"2MSB" => .big, | | |
| 4083 | }; | | |
| 4084 | } | 4430 | } |
| 4085 | fn targetLoad(elf: *const Elf, ptr: anytype) @typeInfo(@TypeOf(ptr)).pointer.child { | 4431 | fn targetLoad(elf: *const Elf, ptr: anytype) @typeInfo(@TypeOf(ptr)).pointer.child { |
| 4086 | const Child = @typeInfo(@TypeOf(ptr)).pointer.child; | 4432 | const pointer_ty = @typeInfo(@TypeOf(ptr)).pointer; |
| | 4433 | const Child = pointer_ty.child; |
| | 4434 | const alignment = pointer_ty.attrs.@"align" orelse @alignOf(Child); |
| 4087 | return switch (@typeInfo(Child)) { | 4435 | return switch (@typeInfo(Child)) { |
| 4088 | else => @compileError(@typeName(Child)), | 4436 | else => @compileError(@typeName(Child)), |
| 4089 | .int => std.mem.toNative(Child, ptr.*, elf.targetEndian()), | 4437 | .int => std.mem.toNative(Child, ptr.*, elf.targetEndian()), |
| 4090 | .@"enum" => |@"enum"| @enumFromInt(elf.targetLoad(@as(*@"enum".tag_type, @ptrCast(ptr)))), | 4438 | .@"enum" => |@"enum"| @enumFromInt(elf.targetLoad(@as(*align(alignment) @"enum".tag_type, @ptrCast(ptr)))), |
| 4091 | .@"struct" => |@"struct"| @bitCast( | 4439 | .@"struct" => |@"struct"| @bitCast( |
| 4092 | elf.targetLoad(@as(*@"struct".backing_integer.?, @ptrCast(ptr))), | 4440 | elf.targetLoad(@as(*align(alignment) @"struct".backing_integer.?, @ptrCast(ptr))), |
| 4093 | ), | 4441 | ), |
| 4094 | }; | 4442 | }; |
| 4095 | } | 4443 | } |
| 4096 | fn targetStore(elf: *const Elf, ptr: anytype, val: @typeInfo(@TypeOf(ptr)).pointer.child) void { | 4444 | fn targetStore(elf: *const Elf, ptr: anytype, val: @typeInfo(@TypeOf(ptr)).pointer.child) void { |
| 4097 | const Child = @typeInfo(@TypeOf(ptr)).pointer.child; | 4445 | const pointer_ty = @typeInfo(@TypeOf(ptr)).pointer; |
| | 4446 | const Child = pointer_ty.child; |
| | 4447 | const alignment = pointer_ty.attrs.@"align" orelse @alignOf(Child); |
| 4098 | return switch (@typeInfo(Child)) { | 4448 | return switch (@typeInfo(Child)) { |
| 4099 | else => @compileError(@typeName(Child)), | 4449 | else => @compileError(@typeName(Child)), |
| 4100 | .int => ptr.* = std.mem.nativeTo(Child, val, elf.targetEndian()), | 4450 | .int => ptr.* = std.mem.nativeTo(Child, val, elf.targetEndian()), |
| 4101 | .@"enum" => |@"enum"| elf.targetStore( | 4451 | .@"enum" => |@"enum"| elf.targetStore( |
| 4102 | @as(*@"enum".tag_type, @ptrCast(ptr)), | 4452 | @as(*align(alignment) @"enum".tag_type, @ptrCast(ptr)), |
| 4103 | @intFromEnum(val), | 4453 | @intFromEnum(val), |
| 4104 | ), | 4454 | ), |
| 4105 | .@"struct" => |@"struct"| elf.targetStore( | 4455 | .@"struct" => |@"struct"| elf.targetStore( |
| 4106 | @as(*@"struct".backing_integer.?, @ptrCast(ptr)), | 4456 | @as(*align(alignment) @"struct".backing_integer.?, @ptrCast(ptr)), |
| 4107 | @bitCast(val), | 4457 | @bitCast(val), |
| 4108 | ), | 4458 | ), |
| 4109 | }; | 4459 | }; |
| ... | @@ -5433,6 +5783,11 @@ fn prelinkInner(elf: *Elf) Error!void { | ... | @@ -5433,6 +5783,11 @@ fn prelinkInner(elf: *Elf) Error!void { |
| 5433 | }; | 5783 | }; |
| 5434 | } | 5784 | } |
| 5435 | | 5785 | |
| | 5786 | const got_plt = switch (elf.ehdrField(.machine)) { |
| | 5787 | .SPARCV9 => false, |
| | 5788 | else => true, |
| | 5789 | }; |
| | 5790 | |
| 5436 | if (elf.shndx.dynamic != .UNDEF) switch (elf.identClass()) { | 5791 | if (elf.shndx.dynamic != .UNDEF) switch (elf.identClass()) { |
| 5437 | .NONE, _ => unreachable, | 5792 | .NONE, _ => unreachable, |
| 5438 | inline else => |ct_class| { | 5793 | inline else => |ct_class| { |
| ... | @@ -5616,7 +5971,7 @@ fn prelinkInner(elf: *Elf) Error!void { | ... | @@ -5616,7 +5971,7 @@ fn prelinkInner(elf: *Elf) Error!void { |
| 5616 | if (dynamic_indices.pltgot) |index| try elf.addSymbolRelocAssumeCapacity( | 5971 | if (dynamic_indices.pltgot) |index| try elf.addSymbolRelocAssumeCapacity( |
| 5617 | dynamic_ni, | 5972 | dynamic_ni, |
| 5618 | @sizeOf(ElfN.Addr) * (2 * index + 1), | 5973 | @sizeOf(ElfN.Addr) * (2 * index + 1), |
| 5619 | .local(elf.shndx.got_plt.get(elf).lsi), | 5974 | .local((if (got_plt) elf.shndx.got_plt else elf.shndx.plt).get(elf).lsi), |
| 5620 | 0, | 5975 | 0, |
| 5621 | dsorel, | 5976 | dsorel, |
| 5622 | ); | 5977 | ); |
| ... | @@ -5938,33 +6293,141 @@ fn addRelocAssumeCapacity( | ... | @@ -5938,33 +6293,141 @@ fn addRelocAssumeCapacity( |
| 5938 | .@"64_PCREL" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel64), | 6293 | .@"64_PCREL" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel64), |
| 5939 | .@"32_PCREL" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel32), | 6294 | .@"32_PCREL" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel32), |
| 5940 | | 6295 | |
| 5941 | .PCALA_LO12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs32_lo12), | 6296 | .PCALA_LO12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_abs32_lo12), |
| 5942 | .PCALA_HI20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel32_hi20), | 6297 | .PCALA_HI20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_rel32_hi20), |
| 5943 | .PCALA64_HI12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel64_hi12), | 6298 | .PCALA64_HI12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_rel64_hi12), |
| 5944 | .PCALA64_LO20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel64_lo20), | 6299 | .PCALA64_LO20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_rel64_lo20), |
| 5945 | | 6300 | |
| 5946 | .B16 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .branch_rel18), | 6301 | .B16 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_branch_rel18), |
| 5947 | .B21 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .branch_rel23), | 6302 | .B21 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_branch_rel23), |
| 5948 | .B26 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .branch_rel28), | 6303 | .B26 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_branch_rel28), |
| 5949 | .CALL36 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .call_rel38), | 6304 | .CALL36 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_call_rel38), |
| 5950 | | 6305 | |
| 5951 | // Relocations targeting a TLS symbol | 6306 | // Relocations targeting a TLS symbol |
| 5952 | .TLS_LE_LO12, .TLS_LE_LO12_R => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .tpoff32_lo12), | 6307 | .TLS_LE_LO12, .TLS_LE_LO12_R => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_tpoff32_lo12), |
| 5953 | .TLS_LE_HI20, .TLS_LE_HI20_R => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .tpoff32_hi20), | 6308 | .TLS_LE_HI20, .TLS_LE_HI20_R => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_tpoff32_hi20), |
| 5954 | .TLS_LE64_LO20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .tpoff64_lo20), | 6309 | .TLS_LE64_LO20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_tpoff64_lo20), |
| 5955 | .TLS_LE64_HI12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .tpoff64_hi12), | 6310 | .TLS_LE64_HI12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_tpoff64_hi12), |
| 5956 | .TLS_LE_ADD_R => {}, // TODO: relaxation is not yet implemented | 6311 | .TLS_LE_ADD_R => {}, // TODO: relaxation is not yet implemented |
| 5957 | | 6312 | |
| 5958 | // Relocations targeting a GOT entry | 6313 | // Relocations targeting a GOT entry |
| 5959 | .GOT_PC_LO12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .abs32_lo12), | 6314 | .GOT_PC_LO12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .larch_abs32_lo12), |
| 5960 | .GOT_PC_HI20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .rel32_hi20), | 6315 | .GOT_PC_HI20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .larch_rel32_hi20), |
| 5961 | .GOT64_PC_LO20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .rel64_lo20), | 6316 | .GOT64_PC_LO20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .larch_rel64_lo20), |
| 5962 | .GOT64_PC_HI12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .rel64_hi12), | 6317 | .GOT64_PC_HI12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .larch_rel64_hi12), |
| 5963 | | 6318 | |
| 5964 | .GOT_LO12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .abs32_lo12), | 6319 | .GOT_LO12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .larch_abs32_lo12), |
| 5965 | .GOT_HI20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .abs32_hi20), | 6320 | .GOT_HI20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .larch_abs32_hi20), |
| 5966 | .GOT64_LO20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .abs64_lo20), | 6321 | .GOT64_LO20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .larch_abs64_lo20), |
| 5967 | .GOT64_HI12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .abs64_hi12), | 6322 | .GOT64_HI12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .larch_abs64_hi12), |
| | 6323 | }, |
| | 6324 | .SPARCV9 => switch (@"type".SPARC) { |
| | 6325 | _, |
| | 6326 | .NONE, |
| | 6327 | .COPY, |
| | 6328 | .GLOB_DAT, |
| | 6329 | .JMP_SLOT, |
| | 6330 | .RELATIVE, |
| | 6331 | .IRELATIVE, |
| | 6332 | => std.debug.panic("TODO: error for illegal or unsupported input relocation, {t}", .{@"type".SPARC}), |
| | 6333 | |
| | 6334 | inline .WDISP22, |
| | 6335 | .HI22, |
| | 6336 | .@"22", |
| | 6337 | .@"13", |
| | 6338 | .LO10, |
| | 6339 | .HIPLT22, |
| | 6340 | .LOPLT10, |
| | 6341 | .PCPLT22, |
| | 6342 | .PCPLT10, |
| | 6343 | .@"10", |
| | 6344 | .@"11", |
| | 6345 | .OLO10, |
| | 6346 | .HH22, |
| | 6347 | .HM10, |
| | 6348 | .LM22, |
| | 6349 | .PC_HH22, |
| | 6350 | .PC_HM10, |
| | 6351 | .PC_LM22, |
| | 6352 | .WDISP16, |
| | 6353 | .WDISP19, |
| | 6354 | .@"7", |
| | 6355 | .@"5", |
| | 6356 | .@"6", |
| | 6357 | .HIX22, |
| | 6358 | .LOX10, |
| | 6359 | .REGISTER, |
| | 6360 | .TLS_GD_HI22, |
| | 6361 | .TLS_GD_LO10, |
| | 6362 | .TLS_IE_HI22, |
| | 6363 | .TLS_IE_LO10, |
| | 6364 | .TLS_DTPMOD32, |
| | 6365 | .TLS_DTPMOD64, |
| | 6366 | .H34, |
| | 6367 | .WDISP10, |
| | 6368 | => |t| @panic("TODO: " ++ @tagName(t)), |
| | 6369 | |
| | 6370 | // Relocations targeting a symbol |
| | 6371 | .@"8" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs8), |
| | 6372 | .@"16" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs16), |
| | 6373 | .@"32" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs32), |
| | 6374 | .DISP8 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel8), |
| | 6375 | .DISP16 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel16), |
| | 6376 | .DISP32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel32), |
| | 6377 | .WDISP30 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_wdisp30), |
| | 6378 | .PC10 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_pc10), |
| | 6379 | .PC22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_pc22), |
| | 6380 | .WPLT30 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_wplt30), |
| | 6381 | .UA32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs32), |
| | 6382 | .PLT32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .pltabs32), |
| | 6383 | .PCPLT32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .pltrel32), |
| | 6384 | .@"64" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs64), |
| | 6385 | .DISP64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel64), |
| | 6386 | .PLT64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .pltabs64), |
| | 6387 | .H44 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_h44), |
| | 6388 | .M44 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_m44), |
| | 6389 | .L44 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_l44), |
| | 6390 | .UA64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs64), |
| | 6391 | .UA16 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs16), |
| | 6392 | .TLS_GD_CALL, .TLS_LDM_CALL => try elf.addSymbolRelocAssumeCapacity(node, offset, try elf.externSymbolInner(.{ |
| | 6393 | .lib_name = null, |
| | 6394 | .name = "__tls_get_addr", |
| | 6395 | .type = .FUNC, |
| | 6396 | }), addend, .sparc_wplt30), |
| | 6397 | .SIZE32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .size32), |
| | 6398 | .SIZE64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .size64), |
| | 6399 | |
| | 6400 | // Relocations targeting a TLS symbol |
| | 6401 | .TLS_LDO_HIX22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_ldo_hix22), |
| | 6402 | .TLS_LDO_LOX10 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_ldo_lox10), |
| | 6403 | .TLS_LE_HIX22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_le_hix22), |
| | 6404 | .TLS_LE_LOX10 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_le_lox10), |
| | 6405 | .TLS_DTPOFF32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .dtpoff32), |
| | 6406 | .TLS_DTPOFF64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .dtpoff64), |
| | 6407 | .TLS_TPOFF32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .tpoff32), |
| | 6408 | .TLS_TPOFF64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .tpoff64), |
| | 6409 | // We currently do no relaxation, so nothing to do for these. |
| | 6410 | .TLS_GD_ADD, |
| | 6411 | .TLS_LDM_ADD, |
| | 6412 | .TLS_LDO_ADD, |
| | 6413 | .TLS_IE_LD, |
| | 6414 | .TLS_IE_LDX, |
| | 6415 | .TLS_IE_ADD, |
| | 6416 | => {}, |
| | 6417 | |
| | 6418 | // Relocations targeting a GOT entry |
| | 6419 | .GOT10 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_10), |
| | 6420 | .GOT13 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_13), |
| | 6421 | .GOT22 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_22), |
| | 6422 | .TLS_LDM_HI22 => elf.addGotRelocAssumeCapacity(node, offset, .tlsld0, addend, .sparc_ldm_hi22), |
| | 6423 | .TLS_LDM_LO10 => elf.addGotRelocAssumeCapacity(node, offset, .tlsld0, addend, .sparc_ldm_lo10), |
| | 6424 | // These need similar handling to `R_X86_64_GOTOFF64`. No compiler seems to emit them though. |
| | 6425 | .GOTDATA_HIX22 => @panic("TODO: R_SPARC_GOTDATA_HIX22"), |
| | 6426 | .GOTDATA_LOX10 => @panic("TODO: R_SPARC_GOTDATA_LOX10"), |
| | 6427 | .GOTDATA_OP_HIX22 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_op_hix22), |
| | 6428 | .GOTDATA_OP_LOX10 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_op_lox10), |
| | 6429 | // We currently do no relaxation, so nothing to do for this one. |
| | 6430 | .GOTDATA_OP => {}, |
| 5968 | }, | 6431 | }, |
| 5969 | }, | 6432 | }, |
| 5970 | } | 6433 | } |
| ... | @@ -6008,29 +6471,46 @@ fn addSymbolRelocAssumeCapacity( | ... | @@ -6008,29 +6471,46 @@ fn addSymbolRelocAssumeCapacity( |
| 6008 | }, | 6471 | }, |
| 6009 | .abs64 => .@"64", | 6472 | .abs64 => .@"64", |
| 6010 | .abs32 => .@"32", | 6473 | .abs32 => .@"32", |
| | 6474 | .abs16 => unreachable, |
| | 6475 | .abs8 => unreachable, |
| 6011 | .abs32s => .@"32S", | 6476 | .abs32s => .@"32S", |
| 6012 | .rel64 => .PC64, | 6477 | .rel64 => .PC64, |
| 6013 | .rel32 => .PC32, | 6478 | .rel32 => .PC32, |
| 6014 | .pltrel64 => break :r .none, | 6479 | .rel16 => unreachable, |
| 6015 | .pltrel32 => break :r .none, | 6480 | .rel8 => unreachable, |
| | 6481 | .pltabs64, .pltabs32, .pltrel64, .pltrel32 => break :r .none, |
| 6016 | .dtpoff64 => .DTPOFF64, | 6482 | .dtpoff64 => .DTPOFF64, |
| 6017 | .dtpoff32 => .DTPOFF32, | 6483 | .dtpoff32 => .DTPOFF32, |
| 6018 | .tpoff64 => .TPOFF64, | 6484 | .tpoff64 => .TPOFF64, |
| 6019 | .tpoff32 => .TPOFF32, | 6485 | .tpoff32 => .TPOFF32, |
| 6020 | .size64 => .SIZE64, | 6486 | .size64 => .SIZE64, |
| 6021 | .size32 => .SIZE32, | 6487 | .size32 => .SIZE32, |
| 6022 | .abs32_lo12, | 6488 | |
| 6023 | .rel32_hi20, | 6489 | .larch_abs32_lo12, |
| 6024 | .rel64_lo20, | 6490 | .larch_rel32_hi20, |
| 6025 | .rel64_hi12, | 6491 | .larch_rel64_lo20, |
| 6026 | .branch_rel18, | 6492 | .larch_rel64_hi12, |
| 6027 | .branch_rel23, | 6493 | .larch_branch_rel18, |
| 6028 | .branch_rel28, | 6494 | .larch_branch_rel23, |
| 6029 | .call_rel38, | 6495 | .larch_branch_rel28, |
| 6030 | .tpoff32_lo12, | 6496 | .larch_call_rel38, |
| 6031 | .tpoff32_hi20, | 6497 | .larch_tpoff32_lo12, |
| 6032 | .tpoff64_lo20, | 6498 | .larch_tpoff32_hi20, |
| 6033 | .tpoff64_hi12, | 6499 | .larch_tpoff64_lo20, |
| | 6500 | .larch_tpoff64_hi12, |
| | 6501 | => unreachable, |
| | 6502 | |
| | 6503 | .sparc_wdisp30, |
| | 6504 | .sparc_pc10, |
| | 6505 | .sparc_pc22, |
| | 6506 | .sparc_wplt30, |
| | 6507 | .sparc_h44, |
| | 6508 | .sparc_m44, |
| | 6509 | .sparc_l44, |
| | 6510 | .sparc_ldo_hix22, |
| | 6511 | .sparc_ldo_lox10, |
| | 6512 | .sparc_le_hix22, |
| | 6513 | .sparc_le_lox10, |
| 6034 | => unreachable, | 6514 | => unreachable, |
| 6035 | } }, | 6515 | } }, |
| 6036 | .LOONGARCH => .{ .LOONGARCH = switch (@"type") { | 6516 | .LOONGARCH => .{ .LOONGARCH = switch (@"type") { |
| ... | @@ -6041,26 +6521,95 @@ fn addSymbolRelocAssumeCapacity( | ... | @@ -6041,26 +6521,95 @@ fn addSymbolRelocAssumeCapacity( |
| 6041 | }, | 6521 | }, |
| 6042 | .abs64 => .@"64", | 6522 | .abs64 => .@"64", |
| 6043 | .abs32 => .@"32", | 6523 | .abs32 => .@"32", |
| 6044 | .abs32s, .size64, .size32 => unreachable, | 6524 | .abs32s => unreachable, |
| | 6525 | .abs16 => unreachable, |
| | 6526 | .abs8 => unreachable, |
| 6045 | .rel64 => .@"64_PCREL", | 6527 | .rel64 => .@"64_PCREL", |
| 6046 | .rel32 => .@"32_PCREL", | 6528 | .rel32 => .@"32_PCREL", |
| 6047 | .pltrel64, .pltrel32 => break :r .none, | 6529 | .rel16 => unreachable, |
| | 6530 | .rel8 => unreachable, |
| | 6531 | .pltabs64, .pltabs32, .pltrel64, .pltrel32 => break :r .none, |
| 6048 | .dtpoff64 => .TLS_DTPREL64, | 6532 | .dtpoff64 => .TLS_DTPREL64, |
| 6049 | .dtpoff32 => .TLS_DTPREL32, | 6533 | .dtpoff32 => .TLS_DTPREL32, |
| 6050 | .tpoff64 => .TLS_TPREL64, | 6534 | .tpoff64 => .TLS_TPREL64, |
| 6051 | .tpoff32 => .TLS_TPREL32, | 6535 | .tpoff32 => .TLS_TPREL32, |
| 6052 | .abs32_lo12 => .PCALA_LO12, | 6536 | .size64 => unreachable, |
| 6053 | .rel32_hi20 => .PCALA_HI20, | 6537 | .size32 => unreachable, |
| 6054 | .rel64_lo20 => .PCALA64_LO20, | 6538 | |
| 6055 | .rel64_hi12 => .PCALA64_HI12, | 6539 | .larch_abs32_lo12 => .PCALA_LO12, |
| 6056 | .branch_rel18 => .B16, | 6540 | .larch_rel32_hi20 => .PCALA_HI20, |
| 6057 | .branch_rel23 => .B21, | 6541 | .larch_rel64_lo20 => .PCALA64_LO20, |
| 6058 | .branch_rel28 => .B26, | 6542 | .larch_rel64_hi12 => .PCALA64_HI12, |
| 6059 | .call_rel38 => .CALL36, | 6543 | .larch_branch_rel18 => .B16, |
| 6060 | .tpoff32_lo12 => .TLS_LE_LO12, | 6544 | .larch_branch_rel23 => .B21, |
| 6061 | .tpoff32_hi20 => .TLS_LE_HI20, | 6545 | .larch_branch_rel28 => .B26, |
| 6062 | .tpoff64_lo20 => .TLS_LE64_LO20, | 6546 | .larch_call_rel38 => .CALL36, |
| 6063 | .tpoff64_hi12 => .TLS_LE64_HI12, | 6547 | .larch_tpoff32_lo12 => .TLS_LE_LO12, |
| | 6548 | .larch_tpoff32_hi20 => .TLS_LE_HI20, |
| | 6549 | .larch_tpoff64_lo20 => .TLS_LE64_LO20, |
| | 6550 | .larch_tpoff64_hi12 => .TLS_LE64_HI12, |
| | 6551 | |
| | 6552 | .sparc_wdisp30, |
| | 6553 | .sparc_pc10, |
| | 6554 | .sparc_pc22, |
| | 6555 | .sparc_wplt30, |
| | 6556 | .sparc_h44, |
| | 6557 | .sparc_m44, |
| | 6558 | .sparc_l44, |
| | 6559 | .sparc_ldo_hix22, |
| | 6560 | .sparc_ldo_lox10, |
| | 6561 | .sparc_le_hix22, |
| | 6562 | .sparc_le_lox10, |
| | 6563 | => unreachable, |
| | 6564 | } }, |
| | 6565 | .SPARCV9 => .{ .SPARC = switch (@"type") { |
| | 6566 | .write_rela => unreachable, |
| | 6567 | .dsorel64, .dsorel32 => { |
| | 6568 | assert(target.unwrap() == .local); |
| | 6569 | break :r .none; |
| | 6570 | }, |
| | 6571 | .abs64 => .@"64", |
| | 6572 | .abs32 => .@"32", |
| | 6573 | .abs32s => unreachable, |
| | 6574 | .abs16 => .@"16", |
| | 6575 | .abs8 => .@"8", |
| | 6576 | .rel64 => .DISP64, |
| | 6577 | .rel32 => .DISP32, |
| | 6578 | .rel16 => .DISP16, |
| | 6579 | .rel8 => .DISP8, |
| | 6580 | .pltabs64, .pltabs32, .pltrel64, .pltrel32 => break :r .none, |
| | 6581 | .dtpoff64 => .TLS_DTPOFF64, |
| | 6582 | .dtpoff32 => .TLS_DTPOFF32, |
| | 6583 | .tpoff64 => .TLS_TPOFF64, |
| | 6584 | .tpoff32 => .TLS_TPOFF32, |
| | 6585 | .size64 => .SIZE64, |
| | 6586 | .size32 => .SIZE32, |
| | 6587 | |
| | 6588 | .larch_abs32_lo12, |
| | 6589 | .larch_rel32_hi20, |
| | 6590 | .larch_rel64_lo20, |
| | 6591 | .larch_rel64_hi12, |
| | 6592 | .larch_branch_rel18, |
| | 6593 | .larch_branch_rel23, |
| | 6594 | .larch_branch_rel28, |
| | 6595 | .larch_call_rel38, |
| | 6596 | .larch_tpoff32_lo12, |
| | 6597 | .larch_tpoff32_hi20, |
| | 6598 | .larch_tpoff64_lo20, |
| | 6599 | .larch_tpoff64_hi12, |
| | 6600 | => unreachable, |
| | 6601 | |
| | 6602 | .sparc_wdisp30 => .WDISP30, |
| | 6603 | .sparc_pc10 => .PC10, |
| | 6604 | .sparc_pc22 => .PC22, |
| | 6605 | .sparc_wplt30 => .WPLT30, |
| | 6606 | .sparc_h44 => .H44, |
| | 6607 | .sparc_m44 => .M44, |
| | 6608 | .sparc_l44 => .L44, |
| | 6609 | .sparc_ldo_hix22 => .TLS_LDO_HIX22, |
| | 6610 | .sparc_ldo_lox10 => .TLS_LDO_LOX10, |
| | 6611 | .sparc_le_hix22 => .TLS_LE_HIX22, |
| | 6612 | .sparc_le_lox10 => .TLS_LE_LOX10, |
| 6064 | } }, | 6613 | } }, |
| 6065 | }; | 6614 | }; |
| 6066 | | 6615 | |
| ... | @@ -6221,8 +6770,9 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { | ... | @@ -6221,8 +6770,9 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { |
| 6221 | } | 6770 | } |
| 6222 | const reloc_type: MachineRelocType = switch (elf.ehdrField(.machine)) { | 6771 | const reloc_type: MachineRelocType = switch (elf.ehdrField(.machine)) { |
| 6223 | else => |machine| @panic(@tagName(machine)), | 6772 | else => |machine| @panic(@tagName(machine)), |
| 6224 | .X86_64 => .{ .X86_64 = .TPOFF64 }, | | |
| 6225 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_TPREL64 else .TLS_TPREL32 }, | 6773 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_TPREL64 else .TLS_TPREL32 }, |
| | 6774 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .TLS_TPOFF64 else .TLS_TPOFF32 }, |
| | 6775 | .X86_64 => .{ .X86_64 = .TPOFF64 }, |
| 6226 | }; | 6776 | }; |
| 6227 | break :val switch (sym_id.unwrap()) { | 6777 | break :val switch (sym_id.unwrap()) { |
| 6228 | // For global symbols, just target the right dynsym with no addend. | 6778 | // For global symbols, just target the right dynsym with no addend. |
| ... | @@ -6270,8 +6820,9 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { | ... | @@ -6270,8 +6820,9 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { |
| 6270 | .dynamic => .{ .reloc = .{ | 6820 | .dynamic => .{ .reloc = .{ |
| 6271 | .type = switch (elf.ehdrField(.machine)) { | 6821 | .type = switch (elf.ehdrField(.machine)) { |
| 6272 | else => |machine| @panic(@tagName(machine)), | 6822 | else => |machine| @panic(@tagName(machine)), |
| 6273 | .X86_64 => .{ .X86_64 = .DTPMOD64 }, | | |
| 6274 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 }, | 6823 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 }, |
| | 6824 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 }, |
| | 6825 | .X86_64 => .{ .X86_64 = .DTPMOD64 }, |
| 6275 | }, | 6826 | }, |
| 6276 | .dynsym_index = switch (elf.classifySymbolValue(sym)) { | 6827 | .dynsym_index = switch (elf.classifySymbolValue(sym)) { |
| 6277 | .static, .static_relative => 0, | 6828 | .static, .static_relative => 0, |
| ... | @@ -6288,8 +6839,9 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { | ... | @@ -6288,8 +6839,9 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { |
| 6288 | .dynamic => .{ .reloc = .{ | 6839 | .dynamic => .{ .reloc = .{ |
| 6289 | .type = switch (elf.ehdrField(.machine)) { | 6840 | .type = switch (elf.ehdrField(.machine)) { |
| 6290 | else => |machine| @panic(@tagName(machine)), | 6841 | else => |machine| @panic(@tagName(machine)), |
| 6291 | .X86_64 => .{ .X86_64 = .DTPMOD64 }, | | |
| 6292 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 }, | 6842 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 }, |
| | 6843 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 }, |
| | 6844 | .X86_64 => .{ .X86_64 = .DTPMOD64 }, |
| 6293 | }, | 6845 | }, |
| 6294 | .dynsym_index = 0, | 6846 | .dynsym_index = 0, |
| 6295 | .addend = 0, | 6847 | .addend = 0, |
| ... | @@ -7341,6 +7893,17 @@ fn flushMovedPltSection(elf: *Elf, which: enum { plt, plt_sec, got_plt }, old_ad | ... | @@ -7341,6 +7893,17 @@ fn flushMovedPltSection(elf: *Elf, which: enum { plt, plt_sec, got_plt }, old_ad |
| 7341 | }, | 7893 | }, |
| 7342 | } | 7894 | } |
| 7343 | }, | 7895 | }, |
| | 7896 | .SPARCV9 => switch (which) { |
| | 7897 | .plt => { |
| | 7898 | // Update the offsets of the relocation entries in `.rela.plt`. |
| | 7899 | const rela_plt_shndx = elf.shndx.rela_plt; |
| | 7900 | for (0..elf.plt.count()) |plt_index| { |
| | 7901 | if (elf.pltEntryIsDead(plt_index)) continue; |
| | 7902 | rela_plt_shndx.relaAdjustOffset(elf, @enumFromInt(plt_index), old_addr, addr); |
| | 7903 | } |
| | 7904 | }, |
| | 7905 | .plt_sec, .got_plt => unreachable, |
| | 7906 | }, |
| 7344 | } | 7907 | } |
| 7345 | } | 7908 | } |
| 7346 | | 7909 | |