| ... | @@ -1,8 +1,5 @@ | ... | @@ -1,8 +1,5 @@ |
| 1 | const Elf = @This(); | 1 | const Elf = @This(); |
| 2 | | 2 | |
| 3 | const builtin = @import("builtin"); | | |
| 4 | const native_endian = builtin.cpu.arch.endian(); | | |
| 5 | | | |
| 6 | const std = @import("std"); | 3 | const std = @import("std"); |
| 7 | const Io = std.Io; | 4 | const Io = std.Io; |
| 8 | const assert = std.debug.assert; | 5 | const assert = std.debug.assert; |
| ... | @@ -10,6 +7,8 @@ const log = std.log.scoped(.link); | ... | @@ -10,6 +7,8 @@ const log = std.log.scoped(.link); |
| 10 | | 7 | |
| 11 | const codegen = @import("../codegen.zig"); | 8 | const codegen = @import("../codegen.zig"); |
| 12 | const Compilation = @import("../Compilation.zig"); | 9 | const Compilation = @import("../Compilation.zig"); |
| | 10 | const dev = @import("../dev.zig"); |
| | 11 | const Dwarf = @import("Dwarf2.zig"); |
| 13 | const InternPool = @import("../InternPool.zig"); | 12 | const InternPool = @import("../InternPool.zig"); |
| 14 | const link = @import("../link.zig"); | 13 | const link = @import("../link.zig"); |
| 15 | const MappedFile = @import("MappedFile.zig"); | 14 | const MappedFile = @import("MappedFile.zig"); |
| ... | @@ -43,6 +42,11 @@ shndx: struct { | ... | @@ -43,6 +42,11 @@ shndx: struct { |
| 43 | tdata: Section.Index, | 42 | tdata: Section.Index, |
| 44 | rela_dyn: Section.Index, | 43 | rela_dyn: Section.Index, |
| 45 | rela_plt: Section.Index, | 44 | rela_plt: Section.Index, |
| | 45 | eh_frame_hdr: Section.Index, |
| | 46 | eh_frame: Section.Index, |
| | 47 | debug_frame: Section.Index, |
| | 48 | debug_info: Section.Index, |
| | 49 | debug_line: Section.Index, |
| 46 | // These sections are created only as needed, and are initially `.UNDEF`. | 50 | // These sections are created only as needed, and are initially `.UNDEF`. |
| 47 | init_array: Section.Index, | 51 | init_array: Section.Index, |
| 48 | fini_array: Section.Index, | 52 | fini_array: Section.Index, |
| ... | @@ -123,6 +127,8 @@ got: std.array_hash_map.Auto(GotKey, Section.RelaIndex.Optional), | ... | @@ -123,6 +127,8 @@ got: std.array_hash_map.Auto(GotKey, Section.RelaIndex.Optional), |
| 123 | plt: std.array_hash_map.Auto(String(.strtab), void), | 127 | plt: std.array_hash_map.Auto(String(.strtab), void), |
| 124 | /// The `.plt` section contains zero or more symbol relocations starting at this index. | 128 | /// The `.plt` section contains zero or more symbol relocations starting at this index. |
| 125 | plt_first_symbol_reloc: SymbolReloc.Index, | 129 | plt_first_symbol_reloc: SymbolReloc.Index, |
| | 130 | /// The `.eh_frame_hdr` section contains zero or more symbol relocations starting at this index. |
| | 131 | eh_frame_hdr_first_symbol_reloc: SymbolReloc.Index, |
| 126 | | 132 | |
| 127 | needed: std.array_hash_map.Auto(String(.dynstr), void), | 133 | needed: std.array_hash_map.Auto(String(.dynstr), void), |
| 128 | inputs: std.ArrayList(struct { | 134 | inputs: std.ArrayList(struct { |
| ... | @@ -175,9 +181,10 @@ lazy: std.EnumArray(link.File.LazySymbol.Kind, struct { | ... | @@ -175,9 +181,10 @@ lazy: std.EnumArray(link.File.LazySymbol.Kind, struct { |
| 175 | }), | 181 | }), |
| 176 | pending_uavs: std.ArrayList(Node.UavMapIndex), | 182 | pending_uavs: std.ArrayList(Node.UavMapIndex), |
| 177 | symbol_relocs: std.ArrayList(SymbolReloc), | 183 | symbol_relocs: std.ArrayList(SymbolReloc), |
| 178 | got_relocs: std.ArrayList(GotReloc), | | |
| 179 | /// Set of relocations which must be re-applied if the size of the TLS segment changes. | 184 | /// Set of relocations which must be re-applied if the size of the TLS segment changes. |
| 180 | tls_size_symbol_relocs: std.array_hash_map.Auto(SymbolReloc.Index, void), | 185 | tls_size_symbol_relocs: std.array_hash_map.Auto(SymbolReloc.Index, void), |
| | 186 | node_relocs: std.ArrayList(NodeReloc), |
| | 187 | got_relocs: std.ArrayList(GotReloc), |
| 181 | /// Index matches the index into `shdrs`. Like `shdrs`, this map excludes `SHN_UNDEF`. | 188 | /// Index matches the index into `shdrs`. Like `shdrs`, this map excludes `SHN_UNDEF`. |
| 182 | section_by_name: std.array_hash_map.Auto(String(.shstrtab), void), | 189 | section_by_name: std.array_hash_map.Auto(String(.shstrtab), void), |
| 183 | /// Key is the name of a global symbol which has been moved to a new symtab index. Any relocation | 190 | /// Key is the name of a global symbol which has been moved to a new symtab index. Any relocation |
| ... | @@ -191,6 +198,17 @@ changed_symtab_index: std.array_hash_map.Auto(String(.strtab), void), | ... | @@ -191,6 +198,17 @@ changed_symtab_index: std.array_hash_map.Auto(String(.strtab), void), |
| 191 | /// section in `flush` only when it is actually necessary. See also `nodeWantsDsoRelocation`. | 198 | /// section in `flush` only when it is actually necessary. See also `nodeWantsDsoRelocation`. |
| 192 | textrel_count: u32, | 199 | textrel_count: u32, |
| 193 | | 200 | |
| | 201 | dwarf: Dwarf, |
| | 202 | dwarf_units: std.ArrayList(struct { |
| | 203 | unit_frame_cie_first_target_reloc: NodeReloc.Index, |
| | 204 | }), |
| | 205 | dwarf_values: std.ArrayList(struct {}), |
| | 206 | dwarf_globals: std.ArrayList(struct {}), |
| | 207 | dwarf_funcs: std.ArrayList(struct { |
| | 208 | func_frame_fde_first_symbol_reloc: SymbolReloc.Index, |
| | 209 | func_frame_fde_first_node_reloc: NodeReloc.Index, |
| | 210 | }), |
| | 211 | |
| 194 | overflowed_reloc_count: u32, | 212 | overflowed_reloc_count: u32, |
| 195 | misaligned_reloc_count: u32, | 213 | misaligned_reloc_count: u32, |
| 196 | | 214 | |
| ... | @@ -232,8 +250,9 @@ const Node = union(enum) { | ... | @@ -232,8 +250,9 @@ const Node = union(enum) { |
| 232 | ehdr, | 250 | ehdr, |
| 233 | shdr, | 251 | shdr, |
| 234 | segment: u32, | 252 | segment: u32, |
| 235 | /// The section '.plt' may contain relocations via `elf.plt_first_symbol_reloc`. | | |
| 236 | section: Section.Index, | 253 | section: Section.Index, |
| | 254 | /// The section '.plt' may contain relocations via `elf.plt_first_symbol_reloc`. |
| | 255 | section_manual_size: Section.Index, |
| 237 | /// May contain relocations. | 256 | /// May contain relocations. |
| 238 | input_section: InputSection.Index, | 257 | input_section: InputSection.Index, |
| 239 | /// Value is the name of a global which has an entry in `elf.copied_globals`, so, a global for | 258 | /// Value is the name of a global which has an entry in `elf.copied_globals`, so, a global for |
| ... | @@ -253,6 +272,15 @@ const Node = union(enum) { | ... | @@ -253,6 +272,15 @@ const Node = union(enum) { |
| 253 | /// May contain relocations. | 272 | /// May contain relocations. |
| 254 | lazy_const_data: LazyMapRef.Index(.const_data), | 273 | lazy_const_data: LazyMapRef.Index(.const_data), |
| 255 | | 274 | |
| | 275 | value_debug_info: link.ConstPool.Index, |
| | 276 | global_debug_info: Dwarf.Global.Index, |
| | 277 | frame_padding, |
| | 278 | unit_frame: Dwarf.Unit.Index, |
| | 279 | unit_frame_cie: Dwarf.Unit.Index, |
| | 280 | func_frame_fde: Dwarf.Func.Index, |
| | 281 | func_debug_info: Dwarf.Func.Index, |
| | 282 | func_debug_line: Dwarf.Func.Index, |
| | 283 | |
| 256 | pub const InputIndex = enum(u32) { | 284 | pub const InputIndex = enum(u32) { |
| 257 | _, | 285 | _, |
| 258 | | 286 | |
| ... | @@ -373,6 +401,7 @@ const Node = union(enum) { | ... | @@ -373,6 +401,7 @@ const Node = union(enum) { |
| 373 | data: MappedFile.Node.Index, | 401 | data: MappedFile.Node.Index, |
| 374 | data_rel_ro: MappedFile.Node.Index, | 402 | data_rel_ro: MappedFile.Node.Index, |
| 375 | tls: MappedFile.Node.Index.Optional, | 403 | tls: MappedFile.Node.Index.Optional, |
| | 404 | gnu_eh_frame: MappedFile.Node.Index.Optional, |
| 376 | }; | 405 | }; |
| 377 | | 406 | |
| 378 | comptime { | 407 | comptime { |
| ... | @@ -649,7 +678,7 @@ const Section = struct { | ... | @@ -649,7 +678,7 @@ const Section = struct { |
| 649 | }, | 678 | }, |
| 650 | .addend = @intCast(old_free_len + 1), // list length | 679 | .addend = @intCast(old_free_len + 1), // list length |
| 651 | }; | 680 | }; |
| 652 | if (elf.targetEndian() != native_endian) { | 681 | if (elf.targetEndian() != std.lang.Endian.native) { |
| 653 | std.mem.byteSwapAllFields(class.ElfN().Rela, &relas[@backingInt(index)]); | 682 | std.mem.byteSwapAllFields(class.ElfN().Rela, &relas[@backingInt(index)]); |
| 654 | } | 683 | } |
| 655 | }, | 684 | }, |
| ... | @@ -708,7 +737,7 @@ const Section = struct { | ... | @@ -708,7 +737,7 @@ const Section = struct { |
| 708 | }, | 737 | }, |
| 709 | .addend = @intCast(opts.addend), | 738 | .addend = @intCast(opts.addend), |
| 710 | }; | 739 | }; |
| 711 | if (elf.targetEndian() != native_endian) { | 740 | if (elf.targetEndian() != std.lang.Endian.native) { |
| 712 | std.mem.byteSwapAllFields(class.ElfN().Rela, &relas[@backingInt(new_index)]); | 741 | std.mem.byteSwapAllFields(class.ElfN().Rela, &relas[@backingInt(new_index)]); |
| 713 | } | 742 | } |
| 714 | return new_index; | 743 | return new_index; |
| ... | @@ -807,244 +836,13 @@ const Section = struct { | ... | @@ -807,244 +836,13 @@ const Section = struct { |
| 807 | }, | 836 | }, |
| 808 | } | 837 | } |
| 809 | } | 838 | } |
| 810 | }; | | |
| 811 | }; | | |
| 812 | | | |
| 813 | /// Identifies a single entry in the GOT. | | |
| 814 | const GotKey = union(enum) { | | |
| 815 | /// The entry is a reserved word, initialized to zero. `initHeaders` will add as many of these | | |
| 816 | /// as the target machine ABI requires. | | |
| 817 | /// | | |
| 818 | /// This `u32` value exists to allow reserving multiple words with distinct keys. | | |
| 819 | reserved: u32, | | |
| 820 | | | |
| 821 | /// Value is the address of the given symbol. | | |
| 822 | symbol: Symbol.Id, | | |
| 823 | | | |
| 824 | /// Value is the signed offset of the given symbol from the TLS pointer. | | |
| 825 | tpoff: Symbol.Id, | | |
| 826 | | | |
| 827 | /// Value is the TLS module ID of the DSO we are creating. | | |
| 828 | /// | | |
| 829 | /// Used for the first of the two GOT entries generated by a TLSLD relocation. | | |
| 830 | tlsld0, | | |
| 831 | /// Value is always 0. | | |
| 832 | /// | | |
| 833 | /// Used for the second of the two GOT entries generated by a TLSLD relocation. | | |
| 834 | tlsld1, | | |
| 835 | | | |
| 836 | /// Value is the TLS module ID for the given STT_TLS symbol. | | |
| 837 | /// | | |
| 838 | /// Used for the first of the two GOT entries generated by a TLSGD relocation. | | |
| 839 | tlsgd0: Symbol.Id, | | |
| 840 | /// Value is the offset of the given STT_TLS symbol from the base of the per-module TLS area. | | |
| 841 | /// | | |
| 842 | /// Used for the second of the two GOT entries generated by a TLSGD relocation. | | |
| 843 | tlsgd1: Symbol.Id, | | |
| 844 | }; | | |
| 845 | | | |
| 846 | /// A relocation targeting a particular GOT entry. | | |
| 847 | const GotReloc = struct { | | |
| 848 | /// The node containing this relocation. Possible values are: | | |
| 849 | /// * An input section | | |
| 850 | /// * A section | | |
| 851 | /// * A NAV, UAV, or lazy code/data | | |
| 852 | /// * `.none`, if this relocation was deleted (in which case it should be ignored) | | |
| 853 | node: MappedFile.Node.Index.Optional, | | |
| 854 | /// The offset of the relocation inside of `node`. | | |
| 855 | offset: u64, | | |
| 856 | target: GotKey, | | |
| 857 | addend: i64, | | |
| 858 | type: GotReloc.Type, | | |
| 859 | result: enum(u8) { ok, overflowed, misaligned }, | | |
| 860 | | | |
| 861 | /// `GotReloc.Type` has the same structure as `SymbolReloc.Type`, just with different `Target` | | |
| 862 | /// and `Special` enums---consult doc comments on `SymbolReloc.Type` for an overview. | | |
| 863 | const Type = packed struct(u16) { | | |
| 864 | fn simple(target: Target, action: Simple) GotReloc.Type { | | |
| 865 | assert(target != .special); | | |
| 866 | return .{ .target = target, .action = .{ .simple = action } }; | | |
| 867 | } | | |
| 868 | | | |
| 869 | fn special(s: Special) GotReloc.Type { | | |
| 870 | return .{ .target = .special, .action = .{ .special = s } }; | | |
| 871 | } | | |
| 872 | | | |
| 873 | target: Target, | | |
| 874 | action: packed union { | | |
| 875 | simple: Simple, | | |
| 876 | special: Special, | | |
| 877 | }, | | |
| 878 | | | |
| 879 | /// Like `SymbolReloc.Target`, but for GOT relocations. There are fewer tags because there | | |
| 880 | /// are fewer different kinds of GOT relocation. | | |
| 881 | const Target = enum(u3) { | | |
| 882 | /// This is a "special" relocation whose specific type is in the `action.special` field. | | |
| 883 | special, | | |
| 884 | | | |
| 885 | /// Absolute address of the GOT entry. | | |
| 886 | abs, | | |
| 887 | /// Offset from the relocation itself to the GOT entry ("PC-relative"). | | |
| 888 | rel, | | |
| 889 | /// Offset from the base of the GOT to the GOT entry. | | |
| 890 | offset, | | |
| 891 | }; | | |
| 892 | | | |
| 893 | const Simple = SymbolReloc.Type.Simple; | | |
| 894 | | | |
| 895 | /// Like `SymbolReloc.Special`, but for GOT relocations. | | |
| 896 | const Special = enum(u13) { | | |
| 897 | larch_pcala_hi20, | | |
| 898 | larch_pcala64_lo20, | | |
| 899 | larch_pcala64_hi12, | | |
| 900 | | | |
| 901 | sparc_op_lox10, | | |
| 902 | sparc_op_hix22, | | |
| 903 | | | |
| 904 | fn applyInner( | | |
| 905 | s: Special, | | |
| 906 | elf: *Elf, | | |
| 907 | got_vaddr: u64, | | |
| 908 | got_offset: u64, | | |
| 909 | addend: u64, | | |
| 910 | dest_vaddr: u64, | | |
| 911 | dest_slice: []u8, | | |
| 912 | ) error{ RelocationMisaligned, RelocationOverflow }!void { | | |
| 913 | switch (s) { | | |
| 914 | .larch_pcala_hi20 => { | | |
| 915 | const val = got_vaddr +% got_offset +% addend; | | |
| 916 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); | | |
| 917 | elf.targetStore(inst, .{ | | |
| 918 | .b0_4 = elf.targetLoad(inst).b0_4, | | |
| 919 | .j20 = link.loongarch.pcalaHi20(val, dest_vaddr), | | |
| 920 | .b25_31 = elf.targetLoad(inst).b25_31, | | |
| 921 | }); | | |
| 922 | }, | | |
| 923 | .larch_pcala64_lo20 => { | | |
| 924 | const val = got_vaddr +% got_offset +% addend; | | |
| 925 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); | | |
| 926 | elf.targetStore(inst, .{ | | |
| 927 | .b0_4 = elf.targetLoad(inst).b0_4, | | |
| 928 | .j20 = link.loongarch.pcala64Lo20(val, dest_vaddr), | | |
| 929 | .b25_31 = elf.targetLoad(inst).b25_31, | | |
| 930 | }); | | |
| 931 | }, | | |
| 932 | .larch_pcala64_hi12 => { | | |
| 933 | const val = got_vaddr +% got_offset +% addend; | | |
| 934 | const inst: *align(1) link.loongarch.K12 = @ptrCast(dest_slice[0..4]); | | |
| 935 | elf.targetStore(inst, .{ | | |
| 936 | .b0_9 = elf.targetLoad(inst).b0_9, | | |
| 937 | .k12 = link.loongarch.pcala64Hi12(val, dest_vaddr), | | |
| 938 | .b22_31 = elf.targetLoad(inst).b22_31, | | |
| 939 | }); | | |
| 940 | }, | | |
| 941 | .sparc_op_lox10 => { | | |
| 942 | const dest_ptr: *align(1) packed struct(u32) { | | |
| 943 | imm13: u13, | | |
| 944 | b13_31: u19, | | |
| 945 | } = @ptrCast(dest_slice); | | |
| 946 | elf.targetStore(dest_ptr, .{ | | |
| 947 | .imm13 = @as(u10, @truncate(got_offset)), | | |
| 948 | .b13_31 = elf.targetLoad(dest_ptr).b13_31, | | |
| 949 | }); | | |
| 950 | }, | | |
| 951 | .sparc_op_hix22 => { | | |
| 952 | const dest_ptr: *align(1) packed struct(u32) { | | |
| 953 | imm22: u22, | | |
| 954 | b22_31: u10, | | |
| 955 | } = @ptrCast(dest_slice); | | |
| 956 | elf.targetStore(dest_ptr, .{ | | |
| 957 | .imm22 = @truncate(got_offset >> 10), | | |
| 958 | .b22_31 = elf.targetLoad(dest_ptr).b22_31, | | |
| 959 | }); | | |
| 960 | }, | | |
| 961 | } | | |
| 962 | } | | |
| 963 | }; | | |
| 964 | }; | | |
| 965 | | | |
| 966 | const Index = enum(u32) { | | |
| 967 | none = std.math.maxInt(u32), | | |
| 968 | _, | | |
| 969 | | 839 | |
| 970 | fn get(index: GotReloc.Index, elf: *Elf) *GotReloc { | 840 | fn debugFrameFormat(shndx: Index, elf: *Elf) ?Dwarf.Frame.Format { |
| 971 | return &elf.got_relocs.items[@backingInt(index)]; | 841 | if (shndx == elf.shndx.eh_frame) return .eh_frame; |
| | 842 | if (shndx == elf.shndx.debug_frame) return .debug_frame; |
| | 843 | return null; |
| 972 | } | 844 | } |
| 973 | }; | 845 | }; |
| 974 | | | |
| 975 | fn apply(reloc: *GotReloc, elf: *Elf) void { | | |
| 976 | assert(elf.ehdrType() != .REL); | | |
| 977 | const node = reloc.node.unwrap() orelse { | | |
| 978 | return; // deleted | | |
| 979 | }; | | |
| 980 | if (node.hasMoved(&elf.mf) or elf.shndx.got.get(elf).ni.hasMoved(&elf.mf)) { | | |
| 981 | // There's no point applying the relocation now, because it will be re-applied by | | |
| 982 | // `flushMoved` at some point anyway. | | |
| 983 | return; | | |
| 984 | } | | |
| 985 | switch (reloc.result) { | | |
| 986 | .ok => {}, | | |
| 987 | .overflowed => elf.overflowed_reloc_count -= 1, | | |
| 988 | .misaligned => elf.misaligned_reloc_count -= 1, | | |
| 989 | } | | |
| 990 | if (reloc.applyInner(elf)) { | | |
| 991 | @branchHint(.likely); | | |
| 992 | reloc.result = .ok; | | |
| 993 | } else |err| switch (err) { | | |
| 994 | error.RelocationOverflow => { | | |
| 995 | reloc.result = .overflowed; | | |
| 996 | elf.overflowed_reloc_count += 1; | | |
| 997 | }, | | |
| 998 | error.RelocationMisaligned => { | | |
| 999 | reloc.result = .misaligned; | | |
| 1000 | elf.misaligned_reloc_count += 1; | | |
| 1001 | }, | | |
| 1002 | } | | |
| 1003 | } | | |
| 1004 | fn applyInner(reloc: *const GotReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void { | | |
| 1005 | const node = reloc.node.unwrap().?; | | |
| 1006 | const dest_vaddr = elf.getNodeVAddr(node) + reloc.offset; | | |
| 1007 | const dest_slice = node.slice(&elf.mf)[@intCast(reloc.offset)..]; | | |
| 1008 | | | |
| 1009 | const got_vaddr = elf.shndx.got.vaddr(elf); | | |
| 1010 | const got_index: u64 = elf.got.getIndex(reloc.target).?; | | |
| 1011 | const got_offset: u64 = switch (elf.identClass()) { | | |
| 1012 | .NONE, _ => unreachable, | | |
| 1013 | inline else => |class| @sizeOf(class.ElfN().Addr) * got_index, | | |
| 1014 | }; | | |
| 1015 | const addend: u64 = @bitCast(reloc.addend); | | |
| 1016 | | | |
| 1017 | const target_val: u64 = switch (reloc.type.target) { | | |
| 1018 | .abs => got_vaddr +% got_offset +% addend, | | |
| 1019 | .rel => got_vaddr +% got_offset +% addend -% dest_vaddr, | | |
| 1020 | .offset => got_offset +% addend, | | |
| 1021 | .special => return reloc.type.action.special.applyInner( | | |
| 1022 | elf, | | |
| 1023 | got_vaddr, | | |
| 1024 | got_offset, | | |
| 1025 | addend, | | |
| 1026 | dest_vaddr, | | |
| 1027 | dest_slice, | | |
| 1028 | ), | | |
| 1029 | }; | | |
| 1030 | try reloc.type.action.simple.write(target_val, dest_slice, elf.targetEndian()); | | |
| 1031 | } | | |
| 1032 | | | |
| 1033 | fn delete(reloc: *GotReloc, elf: *Elf) void { | | |
| 1034 | switch (reloc.result) { | | |
| 1035 | .ok => {}, | | |
| 1036 | .overflowed => elf.overflowed_reloc_count -= 1, | | |
| 1037 | .misaligned => elf.misaligned_reloc_count -= 1, | | |
| 1038 | } | | |
| 1039 | reloc.* = .{ | | |
| 1040 | .node = .none, | | |
| 1041 | .offset = undefined, | | |
| 1042 | .target = undefined, | | |
| 1043 | .addend = undefined, | | |
| 1044 | .type = undefined, | | |
| 1045 | .result = undefined, | | |
| 1046 | }; | | |
| 1047 | } | | |
| 1048 | }; | 846 | }; |
| 1049 | | 847 | |
| 1050 | pub const MachineRelocType = union { | 848 | pub const MachineRelocType = union { |
| ... | @@ -1118,51 +916,144 @@ pub const MachineRelocType = union { | ... | @@ -1118,51 +916,144 @@ pub const MachineRelocType = union { |
| 1118 | pub fn globDat(elf: *const Elf) MachineRelocType { | 916 | pub fn globDat(elf: *const Elf) MachineRelocType { |
| 1119 | return switch (elf.ehdrMachine()) { | 917 | return switch (elf.ehdrMachine()) { |
| 1120 | .AARCH64 => .{ .AARCH64 = .GLOB_DAT }, | 918 | .AARCH64 => .{ .AARCH64 = .GLOB_DAT }, |
| 1121 | .LOONGARCH => .{ .LARCH = if (elf.identClass() == .@"64") .@"64" else .@"32" }, | 919 | .LOONGARCH => .{ .LARCH = switch (elf.identClass()) { |
| | 920 | .NONE, _ => unreachable, |
| | 921 | .@"32" => .@"32", |
| | 922 | .@"64" => .@"64", |
| | 923 | } }, |
| 1122 | .PPC64 => .{ .PPC64 = .GLOB_DAT }, | 924 | .PPC64 => .{ .PPC64 = .GLOB_DAT }, |
| 1123 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .@"64" else .@"32" }, | 925 | .RISCV => .{ .RISCV = switch (elf.identClass()) { |
| | 926 | .NONE, _ => unreachable, |
| | 927 | .@"32" => .@"32", |
| | 928 | .@"64" => .@"64", |
| | 929 | } }, |
| 1124 | .SPARCV9 => .{ .SPARC = .GLOB_DAT }, | 930 | .SPARCV9 => .{ .SPARC = .GLOB_DAT }, |
| 1125 | .X86_64 => .{ .X86_64 = .GLOB_DAT }, | 931 | .X86_64 => .{ .X86_64 = .GLOB_DAT }, |
| 1126 | }; | 932 | }; |
| 1127 | } | 933 | } |
| 1128 | pub fn dtpMod(elf: *const Elf) MachineRelocType { | 934 | pub fn dtpMod(elf: *const Elf) MachineRelocType { |
| 1129 | return switch (elf.ehdrMachine()) { | 935 | return switch (elf.ehdrMachine()) { |
| 1130 | .AARCH64 => .{ .AARCH64 = if (elf.identClass() == .@"64") .TLS_DTPMOD else .P32_TLS_DTPMOD }, | 936 | .AARCH64 => .{ .AARCH64 = switch (elf.identClass()) { |
| 1131 | .LOONGARCH => .{ .LARCH = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 }, | 937 | .NONE, _ => unreachable, |
| | 938 | .@"32" => .P32_TLS_DTPMOD, |
| | 939 | .@"64" => .TLS_DTPMOD, |
| | 940 | } }, |
| | 941 | .LOONGARCH => .{ .LARCH = switch (elf.identClass()) { |
| | 942 | .NONE, _ => unreachable, |
| | 943 | .@"32" => .TLS_DTPMOD32, |
| | 944 | .@"64" => .TLS_DTPMOD64, |
| | 945 | } }, |
| 1132 | .PPC64 => .{ .PPC64 = .DTPMOD64 }, | 946 | .PPC64 => .{ .PPC64 = .DTPMOD64 }, |
| 1133 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 }, | 947 | .RISCV => .{ .RISCV = switch (elf.identClass()) { |
| 1134 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 }, | 948 | .NONE, _ => unreachable, |
| | 949 | .@"32" => .TLS_DTPMOD32, |
| | 950 | .@"64" => .TLS_DTPMOD64, |
| | 951 | } }, |
| | 952 | .SPARCV9 => .{ .SPARC = switch (elf.identClass()) { |
| | 953 | .NONE, _ => unreachable, |
| | 954 | .@"32" => .TLS_DTPMOD32, |
| | 955 | .@"64" => .TLS_DTPMOD64, |
| | 956 | } }, |
| 1135 | .X86_64 => .{ .X86_64 = .DTPMOD64 }, | 957 | .X86_64 => .{ .X86_64 = .DTPMOD64 }, |
| 1136 | }; | 958 | }; |
| 1137 | } | 959 | } |
| 1138 | pub fn dtpOff(elf: *const Elf) MachineRelocType { | 960 | pub fn dtpOff(elf: *const Elf) MachineRelocType { |
| 1139 | return switch (elf.ehdrMachine()) { | 961 | return switch (elf.ehdrMachine()) { |
| 1140 | .AARCH64 => .{ .AARCH64 = if (elf.identClass() == .@"64") .TLS_DTPREL else .P32_TLS_DTPREL }, | 962 | .AARCH64 => .{ .AARCH64 = switch (elf.identClass()) { |
| 1141 | .LOONGARCH => .{ .LARCH = if (elf.identClass() == .@"64") .TLS_DTPREL64 else .TLS_DTPREL32 }, | 963 | .NONE, _ => unreachable, |
| | 964 | .@"32" => .P32_TLS_DTPREL, |
| | 965 | .@"64" => .TLS_DTPREL, |
| | 966 | } }, |
| | 967 | .LOONGARCH => .{ .LARCH = switch (elf.identClass()) { |
| | 968 | .NONE, _ => unreachable, |
| | 969 | .@"32" => .TLS_DTPREL32, |
| | 970 | .@"64" => .TLS_DTPREL64, |
| | 971 | } }, |
| 1142 | .PPC64 => .{ .PPC64 = .DTPREL64 }, | 972 | .PPC64 => .{ .PPC64 = .DTPREL64 }, |
| 1143 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .TLS_DTPREL64 else .TLS_DTPREL32 }, | 973 | .RISCV => .{ .RISCV = switch (elf.identClass()) { |
| 1144 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .TLS_DTPOFF64 else .TLS_DTPOFF32 }, | 974 | .NONE, _ => unreachable, |
| | 975 | .@"32" => .TLS_DTPREL32, |
| | 976 | .@"64" => .TLS_DTPREL64, |
| | 977 | } }, |
| | 978 | .SPARCV9 => .{ .SPARC = switch (elf.identClass()) { |
| | 979 | .NONE, _ => unreachable, |
| | 980 | .@"32" => .TLS_DTPOFF32, |
| | 981 | .@"64" => .TLS_DTPOFF64, |
| | 982 | } }, |
| 1145 | .X86_64 => .{ .X86_64 = .DTPOFF64 }, | 983 | .X86_64 => .{ .X86_64 = .DTPOFF64 }, |
| 1146 | }; | 984 | }; |
| 1147 | } | 985 | } |
| 1148 | pub fn tpOff(elf: *const Elf) MachineRelocType { | 986 | pub fn tpOff(elf: *const Elf) MachineRelocType { |
| 1149 | return switch (elf.ehdrMachine()) { | 987 | return switch (elf.ehdrMachine()) { |
| 1150 | .AARCH64 => .{ .AARCH64 = if (elf.identClass() == .@"64") .TLS_TPREL else .P32_TLS_TPREL }, | 988 | .AARCH64 => .{ .AARCH64 = switch (elf.identClass()) { |
| 1151 | .LOONGARCH => .{ .LARCH = if (elf.identClass() == .@"64") .TLS_TPREL64 else .TLS_TPREL32 }, | 989 | .NONE, _ => unreachable, |
| | 990 | .@"32" => .P32_TLS_TPREL, |
| | 991 | .@"64" => .TLS_TPREL, |
| | 992 | } }, |
| | 993 | .LOONGARCH => .{ .LARCH = switch (elf.identClass()) { |
| | 994 | .NONE, _ => unreachable, |
| | 995 | .@"32" => .TLS_TPREL32, |
| | 996 | .@"64" => .TLS_TPREL64, |
| | 997 | } }, |
| 1152 | .PPC64 => .{ .PPC64 = .TPREL64 }, | 998 | .PPC64 => .{ .PPC64 = .TPREL64 }, |
| 1153 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .TLS_TPREL64 else .TLS_TPREL32 }, | 999 | .RISCV => .{ .RISCV = switch (elf.identClass()) { |
| 1154 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .TLS_TPOFF64 else .TLS_TPOFF32 }, | 1000 | .NONE, _ => unreachable, |
| | 1001 | .@"32" => .TLS_TPREL32, |
| | 1002 | .@"64" => .TLS_TPREL64, |
| | 1003 | } }, |
| | 1004 | .SPARCV9 => .{ .SPARC = switch (elf.identClass()) { |
| | 1005 | .NONE, _ => unreachable, |
| | 1006 | .@"32" => .TLS_TPOFF32, |
| | 1007 | .@"64" => .TLS_TPOFF64, |
| | 1008 | } }, |
| 1155 | .X86_64 => .{ .X86_64 = .TPOFF64 }, | 1009 | .X86_64 => .{ .X86_64 = .TPOFF64 }, |
| 1156 | }; | 1010 | }; |
| 1157 | } | 1011 | } |
| 1158 | pub fn absAddr(elf: *const Elf) MachineRelocType { | 1012 | pub fn absAddr(elf: *const Elf) MachineRelocType { |
| | 1013 | return switch (elf.identClass()) { |
| | 1014 | .NONE, _ => unreachable, |
| | 1015 | .@"32" => .abs32(elf), |
| | 1016 | .@"64" => .abs64(elf), |
| | 1017 | }; |
| | 1018 | } |
| | 1019 | pub fn abs32(elf: *const Elf) MachineRelocType { |
| 1159 | return switch (elf.ehdrMachine()) { | 1020 | return switch (elf.ehdrMachine()) { |
| 1160 | .AARCH64 => .{ .AARCH64 = if (elf.identClass() == .@"64") .ABS64 else .P32_ABS32 }, | 1021 | .AARCH64 => .{ .AARCH64 = .P32_ABS32 }, |
| 1161 | .LOONGARCH => .{ .LARCH = if (elf.identClass() == .@"64") .@"64" else .@"32" }, | 1022 | .LOONGARCH => .{ .LARCH = .@"32" }, |
| | 1023 | .PPC64 => .{ .PPC64 = .ADDR32 }, |
| | 1024 | .RISCV => .{ .RISCV = .@"32" }, |
| | 1025 | .SPARCV9 => .{ .SPARC = .@"32" }, |
| | 1026 | .X86_64 => .{ .X86_64 = .@"32" }, |
| | 1027 | }; |
| | 1028 | } |
| | 1029 | pub fn abs64(elf: *const Elf) MachineRelocType { |
| | 1030 | return switch (elf.ehdrMachine()) { |
| | 1031 | .AARCH64 => .{ .AARCH64 = .ABS64 }, |
| | 1032 | .LOONGARCH => .{ .LARCH = .@"64" }, |
| 1162 | .PPC64 => .{ .PPC64 = .ADDR64 }, | 1033 | .PPC64 => .{ .PPC64 = .ADDR64 }, |
| 1163 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .@"64" else .@"32" }, | 1034 | .RISCV => .{ .RISCV = .@"64" }, |
| 1164 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .@"64" else .@"32" }, | 1035 | .SPARCV9 => .{ .SPARC = .@"64" }, |
| 1165 | .X86_64 => .{ .X86_64 = if (elf.identClass() == .@"64") .@"64" else .@"32" }, | 1036 | .X86_64 => .{ .X86_64 = .@"64" }, |
| | 1037 | }; |
| | 1038 | } |
| | 1039 | pub fn rel32(elf: *const Elf) MachineRelocType { |
| | 1040 | return switch (elf.ehdrMachine()) { |
| | 1041 | .AARCH64 => .{ .AARCH64 = .PREL32 }, |
| | 1042 | .LOONGARCH => .{ .LARCH = .@"32_PCREL" }, |
| | 1043 | .PPC64 => .{ .PPC64 = .REL32 }, |
| | 1044 | .RISCV => .{ .RISCV = .@"32_PCREL" }, |
| | 1045 | .SPARCV9 => .{ .SPARC = .DISP32 }, |
| | 1046 | .X86_64 => .{ .X86_64 = .PC32 }, |
| | 1047 | }; |
| | 1048 | } |
| | 1049 | pub fn rel64(elf: *const Elf) MachineRelocType { |
| | 1050 | return switch (elf.ehdrMachine()) { |
| | 1051 | .AARCH64 => .{ .AARCH64 = .PREL64 }, |
| | 1052 | .LOONGARCH => unreachable, |
| | 1053 | .PPC64 => .{ .PPC64 = .REL64 }, |
| | 1054 | .RISCV => unreachable, |
| | 1055 | .SPARCV9 => .{ .SPARC = .DISP64 }, |
| | 1056 | .X86_64 => .{ .X86_64 = .PC64 }, |
| 1166 | }; | 1057 | }; |
| 1167 | } | 1058 | } |
| 1168 | pub fn size32(elf: *const Elf) ?MachineRelocType { | 1059 | pub fn size32(elf: *const Elf) ?MachineRelocType { |
| ... | @@ -1265,15 +1156,6 @@ const SymbolReloc = struct { | ... | @@ -1265,15 +1156,6 @@ const SymbolReloc = struct { |
| 1265 | return shndx; | 1156 | return shndx; |
| 1266 | } | 1157 | } |
| 1267 | | 1158 | |
| 1268 | const Index = enum(u32) { | | |
| 1269 | none = std.math.maxInt(u32), | | |
| 1270 | _, | | |
| 1271 | | | |
| 1272 | fn get(index: SymbolReloc.Index, elf: *Elf) *SymbolReloc { | | |
| 1273 | return &elf.symbol_relocs.items[@backingInt(index)]; | | |
| 1274 | } | | |
| 1275 | }; | | |
| 1276 | | | |
| 1277 | /// Instead of using the ELF relocation enums, we have our own internal representation for | 1159 | /// Instead of using the ELF relocation enums, we have our own internal representation for |
| 1278 | /// relocation types. This representation is more compact (requiring only 16 bits), and allows | 1160 | /// relocation types. This representation is more compact (requiring only 16 bits), and allows |
| 1279 | /// sharing a lot of relocation handling between multiple relocs and target architectures. | 1161 | /// sharing a lot of relocation handling between multiple relocs and target architectures. |
| ... | @@ -1679,9 +1561,417 @@ const SymbolReloc = struct { | ... | @@ -1679,9 +1561,417 @@ const SymbolReloc = struct { |
| 1679 | } | 1561 | } |
| 1680 | }; | 1562 | }; |
| 1681 | | 1563 | |
| | 1564 | const Index = enum(u32) { |
| | 1565 | none = std.math.maxInt(u32), |
| | 1566 | _, |
| | 1567 | |
| | 1568 | fn get(index: SymbolReloc.Index, elf: *Elf) *SymbolReloc { |
| | 1569 | return &elf.symbol_relocs.items[@backingInt(index)]; |
| | 1570 | } |
| | 1571 | }; |
| | 1572 | |
| 1682 | fn apply(reloc: *SymbolReloc, elf: *Elf) void { | 1573 | fn apply(reloc: *SymbolReloc, elf: *Elf) void { |
| 1683 | assert(elf.ehdrType() != .REL); | 1574 | assert(elf.ehdrType() != .REL); |
| 1684 | if (reloc.node.hasMoved(&elf.mf) or reloc.target.hasMoved(elf)) { | 1575 | if (reloc.node.hasMoved(&elf.mf) or reloc.target.hasMoved(elf)) { |
| | 1576 | // There's no point applying the relocation now, because it will be re-applied by |
| | 1577 | // `flushMoved` at some point anyway. |
| | 1578 | return; |
| | 1579 | } |
| | 1580 | switch (reloc.result) { |
| | 1581 | .ok => {}, |
| | 1582 | .overflowed => elf.overflowed_reloc_count -= 1, |
| | 1583 | .misaligned => elf.misaligned_reloc_count -= 1, |
| | 1584 | } |
| | 1585 | if (reloc.applyInner(elf)) { |
| | 1586 | @branchHint(.likely); |
| | 1587 | reloc.result = .ok; |
| | 1588 | } else |err| switch (err) { |
| | 1589 | error.RelocationOverflow => { |
| | 1590 | reloc.result = .overflowed; |
| | 1591 | elf.overflowed_reloc_count += 1; |
| | 1592 | }, |
| | 1593 | error.RelocationMisaligned => { |
| | 1594 | reloc.result = .misaligned; |
| | 1595 | elf.misaligned_reloc_count += 1; |
| | 1596 | }, |
| | 1597 | } |
| | 1598 | } |
| | 1599 | fn applyInner(reloc: *const SymbolReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void { |
| | 1600 | const dest_vaddr = elf.getNodeVAddr(reloc.node) + reloc.offset; |
| | 1601 | const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..]; |
| | 1602 | |
| | 1603 | const addend: u64 = @bitCast(reloc.addend); |
| | 1604 | const target_val: u64 = type: switch (reloc.type.target) { |
| | 1605 | .abs => reloc.target.value(elf) +% addend, |
| | 1606 | .rel => reloc.target.value(elf) +% addend -% dest_vaddr, |
| | 1607 | .pltabs => { |
| | 1608 | const plt_entry_addr = elf.pltEntryTargetAddr(reloc.target) orelse continue :type .abs; |
| | 1609 | break :type plt_entry_addr +% addend; |
| | 1610 | }, |
| | 1611 | .pltrel => { |
| | 1612 | const plt_entry_addr = elf.pltEntryTargetAddr(reloc.target) orelse continue :type .rel; |
| | 1613 | break :type plt_entry_addr +% addend -% dest_vaddr; |
| | 1614 | }, |
| | 1615 | .dtpoff => reloc.target.value(elf) +% addend, |
| | 1616 | .tpoff => switch (elf.targetTlsVariant()) { |
| | 1617 | .I_original => |tls| tls.tcb_size +% reloc.target.value(elf) +% addend, |
| | 1618 | .I_modified => |tls| 0 -% tls.tp_off +% reloc.target.value(elf) +% addend, |
| | 1619 | .II => { |
| | 1620 | const tls_phndx = elf.getNode(elf.ni.tls.unwrap().?).segment; |
| | 1621 | const tls_size: u64 = switch (elf.phdrSlice()) { |
| | 1622 | inline else => |phdr| tls_size: { |
| | 1623 | assert(elf.targetLoad(&phdr[tls_phndx].type) == .TLS); |
| | 1624 | break :tls_size elf.targetLoad(&phdr[tls_phndx].memsz); |
| | 1625 | }, |
| | 1626 | }; |
| | 1627 | break :type reloc.target.value(elf) +% addend -% tls_size; |
| | 1628 | }, |
| | 1629 | }, |
| | 1630 | .size => switch (elf.symPtr(reloc.target.index(elf))) { |
| | 1631 | inline else => |sym| elf.targetLoad(&sym.size), |
| | 1632 | }, |
| | 1633 | .special => return reloc.type.action.special.applyInner( |
| | 1634 | elf, |
| | 1635 | reloc.target, |
| | 1636 | addend, |
| | 1637 | dest_vaddr, |
| | 1638 | dest_slice, |
| | 1639 | ), |
| | 1640 | }; |
| | 1641 | |
| | 1642 | // Check for the `R_*_RELATIVE` case now, because it is possible only when no shift or cast |
| | 1643 | // is required, meaning we can handle it now and return early. |
| | 1644 | if (reloc.rela_index.unwrap()) |rela_index| switch (elf.classifySymbolValue(reloc.target)) { |
| | 1645 | .static => unreachable, |
| | 1646 | .dynamic => return, // the relocation happens at runtime |
| | 1647 | .static_relative => { |
| | 1648 | // We have emitted an R_*_RELATIVE relocation to help lower an absolute-address |
| | 1649 | // relocation. The value computed above is valid, but instead of writing it to the |
| | 1650 | // destination slice, we actually want to write it to the runtime relocation entry. |
| | 1651 | switch (elf.identClass()) { |
| | 1652 | .NONE, _ => unreachable, |
| | 1653 | .@"32" => assert(reloc.type.action.simple.dest == .@"32"), |
| | 1654 | .@"64" => assert(reloc.type.action.simple.dest == .@"64"), |
| | 1655 | } |
| | 1656 | assert(reloc.type.action.simple.cast == .unsigned); |
| | 1657 | assert(reloc.type.action.simple.shift == .@"0"); |
| | 1658 | elf.shndx.rela_dyn.relaSetRelativeOffset(elf, rela_index, target_val); |
| | 1659 | return; |
| | 1660 | }, |
| | 1661 | }; |
| | 1662 | |
| | 1663 | try reloc.type.action.simple.write(target_val, dest_slice, elf.targetEndian()); |
| | 1664 | } |
| | 1665 | |
| | 1666 | fn delete(reloc: *SymbolReloc, elf: *Elf, index: SymbolReloc.Index) void { |
| | 1667 | assert(index.get(elf) == reloc); |
| | 1668 | |
| | 1669 | reloc.deleteOutputRel(elf); |
| | 1670 | if (reloc.type.dependsOnTlsSize(elf)) { |
| | 1671 | assert(elf.tls_size_symbol_relocs.swapRemove(index)); |
| | 1672 | } |
| | 1673 | |
| | 1674 | switch (reloc.prev) { |
| | 1675 | .none => { |
| | 1676 | const first_target_reloc = &reloc.target.index(elf).ptr(elf).first_target_reloc; |
| | 1677 | assert(first_target_reloc.* == index); |
| | 1678 | first_target_reloc.* = reloc.next; |
| | 1679 | }, |
| | 1680 | else => |prev| prev.get(elf).next = reloc.next, |
| | 1681 | } |
| | 1682 | switch (reloc.next) { |
| | 1683 | .none => {}, |
| | 1684 | else => |next| next.get(elf).prev = reloc.prev, |
| | 1685 | } |
| | 1686 | switch (reloc.result) { |
| | 1687 | .ok => {}, |
| | 1688 | .overflowed => elf.overflowed_reloc_count -= 1, |
| | 1689 | .misaligned => elf.misaligned_reloc_count -= 1, |
| | 1690 | } |
| | 1691 | |
| | 1692 | reloc.* = undefined; |
| | 1693 | } |
| | 1694 | |
| | 1695 | /// If `reloc.rela_index` is populated, reset it to `.none` and delete the relocation, updating |
| | 1696 | /// `elf.textrel_count` if necessary. |
| | 1697 | fn deleteOutputRel(reloc: *SymbolReloc, elf: *Elf) void { |
| | 1698 | const rela_index = reloc.rela_index.unwrap() orelse return; |
| | 1699 | reloc.relaSection(elf).relaDeleteOne(elf, rela_index); |
| | 1700 | switch (elf.ehdrType()) { |
| | 1701 | .REL => {}, |
| | 1702 | .EXEC, .DYN => switch (elf.nodeWantsDsoRelocation(reloc.node)) { |
| | 1703 | .no => unreachable, // there *was* a dynamic relocation! |
| | 1704 | .yes => {}, |
| | 1705 | .yes_textrel => elf.textrel_count -= 1, |
| | 1706 | }, |
| | 1707 | } |
| | 1708 | reloc.rela_index = .none; |
| | 1709 | } |
| | 1710 | }; |
| | 1711 | |
| | 1712 | /// A relocation targeting an arbitrary node (within a section) with a fixed addend. |
| | 1713 | /// This represents a symbol reloc against the section symbol containing the node |
| | 1714 | /// with a variable addend that changes when the target node moves. |
| | 1715 | const NodeReloc = struct { |
| | 1716 | node: MappedFile.Node.Index, |
| | 1717 | offset: u64, |
| | 1718 | target: MappedFile.Node.Index, |
| | 1719 | addend: i64, |
| | 1720 | type: NodeReloc.Type, |
| | 1721 | next: NodeReloc.Index, |
| | 1722 | prev: NodeReloc.Index, |
| | 1723 | rela_index: Section.RelaIndex.Optional, |
| | 1724 | result: enum(u8) { ok, overflowed, misaligned }, |
| | 1725 | |
| | 1726 | const Type = enum { abs32, abs64 }; |
| | 1727 | |
| | 1728 | const Index = enum(u32) { |
| | 1729 | none = std.math.maxInt(u32), |
| | 1730 | _, |
| | 1731 | |
| | 1732 | fn get(index: NodeReloc.Index, elf: *Elf) *NodeReloc { |
| | 1733 | return &elf.node_relocs.items[@backingInt(index)]; |
| | 1734 | } |
| | 1735 | }; |
| | 1736 | |
| | 1737 | fn apply(reloc: *NodeReloc, elf: *Elf) void { |
| | 1738 | assert(elf.ehdrType() != .REL); |
| | 1739 | if (reloc.node.hasMoved(&elf.mf) or reloc.target.hasMoved(&elf.mf)) { |
| | 1740 | // There's no point applying the relocation now, because it will be re-applied by |
| | 1741 | // `flushMoved` at some point anyway. |
| | 1742 | return; |
| | 1743 | } |
| | 1744 | switch (reloc.result) { |
| | 1745 | .ok => {}, |
| | 1746 | .overflowed => elf.overflowed_reloc_count -= 1, |
| | 1747 | .misaligned => elf.misaligned_reloc_count -= 1, |
| | 1748 | } |
| | 1749 | if (reloc.applyInner(elf)) { |
| | 1750 | @branchHint(.likely); |
| | 1751 | reloc.result = .ok; |
| | 1752 | } else |err| switch (err) { |
| | 1753 | error.RelocationOverflow => { |
| | 1754 | reloc.result = .overflowed; |
| | 1755 | elf.overflowed_reloc_count += 1; |
| | 1756 | }, |
| | 1757 | error.RelocationMisaligned => { |
| | 1758 | reloc.result = .misaligned; |
| | 1759 | elf.misaligned_reloc_count += 1; |
| | 1760 | }, |
| | 1761 | } |
| | 1762 | } |
| | 1763 | fn applyInner(reloc: *const NodeReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void { |
| | 1764 | const simple: SymbolReloc.Type.Simple = .{ .dest = switch (reloc.type) { |
| | 1765 | .abs32 => .@"32", |
| | 1766 | .abs64 => .@"64", |
| | 1767 | }, .cast = .unsigned, .shift = .@"0" }; |
| | 1768 | const addend: u64 = @bitCast(reloc.addend); |
| | 1769 | const target_val = elf.getNodeVAddr(reloc.target) +% addend; |
| | 1770 | const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..]; |
| | 1771 | try simple.write(target_val, dest_slice, elf.targetEndian()); |
| | 1772 | } |
| | 1773 | |
| | 1774 | fn delete(reloc: *NodeReloc, elf: *Elf) void { |
| | 1775 | reloc.deleteOutputRel(elf); |
| | 1776 | |
| | 1777 | switch (reloc.prev) { |
| | 1778 | .none => { |
| | 1779 | const first_target_reloc = switch (elf.getNode(reloc.target)) { |
| | 1780 | else => unreachable, |
| | 1781 | .unit_frame_cie => |ui| &elf.dwarf_units.items[@backingInt(ui)].unit_frame_cie_first_target_reloc, |
| | 1782 | }; |
| | 1783 | first_target_reloc.* = reloc.next; |
| | 1784 | }, |
| | 1785 | else => |prev| prev.get(elf).next = reloc.next, |
| | 1786 | } |
| | 1787 | switch (reloc.next) { |
| | 1788 | .none => {}, |
| | 1789 | else => |next| next.get(elf).prev = reloc.prev, |
| | 1790 | } |
| | 1791 | switch (reloc.result) { |
| | 1792 | .ok => {}, |
| | 1793 | .overflowed => elf.overflowed_reloc_count -= 1, |
| | 1794 | .misaligned => elf.misaligned_reloc_count -= 1, |
| | 1795 | } |
| | 1796 | |
| | 1797 | reloc.* = undefined; |
| | 1798 | } |
| | 1799 | |
| | 1800 | /// If `reloc.rela_index` is populated, reset it to `.none` and delete the relocation. |
| | 1801 | fn deleteOutputRel(reloc: *NodeReloc, elf: *Elf) void { |
| | 1802 | const rela_index = reloc.rela_index.unwrap() orelse return; |
| | 1803 | assert(elf.ehdrType() == .REL); |
| | 1804 | elf.getNodeShndx(reloc.node).get(elf).rela.shndx.relaDeleteOne(elf, rela_index); |
| | 1805 | reloc.rela_index = .none; |
| | 1806 | } |
| | 1807 | }; |
| | 1808 | |
| | 1809 | /// Identifies a single entry in the GOT. |
| | 1810 | const GotKey = union(enum) { |
| | 1811 | /// The entry is a reserved word, initialized to zero. `initHeaders` will add as many of these |
| | 1812 | /// as the target machine ABI requires. |
| | 1813 | /// |
| | 1814 | /// This `u32` value exists to allow reserving multiple words with distinct keys. |
| | 1815 | reserved: u32, |
| | 1816 | |
| | 1817 | /// Value is the address of the given symbol. |
| | 1818 | symbol: Symbol.Id, |
| | 1819 | |
| | 1820 | /// Value is the signed offset of the given symbol from the TLS pointer. |
| | 1821 | tpoff: Symbol.Id, |
| | 1822 | |
| | 1823 | /// Value is the TLS module ID of the DSO we are creating. |
| | 1824 | /// |
| | 1825 | /// Used for the first of the two GOT entries generated by a TLSLD relocation. |
| | 1826 | tlsld0, |
| | 1827 | /// Value is always 0. |
| | 1828 | /// |
| | 1829 | /// Used for the second of the two GOT entries generated by a TLSLD relocation. |
| | 1830 | tlsld1, |
| | 1831 | |
| | 1832 | /// Value is the TLS module ID for the given STT_TLS symbol. |
| | 1833 | /// |
| | 1834 | /// Used for the first of the two GOT entries generated by a TLSGD relocation. |
| | 1835 | tlsgd0: Symbol.Id, |
| | 1836 | /// Value is the offset of the given STT_TLS symbol from the base of the per-module TLS area. |
| | 1837 | /// |
| | 1838 | /// Used for the second of the two GOT entries generated by a TLSGD relocation. |
| | 1839 | tlsgd1: Symbol.Id, |
| | 1840 | }; |
| | 1841 | |
| | 1842 | /// A relocation targeting a particular GOT entry. |
| | 1843 | const GotReloc = struct { |
| | 1844 | /// The node containing this relocation. Possible values are: |
| | 1845 | /// * An input section |
| | 1846 | /// * A section |
| | 1847 | /// * A NAV, UAV, or lazy code/data |
| | 1848 | /// * `.none`, if this relocation was deleted (in which case it should be ignored) |
| | 1849 | node: MappedFile.Node.Index.Optional, |
| | 1850 | /// The offset of the relocation inside of `node`. |
| | 1851 | offset: u64, |
| | 1852 | target: GotKey, |
| | 1853 | addend: i64, |
| | 1854 | type: GotReloc.Type, |
| | 1855 | result: enum(u8) { ok, overflowed, misaligned }, |
| | 1856 | |
| | 1857 | /// `GotReloc.Type` has the same structure as `SymbolReloc.Type`, just with different `Target` |
| | 1858 | /// and `Special` enums---consult doc comments on `SymbolReloc.Type` for an overview. |
| | 1859 | const Type = packed struct(u16) { |
| | 1860 | fn simple(target: Target, action: Simple) GotReloc.Type { |
| | 1861 | assert(target != .special); |
| | 1862 | return .{ .target = target, .action = .{ .simple = action } }; |
| | 1863 | } |
| | 1864 | |
| | 1865 | fn special(s: Special) GotReloc.Type { |
| | 1866 | return .{ .target = .special, .action = .{ .special = s } }; |
| | 1867 | } |
| | 1868 | |
| | 1869 | target: Target, |
| | 1870 | action: packed union { |
| | 1871 | simple: Simple, |
| | 1872 | special: Special, |
| | 1873 | }, |
| | 1874 | |
| | 1875 | /// Like `SymbolReloc.Target`, but for GOT relocations. There are fewer tags because there |
| | 1876 | /// are fewer different kinds of GOT relocation. |
| | 1877 | const Target = enum(u3) { |
| | 1878 | /// This is a "special" relocation whose specific type is in the `action.special` field. |
| | 1879 | special, |
| | 1880 | |
| | 1881 | /// Absolute address of the GOT entry. |
| | 1882 | abs, |
| | 1883 | /// Offset from the relocation itself to the GOT entry ("PC-relative"). |
| | 1884 | rel, |
| | 1885 | /// Offset from the base of the GOT to the GOT entry. |
| | 1886 | offset, |
| | 1887 | }; |
| | 1888 | |
| | 1889 | const Simple = SymbolReloc.Type.Simple; |
| | 1890 | |
| | 1891 | /// Like `SymbolReloc.Special`, but for GOT relocations. |
| | 1892 | const Special = enum(u13) { |
| | 1893 | larch_pcala_hi20, |
| | 1894 | larch_pcala64_lo20, |
| | 1895 | larch_pcala64_hi12, |
| | 1896 | |
| | 1897 | sparc_op_lox10, |
| | 1898 | sparc_op_hix22, |
| | 1899 | |
| | 1900 | fn applyInner( |
| | 1901 | s: Special, |
| | 1902 | elf: *Elf, |
| | 1903 | got_vaddr: u64, |
| | 1904 | got_offset: u64, |
| | 1905 | addend: u64, |
| | 1906 | dest_vaddr: u64, |
| | 1907 | dest_slice: []u8, |
| | 1908 | ) error{ RelocationMisaligned, RelocationOverflow }!void { |
| | 1909 | switch (s) { |
| | 1910 | .larch_pcala_hi20 => { |
| | 1911 | const val = got_vaddr +% got_offset +% addend; |
| | 1912 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); |
| | 1913 | elf.targetStore(inst, .{ |
| | 1914 | .b0_4 = elf.targetLoad(inst).b0_4, |
| | 1915 | .j20 = link.loongarch.pcalaHi20(val, dest_vaddr), |
| | 1916 | .b25_31 = elf.targetLoad(inst).b25_31, |
| | 1917 | }); |
| | 1918 | }, |
| | 1919 | .larch_pcala64_lo20 => { |
| | 1920 | const val = got_vaddr +% got_offset +% addend; |
| | 1921 | const inst: *align(1) link.loongarch.J20 = @ptrCast(dest_slice[0..4]); |
| | 1922 | elf.targetStore(inst, .{ |
| | 1923 | .b0_4 = elf.targetLoad(inst).b0_4, |
| | 1924 | .j20 = link.loongarch.pcala64Lo20(val, dest_vaddr), |
| | 1925 | .b25_31 = elf.targetLoad(inst).b25_31, |
| | 1926 | }); |
| | 1927 | }, |
| | 1928 | .larch_pcala64_hi12 => { |
| | 1929 | const val = got_vaddr +% got_offset +% addend; |
| | 1930 | const inst: *align(1) link.loongarch.K12 = @ptrCast(dest_slice[0..4]); |
| | 1931 | elf.targetStore(inst, .{ |
| | 1932 | .b0_9 = elf.targetLoad(inst).b0_9, |
| | 1933 | .k12 = link.loongarch.pcala64Hi12(val, dest_vaddr), |
| | 1934 | .b22_31 = elf.targetLoad(inst).b22_31, |
| | 1935 | }); |
| | 1936 | }, |
| | 1937 | .sparc_op_lox10 => { |
| | 1938 | const dest_ptr: *align(1) packed struct(u32) { |
| | 1939 | imm13: u13, |
| | 1940 | b13_31: u19, |
| | 1941 | } = @ptrCast(dest_slice); |
| | 1942 | elf.targetStore(dest_ptr, .{ |
| | 1943 | .imm13 = @as(u10, @truncate(got_offset)), |
| | 1944 | .b13_31 = elf.targetLoad(dest_ptr).b13_31, |
| | 1945 | }); |
| | 1946 | }, |
| | 1947 | .sparc_op_hix22 => { |
| | 1948 | const dest_ptr: *align(1) packed struct(u32) { |
| | 1949 | imm22: u22, |
| | 1950 | b22_31: u10, |
| | 1951 | } = @ptrCast(dest_slice); |
| | 1952 | elf.targetStore(dest_ptr, .{ |
| | 1953 | .imm22 = @truncate(got_offset >> 10), |
| | 1954 | .b22_31 = elf.targetLoad(dest_ptr).b22_31, |
| | 1955 | }); |
| | 1956 | }, |
| | 1957 | } |
| | 1958 | } |
| | 1959 | }; |
| | 1960 | }; |
| | 1961 | |
| | 1962 | const Index = enum(u32) { |
| | 1963 | none = std.math.maxInt(u32), |
| | 1964 | _, |
| | 1965 | |
| | 1966 | fn get(index: GotReloc.Index, elf: *Elf) *GotReloc { |
| | 1967 | return &elf.got_relocs.items[@backingInt(index)]; |
| | 1968 | } |
| | 1969 | }; |
| | 1970 | |
| | 1971 | fn apply(reloc: *GotReloc, elf: *Elf) void { |
| | 1972 | assert(elf.ehdrType() != .REL); |
| | 1973 | const node = reloc.node.unwrap() orelse return; // deleted |
| | 1974 | if (node.hasMoved(&elf.mf) or elf.shndx.got.get(elf).ni.hasMoved(&elf.mf)) { |
| 1685 | // There's no point applying the relocation now, because it will be re-applied by | 1975 | // There's no point applying the relocation now, because it will be re-applied by |
| 1686 | // `flushMoved` at some point anyway. | 1976 | // `flushMoved` at some point anyway. |
| 1687 | return; | 1977 | return; |
| ... | @@ -1705,118 +1995,99 @@ const SymbolReloc = struct { | ... | @@ -1705,118 +1995,99 @@ const SymbolReloc = struct { |
| 1705 | }, | 1995 | }, |
| 1706 | } | 1996 | } |
| 1707 | } | 1997 | } |
| 1708 | fn applyInner(reloc: *const SymbolReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void { | 1998 | fn applyInner(reloc: *const GotReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void { |
| 1709 | const dest_vaddr = elf.getNodeVAddr(reloc.node) + reloc.offset; | 1999 | const node = reloc.node.unwrap().?; |
| 1710 | const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..]; | 2000 | const dest_vaddr = elf.getNodeVAddr(node) + reloc.offset; |
| | 2001 | const dest_slice = node.slice(&elf.mf)[@intCast(reloc.offset)..]; |
| 1711 | | 2002 | |
| | 2003 | const got_vaddr = elf.shndx.got.vaddr(elf); |
| | 2004 | const got_index: u64 = elf.got.getIndex(reloc.target).?; |
| | 2005 | const got_offset: u64 = switch (elf.identClass()) { |
| | 2006 | .NONE, _ => unreachable, |
| | 2007 | inline else => |class| @sizeOf(class.ElfN().Addr) * got_index, |
| | 2008 | }; |
| 1712 | const addend: u64 = @bitCast(reloc.addend); | 2009 | const addend: u64 = @bitCast(reloc.addend); |
| 1713 | const target_val: u64 = type: switch (reloc.type.target) { | 2010 | |
| 1714 | .abs => reloc.target.value(elf) +% addend, | 2011 | const target_val: u64 = switch (reloc.type.target) { |
| 1715 | .rel => reloc.target.value(elf) +% addend -% dest_vaddr, | 2012 | .abs => got_vaddr +% got_offset +% addend, |
| 1716 | .pltabs => { | 2013 | .rel => got_vaddr +% got_offset +% addend -% dest_vaddr, |
| 1717 | const plt_entry_addr = elf.pltEntryTargetAddr(reloc.target) orelse continue :type .abs; | 2014 | .offset => got_offset +% addend, |
| 1718 | break :type plt_entry_addr +% addend; | | |
| 1719 | }, | | |
| 1720 | .pltrel => { | | |
| 1721 | const plt_entry_addr = elf.pltEntryTargetAddr(reloc.target) orelse continue :type .rel; | | |
| 1722 | break :type plt_entry_addr +% addend -% dest_vaddr; | | |
| 1723 | }, | | |
| 1724 | .dtpoff => reloc.target.value(elf) +% addend, | | |
| 1725 | .tpoff => switch (elf.targetTlsVariant()) { | | |
| 1726 | .I_original => |tls| tls.tcb_size +% reloc.target.value(elf) +% addend, | | |
| 1727 | .I_modified => |tls| 0 -% tls.tp_off +% reloc.target.value(elf) +% addend, | | |
| 1728 | .II => { | | |
| 1729 | const tls_phndx = elf.getNode(elf.ni.tls.unwrap().?).segment; | | |
| 1730 | const tls_size: u64 = switch (elf.phdrSlice()) { | | |
| 1731 | inline else => |phdr| tls_size: { | | |
| 1732 | assert(elf.targetLoad(&phdr[tls_phndx].type) == .TLS); | | |
| 1733 | break :tls_size elf.targetLoad(&phdr[tls_phndx].memsz); | | |
| 1734 | }, | | |
| 1735 | }; | | |
| 1736 | break :type reloc.target.value(elf) +% addend -% tls_size; | | |
| 1737 | }, | | |
| 1738 | }, | | |
| 1739 | .size => switch (elf.symPtr(reloc.target.index(elf))) { | | |
| 1740 | inline else => |sym| elf.targetLoad(&sym.size), | | |
| 1741 | }, | | |
| 1742 | .special => return reloc.type.action.special.applyInner( | 2015 | .special => return reloc.type.action.special.applyInner( |
| 1743 | elf, | 2016 | elf, |
| 1744 | reloc.target, | 2017 | got_vaddr, |
| | 2018 | got_offset, |
| 1745 | addend, | 2019 | addend, |
| 1746 | dest_vaddr, | 2020 | dest_vaddr, |
| 1747 | dest_slice, | 2021 | dest_slice, |
| 1748 | ), | 2022 | ), |
| 1749 | }; | 2023 | }; |
| 1750 | | | |
| 1751 | // Check for the `R_*_RELATIVE` case now, because it is possible only when no shift or cast | | |
| 1752 | // is required, meaning we can handle it now and return early. | | |
| 1753 | if (reloc.rela_index.unwrap()) |rela_index| switch (elf.classifySymbolValue(reloc.target)) { | | |
| 1754 | .static => unreachable, | | |
| 1755 | .dynamic => return, // the relocation happens at runtime | | |
| 1756 | .static_relative => { | | |
| 1757 | // We have emitted an R_*_RELATIVE relocation to help lower an absolute-address | | |
| 1758 | // relocation. The value computed above is valid, but instead of writing it to the | | |
| 1759 | // destination slice, we actually want to write it to the runtime relocation entry. | | |
| 1760 | switch (elf.identClass()) { | | |
| 1761 | .NONE, _ => unreachable, | | |
| 1762 | .@"32" => assert(reloc.type.action.simple.dest == .@"32"), | | |
| 1763 | .@"64" => assert(reloc.type.action.simple.dest == .@"64"), | | |
| 1764 | } | | |
| 1765 | assert(reloc.type.action.simple.cast == .unsigned); | | |
| 1766 | assert(reloc.type.action.simple.shift == .@"0"); | | |
| 1767 | elf.shndx.rela_dyn.relaSetRelativeOffset(elf, rela_index, target_val); | | |
| 1768 | return; | | |
| 1769 | }, | | |
| 1770 | }; | | |
| 1771 | | | |
| 1772 | try reloc.type.action.simple.write(target_val, dest_slice, elf.targetEndian()); | 2024 | try reloc.type.action.simple.write(target_val, dest_slice, elf.targetEndian()); |
| 1773 | } | 2025 | } |
| 1774 | | 2026 | |
| 1775 | fn delete(reloc: *SymbolReloc, elf: *Elf, index: SymbolReloc.Index) void { | 2027 | fn delete(reloc: *GotReloc, elf: *Elf) void { |
| 1776 | assert(index.get(elf) == reloc); | | |
| 1777 | | | |
| 1778 | reloc.deleteOutputRel(elf); | | |
| 1779 | if (reloc.type.dependsOnTlsSize(elf)) { | | |
| 1780 | assert(elf.tls_size_symbol_relocs.swapRemove(index)); | | |
| 1781 | } | | |
| 1782 | | | |
| 1783 | switch (reloc.prev) { | | |
| 1784 | .none => { | | |
| 1785 | const target_ptr = reloc.target.index(elf).ptr(elf); | | |
| 1786 | assert(target_ptr.first_target_reloc == index); | | |
| 1787 | target_ptr.first_target_reloc = reloc.next; | | |
| 1788 | }, | | |
| 1789 | else => |prev| prev.get(elf).next = reloc.next, | | |
| 1790 | } | | |
| 1791 | switch (reloc.next) { | | |
| 1792 | .none => {}, | | |
| 1793 | else => |next| next.get(elf).prev = reloc.prev, | | |
| 1794 | } | | |
| 1795 | switch (reloc.result) { | 2028 | switch (reloc.result) { |
| 1796 | .ok => {}, | 2029 | .ok => {}, |
| 1797 | .overflowed => elf.overflowed_reloc_count -= 1, | 2030 | .overflowed => elf.overflowed_reloc_count -= 1, |
| 1798 | .misaligned => elf.misaligned_reloc_count -= 1, | 2031 | .misaligned => elf.misaligned_reloc_count -= 1, |
| 1799 | } | 2032 | } |
| | 2033 | reloc.* = .{ |
| | 2034 | .node = .none, |
| | 2035 | .offset = undefined, |
| | 2036 | .target = undefined, |
| | 2037 | .addend = undefined, |
| | 2038 | .type = undefined, |
| | 2039 | .result = undefined, |
| | 2040 | }; |
| | 2041 | } |
| | 2042 | }; |
| 1800 | | 2043 | |
| 1801 | reloc.* = undefined; | 2044 | fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe_global }) Error!void { |
| | 2045 | const gpa = elf.base.comp.gpa; |
| | 2046 | |
| | 2047 | try elf.symtab.ensureUnusedCapacity(gpa, len); |
| | 2048 | |
| | 2049 | // If adding locals, we may need to move one global out of the way for each local. If adding |
| | 2050 | // globals, they could all get demoted to STB_LOCAL, meaning we have to move N other globals |
| | 2051 | // around to keep `.dynsym` compact. Either way, the maximum is N. |
| | 2052 | try elf.changed_symtab_index.ensureUnusedCapacity(gpa, len); |
| | 2053 | |
| | 2054 | { |
| | 2055 | // Ensure the symtab section's node is big enough |
| | 2056 | const need_node_size: u64 = switch (elf.shdrPtr(.symtab)) { |
| | 2057 | inline else => |shdr, class| elf.targetLoad(&shdr.size) + len * @sizeOf(class.ElfN().Sym), |
| | 2058 | }; |
| | 2059 | try Section.Index.symtab.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, need_node_size); |
| 1802 | } | 2060 | } |
| 1803 | | 2061 | |
| 1804 | /// If `reloc.rela_index` is populated, reset it to `.none` and delete the relocation, updating | 2062 | switch (kind) { |
| 1805 | /// `elf.textrel_count` if necessary. | 2063 | .all_local => {}, |
| 1806 | fn deleteOutputRel(reloc: *SymbolReloc, elf: *Elf) void { | 2064 | .maybe_global => { |
| 1807 | const rela_index = reloc.rela_index.unwrap() orelse return; | 2065 | try elf.globals.strong_def.ensureUnusedCapacity(gpa, len); |
| 1808 | reloc.relaSection(elf).relaDeleteOne(elf, rela_index); | 2066 | try elf.globals.weak_def.ensureUnusedCapacity(gpa, len); |
| 1809 | switch (elf.ehdrType()) { | 2067 | try elf.globals.strong_undef.ensureUnusedCapacity(gpa, len); |
| 1810 | .REL => {}, | 2068 | try elf.globals.weak_undef.ensureUnusedCapacity(gpa, len); |
| 1811 | .EXEC, .DYN => switch (elf.nodeWantsDsoRelocation(reloc.node)) { | 2069 | |
| 1812 | .no => unreachable, // there *was* a dynamic relocation! | 2070 | try elf.node_global_symbols.ensureUnusedCapacity(gpa, len); |
| 1813 | .yes => {}, | 2071 | |
| 1814 | .yes_textrel => elf.textrel_count -= 1, | 2072 | if (elf.shndx.dynsym != .UNDEF) { |
| 1815 | }, | 2073 | const dynsym_cur_size: u64, const dynsym_ent_size: u32 = switch (elf.shdrPtr(elf.shndx.dynsym)) { |
| 1816 | } | 2074 | inline else => |shdr, class| .{ |
| 1817 | reloc.rela_index = .none; | 2075 | elf.targetLoad(&shdr.size), |
| | 2076 | @sizeOf(class.ElfN().Sym), |
| | 2077 | }, |
| | 2078 | }; |
| | 2079 | const dynsym_cur_len: u32 = @intCast(@divExact(dynsym_cur_size, dynsym_ent_size)); |
| | 2080 | |
| | 2081 | const dynsym_need_size: u64 = (dynsym_cur_len + len) * dynsym_ent_size; |
| | 2082 | try elf.shndx.dynsym.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, dynsym_need_size); |
| | 2083 | |
| | 2084 | try elf.ensureDynsymHashCapacity(dynsym_cur_len + len); |
| | 2085 | |
| | 2086 | try elf.ensureUnusedPltCapacity(len); |
| | 2087 | } |
| | 2088 | }, |
| 1818 | } | 2089 | } |
| 1819 | }; | 2090 | } |
| 1820 | | 2091 | |
| 1821 | fn ensureDynsymHashCapacity(elf: *Elf, max_dynsym_count: u32) Error!void { | 2092 | fn ensureDynsymHashCapacity(elf: *Elf, max_dynsym_count: u32) Error!void { |
| 1822 | const gpa = elf.base.comp.gpa; | 2093 | const gpa = elf.base.comp.gpa; |
| ... | @@ -1984,53 +2255,6 @@ fn clearDynsymHashEntry(elf: *Elf, dynsym_index: u32) void { | ... | @@ -1984,53 +2255,6 @@ fn clearDynsymHashEntry(elf: *Elf, dynsym_index: u32) void { |
| 1984 | } | 2255 | } |
| 1985 | } | 2256 | } |
| 1986 | | 2257 | |
| 1987 | fn ensureUnusedSymbolCapacity(elf: *Elf, len: u32, kind: enum { all_local, maybe_global }) Error!void { | | |
| 1988 | const gpa = elf.base.comp.gpa; | | |
| 1989 | | | |
| 1990 | try elf.symtab.ensureUnusedCapacity(gpa, len); | | |
| 1991 | | | |
| 1992 | // If adding locals, we may need to move one global out of the way for each local. If adding | | |
| 1993 | // globals, they could all get demoted to STB_LOCAL, meaning we have to move N other globals | | |
| 1994 | // around to keep `.dynsym` compact. Either way, the maximum is N. | | |
| 1995 | try elf.changed_symtab_index.ensureUnusedCapacity(gpa, len); | | |
| 1996 | | | |
| 1997 | { | | |
| 1998 | // Ensure the symtab section's node is big enough | | |
| 1999 | const need_node_size: u64 = switch (elf.shdrPtr(.symtab)) { | | |
| 2000 | inline else => |shdr, class| elf.targetLoad(&shdr.size) + len * @sizeOf(class.ElfN().Sym), | | |
| 2001 | }; | | |
| 2002 | try Section.Index.symtab.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, need_node_size); | | |
| 2003 | } | | |
| 2004 | | | |
| 2005 | switch (kind) { | | |
| 2006 | .all_local => {}, | | |
| 2007 | .maybe_global => { | | |
| 2008 | try elf.globals.strong_def.ensureUnusedCapacity(gpa, len); | | |
| 2009 | try elf.globals.weak_def.ensureUnusedCapacity(gpa, len); | | |
| 2010 | try elf.globals.strong_undef.ensureUnusedCapacity(gpa, len); | | |
| 2011 | try elf.globals.weak_undef.ensureUnusedCapacity(gpa, len); | | |
| 2012 | | | |
| 2013 | try elf.node_global_symbols.ensureUnusedCapacity(gpa, len); | | |
| 2014 | | | |
| 2015 | if (elf.shndx.dynsym != .UNDEF) { | | |
| 2016 | const dynsym_cur_size: u64, const dynsym_ent_size: u32 = switch (elf.shdrPtr(elf.shndx.dynsym)) { | | |
| 2017 | inline else => |shdr, class| .{ | | |
| 2018 | elf.targetLoad(&shdr.size), | | |
| 2019 | @sizeOf(class.ElfN().Sym), | | |
| 2020 | }, | | |
| 2021 | }; | | |
| 2022 | const dynsym_cur_len: u32 = @intCast(@divExact(dynsym_cur_size, dynsym_ent_size)); | | |
| 2023 | | | |
| 2024 | const dynsym_need_size: u64 = (dynsym_cur_len + len) * dynsym_ent_size; | | |
| 2025 | try elf.shndx.dynsym.get(elf).ni.ensureMinimumSize(&elf.mf, gpa, dynsym_need_size); | | |
| 2026 | | | |
| 2027 | try elf.ensureDynsymHashCapacity(dynsym_cur_len + len); | | |
| 2028 | | | |
| 2029 | try elf.ensureUnusedPltCapacity(len); | | |
| 2030 | } | | |
| 2031 | }, | | |
| 2032 | } | | |
| 2033 | } | | |
| 2034 | fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void { | 2258 | fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void { |
| 2035 | const gpa = elf.base.comp.gpa; | 2259 | const gpa = elf.base.comp.gpa; |
| 2036 | | 2260 | |
| ... | @@ -2138,7 +2362,7 @@ fn addLocalSymbolAssumeCapacity(elf: *Elf, opts: AddLocalSymbolOptions) Symbol.L | ... | @@ -2138,7 +2362,7 @@ fn addLocalSymbolAssumeCapacity(elf: *Elf, opts: AddLocalSymbolOptions) Symbol.L |
| 2138 | .other = .{ .visibility = .DEFAULT }, | 2362 | .other = .{ .visibility = .DEFAULT }, |
| 2139 | .shndx = opts.shndx.toSection().?, | 2363 | .shndx = opts.shndx.toSection().?, |
| 2140 | }; | 2364 | }; |
| 2141 | if (elf.targetEndian() != native_endian) { | 2365 | if (elf.targetEndian() != std.lang.Endian.native) { |
| 2142 | std.mem.byteSwapAllFields(class.ElfN().Sym, target_sym); | 2366 | std.mem.byteSwapAllFields(class.ElfN().Sym, target_sym); |
| 2143 | } | 2367 | } |
| 2144 | | 2368 | |
| ... | @@ -2323,7 +2547,7 @@ fn addGlobalSymbolAssumeCapacity(elf: *Elf, opts: AddGlobalSymbolOptions) error{ | ... | @@ -2323,7 +2547,7 @@ fn addGlobalSymbolAssumeCapacity(elf: *Elf, opts: AddGlobalSymbolOptions) error{ |
| 2323 | .other = .{ .visibility = opts.visibility }, | 2547 | .other = .{ .visibility = opts.visibility }, |
| 2324 | .shndx = opts.shndx.toSection().?, | 2548 | .shndx = opts.shndx.toSection().?, |
| 2325 | }; | 2549 | }; |
| 2326 | if (elf.targetEndian() != native_endian) { | 2550 | if (elf.targetEndian() != std.lang.Endian.native) { |
| 2327 | std.mem.byteSwapAllFields(Sym, sym); | 2551 | std.mem.byteSwapAllFields(Sym, sym); |
| 2328 | } | 2552 | } |
| 2329 | }, | 2553 | }, |
| ... | @@ -2359,7 +2583,7 @@ fn addGlobalSymbolAssumeCapacity(elf: *Elf, opts: AddGlobalSymbolOptions) error{ | ... | @@ -2359,7 +2583,7 @@ fn addGlobalSymbolAssumeCapacity(elf: *Elf, opts: AddGlobalSymbolOptions) error{ |
| 2359 | .other = .{ .visibility = opts.visibility }, | 2583 | .other = .{ .visibility = opts.visibility }, |
| 2360 | .shndx = opts.shndx.toSection().?, | 2584 | .shndx = opts.shndx.toSection().?, |
| 2361 | }; | 2585 | }; |
| 2362 | if (elf.targetEndian() != native_endian) { | 2586 | if (elf.targetEndian() != std.lang.Endian.native) { |
| 2363 | std.mem.byteSwapAllFields(Sym, sym); | 2587 | std.mem.byteSwapAllFields(Sym, sym); |
| 2364 | } | 2588 | } |
| 2365 | elf.appendDynsymHashEntry(dynsym_index); | 2589 | elf.appendDynsymHashEntry(dynsym_index); |
| ... | @@ -2991,10 +3215,18 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId { | ... | @@ -2991,10 +3215,18 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId { |
| 2991 | .shdr, | 3215 | .shdr, |
| 2992 | .segment, | 3216 | .segment, |
| 2993 | .section, | 3217 | .section, |
| | 3218 | .section_manual_size, |
| 2994 | .input_section, | 3219 | .input_section, |
| 2995 | .copied_global, | 3220 | .copied_global, |
| | 3221 | .value_debug_info, |
| | 3222 | .global_debug_info, |
| | 3223 | .frame_padding, |
| | 3224 | .unit_frame, |
| | 3225 | .unit_frame_cie, |
| | 3226 | .func_frame_fde, |
| | 3227 | .func_debug_info, |
| | 3228 | .func_debug_line, |
| 2996 | => unreachable, | 3229 | => unreachable, |
| 2997 | | | |
| 2998 | inline .nav, | 3230 | inline .nav, |
| 2999 | .uav, | 3231 | .uav, |
| 3000 | .lazy_code, | 3232 | .lazy_code, |
| ... | @@ -3025,7 +3257,7 @@ fn lazySymbolInner(elf: *Elf, lazy: link.File.LazySymbol) Error!link.File.Symbol | ... | @@ -3025,7 +3257,7 @@ fn lazySymbolInner(elf: *Elf, lazy: link.File.LazySymbol) Error!link.File.Symbol |
| 3025 | .const_data => .{ .rodata, .OBJECT }, | 3257 | .const_data => .{ .rodata, .OBJECT }, |
| 3026 | }; | 3258 | }; |
| 3027 | const node = try shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{}); | 3259 | const node = try shndx.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{}); |
| 3028 | var name_buf: [64]u8 = undefined; | 3260 | var name_buf: [std.fmt.count("__lazy_const_data_{d}", .{std.math.maxInt(u32)})]u8 = undefined; |
| 3029 | const name = std.mem.print( | 3261 | const name = std.mem.print( |
| 3030 | &name_buf, | 3262 | &name_buf, |
| 3031 | "__lazy_{t}_{d}", | 3263 | "__lazy_{t}_{d}", |
| ... | @@ -3114,6 +3346,24 @@ pub fn addReloc( | ... | @@ -3114,6 +3346,24 @@ pub fn addReloc( |
| 3114 | else => |e| return e, | 3346 | else => |e| return e, |
| 3115 | }; | 3347 | }; |
| 3116 | } | 3348 | } |
| | 3349 | pub fn addNodeReloc( |
| | 3350 | elf: *Elf, |
| | 3351 | node: MappedFile.Node.Index, |
| | 3352 | offset: u64, |
| | 3353 | target: MappedFile.Node.Index, |
| | 3354 | addend: i64, |
| | 3355 | @"type": NodeReloc.Type, |
| | 3356 | ) link.Error!void { |
| | 3357 | const diags = &elf.base.comp.link_diags; |
| | 3358 | elf.ensureUnusedRelocCapacity(node, 1) catch |err| switch (err) { |
| | 3359 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), |
| | 3360 | else => |e| return e, |
| | 3361 | }; |
| | 3362 | elf.addNodeRelocAssumeCapacity(node, offset, target, addend, @"type") catch |err| switch (err) { |
| | 3363 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), |
| | 3364 | else => |e| return e, |
| | 3365 | }; |
| | 3366 | } |
| 3117 | pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) link.Error!link.File.SymbolId { | 3367 | pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) link.Error!link.File.SymbolId { |
| 3118 | const diags = &elf.base.comp.link_diags; | 3368 | const diags = &elf.base.comp.link_diags; |
| 3119 | const zcu = elf.base.comp.zcu.?; | 3369 | const zcu = elf.base.comp.zcu.?; |
| ... | @@ -3393,6 +3643,7 @@ fn create( | ... | @@ -3393,6 +3643,7 @@ fn create( |
| 3393 | .data = undefined, | 3643 | .data = undefined, |
| 3394 | .data_rel_ro = undefined, | 3644 | .data_rel_ro = undefined, |
| 3395 | .tls = .none, | 3645 | .tls = .none, |
| | 3646 | .gnu_eh_frame = .none, |
| 3396 | }, | 3647 | }, |
| 3397 | .archive = null, | 3648 | .archive = null, |
| 3398 | .nodes = .empty, | 3649 | .nodes = .empty, |
| ... | @@ -3410,6 +3661,11 @@ fn create( | ... | @@ -3410,6 +3661,11 @@ fn create( |
| 3410 | .tdata = .UNDEF, | 3661 | .tdata = .UNDEF, |
| 3411 | .rela_dyn = .UNDEF, | 3662 | .rela_dyn = .UNDEF, |
| 3412 | .rela_plt = .UNDEF, | 3663 | .rela_plt = .UNDEF, |
| | 3664 | .eh_frame_hdr = .UNDEF, |
| | 3665 | .eh_frame = .UNDEF, |
| | 3666 | .debug_frame = .UNDEF, |
| | 3667 | .debug_info = .UNDEF, |
| | 3668 | .debug_line = .UNDEF, |
| 3413 | .init_array = .UNDEF, | 3669 | .init_array = .UNDEF, |
| 3414 | .fini_array = .UNDEF, | 3670 | .fini_array = .UNDEF, |
| 3415 | .preinit_array = .UNDEF, | 3671 | .preinit_array = .UNDEF, |
| ... | @@ -3437,6 +3693,7 @@ fn create( | ... | @@ -3437,6 +3693,7 @@ fn create( |
| 3437 | .got = .empty, | 3693 | .got = .empty, |
| 3438 | .plt = .empty, | 3694 | .plt = .empty, |
| 3439 | .plt_first_symbol_reloc = .none, | 3695 | .plt_first_symbol_reloc = .none, |
| | 3696 | .eh_frame_hdr_first_symbol_reloc = .none, |
| 3440 | .needed = .empty, | 3697 | .needed = .empty, |
| 3441 | .inputs = .empty, | 3698 | .inputs = .empty, |
| 3442 | .input_pending_index = 0, | 3699 | .input_pending_index = 0, |
| ... | @@ -3451,13 +3708,26 @@ fn create( | ... | @@ -3451,13 +3708,26 @@ fn create( |
| 3451 | }), | 3708 | }), |
| 3452 | .pending_uavs = .empty, | 3709 | .pending_uavs = .empty, |
| 3453 | .symbol_relocs = .empty, | 3710 | .symbol_relocs = .empty, |
| 3454 | .got_relocs = .empty, | | |
| 3455 | .tls_size_symbol_relocs = .empty, | 3711 | .tls_size_symbol_relocs = .empty, |
| | 3712 | .node_relocs = .empty, |
| | 3713 | .got_relocs = .empty, |
| 3456 | .section_by_name = .empty, | 3714 | .section_by_name = .empty, |
| 3457 | .changed_symtab_index = .empty, | 3715 | .changed_symtab_index = .empty, |
| 3458 | .textrel_count = 0, | 3716 | .textrel_count = 0, |
| | 3717 | |
| | 3718 | .dwarf = .init(&elf.base, switch (comp.config.debug_format) { |
| | 3719 | .strip => .@"32", |
| | 3720 | .dwarf => |v| v, |
| | 3721 | .code_view => unreachable, |
| | 3722 | }), |
| | 3723 | .dwarf_units = .empty, |
| | 3724 | .dwarf_values = .empty, |
| | 3725 | .dwarf_globals = .empty, |
| | 3726 | .dwarf_funcs = .empty, |
| | 3727 | |
| 3459 | .overflowed_reloc_count = 0, | 3728 | .overflowed_reloc_count = 0, |
| 3460 | .misaligned_reloc_count = 0, | 3729 | .misaligned_reloc_count = 0, |
| | 3730 | |
| 3461 | .const_prog_node = .none, | 3731 | .const_prog_node = .none, |
| 3462 | .synth_prog_node = .none, | 3732 | .synth_prog_node = .none, |
| 3463 | .input_prog_node = .none, | 3733 | .input_prog_node = .none, |
| ... | @@ -3498,10 +3768,18 @@ pub fn deinit(elf: *Elf) void { | ... | @@ -3498,10 +3768,18 @@ pub fn deinit(elf: *Elf) void { |
| 3498 | for (&elf.lazy.values) |*lazy| lazy.map.deinit(gpa); | 3768 | for (&elf.lazy.values) |*lazy| lazy.map.deinit(gpa); |
| 3499 | elf.pending_uavs.deinit(gpa); | 3769 | elf.pending_uavs.deinit(gpa); |
| 3500 | elf.symbol_relocs.deinit(gpa); | 3770 | elf.symbol_relocs.deinit(gpa); |
| 3501 | elf.got_relocs.deinit(gpa); | | |
| 3502 | elf.tls_size_symbol_relocs.deinit(gpa); | 3771 | elf.tls_size_symbol_relocs.deinit(gpa); |
| | 3772 | elf.node_relocs.deinit(gpa); |
| | 3773 | elf.got_relocs.deinit(gpa); |
| 3503 | elf.section_by_name.deinit(gpa); | 3774 | elf.section_by_name.deinit(gpa); |
| 3504 | elf.changed_symtab_index.deinit(gpa); | 3775 | elf.changed_symtab_index.deinit(gpa); |
| | 3776 | |
| | 3777 | elf.dwarf.deinit(gpa); |
| | 3778 | elf.dwarf_units.deinit(gpa); |
| | 3779 | elf.dwarf_values.deinit(gpa); |
| | 3780 | elf.dwarf_globals.deinit(gpa); |
| | 3781 | elf.dwarf_funcs.deinit(gpa); |
| | 3782 | |
| 3505 | elf.* = undefined; | 3783 | elf.* = undefined; |
| 3506 | } | 3784 | } |
| 3507 | | 3785 | |
| ... | @@ -3518,11 +3796,17 @@ fn initHeaders( | ... | @@ -3518,11 +3796,17 @@ fn initHeaders( |
| 3518 | const gpa = comp.gpa; | 3796 | const gpa = comp.gpa; |
| 3519 | | 3797 | |
| 3520 | const is_archive = comp.config.output_mode == .Lib and comp.config.link_mode == .static; | 3798 | const is_archive = comp.config.output_mode == .Lib and comp.config.link_mode == .static; |
| 3521 | const have_dynamic_section = switch (@"type") { | 3799 | const have_dynamic = switch (@"type") { |
| 3522 | .REL => false, | 3800 | .REL => false, |
| 3523 | .EXEC => comp.config.link_mode == .dynamic, | 3801 | .EXEC => comp.config.link_mode == .dynamic, |
| 3524 | .DYN => true, | 3802 | .DYN => true, |
| 3525 | }; | 3803 | }; |
| | 3804 | const have_eh_frame = machine == .X86_64 and comp.config.any_unwind_tables; |
| | 3805 | const have_debug_frame = machine == .X86_64 and switch (comp.config.debug_format) { |
| | 3806 | .strip => false, |
| | 3807 | .dwarf => !comp.config.any_unwind_tables, |
| | 3808 | .code_view => unreachable, |
| | 3809 | }; |
| 3526 | const addr_align: Alignment = switch (class) { | 3810 | const addr_align: Alignment = switch (class) { |
| 3527 | .NONE, _ => unreachable, | 3811 | .NONE, _ => unreachable, |
| 3528 | .@"32" => .@"4", | 3812 | .@"32" => .@"4", |
| ... | @@ -3537,7 +3821,7 @@ fn initHeaders( | ... | @@ -3537,7 +3821,7 @@ fn initHeaders( |
| 3537 | // | 3821 | // |
| 3538 | // It can be handy to temporarily set this to `.@"1"` when working on the linker, because it | 3822 | // It can be handy to temporarily set this to `.@"1"` when working on the linker, because it |
| 3539 | // prevents alignment bugs from being hidden by your filesystem's block alignment. | 3823 | // prevents alignment bugs from being hidden by your filesystem's block alignment. |
| 3540 | const node_block_align: Alignment = elf.mf.flags.block_size; | 3824 | const node_block_align = elf.mf.flags.block_size; |
| 3541 | | 3825 | |
| 3542 | const plt: PltInfo = .fromMachine(machine); | 3826 | const plt: PltInfo = .fromMachine(machine); |
| 3543 | | 3827 | |
| ... | @@ -3552,7 +3836,7 @@ fn initHeaders( | ... | @@ -3552,7 +3836,7 @@ fn initHeaders( |
| 3552 | shnum += 1; // .data | 3836 | shnum += 1; // .data |
| 3553 | shnum += @intFromBool(comp.config.any_non_single_threaded); // .tdata | 3837 | shnum += @intFromBool(comp.config.any_non_single_threaded); // .tdata |
| 3554 | shnum += 1; // .data.rel.ro | 3838 | shnum += 1; // .data.rel.ro |
| 3555 | if (have_dynamic_section) { | 3839 | if (have_dynamic) { |
| 3556 | shnum += 1; // .dynamic | 3840 | shnum += 1; // .dynamic |
| 3557 | shnum += 1; // .dynstr | 3841 | shnum += 1; // .dynstr |
| 3558 | shnum += 1; // .dynsym | 3842 | shnum += 1; // .dynsym |
| ... | @@ -3560,6 +3844,19 @@ fn initHeaders( | ... | @@ -3560,6 +3844,19 @@ fn initHeaders( |
| 3560 | shnum += 1; // .rela.dyn | 3844 | shnum += 1; // .rela.dyn |
| 3561 | shnum += 1; // .rela.plt | 3845 | shnum += 1; // .rela.plt |
| 3562 | } | 3846 | } |
| | 3847 | if (have_eh_frame) { |
| | 3848 | shnum += @intFromBool(@"type" != .REL); // .eh_frame_hdr |
| | 3849 | shnum += 1; // .eh_frame |
| | 3850 | } |
| | 3851 | switch (comp.config.debug_format) { |
| | 3852 | .strip => {}, |
| | 3853 | .dwarf => { |
| | 3854 | shnum += @intFromBool(have_debug_frame); // .debug_frame |
| | 3855 | shnum += 1; // .debug_info |
| | 3856 | shnum += 1; // .debug_line |
| | 3857 | }, |
| | 3858 | .code_view => unreachable, |
| | 3859 | } |
| 3563 | if (@"type" != .REL) { | 3860 | if (@"type" != .REL) { |
| 3564 | shnum += 1; // .got | 3861 | shnum += 1; // .got |
| 3565 | shnum += @intFromBool(plt.got_plt != null); // .got.plt | 3862 | shnum += @intFromBool(plt.got_plt != null); // .got.plt |
| ... | @@ -3574,14 +3871,15 @@ fn initHeaders( | ... | @@ -3574,14 +3871,15 @@ fn initHeaders( |
| 3574 | interp: u32, | 3871 | interp: u32, |
| 3575 | rodata: u32, | 3872 | rodata: u32, |
| 3576 | text: u32, | 3873 | text: u32, |
| 3577 | data: u32, | | |
| 3578 | /// On most targets this is `undefined`, but on machines where JUMP_SLOT relocations write | 3874 | /// On most targets this is `undefined`, but on machines where JUMP_SLOT relocations write |
| 3579 | /// directly to the PLT, we place the PLT in its own segment in order to avoid making the | 3875 | /// directly to the PLT, we place the PLT in its own segment in order to avoid making the |
| 3580 | /// general data segment RWX. | 3876 | /// general data segment RWX. |
| 3581 | plt: u32, | 3877 | plt: u32, |
| | 3878 | data: u32, |
| 3582 | tls: u32, | 3879 | tls: u32, |
| 3583 | dynamic: u32, | 3880 | dynamic: u32, |
| 3584 | relro: u32, | 3881 | relro: u32, |
| | 3882 | gnu_eh_frame: u32, |
| 3585 | gnu_stack: u32, | 3883 | gnu_stack: u32, |
| 3586 | }, const phnum: u32 = ph: { | 3884 | }, const phnum: u32 = ph: { |
| 3587 | switch (@"type") { | 3885 | switch (@"type") { |
| ... | @@ -3622,7 +3920,7 @@ fn initHeaders( | ... | @@ -3622,7 +3920,7 @@ fn initHeaders( |
| 3622 | defer phnum += 1; | 3920 | defer phnum += 1; |
| 3623 | break :phndx phnum; | 3921 | break :phndx phnum; |
| 3624 | } else undefined, | 3922 | } else undefined, |
| 3625 | .dynamic = if (have_dynamic_section) phndx: { | 3923 | .dynamic = if (have_dynamic) phndx: { |
| 3626 | defer phnum += 1; | 3924 | defer phnum += 1; |
| 3627 | break :phndx phnum; | 3925 | break :phndx phnum; |
| 3628 | } else undefined, | 3926 | } else undefined, |
| ... | @@ -3630,6 +3928,10 @@ fn initHeaders( | ... | @@ -3630,6 +3928,10 @@ fn initHeaders( |
| 3630 | defer phnum += 1; | 3928 | defer phnum += 1; |
| 3631 | break :phndx phnum; | 3929 | break :phndx phnum; |
| 3632 | }, | 3930 | }, |
| | 3931 | .gnu_eh_frame = if (have_eh_frame) phndx: { |
| | 3932 | defer phnum += 1; |
| | 3933 | break :phndx phnum; |
| | 3934 | } else undefined, |
| 3633 | .gnu_stack = phndx: { | 3935 | .gnu_stack = phndx: { |
| 3634 | defer phnum += 1; | 3936 | defer phnum += 1; |
| 3635 | break :phndx phnum; | 3937 | break :phndx phnum; |
| ... | @@ -3872,7 +4174,7 @@ fn initHeaders( | ... | @@ -3872,7 +4174,7 @@ fn initHeaders( |
| 3872 | ehdr.shentsize = @sizeOf(ElfN.Shdr); | 4174 | ehdr.shentsize = @sizeOf(ElfN.Shdr); |
| 3873 | ehdr.shnum = 1; // Only the SHN_UNDEF shdr initially---will be incremented by `addSection` | 4175 | ehdr.shnum = 1; // Only the SHN_UNDEF shdr initially---will be incremented by `addSection` |
| 3874 | ehdr.shstrndx = std.elf.SHN_UNDEF; | 4176 | ehdr.shstrndx = std.elf.SHN_UNDEF; |
| 3875 | if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(ElfN.Ehdr, ehdr); | 4177 | if (elf.targetEndian() != std.lang.Endian.native) std.mem.byteSwapAllFields(ElfN.Ehdr, ehdr); |
| 3876 | }, | 4178 | }, |
| 3877 | } | 4179 | } |
| 3878 | | 4180 | |
| ... | @@ -3925,8 +4227,7 @@ fn initHeaders( | ... | @@ -3925,8 +4227,7 @@ fn initHeaders( |
| 3925 | elf.ni.phdr.slice(&elf.mf)[0 .. phnum * @sizeOf(ElfN.Phdr)], | 4227 | elf.ni.phdr.slice(&elf.mf)[0 .. phnum * @sizeOf(ElfN.Phdr)], |
| 3926 | )); | 4228 | )); |
| 3927 | | 4229 | |
| 3928 | const ph_phdr = &phdr[phndx.phdr]; | 4230 | phdr[phndx.phdr] = .{ |
| 3929 | ph_phdr.* = .{ | | |
| 3930 | .type = .PHDR, | 4231 | .type = .PHDR, |
| 3931 | .offset = 0, | 4232 | .offset = 0, |
| 3932 | .vaddr = 0, | 4233 | .vaddr = 0, |
| ... | @@ -3938,8 +4239,7 @@ fn initHeaders( | ... | @@ -3938,8 +4239,7 @@ fn initHeaders( |
| 3938 | }; | 4239 | }; |
| 3939 | | 4240 | |
| 3940 | if (maybe_interp) |_| { | 4241 | if (maybe_interp) |_| { |
| 3941 | const ph_interp = &phdr[phndx.interp]; | 4242 | phdr[phndx.interp] = .{ |
| 3942 | ph_interp.* = .{ | | |
| 3943 | .type = .INTERP, | 4243 | .type = .INTERP, |
| 3944 | .offset = 0, | 4244 | .offset = 0, |
| 3945 | .vaddr = 0, | 4245 | .vaddr = 0, |
| ... | @@ -3951,8 +4251,7 @@ fn initHeaders( | ... | @@ -3951,8 +4251,7 @@ fn initHeaders( |
| 3951 | }; | 4251 | }; |
| 3952 | } | 4252 | } |
| 3953 | | 4253 | |
| 3954 | const ph_rodata = &phdr[phndx.rodata]; | 4254 | phdr[phndx.rodata] = .{ |
| 3955 | ph_rodata.* = .{ | | |
| 3956 | .type = .NULL, | 4255 | .type = .NULL, |
| 3957 | .offset = 0, | 4256 | .offset = 0, |
| 3958 | .vaddr = @intCast(base_vaddr), | 4257 | .vaddr = @intCast(base_vaddr), |
| ... | @@ -3963,74 +4262,62 @@ fn initHeaders( | ... | @@ -3963,74 +4262,62 @@ fn initHeaders( |
| 3963 | .@"align" = @intCast(page_align.toByteUnits()), | 4262 | .@"align" = @intCast(page_align.toByteUnits()), |
| 3964 | }; | 4263 | }; |
| 3965 | | 4264 | |
| 3966 | const ph_text = &phdr[phndx.text]; | 4265 | phdr[phndx.text] = .{ |
| 3967 | ph_text.* = .{ | 4266 | .type = .NULL, |
| | 4267 | .offset = 0, |
| | 4268 | .vaddr = @intCast(base_vaddr), |
| | 4269 | .paddr = @intCast(base_vaddr), |
| | 4270 | .filesz = 0, |
| | 4271 | .memsz = 0, |
| | 4272 | .flags = .{ .R = true, .X = true }, |
| | 4273 | .@"align" = @intCast(page_align.toByteUnits()), |
| | 4274 | }; |
| | 4275 | |
| | 4276 | phdr[phndx.data] = .{ |
| 3968 | .type = .NULL, | 4277 | .type = .NULL, |
| 3969 | .offset = 0, | 4278 | .offset = 0, |
| 3970 | .vaddr = @intCast(base_vaddr), | 4279 | .vaddr = @intCast(base_vaddr), |
| 3971 | .paddr = @intCast(base_vaddr), | 4280 | .paddr = @intCast(base_vaddr), |
| 3972 | .filesz = 0, | 4281 | .filesz = 0, |
| 3973 | .memsz = 0, | 4282 | .memsz = 0, |
| 3974 | .flags = .{ .R = true, .X = true }, | 4283 | .flags = .{ .R = true, .W = true }, |
| 3975 | .@"align" = @intCast(page_align.toByteUnits()), | 4284 | .@"align" = @intCast(page_align.toByteUnits()), |
| 3976 | }; | 4285 | }; |
| 3977 | | 4286 | |
| 3978 | const ph_data = &phdr[phndx.data]; | 4287 | if (plt.got_plt == null) phdr[phndx.plt] = .{ |
| 3979 | ph_data.* = .{ | | |
| 3980 | .type = .NULL, | 4288 | .type = .NULL, |
| 3981 | .offset = 0, | 4289 | .offset = 0, |
| 3982 | .vaddr = @intCast(base_vaddr), | 4290 | .vaddr = @intCast(base_vaddr), |
| 3983 | .paddr = @intCast(base_vaddr), | 4291 | .paddr = @intCast(base_vaddr), |
| 3984 | .filesz = 0, | 4292 | .filesz = 0, |
| 3985 | .memsz = 0, | 4293 | .memsz = 0, |
| 3986 | .flags = .{ .R = true, .W = true }, | 4294 | .flags = .{ .R = true, .W = true, .X = true }, |
| 3987 | .@"align" = @intCast(page_align.toByteUnits()), | 4295 | .@"align" = @intCast(page_align.toByteUnits()), |
| 3988 | }; | 4296 | }; |
| 3989 | | 4297 | |
| 3990 | if (plt.got_plt == null) { | 4298 | if (elf.ni.tls.unwrap()) |tls_segment_ni| phdr[phndx.tls] = .{ |
| 3991 | const ph_plt = &phdr[phndx.plt]; | 4299 | .type = .TLS, |
| 3992 | ph_plt.* = .{ | 4300 | .offset = 0, |
| 3993 | .type = .NULL, | 4301 | .vaddr = 0, |
| 3994 | .offset = 0, | 4302 | .paddr = 0, |
| 3995 | .vaddr = @intCast(base_vaddr), | 4303 | .filesz = 0, |
| 3996 | .paddr = @intCast(base_vaddr), | 4304 | .memsz = 0, |
| 3997 | .filesz = 0, | 4305 | .flags = .{ .R = true }, |
| 3998 | .memsz = 0, | 4306 | .@"align" = @intCast(tls_segment_ni.alignment(&elf.mf).toByteUnits()), |
| 3999 | .flags = .{ .R = true, .W = true, .X = true }, | 4307 | }; |
| 4000 | .@"align" = @intCast(page_align.toByteUnits()), | | |
| 4001 | }; | | |
| 4002 | } | | |
| 4003 | | | |
| 4004 | if (elf.ni.tls.unwrap()) |tls_segment_ni| { | | |
| 4005 | const ph_tls = &phdr[phndx.tls]; | | |
| 4006 | ph_tls.* = .{ | | |
| 4007 | .type = .TLS, | | |
| 4008 | .offset = 0, | | |
| 4009 | .vaddr = 0, | | |
| 4010 | .paddr = 0, | | |
| 4011 | .filesz = 0, | | |
| 4012 | .memsz = 0, | | |
| 4013 | .flags = .{ .R = true }, | | |
| 4014 | .@"align" = @intCast(tls_segment_ni.alignment(&elf.mf).toByteUnits()), | | |
| 4015 | }; | | |
| 4016 | } | | |
| 4017 | | 4308 | |
| 4018 | if (have_dynamic_section) { | 4309 | if (have_dynamic) phdr[phndx.dynamic] = .{ |
| 4019 | const ph_dynamic = &phdr[phndx.dynamic]; | 4310 | .type = .DYNAMIC, |
| 4020 | ph_dynamic.* = .{ | 4311 | .offset = 0, |
| 4021 | .type = .DYNAMIC, | 4312 | .vaddr = 0, |
| 4022 | .offset = 0, | 4313 | .paddr = 0, |
| 4023 | .vaddr = 0, | 4314 | .filesz = 0, |
| 4024 | .paddr = 0, | 4315 | .memsz = 0, |
| 4025 | .filesz = 0, | 4316 | .flags = .{ .R = true, .W = true }, |
| 4026 | .memsz = 0, | 4317 | .@"align" = @intCast(addr_align.toByteUnits()), |
| 4027 | .flags = .{ .R = true, .W = true }, | 4318 | }; |
| 4028 | .@"align" = @intCast(addr_align.toByteUnits()), | | |
| 4029 | }; | | |
| 4030 | } | | |
| 4031 | | 4319 | |
| 4032 | const ph_relro = &phdr[phndx.relro]; | 4320 | phdr[phndx.relro] = .{ |
| 4033 | ph_relro.* = .{ | | |
| 4034 | .type = .GNU_RELRO, | 4321 | .type = .GNU_RELRO, |
| 4035 | .offset = 0, | 4322 | .offset = 0, |
| 4036 | .vaddr = 0, | 4323 | .vaddr = 0, |
| ... | @@ -4041,8 +4328,18 @@ fn initHeaders( | ... | @@ -4041,8 +4328,18 @@ fn initHeaders( |
| 4041 | .@"align" = @intCast(elf.ni.data_rel_ro.alignment(&elf.mf).toByteUnits()), | 4328 | .@"align" = @intCast(elf.ni.data_rel_ro.alignment(&elf.mf).toByteUnits()), |
| 4042 | }; | 4329 | }; |
| 4043 | | 4330 | |
| 4044 | const ph_gnu_stack = &phdr[phndx.gnu_stack]; | 4331 | if (have_eh_frame) phdr[phndx.gnu_eh_frame] = .{ |
| 4045 | ph_gnu_stack.* = .{ | 4332 | .type = .GNU_EH_FRAME, |
| | 4333 | .offset = 0, |
| | 4334 | .vaddr = 0, |
| | 4335 | .paddr = 0, |
| | 4336 | .filesz = @sizeOf(Dwarf.EhFrameHdr), |
| | 4337 | .memsz = @sizeOf(Dwarf.EhFrameHdr), |
| | 4338 | .flags = .{ .R = true }, |
| | 4339 | .@"align" = 4, |
| | 4340 | }; |
| | 4341 | |
| | 4342 | phdr[phndx.gnu_stack] = .{ |
| 4046 | .type = .GNU_STACK, | 4343 | .type = .GNU_STACK, |
| 4047 | .offset = 0, | 4344 | .offset = 0, |
| 4048 | .vaddr = 0, | 4345 | .vaddr = 0, |
| ... | @@ -4071,7 +4368,7 @@ fn initHeaders( | ... | @@ -4071,7 +4368,7 @@ fn initHeaders( |
| 4071 | .addralign = 0, | 4368 | .addralign = 0, |
| 4072 | .entsize = 0, | 4369 | .entsize = 0, |
| 4073 | }; | 4370 | }; |
| 4074 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Shdr, sh_undef); | 4371 | if (target_endian != std.lang.Endian.native) std.mem.byteSwapAllFields(ElfN.Shdr, sh_undef); |
| 4075 | | 4372 | |
| 4076 | elf.symtab.addOneAssumeCapacity().* = .{ | 4373 | elf.symtab.addOneAssumeCapacity().* = .{ |
| 4077 | .node = .none, | 4374 | .node = .none, |
| ... | @@ -4084,6 +4381,7 @@ fn initHeaders( | ... | @@ -4084,6 +4381,7 @@ fn initHeaders( |
| 4084 | .entsize = @sizeOf(ElfN.Sym), | 4381 | .entsize = @sizeOf(ElfN.Sym), |
| 4085 | .node_align = node_block_align, | 4382 | .node_align = node_block_align, |
| 4086 | .info = 1, // index of first non-local symbol | 4383 | .info = 1, // index of first non-local symbol |
| | 4384 | .manual_size = true, |
| 4087 | })); | 4385 | })); |
| 4088 | const symtab_null = @field(elf.symPtr(.null), @tagName(ct_class)); | 4386 | const symtab_null = @field(elf.symPtr(.null), @tagName(ct_class)); |
| 4089 | symtab_null.* = .{ | 4387 | symtab_null.* = .{ |
| ... | @@ -4094,7 +4392,7 @@ fn initHeaders( | ... | @@ -4094,7 +4392,7 @@ fn initHeaders( |
| 4094 | .other = .{ .visibility = .DEFAULT }, | 4392 | .other = .{ .visibility = .DEFAULT }, |
| 4095 | .shndx = std.elf.SHN_UNDEF, | 4393 | .shndx = std.elf.SHN_UNDEF, |
| 4096 | }; | 4394 | }; |
| 4097 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Sym, symtab_null); | 4395 | if (target_endian != std.lang.Endian.native) std.mem.byteSwapAllFields(ElfN.Sym, symtab_null); |
| 4098 | | 4396 | |
| 4099 | const ehdr = @field(elf.ehdrPtr(), @tagName(ct_class)); | 4397 | const ehdr = @field(elf.ehdrPtr(), @tagName(ct_class)); |
| 4100 | ehdr.shstrndx = ehdr.shnum; | 4398 | ehdr.shstrndx = ehdr.shnum; |
| ... | @@ -4105,6 +4403,7 @@ fn initHeaders( | ... | @@ -4105,6 +4403,7 @@ fn initHeaders( |
| 4105 | .size = 1, | 4403 | .size = 1, |
| 4106 | .entsize = 1, | 4404 | .entsize = 1, |
| 4107 | .node_align = node_block_align, | 4405 | .node_align = node_block_align, |
| | 4406 | .manual_size = true, |
| 4108 | })); | 4407 | })); |
| 4109 | Section.Index.get(.shstrtab, elf).ni.slice(&elf.mf)[0] = 0; | 4408 | Section.Index.get(.shstrtab, elf).ni.slice(&elf.mf)[0] = 0; |
| 4110 | | 4409 | |
| ... | @@ -4117,6 +4416,7 @@ fn initHeaders( | ... | @@ -4117,6 +4416,7 @@ fn initHeaders( |
| 4117 | .size = 1, | 4416 | .size = 1, |
| 4118 | .entsize = 1, | 4417 | .entsize = 1, |
| 4119 | .node_align = node_block_align, | 4418 | .node_align = node_block_align, |
| | 4419 | .manual_size = true, |
| 4120 | })); | 4420 | })); |
| 4121 | Section.Index.get(.strtab, elf).ni.slice(&elf.mf)[0] = 0; | 4421 | Section.Index.get(.strtab, elf).ni.slice(&elf.mf)[0] = 0; |
| 4122 | switch (elf.shdrPtr(.symtab)) { | 4422 | switch (elf.shdrPtr(.symtab)) { |
| ... | @@ -4156,6 +4456,7 @@ fn initHeaders( | ... | @@ -4156,6 +4456,7 @@ fn initHeaders( |
| 4156 | .flags = .{ .WRITE = true, .ALLOC = true }, | 4456 | .flags = .{ .WRITE = true, .ALLOC = true }, |
| 4157 | .addralign = addr_align, | 4457 | .addralign = addr_align, |
| 4158 | .entsize = @intCast(addr_align.toByteUnits()), | 4458 | .entsize = @intCast(addr_align.toByteUnits()), |
| | 4459 | .manual_size = true, |
| 4159 | }); | 4460 | }); |
| 4160 | { | 4461 | { |
| 4161 | const init_plt_size = plt.entry_size * plt.header_entries; | 4462 | const init_plt_size = plt.entry_size * plt.header_entries; |
| ... | @@ -4168,6 +4469,7 @@ fn initHeaders( | ... | @@ -4168,6 +4469,7 @@ fn initHeaders( |
| 4168 | .size = got_plt.header_entries * elf.targetPtrSize(), | 4469 | .size = got_plt.header_entries * elf.targetPtrSize(), |
| 4169 | .addralign = addr_align, | 4470 | .addralign = addr_align, |
| 4170 | .entsize = @intCast(addr_align.toByteUnits()), | 4471 | .entsize = @intCast(addr_align.toByteUnits()), |
| | 4472 | .manual_size = true, |
| 4171 | }); | 4473 | }); |
| 4172 | elf.shndx.plt = try elf.addSection(elf.ni.text, .{ | 4474 | elf.shndx.plt = try elf.addSection(elf.ni.text, .{ |
| 4173 | .name = ".plt", | 4475 | .name = ".plt", |
| ... | @@ -4176,6 +4478,7 @@ fn initHeaders( | ... | @@ -4176,6 +4478,7 @@ fn initHeaders( |
| 4176 | .size = plt.@"align".forward(init_plt_size), | 4478 | .size = plt.@"align".forward(init_plt_size), |
| 4177 | .addralign = plt.@"align", | 4479 | .addralign = plt.@"align", |
| 4178 | .node_align = node_block_align, | 4480 | .node_align = node_block_align, |
| | 4481 | .manual_size = true, |
| 4179 | }); | 4482 | }); |
| 4180 | } else { | 4483 | } else { |
| 4181 | elf.shndx.plt = try elf.addSection(elf.phdrs.items[phndx.plt].unwrap().?, .{ | 4484 | elf.shndx.plt = try elf.addSection(elf.phdrs.items[phndx.plt].unwrap().?, .{ |
| ... | @@ -4185,6 +4488,7 @@ fn initHeaders( | ... | @@ -4185,6 +4488,7 @@ fn initHeaders( |
| 4185 | .size = plt.@"align".forward(init_plt_size), | 4488 | .size = plt.@"align".forward(init_plt_size), |
| 4186 | .addralign = plt.@"align", | 4489 | .addralign = plt.@"align", |
| 4187 | .node_align = node_block_align, | 4490 | .node_align = node_block_align, |
| | 4491 | .manual_size = true, |
| 4188 | }); | 4492 | }); |
| 4189 | } | 4493 | } |
| 4190 | // And the award for most annoying PLT requirement goes to SPARC, which decided that the | 4494 | // And the award for most annoying PLT requirement goes to SPARC, which decided that the |
| ... | @@ -4222,7 +4526,7 @@ fn initHeaders( | ... | @@ -4222,7 +4526,7 @@ fn initHeaders( |
| 4222 | @memcpy(sec_interp[0..interp.len], interp); | 4526 | @memcpy(sec_interp[0..interp.len], interp); |
| 4223 | sec_interp[interp.len] = 0; | 4527 | sec_interp[interp.len] = 0; |
| 4224 | } | 4528 | } |
| 4225 | if (have_dynamic_section) { | 4529 | if (have_dynamic) { |
| 4226 | assert(elf.ni.data_rel_ro.alignment(&elf.mf).compare(.gte, addr_align)); | 4530 | assert(elf.ni.data_rel_ro.alignment(&elf.mf).compare(.gte, addr_align)); |
| 4227 | const dynamic_ni = try elf.ni.data_rel_ro.addFloatingChild(&elf.mf, gpa, .{ | 4531 | const dynamic_ni = try elf.ni.data_rel_ro.addFloatingChild(&elf.mf, gpa, .{ |
| 4228 | .alignment = addr_align, | 4532 | .alignment = addr_align, |
| ... | @@ -4239,6 +4543,7 @@ fn initHeaders( | ... | @@ -4239,6 +4543,7 @@ fn initHeaders( |
| 4239 | .size = 1, | 4543 | .size = 1, |
| 4240 | .entsize = 1, | 4544 | .entsize = 1, |
| 4241 | .node_align = node_block_align, | 4545 | .node_align = node_block_align, |
| | 4546 | .manual_size = true, |
| 4242 | }); | 4547 | }); |
| 4243 | dynstr_shndx.get(elf).ni.slice(&elf.mf)[0] = 0; | 4548 | dynstr_shndx.get(elf).ni.slice(&elf.mf)[0] = 0; |
| 4244 | elf.shndx.dynstr = dynstr_shndx; | 4549 | elf.shndx.dynstr = dynstr_shndx; |
| ... | @@ -4257,6 +4562,7 @@ fn initHeaders( | ... | @@ -4257,6 +4562,7 @@ fn initHeaders( |
| 4257 | .addralign = addr_align, | 4562 | .addralign = addr_align, |
| 4258 | .entsize = @sizeOf(Sym), | 4563 | .entsize = @sizeOf(Sym), |
| 4259 | .node_align = node_block_align, | 4564 | .node_align = node_block_align, |
| | 4565 | .manual_size = true, |
| 4260 | }); | 4566 | }); |
| 4261 | const dynsym_null = @field(elf.dynsymPtr(0), @tagName(ct_class)); | 4567 | const dynsym_null = @field(elf.dynsymPtr(0), @tagName(ct_class)); |
| 4262 | dynsym_null.* = .{ | 4568 | dynsym_null.* = .{ |
| ... | @@ -4267,7 +4573,7 @@ fn initHeaders( | ... | @@ -4267,7 +4573,7 @@ fn initHeaders( |
| 4267 | .other = .{ .visibility = .DEFAULT }, | 4573 | .other = .{ .visibility = .DEFAULT }, |
| 4268 | .shndx = std.elf.SHN_UNDEF, | 4574 | .shndx = std.elf.SHN_UNDEF, |
| 4269 | }; | 4575 | }; |
| 4270 | if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields( | 4576 | if (elf.targetEndian() != std.lang.Endian.native) std.mem.byteSwapAllFields( |
| 4271 | Sym, | 4577 | Sym, |
| 4272 | dynsym_null, | 4578 | dynsym_null, |
| 4273 | ); | 4579 | ); |
| ... | @@ -4285,6 +4591,7 @@ fn initHeaders( | ... | @@ -4285,6 +4591,7 @@ fn initHeaders( |
| 4285 | .addralign = addr_align, | 4591 | .addralign = addr_align, |
| 4286 | .entsize = rela_size, | 4592 | .entsize = rela_size, |
| 4287 | .node_align = node_block_align, | 4593 | .node_align = node_block_align, |
| | 4594 | .manual_size = true, |
| 4288 | }); | 4595 | }); |
| 4289 | elf.shndx.rela_plt = try elf.addSection(elf.ni.rodata, .{ | 4596 | elf.shndx.rela_plt = try elf.addSection(elf.ni.rodata, .{ |
| 4290 | .name = ".rela.plt", | 4597 | .name = ".rela.plt", |
| ... | @@ -4295,6 +4602,7 @@ fn initHeaders( | ... | @@ -4295,6 +4602,7 @@ fn initHeaders( |
| 4295 | .addralign = addr_align, | 4602 | .addralign = addr_align, |
| 4296 | .entsize = rela_size, | 4603 | .entsize = rela_size, |
| 4297 | .node_align = node_block_align, | 4604 | .node_align = node_block_align, |
| | 4605 | .manual_size = true, |
| 4298 | }); | 4606 | }); |
| 4299 | elf.shndx.dynamic = try elf.addSection(dynamic_ni, .{ | 4607 | elf.shndx.dynamic = try elf.addSection(dynamic_ni, .{ |
| 4300 | .name = ".dynamic", | 4608 | .name = ".dynamic", |
| ... | @@ -4303,6 +4611,7 @@ fn initHeaders( | ... | @@ -4303,6 +4611,7 @@ fn initHeaders( |
| 4303 | .link = dynstr_shndx.toSection().?, | 4611 | .link = dynstr_shndx.toSection().?, |
| 4304 | .entsize = @intCast(addr_align.toByteUnits() * 2), | 4612 | .entsize = @intCast(addr_align.toByteUnits() * 2), |
| 4305 | .addralign = addr_align, | 4613 | .addralign = addr_align, |
| | 4614 | .manual_size = true, |
| 4306 | }); | 4615 | }); |
| 4307 | switch (elf.targetDynsymHashInfo()) { | 4616 | switch (elf.targetDynsymHashInfo()) { |
| 4308 | inline else => |info| { | 4617 | inline else => |info| { |
| ... | @@ -4318,6 +4627,7 @@ fn initHeaders( | ... | @@ -4318,6 +4627,7 @@ fn initHeaders( |
| 4318 | .addralign = .fromByteUnits(@sizeOf(info.Int())), | 4627 | .addralign = .fromByteUnits(@sizeOf(info.Int())), |
| 4319 | // initially: nbucket = 8 + nchain = 1 | 4628 | // initially: nbucket = 8 + nchain = 1 |
| 4320 | .size = @sizeOf(info.Header()) + @sizeOf(info.Int()) * (8 + 1), | 4629 | .size = @sizeOf(info.Header()) + @sizeOf(info.Int()) * (8 + 1), |
| | 4630 | .manual_size = true, |
| 4321 | }); | 4631 | }); |
| 4322 | const hash_slice: []align(@sizeOf(info.Int())) u8 = @alignCast(elf.shndx.hash.get(elf).ni.slice(&elf.mf)); | 4632 | const hash_slice: []align(@sizeOf(info.Int())) u8 = @alignCast(elf.shndx.hash.get(elf).ni.slice(&elf.mf)); |
| 4323 | const header: *info.Header() = @ptrCast(hash_slice[0..@sizeOf(info.Header())]); | 4633 | const header: *info.Header() = @ptrCast(hash_slice[0..@sizeOf(info.Header())]); |
| ... | @@ -4407,13 +4717,45 @@ fn initHeaders( | ... | @@ -4407,13 +4717,45 @@ fn initHeaders( |
| 4407 | .SPARCV9 => {}, | 4717 | .SPARCV9 => {}, |
| 4408 | } | 4718 | } |
| 4409 | } | 4719 | } |
| | 4720 | if (have_eh_frame) { |
| | 4721 | elf.ni.gnu_eh_frame = .wrap(try elf.ni.rodata.addFloatingChild(&elf.mf, gpa, .{ |
| | 4722 | .size = @sizeOf(Dwarf.EhFrameHdr), |
| | 4723 | .alignment = .@"4", |
| | 4724 | .moved = true, |
| | 4725 | .bubbles_moved = false, |
| | 4726 | })); |
| | 4727 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.gnu_eh_frame }); |
| | 4728 | elf.phdrs.items[phndx.gnu_eh_frame] = elf.ni.gnu_eh_frame; |
| | 4729 | |
| | 4730 | elf.shndx.eh_frame_hdr = try elf.addSection(elf.ni.gnu_eh_frame.unwrap().?, .{ |
| | 4731 | .name = ".eh_frame_hdr", |
| | 4732 | .type = .PROGBITS, |
| | 4733 | .flags = .{ .ALLOC = true }, |
| | 4734 | .size = @sizeOf(Dwarf.EhFrameHdr), |
| | 4735 | .addralign = .@"4", |
| | 4736 | }); |
| | 4737 | elf.shndx.eh_frame = try elf.addSection(elf.ni.rodata, .{ |
| | 4738 | .name = ".eh_frame", |
| | 4739 | .flags = .{ .ALLOC = true }, |
| | 4740 | .addralign = addr_align, |
| | 4741 | .node_align = elf.mf.flags.block_size, |
| | 4742 | }); |
| | 4743 | const eh_frame_hdr_ni = elf.shndx.eh_frame_hdr.get(elf).ni; |
| | 4744 | elf.eh_frame_hdr_first_symbol_reloc = |
| | 4745 | @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); |
| | 4746 | try elf.dwarf.genEhFrameHdr( |
| | 4747 | Node.toAtom(eh_frame_hdr_ni), |
| | 4748 | @ptrCast(@alignCast(eh_frame_hdr_ni.slice(&elf.mf))), |
| | 4749 | Symbol.Id.local(elf.shndx.eh_frame.get(elf).lsi).toTypeErased(), |
| | 4750 | ); |
| | 4751 | } |
| 4410 | | 4752 | |
| 4411 | // Populate reserved GOT words. | 4753 | // Populate reserved GOT words. |
| 4412 | switch (machine) { | 4754 | switch (machine) { |
| 4413 | .AARCH64, .PPC64, .RISCV => @panic(@tagName(machine)), | 4755 | .AARCH64, .PPC64, .RISCV => @panic(@tagName(machine)), |
| 4414 | .X86_64 => { | 4756 | .X86_64 => { |
| 4415 | try elf.got.ensureUnusedCapacity(gpa, 3); | 4757 | try elf.got.ensureUnusedCapacity(gpa, 3); |
| 4416 | elf.got.putAssumeCapacityNoClobber(switch (have_dynamic_section) { | 4758 | elf.got.putAssumeCapacityNoClobber(switch (have_dynamic) { |
| 4417 | true => .{ .symbol = .local(elf.shndx.dynamic.get(elf).lsi) }, | 4759 | true => .{ .symbol = .local(elf.shndx.dynamic.get(elf).lsi) }, |
| 4418 | false => .{ .reserved = 0 }, | 4760 | false => .{ .reserved = 0 }, |
| 4419 | }, .none); | 4761 | }, .none); |
| ... | @@ -4422,7 +4764,7 @@ fn initHeaders( | ... | @@ -4422,7 +4764,7 @@ fn initHeaders( |
| 4422 | }, | 4764 | }, |
| 4423 | .LOONGARCH, .SPARCV9 => { | 4765 | .LOONGARCH, .SPARCV9 => { |
| 4424 | try elf.got.ensureUnusedCapacity(gpa, 1); | 4766 | try elf.got.ensureUnusedCapacity(gpa, 1); |
| 4425 | elf.got.putAssumeCapacityNoClobber(switch (have_dynamic_section) { | 4767 | elf.got.putAssumeCapacityNoClobber(switch (have_dynamic) { |
| 4426 | true => .{ .symbol = .local(elf.shndx.dynamic.get(elf).lsi) }, | 4768 | true => .{ .symbol = .local(elf.shndx.dynamic.get(elf).lsi) }, |
| 4427 | false => .{ .reserved = 0 }, | 4769 | false => .{ .reserved = 0 }, |
| 4428 | }, .none); | 4770 | }, .none); |
| ... | @@ -4567,7 +4909,7 @@ fn initHeaders( | ... | @@ -4567,7 +4909,7 @@ fn initHeaders( |
| 4567 | }) catch |err| switch (err) { | 4909 | }) catch |err| switch (err) { |
| 4568 | error.MultipleDefinitions => unreachable, // no inputs are processed yet | 4910 | error.MultipleDefinitions => unreachable, // no inputs are processed yet |
| 4569 | }; | 4911 | }; |
| 4570 | if (have_dynamic_section) { | 4912 | if (have_dynamic) { |
| 4571 | _ = elf.addGlobalSymbolAssumeCapacity(.{ | 4913 | _ = elf.addGlobalSymbolAssumeCapacity(.{ |
| 4572 | .node = .wrap(elf.shndx.dynamic.get(elf).ni), | 4914 | .node = .wrap(elf.shndx.dynamic.get(elf).ni), |
| 4573 | .name = try .string(elf, "_DYNAMIC"), | 4915 | .name = try .string(elf, "_DYNAMIC"), |
| ... | @@ -4583,13 +4925,39 @@ fn initHeaders( | ... | @@ -4583,13 +4925,39 @@ fn initHeaders( |
| 4583 | } | 4925 | } |
| 4584 | } else { | 4926 | } else { |
| 4585 | assert(maybe_interp == null); | 4927 | assert(maybe_interp == null); |
| 4586 | assert(!have_dynamic_section); | 4928 | assert(!have_dynamic); |
| | 4929 | if (have_eh_frame) elf.shndx.eh_frame = try elf.addSection(elf.ni.rodata, .{ |
| | 4930 | .name = ".eh_frame", |
| | 4931 | .type = if (machine == .X86_64) .X86_64_UNWIND else .NULL, |
| | 4932 | .flags = .{ .ALLOC = true }, |
| | 4933 | .addralign = addr_align, |
| | 4934 | .node_align = elf.mf.flags.block_size, |
| | 4935 | }); |
| 4587 | } | 4936 | } |
| 4588 | if (elf.ni.tls.unwrap()) |tls_segment_ni| elf.shndx.tdata = try elf.addSection(tls_segment_ni, .{ | 4937 | if (elf.ni.tls.unwrap()) |tls_segment_ni| elf.shndx.tdata = try elf.addSection(tls_segment_ni, .{ |
| 4589 | .name = ".tdata", | 4938 | .name = ".tdata", |
| 4590 | .flags = .{ .WRITE = true, .ALLOC = true, .TLS = true }, | 4939 | .flags = .{ .WRITE = true, .ALLOC = true, .TLS = true }, |
| 4591 | .node_align = node_block_align, | 4940 | .node_align = node_block_align, |
| 4592 | }); | 4941 | }); |
| | 4942 | switch (comp.config.debug_format) { |
| | 4943 | .strip => {}, |
| | 4944 | .dwarf => { |
| | 4945 | if (have_debug_frame) elf.shndx.debug_frame = try elf.addSection(elf.ni.elf, .{ |
| | 4946 | .name = ".debug_frame", |
| | 4947 | .addralign = addr_align, |
| | 4948 | .node_align = elf.mf.flags.block_size, |
| | 4949 | }); |
| | 4950 | elf.shndx.debug_info = try elf.addSection(elf.ni.elf, .{ |
| | 4951 | .name = ".debug_info", |
| | 4952 | .node_align = elf.mf.flags.block_size, |
| | 4953 | }); |
| | 4954 | elf.shndx.debug_line = try elf.addSection(elf.ni.elf, .{ |
| | 4955 | .name = ".debug_line", |
| | 4956 | .node_align = elf.mf.flags.block_size, |
| | 4957 | }); |
| | 4958 | }, |
| | 4959 | .code_view => unreachable, |
| | 4960 | } |
| 4593 | | 4961 | |
| 4594 | assert(elf.nodes.len == expected_nodes_len); | 4962 | assert(elf.nodes.len == expected_nodes_len); |
| 4595 | assert(elf.shdrs.items.len == shnum - 1); // -1 to exclude SHN_UNDEF | 4963 | assert(elf.shdrs.items.len == shnum - 1); // -1 to exclude SHN_UNDEF |
| ... | @@ -4599,7 +4967,7 @@ fn initHeaders( | ... | @@ -4599,7 +4967,7 @@ fn initHeaders( |
| 4599 | elf.section_by_name.putAssumeCapacityNoClobber(shndx.name(elf), {}); | 4967 | elf.section_by_name.putAssumeCapacityNoClobber(shndx.name(elf), {}); |
| 4600 | } | 4968 | } |
| 4601 | | 4969 | |
| 4602 | if (have_dynamic_section) elf.dynamic = .{ | 4970 | if (have_dynamic) elf.dynamic = .{ |
| 4603 | .flags = if (elf.options.z_now) std.elf.DF_BIND_NOW else 0, | 4971 | .flags = if (elf.options.z_now) std.elf.DF_BIND_NOW else 0, |
| 4604 | .flags_1 = f: { | 4972 | .flags_1 = f: { |
| 4605 | var f: u32 = 0; | 4973 | var f: u32 = 0; |
| ... | @@ -4677,15 +5045,26 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index { | ... | @@ -4677,15 +5045,26 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index { |
| 4677 | .ehdr, | 5045 | .ehdr, |
| 4678 | .shdr, | 5046 | .shdr, |
| 4679 | .segment, | 5047 | .segment, |
| | 5048 | .value_debug_info, |
| | 5049 | .global_debug_info, |
| | 5050 | .frame_padding, |
| | 5051 | .func_debug_info, |
| | 5052 | .func_debug_line, |
| 4680 | => unreachable, | 5053 | => unreachable, |
| 4681 | .section => |shndx| shndx, | 5054 | .section, .section_manual_size => |shndx| shndx, |
| 4682 | .input_section, | 5055 | .input_section, |
| 4683 | .copied_global, | 5056 | .copied_global, |
| 4684 | .nav, | 5057 | .nav, |
| 4685 | .uav, | 5058 | .uav, |
| 4686 | .lazy_code, | 5059 | .lazy_code, |
| 4687 | .lazy_const_data, | 5060 | .lazy_const_data, |
| | 5061 | .unit_frame, |
| 4688 | => elf.getNode(ni.parent(&elf.mf).unwrap().?).section, | 5062 | => elf.getNode(ni.parent(&elf.mf).unwrap().?).section, |
| | 5063 | .unit_frame_cie, .func_frame_fde => { |
| | 5064 | const unit_frame_ni = ni.parent(&elf.mf).unwrap().?; |
| | 5065 | assert(elf.getNode(unit_frame_ni) == .unit_frame); |
| | 5066 | return elf.getNode(unit_frame_ni.parent(&elf.mf).unwrap().?).section; |
| | 5067 | }, |
| 4689 | }; | 5068 | }; |
| 4690 | } | 5069 | } |
| 4691 | fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { | 5070 | fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| ... | @@ -4699,31 +5078,52 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { | ... | @@ -4699,31 +5078,52 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 4699 | .shdr, | 5078 | .shdr, |
| 4700 | .segment, | 5079 | .segment, |
| 4701 | .copied_global, | 5080 | .copied_global, |
| | 5081 | .value_debug_info, |
| | 5082 | .global_debug_info, |
| | 5083 | .frame_padding, |
| | 5084 | .func_debug_info, |
| | 5085 | .func_debug_line, |
| 4702 | => unreachable, | 5086 | => unreachable, |
| 4703 | .section => |shndx| shndx.vaddr(elf), | 5087 | .section, .section_manual_size => |shndx| shndx.vaddr(elf), |
| 4704 | .input_section => |isi| isi.ptrConst(elf).vaddr, | 5088 | .input_section => |isi| isi.ptrConst(elf).vaddr, |
| 4705 | inline .nav, | 5089 | inline .nav, |
| 4706 | .uav, | 5090 | .uav, |
| 4707 | .lazy_code, | 5091 | .lazy_code, |
| 4708 | .lazy_const_data, | 5092 | .lazy_const_data, |
| 4709 | => |i| Symbol.Id.local(i.symbol(elf)).value(elf), | 5093 | => |i| Symbol.Id.local(i.symbol(elf)).value(elf), |
| | 5094 | .unit_frame, .unit_frame_cie, .func_frame_fde => elf.computeNodeVAddr(ni), |
| 4710 | }; | 5095 | }; |
| 4711 | } | 5096 | } |
| 4712 | fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { | 5097 | fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 4713 | const parent_vaddr = switch (elf.getNode(ni.parent(&elf.mf).unwrap().?)) { | 5098 | const parent_ni = ni.parent(&elf.mf).unwrap().?; |
| 4714 | .archive, | 5099 | const parent_vaddr = parent_vaddr: switch (elf.getNode(parent_ni)) { |
| 4715 | .archive_header, | 5100 | .archive, .archive_header, .archive_input_member, .archive_elf_member_header => unreachable, |
| 4716 | .archive_input_member, | | |
| 4717 | .archive_elf_member_header, | | |
| 4718 | => unreachable, | | |
| 4719 | .elf => return 0, | 5101 | .elf => return 0, |
| 4720 | .ehdr, .shdr => unreachable, | 5102 | .ehdr, .shdr => unreachable, |
| 4721 | .segment => |phndx| switch (elf.phdrSlice()) { | 5103 | .segment => |phndx| switch (elf.phdrSlice()) { |
| 4722 | inline else => |phdr| elf.targetLoad(&phdr[phndx].vaddr), | 5104 | inline else => |phdr| elf.targetLoad(&phdr[phndx].vaddr), |
| 4723 | }, | 5105 | }, |
| 4724 | .section => |shndx| if (shndx == elf.shndx.tdata) 0 else shndx.vaddr(elf), | 5106 | .section, .section_manual_size => |shndx| if (shndx == elf.shndx.tdata) 0 else shndx.vaddr(elf), |
| 4725 | .input_section, .copied_global => unreachable, | 5107 | .input_section, .copied_global => unreachable, |
| 4726 | inline .nav, .uav, .lazy_code, .lazy_const_data => |i| Symbol.Id.local(i.symbol(elf)).value(elf), | 5108 | inline .nav, |
| | 5109 | .uav, |
| | 5110 | .lazy_code, |
| | 5111 | .lazy_const_data, |
| | 5112 | => |i| Symbol.Id.local(i.symbol(elf)).value(elf), |
| | 5113 | .value_debug_info, |
| | 5114 | .global_debug_info, |
| | 5115 | .frame_padding, |
| | 5116 | => unreachable, |
| | 5117 | .unit_frame => { |
| | 5118 | const section_ni = parent_ni.parent(&elf.mf).unwrap().?; |
| | 5119 | const section_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf); |
| | 5120 | break :parent_vaddr elf.getNode(section_ni).section.vaddr(elf) + section_offset; |
| | 5121 | }, |
| | 5122 | .unit_frame_cie, |
| | 5123 | .func_frame_fde, |
| | 5124 | .func_debug_info, |
| | 5125 | .func_debug_line, |
| | 5126 | => unreachable, |
| 4727 | }; | 5127 | }; |
| 4728 | const offset, _ = ni.location(&elf.mf).resolve(&elf.mf); | 5128 | const offset, _ = ni.location(&elf.mf).resolve(&elf.mf); |
| 4729 | return parent_vaddr + offset; | 5129 | return parent_vaddr + offset; |
| ... | @@ -4736,9 +5136,9 @@ fn getNodeElfOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 { | ... | @@ -4736,9 +5136,9 @@ fn getNodeElfOffset(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 4736 | /// sequence of relocations, so that the caller may append the node's updated relocations. | 5136 | /// sequence of relocations, so that the caller may append the node's updated relocations. |
| 4737 | /// | 5137 | /// |
| 4738 | /// Asserts that `ni` must be a node which supports relocations (see `Elf.Node`). Does not support | 5138 | /// Asserts that `ni` must be a node which supports relocations (see `Elf.Node`). Does not support |
| 4739 | /// the special-case sections '.plt' and '.dynamic'. | 5139 | /// the special-case sections '.plt', '.dynamic', and '.eh_frame_hdr'. |
| 4740 | fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { | 5140 | fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 4741 | const symbol_relocs: *SymbolReloc.Index, const got_relocs: ?*GotReloc.Index = switch (elf.getNode(ni)) { | 5141 | const symbol_relocs: *SymbolReloc.Index, const node_relocs: ?*NodeReloc.Index, const got_relocs: ?*GotReloc.Index = switch (elf.getNode(ni)) { |
| 4742 | .archive, | 5142 | .archive, |
| 4743 | .archive_header, | 5143 | .archive_header, |
| 4744 | .archive_input_member, | 5144 | .archive_input_member, |
| ... | @@ -4748,24 +5148,42 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { | ... | @@ -4748,24 +5148,42 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 4748 | .shdr, | 5148 | .shdr, |
| 4749 | .segment, | 5149 | .segment, |
| 4750 | .copied_global, | 5150 | .copied_global, |
| | 5151 | .value_debug_info, |
| | 5152 | .global_debug_info, |
| | 5153 | .frame_padding, |
| | 5154 | .unit_frame, |
| | 5155 | .unit_frame_cie, |
| | 5156 | .func_debug_info, |
| | 5157 | .func_debug_line, |
| 4751 | => unreachable, // cannot contain relocs | 5158 | => unreachable, // cannot contain relocs |
| 4752 | .section => unreachable, // cannot contain relocs (.plt and .dynamic unsupported) | 5159 | .section, |
| | 5160 | .section_manual_size, |
| | 5161 | => unreachable, // cannot contain relocs (.plt, .dynamic, and .eh_frame_hdr unsupported) |
| 4753 | .input_section => |isi| .{ | 5162 | .input_section => |isi| .{ |
| 4754 | &elf.input_sections.items[@backingInt(isi)].first_symbol_reloc, | 5163 | &elf.input_sections.items[@backingInt(isi)].first_symbol_reloc, |
| | 5164 | null, |
| 4755 | &elf.input_sections.items[@backingInt(isi)].first_got_reloc, | 5165 | &elf.input_sections.items[@backingInt(isi)].first_got_reloc, |
| 4756 | }, | 5166 | }, |
| 4757 | .nav => |nmi| .{ | 5167 | .nav => |nmi| .{ |
| 4758 | &elf.navs.values()[@backingInt(nmi)].first_symbol_reloc, | 5168 | &elf.navs.values()[@backingInt(nmi)].first_symbol_reloc, |
| | 5169 | null, |
| 4759 | &elf.navs.values()[@backingInt(nmi)].first_got_reloc, | 5170 | &elf.navs.values()[@backingInt(nmi)].first_got_reloc, |
| 4760 | }, | 5171 | }, |
| 4761 | .uav => |umi| .{ | 5172 | .uav => |umi| .{ |
| 4762 | &elf.uavs.values()[@backingInt(umi)].first_symbol_reloc, | 5173 | &elf.uavs.values()[@backingInt(umi)].first_symbol_reloc, |
| 4763 | null, | 5174 | null, |
| | 5175 | null, |
| 4764 | }, | 5176 | }, |
| 4765 | inline .lazy_code, .lazy_const_data => |lmi| .{ | 5177 | inline .lazy_code, .lazy_const_data => |lmi| .{ |
| 4766 | &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_symbol_reloc, | 5178 | &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_symbol_reloc, |
| | 5179 | null, |
| 4767 | &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_got_reloc, | 5180 | &elf.lazy.getPtr(lmi.ref().kind).map.values()[lmi.ref().index].first_got_reloc, |
| 4768 | }, | 5181 | }, |
| | 5182 | .func_frame_fde => |fi| .{ |
| | 5183 | &elf.dwarf_funcs.items[@backingInt(fi)].func_frame_fde_first_symbol_reloc, |
| | 5184 | &elf.dwarf_funcs.items[@backingInt(fi)].func_frame_fde_first_node_reloc, |
| | 5185 | null, |
| | 5186 | }, |
| 4769 | }; | 5187 | }; |
| 4770 | | 5188 | |
| 4771 | if (symbol_relocs.* != .none) { | 5189 | if (symbol_relocs.* != .none) { |
| ... | @@ -4779,6 +5197,16 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { | ... | @@ -4779,6 +5197,16 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 4779 | } | 5197 | } |
| 4780 | symbol_relocs.* = @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); | 5198 | symbol_relocs.* = @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); |
| 4781 | | 5199 | |
| | 5200 | if (node_relocs) |ptr| { |
| | 5201 | if (ptr.* != .none) { |
| | 5202 | for (elf.node_relocs.items[@backingInt(ptr.*)..]) |*reloc| { |
| | 5203 | if (reloc.node != ni) break; |
| | 5204 | reloc.delete(elf); |
| | 5205 | } |
| | 5206 | } |
| | 5207 | ptr.* = @fromBackingInt(@intCast(elf.node_relocs.items.len)); |
| | 5208 | } |
| | 5209 | |
| 4782 | if (got_relocs) |ptr| { | 5210 | if (got_relocs) |ptr| { |
| 4783 | if (ptr.* != .none) { | 5211 | if (ptr.* != .none) { |
| 4784 | for (elf.got_relocs.items[@backingInt(ptr.*)..]) |*reloc| { | 5212 | for (elf.got_relocs.items[@backingInt(ptr.*)..]) |*reloc| { |
| ... | @@ -4797,6 +5225,7 @@ fn flushMovedNodeRelocs( | ... | @@ -4797,6 +5225,7 @@ fn flushMovedNodeRelocs( |
| 4797 | node: MappedFile.Node.Index, | 5225 | node: MappedFile.Node.Index, |
| 4798 | node_vaddr: u64, | 5226 | node_vaddr: u64, |
| 4799 | first_symbol_reloc: SymbolReloc.Index, | 5227 | first_symbol_reloc: SymbolReloc.Index, |
| | 5228 | first_node_reloc: NodeReloc.Index, |
| 4800 | first_got_reloc: GotReloc.Index, | 5229 | first_got_reloc: GotReloc.Index, |
| 4801 | ) void { | 5230 | ) void { |
| 4802 | if (first_symbol_reloc != .none) { | 5231 | if (first_symbol_reloc != .none) { |
| ... | @@ -4816,6 +5245,21 @@ fn flushMovedNodeRelocs( | ... | @@ -4816,6 +5245,21 @@ fn flushMovedNodeRelocs( |
| 4816 | } | 5245 | } |
| 4817 | } | 5246 | } |
| 4818 | | 5247 | |
| | 5248 | if (first_node_reloc != .none) { |
| | 5249 | for (elf.node_relocs.items[@backingInt(first_node_reloc)..]) |*reloc| { |
| | 5250 | if (reloc.node != node) break; |
| | 5251 | if (reloc.rela_index.unwrap()) |rela_index| { |
| | 5252 | assert(elf.ehdrType() == .REL); |
| | 5253 | // The node has moved, so the offset of the relocation within the section might have |
| | 5254 | // changed, so update the `offset` field of the `ElfN.Rela` entry. |
| | 5255 | elf.getNodeShndx(reloc.node).get(elf).rela.shndx.relaSetOffset(elf, rela_index, node_vaddr + reloc.offset); |
| | 5256 | } else { |
| | 5257 | assert(elf.ehdrType() != .REL); |
| | 5258 | reloc.apply(elf); |
| | 5259 | } |
| | 5260 | } |
| | 5261 | } |
| | 5262 | |
| 4819 | if (first_got_reloc != .none) { | 5263 | if (first_got_reloc != .none) { |
| 4820 | for (elf.got_relocs.items[@backingInt(first_got_reloc)..]) |*reloc| { | 5264 | for (elf.got_relocs.items[@backingInt(first_got_reloc)..]) |*reloc| { |
| 4821 | if (reloc.node != node.toOptional()) break; | 5265 | if (reloc.node != node.toOptional()) break; |
| ... | @@ -5226,7 +5670,7 @@ fn mapInputSection(elf: *Elf, opts: struct { | ... | @@ -5226,7 +5670,7 @@ fn mapInputSection(elf: *Elf, opts: struct { |
| 5226 | } | 5670 | } |
| 5227 | | 5671 | |
| 5228 | switch (elf.targetLoad(&shdr.type)) { | 5672 | switch (elf.targetLoad(&shdr.type)) { |
| 5229 | .NULL, .PROGBITS => {}, | 5673 | .NULL, .PROGBITS, .X86_64_UNWIND => {}, |
| 5230 | else => return error.SectionTypeConflict, | 5674 | else => return error.SectionTypeConflict, |
| 5231 | } | 5675 | } |
| 5232 | | 5676 | |
| ... | @@ -5360,7 +5804,7 @@ fn uavMapIndex( | ... | @@ -5360,7 +5804,7 @@ fn uavMapIndex( |
| 5360 | .moved = true, // see assert at end of `genUav` | 5804 | .moved = true, // see assert at end of `genUav` |
| 5361 | .alignment = resolved_align, | 5805 | .alignment = resolved_align, |
| 5362 | }); | 5806 | }); |
| 5363 | var name_buf: [32]u8 = undefined; | 5807 | var name_buf: [std.fmt.count("__anon_{d}", .{std.math.maxInt(u32)})]u8 = undefined; |
| 5364 | const name = std.mem.print( | 5808 | const name = std.mem.print( |
| 5365 | &name_buf, | 5809 | &name_buf, |
| 5366 | "__anon_{d}", | 5810 | "__anon_{d}", |
| ... | @@ -5520,7 +5964,7 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load | ... | @@ -5520,7 +5964,7 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (Load |
| 5520 | } | 5964 | } |
| 5521 | var strtab: std.Io.Writer.Allocating = .init(gpa); | 5965 | var strtab: std.Io.Writer.Allocating = .init(gpa); |
| 5522 | defer strtab.deinit(); | 5966 | defer strtab.deinit(); |
| 5523 | while (r.takeStruct(std.elf.ar_hdr, native_endian)) |header| { | 5967 | while (r.takeStruct(std.elf.ar_hdr, .native)) |header| { |
| 5524 | if (!std.mem.eql(u8, &header.ar_fmag, std.elf.ARFMAG)) | 5968 | if (!std.mem.eql(u8, &header.ar_fmag, std.elf.ARFMAG)) |
| 5525 | return diags.failParse(path, "bad file magic", .{}); | 5969 | return diags.failParse(path, "bad file magic", .{}); |
| 5526 | const offset = fr.logicalPos(); | 5970 | const offset = fr.logicalPos(); |
| ... | @@ -5717,13 +6161,13 @@ fn loadObject( | ... | @@ -5717,13 +6161,13 @@ fn loadObject( |
| 5717 | for (sections[1..]) |*section| { | 6161 | for (sections[1..]) |*section| { |
| 5718 | if (section.shdr.name >= shstrtab.len) continue; | 6162 | if (section.shdr.name >= shstrtab.len) continue; |
| 5719 | const name = std.mem.sliceTo(shstrtab[section.shdr.name..], 0); | 6163 | const name = std.mem.sliceTo(shstrtab[section.shdr.name..], 0); |
| | 6164 | if (!comp.config.any_unwind_tables and std.mem.eql(u8, name, ".eh_frame")) continue; |
| 5720 | const opts: struct { | 6165 | const opts: struct { |
| 5721 | shndx: Section.Index, | 6166 | shndx: Section.Index, |
| 5722 | has_file_bits: bool, | | |
| 5723 | node_fixed: bool, | 6167 | node_fixed: bool, |
| 5724 | } = switch (section.shdr.type) { | 6168 | } = switch (section.shdr.type) { |
| 5725 | else => continue, | 6169 | else => continue, |
| 5726 | .PROGBITS, .NOBITS => opts: { | 6170 | .PROGBITS, .NOBITS, .X86_64_UNWIND => opts: { |
| 5727 | const shndx = elf.mapInputSection(.{ | 6171 | const shndx = elf.mapInputSection(.{ |
| 5728 | .name = name, | 6172 | .name = name, |
| 5729 | .flags = section.shdr.flags.shf, | 6173 | .flags = section.shdr.flags.shf, |
| ... | @@ -5776,7 +6220,6 @@ fn loadObject( | ... | @@ -5776,7 +6220,6 @@ fn loadObject( |
| 5776 | } | 6220 | } |
| 5777 | break :opts .{ | 6221 | break :opts .{ |
| 5778 | .shndx = shndx, | 6222 | .shndx = shndx, |
| 5779 | .has_file_bits = section.shdr.type == .PROGBITS, | | |
| 5780 | // For well-known sections, we know that it's fine to have e.g. random | 6223 | // For well-known sections, we know that it's fine to have e.g. random |
| 5781 | // padding, so there's no need to make the sections fixed. For custom | 6224 | // padding, so there's no need to make the sections fixed. For custom |
| 5782 | // sections, however, we do want fixed nodes to avoid padding. | 6225 | // sections, however, we do want fixed nodes to avoid padding. |
| ... | @@ -5819,7 +6262,6 @@ fn loadObject( | ... | @@ -5819,7 +6262,6 @@ fn loadObject( |
| 5819 | } | 6262 | } |
| 5820 | break :shndx shndx.*; | 6263 | break :shndx shndx.*; |
| 5821 | }, | 6264 | }, |
| 5822 | .has_file_bits = true, | | |
| 5823 | // This node must be fixed to prevent padding from being added between different | 6265 | // This node must be fixed to prevent padding from being added between different |
| 5824 | // INIT_ARRAY/FINI_ARRAY/PREINIT_ARRAY input sections. | 6266 | // INIT_ARRAY/FINI_ARRAY/PREINIT_ARRAY input sections. |
| 5825 | .node_fixed = true, | 6267 | .node_fixed = true, |
| ... | @@ -5855,7 +6297,7 @@ fn loadObject( | ... | @@ -5855,7 +6297,7 @@ fn loadObject( |
| 5855 | .input = input_index, | 6297 | .input = input_index, |
| 5856 | .file_location = .{ | 6298 | .file_location = .{ |
| 5857 | .offset = fl.offset + section.shdr.offset, | 6299 | .offset = fl.offset + section.shdr.offset, |
| 5858 | .size = if (opts.has_file_bits) section.shdr.size else 0, | 6300 | .size = if (section.shdr.type == .NOBITS) 0 else section.shdr.size, |
| 5859 | }, | 6301 | }, |
| 5860 | // The section vaddr is initially 0, because the symbol addresses are | 6302 | // The section vaddr is initially 0, because the symbol addresses are |
| 5861 | // zero-based. This will eventually be updated by `flushMoved`. | 6303 | // zero-based. This will eventually be updated by `flushMoved`. |
| ... | @@ -6407,6 +6849,7 @@ fn createInitFiniArraySection( | ... | @@ -6407,6 +6849,7 @@ fn createInitFiniArraySection( |
| 6407 | .type = @"type", | 6849 | .type = @"type", |
| 6408 | .flags = .{ .WRITE = true, .ALLOC = true }, | 6850 | .flags = .{ .WRITE = true, .ALLOC = true }, |
| 6409 | .node_align = addr_align, | 6851 | .node_align = addr_align, |
| | 6852 | .manual_size = true, |
| 6410 | }); | 6853 | }); |
| 6411 | elf.section_by_name.putAssumeCapacityNoClobber(shndx.name(elf), {}); | 6854 | elf.section_by_name.putAssumeCapacityNoClobber(shndx.name(elf), {}); |
| 6412 | try elf.ensureUnusedSymbolCapacity(2, .maybe_global); | 6855 | try elf.ensureUnusedSymbolCapacity(2, .maybe_global); |
| ... | @@ -6455,7 +6898,9 @@ fn prelinkInner(elf: *Elf) Error!void { | ... | @@ -6455,7 +6898,9 @@ fn prelinkInner(elf: *Elf) Error!void { |
| 6455 | const comp = elf.base.comp; | 6898 | const comp = elf.base.comp; |
| 6456 | const gpa = comp.gpa; | 6899 | const gpa = comp.gpa; |
| 6457 | | 6900 | |
| 6458 | if (comp.zcu != null and !comp.config.use_llvm and elf.ni.elf == .root) { | 6901 | if (comp.zcu) |zcu| self_hosted_codegen: { |
| | 6902 | if (comp.config.use_llvm) break :self_hosted_codegen; |
| | 6903 | |
| 6459 | // We're using self-hosted codegen---add an input representing the Zig "object". | 6904 | // We're using self-hosted codegen---add an input representing the Zig "object". |
| 6460 | try elf.ensureUnusedSymbolCapacity(1, .all_local); | 6905 | try elf.ensureUnusedSymbolCapacity(1, .all_local); |
| 6461 | try elf.inputs.ensureUnusedCapacity(gpa, 1); | 6906 | try elf.inputs.ensureUnusedCapacity(gpa, 1); |
| ... | @@ -6475,6 +6920,37 @@ fn prelinkInner(elf: *Elf) Error!void { | ... | @@ -6475,6 +6920,37 @@ fn prelinkInner(elf: *Elf) Error!void { |
| 6475 | .extra = .{ .file_symbol = zcu_file_symbol }, | 6920 | .extra = .{ .file_symbol = zcu_file_symbol }, |
| 6476 | }; | 6921 | }; |
| 6477 | elf.input_pending_index += 1; | 6922 | elf.input_pending_index += 1; |
| | 6923 | |
| | 6924 | try elf.dwarf.initUnits(zcu); |
| | 6925 | try elf.dwarf_units.appendNTimes(gpa, .{ |
| | 6926 | .unit_frame_cie_first_target_reloc = .none, |
| | 6927 | }, elf.dwarf.units.count()); |
| | 6928 | |
| | 6929 | try elf.nodes.ensureUnusedCapacity(gpa, 2); |
| | 6930 | for ( |
| | 6931 | [2]Dwarf.Frame.Format{ .eh_frame, .debug_frame }, |
| | 6932 | [2]Section.Index{ elf.shndx.eh_frame, elf.shndx.debug_frame }, |
| | 6933 | ) |format, frame_shndx| { |
| | 6934 | if (frame_shndx == .UNDEF) continue; |
| | 6935 | const frame_ni = frame_shndx.get(elf).ni; |
| | 6936 | _ = frame_ni.last(&elf.mf).unwrap() orelse continue; |
| | 6937 | const frame_padding_ni = try frame_ni.addFloatingChild(&elf.mf, gpa, .{ |
| | 6938 | .alignment = switch (elf.identClass()) { |
| | 6939 | .NONE, _ => unreachable, |
| | 6940 | .@"32" => .@"4", |
| | 6941 | .@"64" => .@"8", |
| | 6942 | }, |
| | 6943 | .next_moved = true, |
| | 6944 | .enable_next_moved = true, |
| | 6945 | }); |
| | 6946 | elf.nodes.appendAssumeCapacity(.frame_padding); |
| | 6947 | var cie_writer: MappedFile.Node.Writer = undefined; |
| | 6948 | frame_padding_ni.writer(&elf.mf, gpa, &cie_writer); |
| | 6949 | defer cie_writer.deinit(); |
| | 6950 | elf.dwarf.genDebugFrameCie(&cie_writer.interface, null, format) catch |err| switch (err) { |
| | 6951 | error.WriteFailed => return cie_writer.err.?, |
| | 6952 | }; |
| | 6953 | } |
| 6478 | } | 6954 | } |
| 6479 | } | 6955 | } |
| 6480 | | 6956 | |
| ... | @@ -6610,7 +7086,7 @@ fn flushDynamic(elf: *Elf) void { | ... | @@ -6610,7 +7086,7 @@ fn flushDynamic(elf: *Elf) void { |
| 6610 | dynamic_index += 9; | 7086 | dynamic_index += 9; |
| 6611 | | 7087 | |
| 6612 | assert(dynamic_index == dynamic_entries.len); | 7088 | assert(dynamic_index == dynamic_entries.len); |
| 6613 | if (elf.targetEndian() != native_endian) for (dynamic_entries) |*dynamic_entry| | 7089 | if (elf.targetEndian() != std.lang.Endian.native) for (dynamic_entries) |*dynamic_entry| |
| 6614 | std.mem.byteSwapAllFields(@TypeOf(dynamic_entry.*), dynamic_entry); | 7090 | std.mem.byteSwapAllFields(@TypeOf(dynamic_entry.*), dynamic_entry); |
| 6615 | }, | 7091 | }, |
| 6616 | } | 7092 | } |
| ... | @@ -6626,6 +7102,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { | ... | @@ -6626,6 +7102,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 6626 | addralign: Alignment = .@"1", | 7102 | addralign: Alignment = .@"1", |
| 6627 | entsize: std.elf.Word = 0, | 7103 | entsize: std.elf.Word = 0, |
| 6628 | node_align: Alignment = .@"1", | 7104 | node_align: Alignment = .@"1", |
| | 7105 | manual_size: bool = false, |
| 6629 | }) Error!Section.Index { | 7106 | }) Error!Section.Index { |
| 6630 | switch (opts.type) { | 7107 | switch (opts.type) { |
| 6631 | .NULL => assert(opts.size == 0), | 7108 | .NULL => assert(opts.size == 0), |
| ... | @@ -6679,6 +7156,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { | ... | @@ -6679,6 +7156,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 6679 | .size = opts.node_align.forward(opts.size), | 7156 | .size = opts.node_align.forward(opts.size), |
| 6680 | .alignment = opts.addralign.max(opts.node_align), | 7157 | .alignment = opts.addralign.max(opts.node_align), |
| 6681 | .resized = opts.size > 0, | 7158 | .resized = opts.size > 0, |
| | 7159 | .bubbles_moved = opts.flags.ALLOC, |
| 6682 | }); | 7160 | }); |
| 6683 | const addr = elf.computeNodeVAddr(ni); | 7161 | const addr = elf.computeNodeVAddr(ni); |
| 6684 | const lsi: Symbol.LocalIndex = if (opts.flags.ALLOC) elf.addLocalSymbolAssumeCapacity(.{ | 7162 | const lsi: Symbol.LocalIndex = if (opts.flags.ALLOC) elf.addLocalSymbolAssumeCapacity(.{ |
| ... | @@ -6694,7 +7172,10 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { | ... | @@ -6694,7 +7172,10 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 6694 | .RELA => .{ .free_head = .none }, | 7172 | .RELA => .{ .free_head = .none }, |
| 6695 | else => .{ .shndx = .UNDEF }, | 7173 | else => .{ .shndx = .UNDEF }, |
| 6696 | } }); | 7174 | } }); |
| 6697 | elf.nodes.appendAssumeCapacity(.{ .section = shndx }); | 7175 | elf.nodes.appendAssumeCapacity(switch (opts.manual_size) { |
| | 7176 | false => .{ .section = shndx }, |
| | 7177 | true => .{ .section_manual_size = shndx }, |
| | 7178 | }); |
| 6698 | switch (elf.shdrPtr(shndx)) { | 7179 | switch (elf.shdrPtr(shndx)) { |
| 6699 | inline else => |shdr, class| { | 7180 | inline else => |shdr, class| { |
| 6700 | shdr.* = .{ | 7181 | shdr.* = .{ |
| ... | @@ -6709,7 +7190,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { | ... | @@ -6709,7 +7190,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 6709 | .addralign = @intCast(opts.addralign.toByteUnits()), | 7190 | .addralign = @intCast(opts.addralign.toByteUnits()), |
| 6710 | .entsize = opts.entsize, | 7191 | .entsize = opts.entsize, |
| 6711 | }; | 7192 | }; |
| 6712 | if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(class.ElfN().Shdr, shdr); | 7193 | if (elf.targetEndian() != std.lang.Endian.native) std.mem.byteSwapAllFields(class.ElfN().Shdr, shdr); |
| 6713 | }, | 7194 | }, |
| 6714 | } | 7195 | } |
| 6715 | return shndx; | 7196 | return shndx; |
| ... | @@ -6719,6 +7200,7 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) | ... | @@ -6719,6 +7200,7 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) |
| 6719 | if (len == 0) return; | 7200 | if (len == 0) return; |
| 6720 | const gpa = elf.base.comp.gpa; | 7201 | const gpa = elf.base.comp.gpa; |
| 6721 | try elf.symbol_relocs.ensureUnusedCapacity(gpa, len); | 7202 | try elf.symbol_relocs.ensureUnusedCapacity(gpa, len); |
| | 7203 | try elf.node_relocs.ensureUnusedCapacity(gpa, len); |
| 6722 | try elf.got_relocs.ensureUnusedCapacity(gpa, len); | 7204 | try elf.got_relocs.ensureUnusedCapacity(gpa, len); |
| 6723 | const class = elf.identClass(); | 7205 | const class = elf.identClass(); |
| 6724 | switch (elf.ehdrType()) { | 7206 | switch (elf.ehdrType()) { |
| ... | @@ -6749,6 +7231,7 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) | ... | @@ -6749,6 +7231,7 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) |
| 6749 | inline else => |ct_class| @sizeOf(ct_class.ElfN().Rela), | 7231 | inline else => |ct_class| @sizeOf(ct_class.ElfN().Rela), |
| 6750 | }, | 7232 | }, |
| 6751 | .node_align = elf.mf.flags.block_size, | 7233 | .node_align = elf.mf.flags.block_size, |
| | 7234 | .manual_size = true, |
| 6752 | }); | 7235 | }); |
| 6753 | elf.section_by_name.putAssumeCapacityNoClobber(rela_shndx.name(elf), {}); | 7236 | elf.section_by_name.putAssumeCapacityNoClobber(rela_shndx.name(elf), {}); |
| 6754 | shndx.get(elf).rela.shndx = rela_shndx; | 7237 | shndx.get(elf).rela.shndx = rela_shndx; |
| ... | @@ -6795,15 +7278,10 @@ fn addRelocAssumeCapacity( | ... | @@ -6795,15 +7278,10 @@ fn addRelocAssumeCapacity( |
| 6795 | .addend = addend, | 7278 | .addend = addend, |
| 6796 | }); | 7279 | }); |
| 6797 | const ri: SymbolReloc.Index = @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); | 7280 | const ri: SymbolReloc.Index = @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); |
| 6798 | const next: SymbolReloc.Index = next: { | 7281 | const first_target_reloc = &target.index(elf).ptr(elf).first_target_reloc; |
| 6799 | const target_ptr = target.index(elf).ptr(elf); | 7282 | const next = first_target_reloc.*; |
| 6800 | const next = target_ptr.first_target_reloc; | 7283 | first_target_reloc.* = ri; |
| 6801 | target_ptr.first_target_reloc = ri; | 7284 | if (next != .none) next.get(elf).prev = ri; |
| 6802 | break :next next; | | |
| 6803 | }; | | |
| 6804 | if (next != .none) { | | |
| 6805 | next.get(elf).prev = ri; | | |
| 6806 | } | | |
| 6807 | elf.symbol_relocs.appendAssumeCapacity(.{ | 7285 | elf.symbol_relocs.appendAssumeCapacity(.{ |
| 6808 | .node = node, | 7286 | .node = node, |
| 6809 | .offset = offset, | 7287 | .offset = offset, |
| ... | @@ -6816,7 +7294,6 @@ fn addRelocAssumeCapacity( | ... | @@ -6816,7 +7294,6 @@ fn addRelocAssumeCapacity( |
| 6816 | .result = .ok, | 7294 | .result = .ok, |
| 6817 | }); | 7295 | }); |
| 6818 | }, | 7296 | }, |
| 6819 | | | |
| 6820 | .DYN, .EXEC => switch (elf.ehdrMachine()) { | 7297 | .DYN, .EXEC => switch (elf.ehdrMachine()) { |
| 6821 | .AARCH64 => switch (@"type".AARCH64) { | 7298 | .AARCH64 => switch (@"type".AARCH64) { |
| 6822 | .NONE => {}, | 7299 | .NONE => {}, |
| ... | @@ -7239,12 +7716,10 @@ fn addSymbolRelocAssumeCapacity( | ... | @@ -7239,12 +7716,10 @@ fn addSymbolRelocAssumeCapacity( |
| 7239 | }; | 7716 | }; |
| 7240 | | 7717 | |
| 7241 | const ri: SymbolReloc.Index = @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); | 7718 | const ri: SymbolReloc.Index = @fromBackingInt(@intCast(elf.symbol_relocs.items.len)); |
| 7242 | const target_ptr = target.index(elf).ptr(elf); | 7719 | const first_target_reloc = &target.index(elf).ptr(elf).first_target_reloc; |
| 7243 | const next = target_ptr.first_target_reloc; | 7720 | const next = first_target_reloc.*; |
| 7244 | target_ptr.first_target_reloc = ri; | 7721 | first_target_reloc.* = ri; |
| 7245 | if (next != .none) { | 7722 | if (next != .none) next.get(elf).prev = ri; |
| 7246 | next.get(elf).prev = ri; | | |
| 7247 | } | | |
| 7248 | elf.symbol_relocs.appendAssumeCapacity(.{ | 7723 | elf.symbol_relocs.appendAssumeCapacity(.{ |
| 7249 | .node = node, | 7724 | .node = node, |
| 7250 | .offset = offset, | 7725 | .offset = offset, |
| ... | @@ -7263,6 +7738,92 @@ fn addSymbolRelocAssumeCapacity( | ... | @@ -7263,6 +7738,92 @@ fn addSymbolRelocAssumeCapacity( |
| 7263 | // Actually apply the new relocation! | 7738 | // Actually apply the new relocation! |
| 7264 | ri.get(elf).apply(elf); | 7739 | ri.get(elf).apply(elf); |
| 7265 | } | 7740 | } |
| | 7741 | fn addNodeRelocAssumeCapacity( |
| | 7742 | elf: *Elf, |
| | 7743 | node: MappedFile.Node.Index, |
| | 7744 | offset: u64, |
| | 7745 | target: MappedFile.Node.Index, |
| | 7746 | addend: i64, |
| | 7747 | @"type": NodeReloc.Type, |
| | 7748 | ) Error!void { |
| | 7749 | const shndx = elf.getNodeShndx(target); |
| | 7750 | assert(!shndx.flags(elf).ALLOC); // not yet needed so not implemented |
| | 7751 | const first_target_reloc = switch (elf.getNode(target)) { |
| | 7752 | else => unreachable, |
| | 7753 | .unit_frame_cie => |ui| &elf.dwarf_units.items[@backingInt(ui)].unit_frame_cie_first_target_reloc, |
| | 7754 | }; |
| | 7755 | const next = first_target_reloc.*; |
| | 7756 | const ri: NodeReloc.Index = @fromBackingInt(@intCast(elf.node_relocs.items.len)); |
| | 7757 | first_target_reloc.* = ri; |
| | 7758 | if (next != .none) next.get(elf).prev = ri; |
| | 7759 | switch (elf.ehdrType()) { |
| | 7760 | .REL => { |
| | 7761 | const rela_shndx = elf.getNodeShndx(node).get(elf).rela.shndx; |
| | 7762 | const rela_index = rela_shndx.relaAddOneAssumeCapacity(elf, .{ |
| | 7763 | .type = switch (elf.ehdrMachine()) { |
| | 7764 | .AARCH64 => .{ .AARCH64 = switch (@"type") { |
| | 7765 | .abs32 => .ABS32, |
| | 7766 | .abs64 => .ABS64, |
| | 7767 | } }, |
| | 7768 | .LOONGARCH => .{ .LARCH = switch (@"type") { |
| | 7769 | .abs32 => .@"32", |
| | 7770 | .abs64 => .@"64", |
| | 7771 | } }, |
| | 7772 | .PPC64 => .{ .PPC64 = switch (@"type") { |
| | 7773 | .abs32 => .ADDR32, |
| | 7774 | .abs64 => .ADDR64, |
| | 7775 | } }, |
| | 7776 | .RISCV => .{ .RISCV = switch (@"type") { |
| | 7777 | .abs32 => .@"32", |
| | 7778 | .abs64 => .@"64", |
| | 7779 | } }, |
| | 7780 | .SPARCV9 => .{ .SPARC = switch (@"type") { |
| | 7781 | .abs32 => .UA32, |
| | 7782 | .abs64 => .UA64, |
| | 7783 | } }, |
| | 7784 | .X86_64 => .{ .SPARC = switch (@"type") { |
| | 7785 | .abs32 => .@"32", |
| | 7786 | .abs64 => .@"64", |
| | 7787 | } }, |
| | 7788 | }, |
| | 7789 | // This field needs to equal the offset into the section, which is *not* necessarily |
| | 7790 | // the same thing as our `offset`, which is the offset into `node`. We could compute |
| | 7791 | // the section offset now, but there's no point, because `flushMovedNodeRelocs` will |
| | 7792 | // eventually do it for us anyway, so just init to 0. |
| | 7793 | .offset = 0, |
| | 7794 | .raw_sym_index = @backingInt(shndx.get(elf).lsi.index()), |
| | 7795 | .addend = addend, |
| | 7796 | }); |
| | 7797 | elf.node_relocs.appendAssumeCapacity(.{ |
| | 7798 | .node = node, |
| | 7799 | .offset = offset, |
| | 7800 | .type = undefined, |
| | 7801 | .target = target, |
| | 7802 | .addend = addend, |
| | 7803 | .next = next, |
| | 7804 | .prev = .none, |
| | 7805 | .rela_index = rela_index.toOptional(), |
| | 7806 | .result = .ok, |
| | 7807 | }); |
| | 7808 | }, |
| | 7809 | .DYN, .EXEC => { |
| | 7810 | elf.node_relocs.appendAssumeCapacity(.{ |
| | 7811 | .node = node, |
| | 7812 | .offset = offset, |
| | 7813 | .target = target, |
| | 7814 | .addend = addend, |
| | 7815 | .type = @"type", |
| | 7816 | .next = next, |
| | 7817 | .prev = .none, |
| | 7818 | .rela_index = .none, |
| | 7819 | .result = .ok, |
| | 7820 | }); |
| | 7821 | |
| | 7822 | // Actually apply the new relocation! |
| | 7823 | ri.get(elf).apply(elf); |
| | 7824 | }, |
| | 7825 | } |
| | 7826 | } |
| 7266 | fn addGotRelocAssumeCapacity( | 7827 | fn addGotRelocAssumeCapacity( |
| 7267 | elf: *Elf, | 7828 | elf: *Elf, |
| 7268 | node: MappedFile.Node.Index, | 7829 | node: MappedFile.Node.Index, |
| ... | @@ -7282,8 +7843,17 @@ fn addGotRelocAssumeCapacity( | ... | @@ -7282,8 +7843,17 @@ fn addGotRelocAssumeCapacity( |
| 7282 | .shdr, | 7843 | .shdr, |
| 7283 | .segment, | 7844 | .segment, |
| 7284 | .copied_global, | 7845 | .copied_global, |
| | 7846 | .value_debug_info, |
| | 7847 | .global_debug_info, |
| | 7848 | .frame_padding, |
| | 7849 | .unit_frame, |
| | 7850 | .unit_frame_cie, |
| | 7851 | .func_frame_fde, |
| | 7852 | .func_debug_info, |
| | 7853 | .func_debug_line, |
| 7285 | => unreachable, // cannot contain relocs, | 7854 | => unreachable, // cannot contain relocs, |
| 7286 | .section, | 7855 | .section, |
| | 7856 | .section_manual_size, |
| 7287 | .uav, | 7857 | .uav, |
| 7288 | => unreachable, // cannot contain GOT relocs | 7858 | => unreachable, // cannot contain GOT relocs |
| 7289 | .input_section, | 7859 | .input_section, |
| ... | @@ -7572,7 +8142,6 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) | ... | @@ -7572,7 +8142,6 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) |
| 7572 | | 8142 | |
| 7573 | const nmi = try elf.navMapIndex(zcu, nav_index); | 8143 | const nmi = try elf.navMapIndex(zcu, nav_index); |
| 7574 | const ni = nmi.symbol(elf).index().ptr(elf).node.unwrap().?; | 8144 | const ni = nmi.symbol(elf).index().ptr(elf).node.unwrap().?; |
| 7575 | elf.resetNodeRelocs(ni); | | |
| 7576 | | 8145 | |
| 7577 | // Ensure the NAV is marked as moved so that once we're done, `flushMoved` will eventually be | 8146 | // Ensure the NAV is marked as moved so that once we're done, `flushMoved` will eventually be |
| 7578 | // called to apply the NAV's new relocations. | 8147 | // called to apply the NAV's new relocations. |
| ... | @@ -7582,6 +8151,7 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) | ... | @@ -7582,6 +8151,7 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) |
| 7582 | var nw: MappedFile.Node.Writer = undefined; | 8151 | var nw: MappedFile.Node.Writer = undefined; |
| 7583 | ni.writer(&elf.mf, gpa, &nw); | 8152 | ni.writer(&elf.mf, gpa, &nw); |
| 7584 | defer nw.deinit(); | 8153 | defer nw.deinit(); |
| | 8154 | elf.resetNodeRelocs(ni); |
| 7585 | codegen.generateSymbol( | 8155 | codegen.generateSymbol( |
| 7586 | &elf.base, | 8156 | &elf.base, |
| 7587 | pt, | 8157 | pt, |
| ... | @@ -7628,7 +8198,6 @@ fn updateFuncInner( | ... | @@ -7628,7 +8198,6 @@ fn updateFuncInner( |
| 7628 | const nmi = try elf.navMapIndex(zcu, func.owner_nav); | 8198 | const nmi = try elf.navMapIndex(zcu, func.owner_nav); |
| 7629 | log.debug("updateFunc({f}) = {d}", .{ nav.fqn.fmt(ip), nmi.symbol(elf) }); | 8199 | log.debug("updateFunc({f}) = {d}", .{ nav.fqn.fmt(ip), nmi.symbol(elf) }); |
| 7630 | const ni = nmi.symbol(elf).index().ptr(elf).node.unwrap().?; | 8200 | const ni = nmi.symbol(elf).index().ptr(elf).node.unwrap().?; |
| 7631 | elf.resetNodeRelocs(ni); | | |
| 7632 | | 8201 | |
| 7633 | // Ensure the NAV is marked as moved so that once we're done, `flushMoved` will eventually be | 8202 | // Ensure the NAV is marked as moved so that once we're done, `flushMoved` will eventually be |
| 7634 | // called to apply the NAV's new relocations. | 8203 | // called to apply the NAV's new relocations. |
| ... | @@ -7638,6 +8207,132 @@ fn updateFuncInner( | ... | @@ -7638,6 +8207,132 @@ fn updateFuncInner( |
| 7638 | var nw: MappedFile.Node.Writer = undefined; | 8207 | var nw: MappedFile.Node.Writer = undefined; |
| 7639 | ni.writer(&elf.mf, gpa, &nw); | 8208 | ni.writer(&elf.mf, gpa, &nw); |
| 7640 | defer nw.deinit(); | 8209 | defer nw.deinit(); |
| | 8210 | var debug: Dwarf.WipNav.Debug = undefined; |
| | 8211 | const debug_output: link.File.DebugInfoOutput = debug_output: { |
| | 8212 | if (elf.ehdrMachine() != .X86_64) break :debug_output .none; |
| | 8213 | const dwarf = &elf.dwarf; |
| | 8214 | const mod = zcu.navFileScope(func.owner_nav).mod.?; |
| | 8215 | if (mod.strip and mod.unwind_tables == .none) break :debug_output .none; |
| | 8216 | |
| | 8217 | try elf.nodes.ensureUnusedCapacity(gpa, 5); |
| | 8218 | const dwarf_func_index = try dwarf.getFunc(func.owner_nav); |
| | 8219 | try elf.dwarf_funcs.appendNTimes(gpa, .{ |
| | 8220 | .func_frame_fde_first_symbol_reloc = .none, |
| | 8221 | .func_frame_fde_first_node_reloc = .none, |
| | 8222 | }, @backingInt(dwarf_func_index) + 1 -| elf.dwarf_funcs.items.len); |
| | 8223 | |
| | 8224 | debug.wip_nav = .{ |
| | 8225 | .dwarf = dwarf, |
| | 8226 | .unit = dwarf.getUnit(mod), |
| | 8227 | .func = dwarf_func_index, |
| | 8228 | .func_si = Symbol.Id.local(nmi.symbol(elf)).toTypeErased(), |
| | 8229 | .cfi = .{ |
| | 8230 | .loc = 0, |
| | 8231 | .cfa = dwarf.frame.header.initial_instructions[0].def_cfa, |
| | 8232 | }, |
| | 8233 | .frame_format = switch (mod.unwind_tables) { |
| | 8234 | .none => .debug_frame, |
| | 8235 | .sync, .async => .eh_frame, |
| | 8236 | }, |
| | 8237 | .fde_writer = undefined, |
| | 8238 | .frame_func_length_offset = std.math.maxInt(usize), |
| | 8239 | }; |
| | 8240 | const unit = debug.wip_nav.unit.get(dwarf); |
| | 8241 | const frame_align: Alignment = switch (elf.identClass()) { |
| | 8242 | .NONE, _ => unreachable, |
| | 8243 | .@"32" => .@"4", |
| | 8244 | .@"64" => .@"8", |
| | 8245 | }; |
| | 8246 | const frame_ni = unit.frame_ni.unwrap() orelse frame_ni: { |
| | 8247 | const frame_ni = try switch (debug.wip_nav.frame_format) { |
| | 8248 | .debug_frame => elf.shndx.debug_frame, |
| | 8249 | .eh_frame => elf.shndx.eh_frame, |
| | 8250 | }.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{ |
| | 8251 | .alignment = frame_align.max(elf.mf.flags.block_size), |
| | 8252 | .next_moved = true, |
| | 8253 | .enable_next_moved = true, |
| | 8254 | }); |
| | 8255 | unit.frame_ni = .wrap(frame_ni); |
| | 8256 | elf.nodes.appendAssumeCapacity(.{ .unit_frame = debug.wip_nav.unit }); |
| | 8257 | break :frame_ni frame_ni; |
| | 8258 | }; |
| | 8259 | _ = unit.cie_ni.unwrap() orelse { |
| | 8260 | const cie_ni = try frame_ni.addOnlyHeaderChild(&elf.mf, gpa, .{ |
| | 8261 | .alignment = frame_align, |
| | 8262 | .next_moved = true, |
| | 8263 | .enable_next_moved = true, |
| | 8264 | }); |
| | 8265 | unit.cie_ni = .wrap(cie_ni); |
| | 8266 | elf.nodes.appendAssumeCapacity(.{ .unit_frame_cie = debug.wip_nav.unit }); |
| | 8267 | var cie_writer: MappedFile.Node.Writer = undefined; |
| | 8268 | cie_ni.writer(&elf.mf, gpa, &cie_writer); |
| | 8269 | defer cie_writer.deinit(); |
| | 8270 | dwarf.genDebugFrameCie(&cie_writer.interface, switch (elf.ehdrMachine()) { |
| | 8271 | else => unreachable, |
| | 8272 | .X86_64 => .x86_64, |
| | 8273 | }, debug.wip_nav.frame_format) catch |err| switch (err) { |
| | 8274 | error.WriteFailed => return cie_writer.err.?, |
| | 8275 | }; |
| | 8276 | @memset(cie_writer.interface.unusedCapacitySlice(), std.dwarf.CFA.nop); |
| | 8277 | }; |
| | 8278 | const dwarf_func = dwarf_func_index.get(dwarf); |
| | 8279 | const fde_ni = if (dwarf_func.fde_ni.unwrap()) |fde_ni| fde_ni: { |
| | 8280 | try fde_ni.moved(gpa, &elf.mf); |
| | 8281 | try fde_ni.nextMoved(gpa, &elf.mf); |
| | 8282 | break :fde_ni fde_ni; |
| | 8283 | } else fde_ni: { |
| | 8284 | const fde_ni = try frame_ni.addFloatingChild(&elf.mf, gpa, .{ |
| | 8285 | .alignment = frame_align, |
| | 8286 | .moved = true, |
| | 8287 | .next_moved = true, |
| | 8288 | .enable_next_moved = true, |
| | 8289 | }); |
| | 8290 | dwarf_func.fde_ni = .wrap(fde_ni); |
| | 8291 | break :fde_ni fde_ni; |
| | 8292 | }; |
| | 8293 | fde_ni.writer(&elf.mf, gpa, &debug.wip_nav.fde_writer); |
| | 8294 | if (mod.strip) break :debug_output .{ .eh_frame = &debug.wip_nav }; |
| | 8295 | |
| | 8296 | debug.pt = pt; |
| | 8297 | debug.any_children = false; |
| | 8298 | debug.blocks = .empty; |
| | 8299 | const debug_info_ni = dwarf_func.debug_info_ni.unwrap() orelse debug_info_ni: { |
| | 8300 | const debug_info_ni = |
| | 8301 | try elf.shndx.debug_info.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{ |
| | 8302 | .next_moved = true, |
| | 8303 | .enable_next_moved = true, |
| | 8304 | }); |
| | 8305 | dwarf_func.debug_info_ni = .wrap(debug_info_ni); |
| | 8306 | elf.nodes.appendAssumeCapacity(.{ .func_debug_info = dwarf_func_index }); |
| | 8307 | break :debug_info_ni debug_info_ni; |
| | 8308 | }; |
| | 8309 | debug_info_ni.writer(&elf.mf, gpa, &debug.info_writer); |
| | 8310 | const debug_line_ni = dwarf_func.debug_line_ni.unwrap() orelse debug_line_ni: { |
| | 8311 | const debug_line_ni = |
| | 8312 | try elf.shndx.debug_line.get(elf).ni.addFloatingChild(&elf.mf, gpa, .{ |
| | 8313 | .next_moved = true, |
| | 8314 | .enable_next_moved = true, |
| | 8315 | }); |
| | 8316 | elf.nodes.appendAssumeCapacity(.{ .func_debug_line = dwarf_func_index }); |
| | 8317 | break :debug_line_ni debug_line_ni; |
| | 8318 | }; |
| | 8319 | debug_line_ni.writer(&elf.mf, gpa, &debug.line_writer); |
| | 8320 | break :debug_output .{ .dwarf2 = &debug }; |
| | 8321 | }; |
| | 8322 | defer switch (debug_output) { |
| | 8323 | .dwarf => unreachable, |
| | 8324 | inline .eh_frame, .dwarf2 => |dwarf| dwarf.deinit(gpa), |
| | 8325 | .none => {}, |
| | 8326 | }; |
| | 8327 | switch (debug_output) { |
| | 8328 | .dwarf => unreachable, |
| | 8329 | inline .eh_frame, .dwarf2 => |dwarf| { |
| | 8330 | elf.resetNodeRelocs(debug.wip_nav.func.?.get(&elf.dwarf).fde_ni.unwrap().?); |
| | 8331 | try dwarf.genFuncHeaders(); |
| | 8332 | }, |
| | 8333 | .none => {}, |
| | 8334 | } |
| | 8335 | elf.resetNodeRelocs(ni); |
| 7641 | codegen.emitFunction( | 8336 | codegen.emitFunction( |
| 7642 | &elf.base, | 8337 | &elf.base, |
| 7643 | pt, | 8338 | pt, |
| ... | @@ -7645,13 +8340,35 @@ fn updateFuncInner( | ... | @@ -7645,13 +8340,35 @@ fn updateFuncInner( |
| 7645 | Node.toAtom(ni), | 8340 | Node.toAtom(ni), |
| 7646 | mir, | 8341 | mir, |
| 7647 | &nw.interface, | 8342 | &nw.interface, |
| 7648 | .none, | 8343 | debug_output, |
| 7649 | ) catch |err| switch (err) { | 8344 | ) catch |err| switch (err) { |
| 7650 | error.WriteFailed => return nw.err.?, | 8345 | error.WriteFailed => return nw.err.?, |
| 7651 | else => |e| return e, | 8346 | else => |e| return e, |
| 7652 | }; | 8347 | }; |
| | 8348 | const func_length = nw.interface.end; |
| | 8349 | switch (debug_output) { |
| | 8350 | .dwarf => unreachable, |
| | 8351 | .eh_frame, .dwarf2 => { |
| | 8352 | debug.wip_nav.finishDebugFrameFde(func_length); |
| | 8353 | const frame_ni = switch (debug.wip_nav.frame_format) { |
| | 8354 | .debug_frame => elf.shndx.debug_frame, |
| | 8355 | .eh_frame => elf.shndx.eh_frame, |
| | 8356 | }.get(elf).ni; |
| | 8357 | try frame_ni.trimStart(&elf.mf, elf.base.comp.gpa); |
| | 8358 | switch (debug.wip_nav.frame_format) { |
| | 8359 | .debug_frame => {}, |
| | 8360 | .eh_frame => { |
| | 8361 | const last_offset, const last_size = |
| | 8362 | frame_ni.last(&elf.mf).unwrap().?.location(&elf.mf).resolve(&elf.mf); |
| | 8363 | const last_end = last_offset + last_size; |
| | 8364 | try frame_ni.ensureMinimumSize(&elf.mf, elf.base.comp.gpa, last_end + 4); |
| | 8365 | }, |
| | 8366 | } |
| | 8367 | }, |
| | 8368 | .none => {}, |
| | 8369 | } |
| 7653 | switch (elf.symPtr(nmi.symbol(elf).index())) { | 8370 | switch (elf.symPtr(nmi.symbol(elf).index())) { |
| 7654 | inline else => |sym| elf.targetStore(&sym.size, @intCast(nw.interface.end)), | 8371 | inline else => |sym| elf.targetStore(&sym.size, @intCast(func_length)), |
| 7655 | } | 8372 | } |
| 7656 | } | 8373 | } |
| 7657 | | 8374 | |
| ... | @@ -7915,11 +8632,11 @@ fn idleProgNode( | ... | @@ -7915,11 +8632,11 @@ fn idleProgNode( |
| 7915 | var name: [std.Progress.Node.max_name_len]u8 = undefined; | 8632 | var name: [std.Progress.Node.max_name_len]u8 = undefined; |
| 7916 | return prog_node.start(name: switch (node) { | 8633 | return prog_node.start(name: switch (node) { |
| 7917 | else => |tag| @tagName(tag), | 8634 | else => |tag| @tagName(tag), |
| 7918 | .section => |shndx| shndx.name(elf).slice(elf), | | |
| 7919 | .archive_input_member => |ii| std.mem.print(&name, "{f}{f}", .{ | 8635 | .archive_input_member => |ii| std.mem.print(&name, "{f}{f}", .{ |
| 7920 | ii.path(elf).fmtEscapeString(), | 8636 | ii.path(elf).fmtEscapeString(), |
| 7921 | fmtMemberString(ii.member(elf)), | 8637 | fmtMemberString(ii.member(elf)), |
| 7922 | }) catch &name, | 8638 | }) catch &name, |
| | 8639 | .section, .section_manual_size => |shndx| shndx.name(elf).slice(elf), |
| 7923 | .input_section => |isi| { | 8640 | .input_section => |isi| { |
| 7924 | const ii = isi.input(elf); | 8641 | const ii = isi.input(elf); |
| 7925 | break :name std.mem.print(&name, "{f}{f} {s}", .{ | 8642 | break :name std.mem.print(&name, "{f}{f} {s}", .{ |
| ... | @@ -7935,6 +8652,31 @@ fn idleProgNode( | ... | @@ -7935,6 +8652,31 @@ fn idleProgNode( |
| 7935 | .uav => |umi| std.mem.print(&name, "{f}", .{ | 8652 | .uav => |umi| std.mem.print(&name, "{f}", .{ |
| 7936 | Value.fromInterned(umi.uavValue(elf)).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }), | 8653 | Value.fromInterned(umi.uavValue(elf)).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }), |
| 7937 | }) catch &name, | 8654 | }) catch &name, |
| | 8655 | .value_debug_info => |cpi| std.mem.print(&name, "debug info for {f}", .{ |
| | 8656 | Value.fromInterned(cpi.val(&elf.dwarf.const_pool)) |
| | 8657 | .fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }), |
| | 8658 | }) catch &name, |
| | 8659 | .global_debug_info => |gi| { |
| | 8660 | const ip = &elf.base.comp.zcu.?.intern_pool; |
| | 8661 | break :name std.mem.print(&name, "debug info for {f}", .{ |
| | 8662 | ip.getNav(gi.nav(&elf.dwarf)).fqn.fmt(ip), |
| | 8663 | }) catch &name; |
| | 8664 | }, |
| | 8665 | .unit_frame, .unit_frame_cie => |ui| std.mem.print(&name, "unwind info for {s}", .{ |
| | 8666 | ui.mod(&elf.dwarf).fully_qualified_name, |
| | 8667 | }) catch &name, |
| | 8668 | .func_frame_fde, .func_debug_info, .func_debug_line => |fi, tag| { |
| | 8669 | const ip = &elf.base.comp.zcu.?.intern_pool; |
| | 8670 | break :name std.mem.print(&name, "{s} info for {f}", .{ |
| | 8671 | switch (tag) { |
| | 8672 | else => unreachable, |
| | 8673 | .func_frame_fde => "unwind", |
| | 8674 | .func_debug_info => "debug", |
| | 8675 | .func_debug_line => "line", |
| | 8676 | }, |
| | 8677 | ip.getNav(fi.nav(&elf.dwarf)).fqn.fmt(ip), |
| | 8678 | }) catch &name; |
| | 8679 | }, |
| 7938 | }, 0); | 8680 | }, 0); |
| 7939 | } | 8681 | } |
| 7940 | | 8682 | |
| ... | @@ -7984,11 +8726,11 @@ fn genUav( | ... | @@ -7984,11 +8726,11 @@ fn genUav( |
| 7984 | | 8726 | |
| 7985 | const uav_val = umi.uavValue(elf); | 8727 | const uav_val = umi.uavValue(elf); |
| 7986 | const ni = umi.symbol(elf).index().ptr(elf).node.unwrap().?; | 8728 | const ni = umi.symbol(elf).index().ptr(elf).node.unwrap().?; |
| 7987 | elf.resetNodeRelocs(ni); | | |
| 7988 | | 8729 | |
| 7989 | var nw: MappedFile.Node.Writer = undefined; | 8730 | var nw: MappedFile.Node.Writer = undefined; |
| 7990 | ni.writer(&elf.mf, gpa, &nw); | 8731 | ni.writer(&elf.mf, gpa, &nw); |
| 7991 | defer nw.deinit(); | 8732 | defer nw.deinit(); |
| | 8733 | elf.resetNodeRelocs(ni); |
| 7992 | codegen.generateSymbol( | 8734 | codegen.generateSymbol( |
| 7993 | &elf.base, | 8735 | &elf.base, |
| 7994 | pt, | 8736 | pt, |
| ... | @@ -8013,7 +8755,6 @@ fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void { | ... | @@ -8013,7 +8755,6 @@ fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void { |
| 8013 | | 8755 | |
| 8014 | const lazy = lmr.lazySymbol(elf); | 8756 | const lazy = lmr.lazySymbol(elf); |
| 8015 | const ni = lmr.symbol(elf).index().ptr(elf).node.unwrap().?; | 8757 | const ni = lmr.symbol(elf).index().ptr(elf).node.unwrap().?; |
| 8016 | elf.resetNodeRelocs(ni); | | |
| 8017 | | 8758 | |
| 8018 | // Ensure the lazy node is marked as moved so that once we're done, `flushMoved` will eventually | 8759 | // Ensure the lazy node is marked as moved so that once we're done, `flushMoved` will eventually |
| 8019 | // be called to apply the lazy node's new relocations. | 8760 | // be called to apply the lazy node's new relocations. |
| ... | @@ -8023,6 +8764,7 @@ fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void { | ... | @@ -8023,6 +8764,7 @@ fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void { |
| 8023 | var nw: MappedFile.Node.Writer = undefined; | 8764 | var nw: MappedFile.Node.Writer = undefined; |
| 8024 | ni.writer(&elf.mf, gpa, &nw); | 8765 | ni.writer(&elf.mf, gpa, &nw); |
| 8025 | defer nw.deinit(); | 8766 | defer nw.deinit(); |
| | 8767 | elf.resetNodeRelocs(ni); |
| 8026 | codegen.generateLazySymbol( | 8768 | codegen.generateLazySymbol( |
| 8027 | &elf.base, | 8769 | &elf.base, |
| 8028 | pt, | 8770 | pt, |
| ... | @@ -8155,7 +8897,7 @@ fn flushElfOffset(elf: *Elf, ni: MappedFile.Node.Index) void { | ... | @@ -8155,7 +8897,7 @@ fn flushElfOffset(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 8155 | elf.flushElfOffset(child_ni); | 8897 | elf.flushElfOffset(child_ni); |
| 8156 | } | 8898 | } |
| 8157 | }, | 8899 | }, |
| 8158 | .section => |shndx| switch (elf.shdrPtr(shndx)) { | 8900 | .section, .section_manual_size => |shndx| switch (elf.shdrPtr(shndx)) { |
| 8159 | inline else => |shdr| elf.targetStore(&shdr.offset, @intCast(elf_offset)), | 8901 | inline else => |shdr| elf.targetStore(&shdr.offset, @intCast(elf_offset)), |
| 8160 | }, | 8902 | }, |
| 8161 | } | 8903 | } |
| ... | @@ -8194,6 +8936,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -8194,6 +8936,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 8194 | .INTERP, | 8936 | .INTERP, |
| 8195 | .PHDR, | 8937 | .PHDR, |
| 8196 | .TLS, | 8938 | .TLS, |
| | 8939 | .GNU_EH_FRAME, |
| 8197 | .GNU_RELRO, | 8940 | .GNU_RELRO, |
| 8198 | => { | 8941 | => { |
| 8199 | const new_vaddr = elf.computeNodeVAddr(ni); | 8942 | const new_vaddr = elf.computeNodeVAddr(ni); |
| ... | @@ -8204,14 +8947,11 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -8204,14 +8947,11 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 8204 | }, | 8947 | }, |
| 8205 | } | 8948 | } |
| 8206 | }, | 8949 | }, |
| 8207 | .section => |shndx| { | 8950 | .section, .section_manual_size => |shndx| { |
| 8208 | elf.flushElfOffset(ni); | 8951 | elf.flushElfOffset(ni); |
| 8209 | const addr = elf.computeNodeVAddr(ni); | 8952 | const addr = elf.computeNodeVAddr(ni); |
| 8210 | const old_addr: u64, const flags: std.elf.SHF = switch (elf.shdrPtr(shndx)) { | 8953 | const old_addr: u64, const flags: std.elf.SHF = switch (elf.shdrPtr(shndx)) { |
| 8211 | inline else => |shdr| .{ | 8954 | inline else => |shdr| .{ elf.targetLoad(&shdr.addr), elf.targetLoad(&shdr.flags).shf }, |
| 8212 | elf.targetLoad(&shdr.addr), | | |
| 8213 | elf.targetLoad(&shdr.flags).shf, | | |
| 8214 | }, | | |
| 8215 | }; | 8955 | }; |
| 8216 | | 8956 | |
| 8217 | if (flags.ALLOC) { | 8957 | if (flags.ALLOC) { |
| ... | @@ -8225,10 +8965,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -8225,10 +8965,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 8225 | var name = first_name; | 8965 | var name = first_name; |
| 8226 | while (name != .empty) { | 8966 | while (name != .empty) { |
| 8227 | const old_sym_addr = Symbol.Id.global(name).value(elf); | 8967 | const old_sym_addr = Symbol.Id.global(name).value(elf); |
| 8228 | Symbol.Id.global(name).flushMoved( | 8968 | Symbol.Id.global(name).flushMoved(elf, old_sym_addr - old_addr + addr); |
| 8229 | elf, | | |
| 8230 | old_sym_addr - old_addr + addr, | | |
| 8231 | ); | | |
| 8232 | name = elf.globalByName(name).?.next_in_node; | 8969 | name = elf.globalByName(name).?.next_in_node; |
| 8233 | } | 8970 | } |
| 8234 | } | 8971 | } |
| ... | @@ -8246,12 +8983,14 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -8246,12 +8983,14 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 8246 | reloc.apply(elf); | 8983 | reloc.apply(elf); |
| 8247 | } | 8984 | } |
| 8248 | } else if (shndx == elf.shndx.plt) { | 8985 | } else if (shndx == elf.shndx.plt) { |
| 8249 | elf.flushMovedNodeRelocs(ni, addr, elf.plt_first_symbol_reloc, .none); | 8986 | elf.flushMovedNodeRelocs(ni, addr, elf.plt_first_symbol_reloc, .none, .none); |
| 8250 | elf.flushMovedPltSection(.plt, old_addr, addr); | 8987 | elf.flushMovedPltSection(.plt, old_addr, addr); |
| 8251 | } else if (shndx == elf.shndx.got_plt) { | 8988 | } else if (shndx == elf.shndx.got_plt) { |
| 8252 | elf.flushMovedPltSection(.got_plt, old_addr, addr); | 8989 | elf.flushMovedPltSection(.got_plt, old_addr, addr); |
| 8253 | } else if (shndx == elf.shndx.plt_sec) { | 8990 | } else if (shndx == elf.shndx.plt_sec) { |
| 8254 | elf.flushMovedPltSection(.plt_sec, old_addr, addr); | 8991 | elf.flushMovedPltSection(.plt_sec, old_addr, addr); |
| | 8992 | } else if (shndx == elf.shndx.eh_frame_hdr) { |
| | 8993 | elf.flushMovedNodeRelocs(ni, addr, elf.eh_frame_hdr_first_symbol_reloc, .none, .none); |
| 8255 | } | 8994 | } |
| 8256 | }, | 8995 | }, |
| 8257 | .input_section => |isi| { | 8996 | .input_section => |isi| { |
| ... | @@ -8302,6 +9041,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -8302,6 +9041,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 8302 | ni, | 9041 | ni, |
| 8303 | new_section_addr, | 9042 | new_section_addr, |
| 8304 | isi.ptrConst(elf).first_symbol_reloc, | 9043 | isi.ptrConst(elf).first_symbol_reloc, |
| | 9044 | .none, |
| 8305 | isi.ptrConst(elf).first_got_reloc, | 9045 | isi.ptrConst(elf).first_got_reloc, |
| 8306 | ); | 9046 | ); |
| 8307 | }, | 9047 | }, |
| ... | @@ -8329,13 +9069,45 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -8329,13 +9069,45 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 8329 | name = elf.globalByName(name).?.next_in_node; | 9069 | name = elf.globalByName(name).?.next_in_node; |
| 8330 | } | 9070 | } |
| 8331 | } | 9071 | } |
| | 9072 | elf.flushMovedNodeRelocs(ni, new_addr, mi.firstSymbolReloc(elf), .none, mi.firstGotReloc(elf)); |
| | 9073 | }, |
| | 9074 | .value_debug_info, |
| | 9075 | .global_debug_info, |
| | 9076 | .frame_padding, |
| | 9077 | .unit_frame, |
| | 9078 | => {}, |
| | 9079 | .unit_frame_cie => |ui| { |
| | 9080 | const dwarf_unit = &elf.dwarf_units.items[@backingInt(ui)]; |
| | 9081 | var target_ri = dwarf_unit.unit_frame_cie_first_target_reloc; |
| | 9082 | while (target_ri != .none) { |
| | 9083 | const target_reloc = target_ri.get(elf); |
| | 9084 | assert(target_reloc.target == ni); |
| | 9085 | target_reloc.apply(elf); |
| | 9086 | target_ri = target_reloc.next; |
| | 9087 | } |
| | 9088 | }, |
| | 9089 | .func_frame_fde => |fi| { |
| | 9090 | const new_addr = elf.computeNodeVAddr(ni); |
| | 9091 | const dwarf_func = &elf.dwarf_funcs.items[@backingInt(fi)]; |
| | 9092 | const mod = elf.base.comp.zcu.?.navFileScope(fi.nav(&elf.dwarf)).mod.?; |
| | 9093 | switch (mod.unwind_tables) { |
| | 9094 | .none => {}, |
| | 9095 | .sync, .async => { |
| | 9096 | const offset, _ = ni.location(&elf.mf).resolve(&elf.mf); |
| | 9097 | elf.dwarf.updateEhFrameFde(ni.slice(&elf.mf), offset); |
| | 9098 | }, |
| | 9099 | } |
| 8332 | elf.flushMovedNodeRelocs( | 9100 | elf.flushMovedNodeRelocs( |
| 8333 | ni, | 9101 | ni, |
| 8334 | new_addr, | 9102 | new_addr, |
| 8335 | mi.firstSymbolReloc(elf), | 9103 | dwarf_func.func_frame_fde_first_symbol_reloc, |
| 8336 | mi.firstGotReloc(elf), | 9104 | dwarf_func.func_frame_fde_first_node_reloc, |
| | 9105 | .none, |
| 8337 | ); | 9106 | ); |
| 8338 | }, | 9107 | }, |
| | 9108 | .func_debug_info, |
| | 9109 | .func_debug_line, |
| | 9110 | => {}, |
| 8339 | } | 9111 | } |
| 8340 | try ni.childrenMoved(elf.base.comp.gpa, &elf.mf); | 9112 | try ni.childrenMoved(elf.base.comp.gpa, &elf.mf); |
| 8341 | } | 9113 | } |
| ... | @@ -8523,7 +9295,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo | ... | @@ -8523,7 +9295,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo |
| 8523 | elf.targetStore(&ph.type, if (size > 0) .LOAD else .NULL); | 9295 | elf.targetStore(&ph.type, if (size > 0) .LOAD else .NULL); |
| 8524 | try elf.allocateSegmentLoadAddress(phndx); | 9296 | try elf.allocateSegmentLoadAddress(phndx); |
| 8525 | }, | 9297 | }, |
| 8526 | .DYNAMIC, .INTERP, .PHDR, std.elf.PT.GNU_RELRO => { | 9298 | .DYNAMIC, .INTERP, .PHDR, .GNU_EH_FRAME, .GNU_RELRO => { |
| 8527 | elf.targetStore(&ph.memsz, @intCast(size)); | 9299 | elf.targetStore(&ph.memsz, @intCast(size)); |
| 8528 | }, | 9300 | }, |
| 8529 | .TLS => { | 9301 | .TLS => { |
| ... | @@ -8558,31 +9330,29 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo | ... | @@ -8558,31 +9330,29 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo |
| 8558 | inline else => |shdr| { | 9330 | inline else => |shdr| { |
| 8559 | switch (elf.targetLoad(&shdr.type)) { | 9331 | switch (elf.targetLoad(&shdr.type)) { |
| 8560 | else => unreachable, | 9332 | else => unreachable, |
| 8561 | | | |
| 8562 | .NULL => if (size > 0) elf.targetStore(&shdr.type, .PROGBITS), | 9333 | .NULL => if (size > 0) elf.targetStore(&shdr.type, .PROGBITS), |
| 8563 | .PROGBITS => if (size == 0) elf.targetStore(&shdr.type, .NULL), | 9334 | .PROGBITS => if (size == 0) elf.targetStore(&shdr.type, .NULL), |
| 8564 | | 9335 | .X86_64_UNWIND => {}, |
| 8565 | .INIT_ARRAY, | | |
| 8566 | .FINI_ARRAY, | | |
| 8567 | .PREINIT_ARRAY, | | |
| 8568 | .STRTAB, | | |
| 8569 | .SYMTAB, | | |
| 8570 | .DYNAMIC, | | |
| 8571 | .REL, | | |
| 8572 | .RELA, | | |
| 8573 | .DYNSYM, | | |
| 8574 | .HASH, | | |
| 8575 | => return, | | |
| 8576 | } | | |
| 8577 | if (shndx != elf.shndx.plt and | | |
| 8578 | shndx != elf.shndx.got and | | |
| 8579 | shndx != elf.shndx.got_plt) | | |
| 8580 | { | | |
| 8581 | elf.targetStore(&shdr.size, @intCast(size)); | | |
| 8582 | } | 9336 | } |
| | 9337 | elf.targetStore(&shdr.size, @intCast(size)); |
| 8583 | }, | 9338 | }, |
| 8584 | }, | 9339 | }, |
| 8585 | .input_section, .copied_global, .nav, .uav, .lazy_code, .lazy_const_data => {}, | 9340 | .section_manual_size, |
| | 9341 | .input_section, |
| | 9342 | .copied_global, |
| | 9343 | .nav, |
| | 9344 | .uav, |
| | 9345 | .lazy_code, |
| | 9346 | .lazy_const_data, |
| | 9347 | .value_debug_info, |
| | 9348 | .global_debug_info, |
| | 9349 | .frame_padding, |
| | 9350 | .unit_frame, |
| | 9351 | .unit_frame_cie, |
| | 9352 | .func_frame_fde, |
| | 9353 | .func_debug_info, |
| | 9354 | .func_debug_line, |
| | 9355 | => {}, |
| 8586 | } | 9356 | } |
| 8587 | } | 9357 | } |
| 8588 | | 9358 | |
| ... | @@ -8599,6 +9369,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error! | ... | @@ -8599,6 +9369,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error! |
| 8599 | .shdr, | 9369 | .shdr, |
| 8600 | .segment, | 9370 | .segment, |
| 8601 | .section, | 9371 | .section, |
| | 9372 | .section_manual_size, |
| 8602 | .input_section, | 9373 | .input_section, |
| 8603 | .copied_global, | 9374 | .copied_global, |
| 8604 | .nav, | 9375 | .nav, |
| ... | @@ -8633,6 +9404,66 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error! | ... | @@ -8633,6 +9404,66 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error! |
| 8633 | error.NoSpaceLeft => archive.strtab_member_too_big = true, | 9404 | error.NoSpaceLeft => archive.strtab_member_too_big = true, |
| 8634 | } | 9405 | } |
| 8635 | }, | 9406 | }, |
| | 9407 | .value_debug_info, |
| | 9408 | .global_debug_info, |
| | 9409 | => {}, |
| | 9410 | .frame_padding, .unit_frame_cie, .func_frame_fde => |_, tag| { |
| | 9411 | const offset, const size = ni.location(&elf.mf).resolve(&elf.mf); |
| | 9412 | const slice = slice: { |
| | 9413 | const parent_ni = ni.parent(&elf.mf).unwrap().?; |
| | 9414 | if (ni.next(&elf.mf).unwrap()) |next_ni| { |
| | 9415 | const parent_slice = parent_ni.slicePadding(&elf.mf); |
| | 9416 | const next_offset, _ = next_ni.location(&elf.mf).resolve(&elf.mf); |
| | 9417 | break :slice parent_slice[@intCast(offset)..@intCast(next_offset)]; |
| | 9418 | } else switch (tag) { |
| | 9419 | else => unreachable, |
| | 9420 | .frame_padding => { |
| | 9421 | const frame_slice = parent_ni.slicePadding(&elf.mf); |
| | 9422 | switch (elf.getNode(parent_ni).section.debugFrameFormat(elf).?) { |
| | 9423 | .eh_frame => { |
| | 9424 | const end = frame_slice.len - 4; |
| | 9425 | std.mem.writeInt(u32, frame_slice[end..][0..4], 0, elf.dwarf.endian); |
| | 9426 | break :slice frame_slice[@intCast(offset)..end]; |
| | 9427 | }, |
| | 9428 | .debug_frame => break :slice frame_slice[@intCast(offset)..], |
| | 9429 | } |
| | 9430 | }, |
| | 9431 | .unit_frame_cie, .func_frame_fde => { |
| | 9432 | const parent_offset, _ = parent_ni.location(&elf.mf).resolve(&elf.mf); |
| | 9433 | const frame_ni = parent_ni.parent(&elf.mf).unwrap().?; |
| | 9434 | const frame_slice = frame_ni.slicePadding(&elf.mf); |
| | 9435 | const format = elf.getNode(frame_ni).section.debugFrameFormat(elf).?; |
| | 9436 | const slice = frame_slice[@intCast(parent_offset + offset)..if (parent_ni.next(&elf.mf).unwrap()) |parent_next_ni| frame_end: { |
| | 9437 | const parent_next_offset, _ = parent_next_ni.location(&elf.mf).resolve(&elf.mf); |
| | 9438 | break :frame_end @intCast(parent_next_offset); |
| | 9439 | } else frame_end: switch (format) { |
| | 9440 | .eh_frame => { |
| | 9441 | const frame_end = frame_slice.len - 4; |
| | 9442 | std.mem.writeInt(u32, frame_slice[frame_end..][0..4], 0, elf.dwarf.endian); |
| | 9443 | break :frame_end frame_end; |
| | 9444 | }, |
| | 9445 | .debug_frame => frame_slice.len, |
| | 9446 | }]; |
| | 9447 | var fw: std.Io.Writer = .fixed(slice[@intCast(size)..]); |
| | 9448 | elf.dwarf.genDebugFrameCie(&fw, null, format) catch |err| switch (err) { |
| | 9449 | error.WriteFailed => break :slice slice, |
| | 9450 | }; |
| | 9451 | elf.dwarf.updateUnitLength(fw.buffer, fw.buffer.len); |
| | 9452 | break :slice slice[0..@intCast(size)]; |
| | 9453 | }, |
| | 9454 | } |
| | 9455 | }; |
| | 9456 | elf.dwarf.updateUnitLength(slice, slice.len); |
| | 9457 | switch (tag) { |
| | 9458 | else => unreachable, |
| | 9459 | .frame_padding => {}, |
| | 9460 | .unit_frame_cie, .func_frame_fde => @memset(slice[@intCast(size)..], std.dwarf.CFA.nop), |
| | 9461 | } |
| | 9462 | }, |
| | 9463 | .unit_frame, |
| | 9464 | .func_debug_info, |
| | 9465 | .func_debug_line, |
| | 9466 | => {}, |
| 8636 | } | 9467 | } |
| 8637 | } | 9468 | } |
| 8638 | | 9469 | |
| ... | @@ -9118,7 +9949,7 @@ pub fn printNode( | ... | @@ -9118,7 +9949,7 @@ pub fn printNode( |
| 9118 | try w.writeByte(')'); | 9949 | try w.writeByte(')'); |
| 9119 | }, | 9950 | }, |
| 9120 | }, | 9951 | }, |
| 9121 | .section => |shndx| try w.print("({s})", .{shndx.name(elf).slice(elf)}), | 9952 | .section, .section_manual_size => |shndx| try w.print("({s})", .{shndx.name(elf).slice(elf)}), |
| 9122 | .input_section => |isi| { | 9953 | .input_section => |isi| { |
| 9123 | const ii = isi.input(elf); | 9954 | const ii = isi.input(elf); |
| 9124 | try w.print("({f}{f}, {s})", .{ | 9955 | try w.print("({f}{f}, {s})", .{ |
| ... | @@ -9151,6 +9982,31 @@ pub fn printNode( | ... | @@ -9151,6 +9982,31 @@ pub fn printNode( |
| 9151 | .tid = tid, | 9982 | .tid = tid, |
| 9152 | }), | 9983 | }), |
| 9153 | }), | 9984 | }), |
| | 9985 | .value_debug_info => |cpi| try w.print("({f})", .{ |
| | 9986 | Value.fromInterned(cpi.val(&elf.dwarf.const_pool)) |
| | 9987 | .fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }), |
| | 9988 | }), |
| | 9989 | .global_debug_info => |gi| { |
| | 9990 | const zcu = elf.base.comp.zcu.?; |
| | 9991 | const ip = &zcu.intern_pool; |
| | 9992 | const nav = ip.getNav(gi.nav(&elf.dwarf)); |
| | 9993 | try w.print("({f}, {f})", .{ |
| | 9994 | Type.fromInterned(ip.typeOf(nav.resolved.?.value)).fmt(.{ .zcu = zcu, .tid = tid }), |
| | 9995 | nav.fqn.fmt(ip), |
| | 9996 | }); |
| | 9997 | }, |
| | 9998 | .unit_frame, .unit_frame_cie => |ui| try w.print("({s})", .{ |
| | 9999 | ui.mod(&elf.dwarf).fully_qualified_name, |
| | 10000 | }), |
| | 10001 | .func_frame_fde, .func_debug_info, .func_debug_line => |fi| { |
| | 10002 | const zcu = elf.base.comp.zcu.?; |
| | 10003 | const ip = &zcu.intern_pool; |
| | 10004 | const nav = ip.getNav(fi.nav(&elf.dwarf)); |
| | 10005 | try w.print("({f}, {f})", .{ |
| | 10006 | Type.fromInterned(ip.typeOf(nav.resolved.?.value)).fmt(.{ .zcu = zcu, .tid = tid }), |
| | 10007 | nav.fqn.fmt(ip), |
| | 10008 | }); |
| | 10009 | }, |
| 9154 | } | 10010 | } |
| 9155 | { | 10011 | { |
| 9156 | const mf_node = &elf.mf.nodes.items[@backingInt(ni)]; | 10012 | const mf_node = &elf.mf.nodes.items[@backingInt(ni)]; |