| ... | @@ -147,6 +147,7 @@ thunks: std.ArrayListUnmanaged(Thunk) = .empty, | ... | @@ -147,6 +147,7 @@ thunks: std.ArrayListUnmanaged(Thunk) = .empty, |
| 147 | | 147 | |
| 148 | /// List of output merge sections with deduped contents. | 148 | /// List of output merge sections with deduped contents. |
| 149 | merge_sections: std.ArrayListUnmanaged(MergeSection) = .empty, | 149 | merge_sections: std.ArrayListUnmanaged(MergeSection) = .empty, |
| | 150 | comment_merge_section_index: ?MergeSection.Index = null, |
| 150 | | 151 | |
| 151 | first_eflags: ?elf.Elf64_Word = null, | 152 | first_eflags: ?elf.Elf64_Word = null, |
| 152 | | 153 | |
| ... | @@ -568,19 +569,6 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64, min_align | ... | @@ -568,19 +569,6 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64, min_align |
| 568 | if (maybe_phdr) |phdr| phdr.p_filesz = needed_size; | 569 | if (maybe_phdr) |phdr| phdr.p_filesz = needed_size; |
| 569 | } | 570 | } |
| 570 | shdr.sh_size = needed_size; | 571 | shdr.sh_size = needed_size; |
| 571 | | | |
| 572 | if (maybe_phdr) |phdr| { | | |
| 573 | const mem_capacity = self.allocatedVirtualSize(phdr.p_vaddr); | | |
| 574 | if (needed_size > mem_capacity) { | | |
| 575 | var err = try self.base.addErrorWithNotes(2); | | |
| 576 | try err.addMsg("fatal linker error: cannot expand load segment phdr({d}) in virtual memory", .{phndx.?}); | | |
| 577 | try err.addNote("TODO: emit relocations to memory locations in self-hosted backends", .{}); | | |
| 578 | try err.addNote("as a workaround, try increasing pre-allocated virtual memory of each segment", .{}); | | |
| 579 | } | | |
| 580 | | | |
| 581 | phdr.p_memsz = needed_size; | | |
| 582 | } | | |
| 583 | | | |
| 584 | self.markDirty(shdr_index); | 572 | self.markDirty(shdr_index); |
| 585 | } | 573 | } |
| 586 | | 574 | |
| ... | @@ -1047,6 +1035,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -1047,6 +1035,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 1047 | try self.updateMergeSectionSizes(); | 1035 | try self.updateMergeSectionSizes(); |
| 1048 | try self.updateSectionSizes(); | 1036 | try self.updateSectionSizes(); |
| 1049 | | 1037 | |
| | 1038 | try self.addLoadPhdrs(); |
| 1050 | try self.allocatePhdrTable(); | 1039 | try self.allocatePhdrTable(); |
| 1051 | try self.allocateAllocSections(); | 1040 | try self.allocateAllocSections(); |
| 1052 | try self.sortPhdrs(); | 1041 | try self.sortPhdrs(); |
| ... | @@ -2790,6 +2779,7 @@ fn checkDuplicates(self: *Elf) !void { | ... | @@ -2790,6 +2779,7 @@ fn checkDuplicates(self: *Elf) !void { |
| 2790 | | 2779 | |
| 2791 | pub fn addCommentString(self: *Elf) !void { | 2780 | pub fn addCommentString(self: *Elf) !void { |
| 2792 | const gpa = self.base.comp.gpa; | 2781 | const gpa = self.base.comp.gpa; |
| | 2782 | if (self.comment_merge_section_index != null) return; |
| 2793 | const msec_index = try self.getOrCreateMergeSection(".comment", elf.SHF_MERGE | elf.SHF_STRINGS, elf.SHT_PROGBITS); | 2783 | const msec_index = try self.getOrCreateMergeSection(".comment", elf.SHF_MERGE | elf.SHF_STRINGS, elf.SHT_PROGBITS); |
| 2794 | const msec = self.mergeSection(msec_index); | 2784 | const msec = self.mergeSection(msec_index); |
| 2795 | const res = try msec.insertZ(gpa, "zig " ++ builtin.zig_version_string); | 2785 | const res = try msec.insertZ(gpa, "zig " ++ builtin.zig_version_string); |
| ... | @@ -2803,6 +2793,7 @@ pub fn addCommentString(self: *Elf) !void { | ... | @@ -2803,6 +2793,7 @@ pub fn addCommentString(self: *Elf) !void { |
| 2803 | msub.entsize = 1; | 2793 | msub.entsize = 1; |
| 2804 | msub.alive = true; | 2794 | msub.alive = true; |
| 2805 | res.sub.* = msub_index; | 2795 | res.sub.* = msub_index; |
| | 2796 | self.comment_merge_section_index = msec_index; |
| 2806 | } | 2797 | } |
| 2807 | | 2798 | |
| 2808 | pub fn resolveMergeSections(self: *Elf) !void { | 2799 | pub fn resolveMergeSections(self: *Elf) !void { |
| ... | @@ -2920,7 +2911,7 @@ fn initSyntheticSections(self: *Elf) !void { | ... | @@ -2920,7 +2911,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 2920 | .offset = std.math.maxInt(u64), | 2911 | .offset = std.math.maxInt(u64), |
| 2921 | }); | 2912 | }); |
| 2922 | } | 2913 | } |
| 2923 | if (comp.link_eh_frame_hdr) { | 2914 | if (comp.link_eh_frame_hdr and self.eh_frame_hdr_section_index == null) { |
| 2924 | self.eh_frame_hdr_section_index = try self.addSection(.{ | 2915 | self.eh_frame_hdr_section_index = try self.addSection(.{ |
| 2925 | .name = try self.insertShString(".eh_frame_hdr"), | 2916 | .name = try self.insertShString(".eh_frame_hdr"), |
| 2926 | .type = elf.SHT_PROGBITS, | 2917 | .type = elf.SHT_PROGBITS, |
| ... | @@ -2931,7 +2922,7 @@ fn initSyntheticSections(self: *Elf) !void { | ... | @@ -2931,7 +2922,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 2931 | } | 2922 | } |
| 2932 | } | 2923 | } |
| 2933 | | 2924 | |
| 2934 | if (self.got.entries.items.len > 0) { | 2925 | if (self.got.entries.items.len > 0 and self.got_section_index == null) { |
| 2935 | self.got_section_index = try self.addSection(.{ | 2926 | self.got_section_index = try self.addSection(.{ |
| 2936 | .name = try self.insertShString(".got"), | 2927 | .name = try self.insertShString(".got"), |
| 2937 | .type = elf.SHT_PROGBITS, | 2928 | .type = elf.SHT_PROGBITS, |
| ... | @@ -2941,13 +2932,15 @@ fn initSyntheticSections(self: *Elf) !void { | ... | @@ -2941,13 +2932,15 @@ fn initSyntheticSections(self: *Elf) !void { |
| 2941 | }); | 2932 | }); |
| 2942 | } | 2933 | } |
| 2943 | | 2934 | |
| 2944 | self.got_plt_section_index = try self.addSection(.{ | 2935 | if (self.got_plt_section_index == null) { |
| 2945 | .name = try self.insertShString(".got.plt"), | 2936 | self.got_plt_section_index = try self.addSection(.{ |
| 2946 | .type = elf.SHT_PROGBITS, | 2937 | .name = try self.insertShString(".got.plt"), |
| 2947 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | 2938 | .type = elf.SHT_PROGBITS, |
| 2948 | .addralign = @alignOf(u64), | 2939 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| 2949 | .offset = std.math.maxInt(u64), | 2940 | .addralign = @alignOf(u64), |
| 2950 | }); | 2941 | .offset = std.math.maxInt(u64), |
| | 2942 | }); |
| | 2943 | } |
| 2951 | | 2944 | |
| 2952 | const needs_rela_dyn = blk: { | 2945 | const needs_rela_dyn = blk: { |
| 2953 | if (self.got.flags.needs_rela or self.got.flags.needs_tlsld or self.copy_rel.symbols.items.len > 0) | 2946 | if (self.got.flags.needs_rela or self.got.flags.needs_tlsld or self.copy_rel.symbols.items.len > 0) |
| ... | @@ -2960,7 +2953,7 @@ fn initSyntheticSections(self: *Elf) !void { | ... | @@ -2960,7 +2953,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 2960 | } | 2953 | } |
| 2961 | break :blk false; | 2954 | break :blk false; |
| 2962 | }; | 2955 | }; |
| 2963 | if (needs_rela_dyn) { | 2956 | if (needs_rela_dyn and self.rela_dyn_section_index == null) { |
| 2964 | self.rela_dyn_section_index = try self.addSection(.{ | 2957 | self.rela_dyn_section_index = try self.addSection(.{ |
| 2965 | .name = try self.insertShString(".rela.dyn"), | 2958 | .name = try self.insertShString(".rela.dyn"), |
| 2966 | .type = elf.SHT_RELA, | 2959 | .type = elf.SHT_RELA, |
| ... | @@ -2972,24 +2965,28 @@ fn initSyntheticSections(self: *Elf) !void { | ... | @@ -2972,24 +2965,28 @@ fn initSyntheticSections(self: *Elf) !void { |
| 2972 | } | 2965 | } |
| 2973 | | 2966 | |
| 2974 | if (self.plt.symbols.items.len > 0) { | 2967 | if (self.plt.symbols.items.len > 0) { |
| 2975 | self.plt_section_index = try self.addSection(.{ | 2968 | if (self.plt_section_index == null) { |
| 2976 | .name = try self.insertShString(".plt"), | 2969 | self.plt_section_index = try self.addSection(.{ |
| 2977 | .type = elf.SHT_PROGBITS, | 2970 | .name = try self.insertShString(".plt"), |
| 2978 | .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, | 2971 | .type = elf.SHT_PROGBITS, |
| 2979 | .addralign = 16, | 2972 | .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, |
| 2980 | .offset = std.math.maxInt(u64), | 2973 | .addralign = 16, |
| 2981 | }); | 2974 | .offset = std.math.maxInt(u64), |
| 2982 | self.rela_plt_section_index = try self.addSection(.{ | 2975 | }); |
| 2983 | .name = try self.insertShString(".rela.plt"), | 2976 | } |
| 2984 | .type = elf.SHT_RELA, | 2977 | if (self.rela_plt_section_index == null) { |
| 2985 | .flags = elf.SHF_ALLOC, | 2978 | self.rela_plt_section_index = try self.addSection(.{ |
| 2986 | .addralign = @alignOf(elf.Elf64_Rela), | 2979 | .name = try self.insertShString(".rela.plt"), |
| 2987 | .entsize = @sizeOf(elf.Elf64_Rela), | 2980 | .type = elf.SHT_RELA, |
| 2988 | .offset = std.math.maxInt(u64), | 2981 | .flags = elf.SHF_ALLOC, |
| 2989 | }); | 2982 | .addralign = @alignOf(elf.Elf64_Rela), |
| | 2983 | .entsize = @sizeOf(elf.Elf64_Rela), |
| | 2984 | .offset = std.math.maxInt(u64), |
| | 2985 | }); |
| | 2986 | } |
| 2990 | } | 2987 | } |
| 2991 | | 2988 | |
| 2992 | if (self.plt_got.symbols.items.len > 0) { | 2989 | if (self.plt_got.symbols.items.len > 0 and self.plt_got_section_index == null) { |
| 2993 | self.plt_got_section_index = try self.addSection(.{ | 2990 | self.plt_got_section_index = try self.addSection(.{ |
| 2994 | .name = try self.insertShString(".plt.got"), | 2991 | .name = try self.insertShString(".plt.got"), |
| 2995 | .type = elf.SHT_PROGBITS, | 2992 | .type = elf.SHT_PROGBITS, |
| ... | @@ -2999,7 +2996,7 @@ fn initSyntheticSections(self: *Elf) !void { | ... | @@ -2999,7 +2996,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 2999 | }); | 2996 | }); |
| 3000 | } | 2997 | } |
| 3001 | | 2998 | |
| 3002 | if (self.copy_rel.symbols.items.len > 0) { | 2999 | if (self.copy_rel.symbols.items.len > 0 and self.copy_rel_section_index == null) { |
| 3003 | self.copy_rel_section_index = try self.addSection(.{ | 3000 | self.copy_rel_section_index = try self.addSection(.{ |
| 3004 | .name = try self.insertShString(".copyrel"), | 3001 | .name = try self.insertShString(".copyrel"), |
| 3005 | .type = elf.SHT_NOBITS, | 3002 | .type = elf.SHT_NOBITS, |
| ... | @@ -3017,7 +3014,7 @@ fn initSyntheticSections(self: *Elf) !void { | ... | @@ -3017,7 +3014,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3017 | if (self.base.isStatic() and !comp.config.pie) break :blk false; | 3014 | if (self.base.isStatic() and !comp.config.pie) break :blk false; |
| 3018 | break :blk target.dynamic_linker.get() != null; | 3015 | break :blk target.dynamic_linker.get() != null; |
| 3019 | }; | 3016 | }; |
| 3020 | if (needs_interp) { | 3017 | if (needs_interp and self.interp_section_index == null) { |
| 3021 | self.interp_section_index = try self.addSection(.{ | 3018 | self.interp_section_index = try self.addSection(.{ |
| 3022 | .name = try self.insertShString(".interp"), | 3019 | .name = try self.insertShString(".interp"), |
| 3023 | .type = elf.SHT_PROGBITS, | 3020 | .type = elf.SHT_PROGBITS, |
| ... | @@ -3028,68 +3025,82 @@ fn initSyntheticSections(self: *Elf) !void { | ... | @@ -3028,68 +3025,82 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3028 | } | 3025 | } |
| 3029 | | 3026 | |
| 3030 | if (self.isEffectivelyDynLib() or self.shared_objects.items.len > 0 or comp.config.pie) { | 3027 | if (self.isEffectivelyDynLib() or self.shared_objects.items.len > 0 or comp.config.pie) { |
| 3031 | self.dynstrtab_section_index = try self.addSection(.{ | 3028 | if (self.dynstrtab_section_index == null) { |
| 3032 | .name = try self.insertShString(".dynstr"), | 3029 | self.dynstrtab_section_index = try self.addSection(.{ |
| 3033 | .flags = elf.SHF_ALLOC, | 3030 | .name = try self.insertShString(".dynstr"), |
| 3034 | .type = elf.SHT_STRTAB, | | |
| 3035 | .entsize = 1, | | |
| 3036 | .addralign = 1, | | |
| 3037 | .offset = std.math.maxInt(u64), | | |
| 3038 | }); | | |
| 3039 | self.dynamic_section_index = try self.addSection(.{ | | |
| 3040 | .name = try self.insertShString(".dynamic"), | | |
| 3041 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | | |
| 3042 | .type = elf.SHT_DYNAMIC, | | |
| 3043 | .entsize = @sizeOf(elf.Elf64_Dyn), | | |
| 3044 | .addralign = @alignOf(elf.Elf64_Dyn), | | |
| 3045 | .offset = std.math.maxInt(u64), | | |
| 3046 | }); | | |
| 3047 | self.dynsymtab_section_index = try self.addSection(.{ | | |
| 3048 | .name = try self.insertShString(".dynsym"), | | |
| 3049 | .flags = elf.SHF_ALLOC, | | |
| 3050 | .type = elf.SHT_DYNSYM, | | |
| 3051 | .addralign = @alignOf(elf.Elf64_Sym), | | |
| 3052 | .entsize = @sizeOf(elf.Elf64_Sym), | | |
| 3053 | .info = 1, | | |
| 3054 | .offset = std.math.maxInt(u64), | | |
| 3055 | }); | | |
| 3056 | self.hash_section_index = try self.addSection(.{ | | |
| 3057 | .name = try self.insertShString(".hash"), | | |
| 3058 | .flags = elf.SHF_ALLOC, | | |
| 3059 | .type = elf.SHT_HASH, | | |
| 3060 | .addralign = 4, | | |
| 3061 | .entsize = 4, | | |
| 3062 | .offset = std.math.maxInt(u64), | | |
| 3063 | }); | | |
| 3064 | self.gnu_hash_section_index = try self.addSection(.{ | | |
| 3065 | .name = try self.insertShString(".gnu.hash"), | | |
| 3066 | .flags = elf.SHF_ALLOC, | | |
| 3067 | .type = elf.SHT_GNU_HASH, | | |
| 3068 | .addralign = 8, | | |
| 3069 | .offset = std.math.maxInt(u64), | | |
| 3070 | }); | | |
| 3071 | | | |
| 3072 | const needs_versions = for (self.dynsym.entries.items) |entry| { | | |
| 3073 | const sym = self.symbol(entry.ref).?; | | |
| 3074 | if (sym.flags.import and sym.version_index & elf.VERSYM_VERSION > elf.VER_NDX_GLOBAL) break true; | | |
| 3075 | } else false; | | |
| 3076 | if (needs_versions) { | | |
| 3077 | self.versym_section_index = try self.addSection(.{ | | |
| 3078 | .name = try self.insertShString(".gnu.version"), | | |
| 3079 | .flags = elf.SHF_ALLOC, | 3031 | .flags = elf.SHF_ALLOC, |
| 3080 | .type = elf.SHT_GNU_VERSYM, | 3032 | .type = elf.SHT_STRTAB, |
| 3081 | .addralign = @alignOf(elf.Elf64_Versym), | 3033 | .entsize = 1, |
| 3082 | .entsize = @sizeOf(elf.Elf64_Versym), | 3034 | .addralign = 1, |
| 3083 | .offset = std.math.maxInt(u64), | 3035 | .offset = std.math.maxInt(u64), |
| 3084 | }); | 3036 | }); |
| 3085 | self.verneed_section_index = try self.addSection(.{ | 3037 | } |
| 3086 | .name = try self.insertShString(".gnu.version_r"), | 3038 | if (self.dynamic_section_index == null) { |
| | 3039 | self.dynamic_section_index = try self.addSection(.{ |
| | 3040 | .name = try self.insertShString(".dynamic"), |
| | 3041 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| | 3042 | .type = elf.SHT_DYNAMIC, |
| | 3043 | .entsize = @sizeOf(elf.Elf64_Dyn), |
| | 3044 | .addralign = @alignOf(elf.Elf64_Dyn), |
| | 3045 | .offset = std.math.maxInt(u64), |
| | 3046 | }); |
| | 3047 | } |
| | 3048 | if (self.dynsymtab_section_index == null) { |
| | 3049 | self.dynsymtab_section_index = try self.addSection(.{ |
| | 3050 | .name = try self.insertShString(".dynsym"), |
| 3087 | .flags = elf.SHF_ALLOC, | 3051 | .flags = elf.SHF_ALLOC, |
| 3088 | .type = elf.SHT_GNU_VERNEED, | 3052 | .type = elf.SHT_DYNSYM, |
| 3089 | .addralign = @alignOf(elf.Elf64_Verneed), | 3053 | .addralign = @alignOf(elf.Elf64_Sym), |
| | 3054 | .entsize = @sizeOf(elf.Elf64_Sym), |
| | 3055 | .info = 1, |
| 3090 | .offset = std.math.maxInt(u64), | 3056 | .offset = std.math.maxInt(u64), |
| 3091 | }); | 3057 | }); |
| 3092 | } | 3058 | } |
| | 3059 | if (self.hash_section_index == null) { |
| | 3060 | self.hash_section_index = try self.addSection(.{ |
| | 3061 | .name = try self.insertShString(".hash"), |
| | 3062 | .flags = elf.SHF_ALLOC, |
| | 3063 | .type = elf.SHT_HASH, |
| | 3064 | .addralign = 4, |
| | 3065 | .entsize = 4, |
| | 3066 | .offset = std.math.maxInt(u64), |
| | 3067 | }); |
| | 3068 | } |
| | 3069 | if (self.gnu_hash_section_index == null) { |
| | 3070 | self.gnu_hash_section_index = try self.addSection(.{ |
| | 3071 | .name = try self.insertShString(".gnu.hash"), |
| | 3072 | .flags = elf.SHF_ALLOC, |
| | 3073 | .type = elf.SHT_GNU_HASH, |
| | 3074 | .addralign = 8, |
| | 3075 | .offset = std.math.maxInt(u64), |
| | 3076 | }); |
| | 3077 | } |
| | 3078 | |
| | 3079 | const needs_versions = for (self.dynsym.entries.items) |entry| { |
| | 3080 | const sym = self.symbol(entry.ref).?; |
| | 3081 | if (sym.flags.import and sym.version_index & elf.VERSYM_VERSION > elf.VER_NDX_GLOBAL) break true; |
| | 3082 | } else false; |
| | 3083 | if (needs_versions) { |
| | 3084 | if (self.versym_section_index == null) { |
| | 3085 | self.versym_section_index = try self.addSection(.{ |
| | 3086 | .name = try self.insertShString(".gnu.version"), |
| | 3087 | .flags = elf.SHF_ALLOC, |
| | 3088 | .type = elf.SHT_GNU_VERSYM, |
| | 3089 | .addralign = @alignOf(elf.Elf64_Versym), |
| | 3090 | .entsize = @sizeOf(elf.Elf64_Versym), |
| | 3091 | .offset = std.math.maxInt(u64), |
| | 3092 | }); |
| | 3093 | } |
| | 3094 | if (self.verneed_section_index == null) { |
| | 3095 | self.verneed_section_index = try self.addSection(.{ |
| | 3096 | .name = try self.insertShString(".gnu.version_r"), |
| | 3097 | .flags = elf.SHF_ALLOC, |
| | 3098 | .type = elf.SHT_GNU_VERNEED, |
| | 3099 | .addralign = @alignOf(elf.Elf64_Verneed), |
| | 3100 | .offset = std.math.maxInt(u64), |
| | 3101 | }); |
| | 3102 | } |
| | 3103 | } |
| 3093 | } | 3104 | } |
| 3094 | | 3105 | |
| 3095 | try self.initSymtab(); | 3106 | try self.initSymtab(); |
| ... | @@ -3136,36 +3147,38 @@ pub fn initShStrtab(self: *Elf) !void { | ... | @@ -3136,36 +3147,38 @@ pub fn initShStrtab(self: *Elf) !void { |
| 3136 | fn initSpecialPhdrs(self: *Elf) !void { | 3147 | fn initSpecialPhdrs(self: *Elf) !void { |
| 3137 | comptime assert(max_number_of_special_phdrs == 5); | 3148 | comptime assert(max_number_of_special_phdrs == 5); |
| 3138 | | 3149 | |
| 3139 | if (self.interp_section_index != null) { | 3150 | if (self.interp_section_index != null and self.phdr_interp_index == null) { |
| 3140 | self.phdr_interp_index = try self.addPhdr(.{ | 3151 | self.phdr_interp_index = try self.addPhdr(.{ |
| 3141 | .type = elf.PT_INTERP, | 3152 | .type = elf.PT_INTERP, |
| 3142 | .flags = elf.PF_R, | 3153 | .flags = elf.PF_R, |
| 3143 | .@"align" = 1, | 3154 | .@"align" = 1, |
| 3144 | }); | 3155 | }); |
| 3145 | } | 3156 | } |
| 3146 | if (self.dynamic_section_index != null) { | 3157 | if (self.dynamic_section_index != null and self.phdr_dynamic_index == null) { |
| 3147 | self.phdr_dynamic_index = try self.addPhdr(.{ | 3158 | self.phdr_dynamic_index = try self.addPhdr(.{ |
| 3148 | .type = elf.PT_DYNAMIC, | 3159 | .type = elf.PT_DYNAMIC, |
| 3149 | .flags = elf.PF_R | elf.PF_W, | 3160 | .flags = elf.PF_R | elf.PF_W, |
| 3150 | }); | 3161 | }); |
| 3151 | } | 3162 | } |
| 3152 | if (self.eh_frame_hdr_section_index != null) { | 3163 | if (self.eh_frame_hdr_section_index != null and self.phdr_gnu_eh_frame_index == null) { |
| 3153 | self.phdr_gnu_eh_frame_index = try self.addPhdr(.{ | 3164 | self.phdr_gnu_eh_frame_index = try self.addPhdr(.{ |
| 3154 | .type = elf.PT_GNU_EH_FRAME, | 3165 | .type = elf.PT_GNU_EH_FRAME, |
| 3155 | .flags = elf.PF_R, | 3166 | .flags = elf.PF_R, |
| 3156 | }); | 3167 | }); |
| 3157 | } | 3168 | } |
| 3158 | self.phdr_gnu_stack_index = try self.addPhdr(.{ | 3169 | if (self.phdr_gnu_stack_index == null) { |
| 3159 | .type = elf.PT_GNU_STACK, | 3170 | self.phdr_gnu_stack_index = try self.addPhdr(.{ |
| 3160 | .flags = elf.PF_W | elf.PF_R, | 3171 | .type = elf.PT_GNU_STACK, |
| 3161 | .memsz = self.base.stack_size, | 3172 | .flags = elf.PF_W | elf.PF_R, |
| 3162 | .@"align" = 1, | 3173 | .memsz = self.base.stack_size, |
| 3163 | }); | 3174 | .@"align" = 1, |
| | 3175 | }); |
| | 3176 | } |
| 3164 | | 3177 | |
| 3165 | const has_tls = for (self.sections.items(.shdr)) |shdr| { | 3178 | const has_tls = for (self.sections.items(.shdr)) |shdr| { |
| 3166 | if (shdr.sh_flags & elf.SHF_TLS != 0) break true; | 3179 | if (shdr.sh_flags & elf.SHF_TLS != 0) break true; |
| 3167 | } else false; | 3180 | } else false; |
| 3168 | if (has_tls) { | 3181 | if (has_tls and self.phdr_tls_index == null) { |
| 3169 | self.phdr_tls_index = try self.addPhdr(.{ | 3182 | self.phdr_tls_index = try self.addPhdr(.{ |
| 3170 | .type = elf.PT_TLS, | 3183 | .type = elf.PT_TLS, |
| 3171 | .flags = elf.PF_R, | 3184 | .flags = elf.PF_R, |
| ... | @@ -3704,27 +3717,19 @@ fn getMaxNumberOfPhdrs() u64 { | ... | @@ -3704,27 +3717,19 @@ fn getMaxNumberOfPhdrs() u64 { |
| 3704 | return num; | 3717 | return num; |
| 3705 | } | 3718 | } |
| 3706 | | 3719 | |
| 3707 | /// Calculates how many segments (PT_LOAD progam headers) are required | 3720 | fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void { |
| 3708 | /// to cover the set of sections. | | |
| 3709 | /// We permit a maximum of 3**2 number of segments. | | |
| 3710 | fn calcNumberOfSegments(self: *Elf) usize { | | |
| 3711 | var covers: [9]bool = [_]bool{false} ** 9; | | |
| 3712 | for (self.sections.items(.shdr)) |shdr| { | 3721 | for (self.sections.items(.shdr)) |shdr| { |
| 3713 | if (shdr.sh_type == elf.SHT_NULL) continue; | 3722 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| 3714 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; | 3723 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| 3715 | const flags = shdrToPhdrFlags(shdr.sh_flags); | 3724 | const flags = shdrToPhdrFlags(shdr.sh_flags); |
| 3716 | covers[flags - 1] = true; | 3725 | if (self.getPhdr(.{ .flags = flags, .type = elf.PT_LOAD }) == null) { |
| 3717 | } | 3726 | _ = try self.addPhdr(.{ .flags = flags, .type = elf.PT_LOAD }); |
| 3718 | var count: usize = 0; | 3727 | } |
| 3719 | for (covers) |cover| { | | |
| 3720 | if (cover) count += 1; | | |
| 3721 | } | 3728 | } |
| 3722 | return count; | | |
| 3723 | } | 3729 | } |
| 3724 | | 3730 | |
| 3725 | /// Allocates PHDR table in virtual memory and in file. | 3731 | /// Allocates PHDR table in virtual memory and in file. |
| 3726 | fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { | 3732 | fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { |
| 3727 | const new_load_segments = self.calcNumberOfSegments(); | | |
| 3728 | const phdr_table = &self.phdrs.items[self.phdr_table_index.?]; | 3733 | const phdr_table = &self.phdrs.items[self.phdr_table_index.?]; |
| 3729 | const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?]; | 3734 | const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?]; |
| 3730 | | 3735 | |
| ... | @@ -3736,7 +3741,7 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { | ... | @@ -3736,7 +3741,7 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { |
| 3736 | .p32 => @sizeOf(elf.Elf32_Phdr), | 3741 | .p32 => @sizeOf(elf.Elf32_Phdr), |
| 3737 | .p64 => @sizeOf(elf.Elf64_Phdr), | 3742 | .p64 => @sizeOf(elf.Elf64_Phdr), |
| 3738 | }; | 3743 | }; |
| 3739 | const needed_size = (self.phdrs.items.len + new_load_segments) * phsize; | 3744 | const needed_size = self.phdrs.items.len * phsize; |
| 3740 | const available_space = self.allocatedSize(phdr_table.p_offset); | 3745 | const available_space = self.allocatedSize(phdr_table.p_offset); |
| 3741 | | 3746 | |
| 3742 | if (needed_size > available_space) { | 3747 | if (needed_size > available_space) { |
| ... | @@ -3879,15 +3884,14 @@ pub fn allocateAllocSections(self: *Elf) !void { | ... | @@ -3879,15 +3884,14 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 3879 | | 3884 | |
| 3880 | const first = slice.items(.shdr)[cover.items[0]]; | 3885 | const first = slice.items(.shdr)[cover.items[0]]; |
| 3881 | var new_offset = try self.findFreeSpace(filesz, @"align"); | 3886 | var new_offset = try self.findFreeSpace(filesz, @"align"); |
| 3882 | const phndx = try self.addPhdr(.{ | 3887 | const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).?; |
| 3883 | .type = elf.PT_LOAD, | 3888 | const phdr = &self.phdrs.items[phndx]; |
| 3884 | .offset = new_offset, | 3889 | phdr.p_offset = new_offset; |
| 3885 | .addr = first.sh_addr, | 3890 | phdr.p_vaddr = first.sh_addr; |
| 3886 | .memsz = memsz, | 3891 | phdr.p_paddr = first.sh_addr; |
| 3887 | .filesz = filesz, | 3892 | phdr.p_memsz = memsz; |
| 3888 | .@"align" = @"align", | 3893 | phdr.p_filesz = filesz; |
| 3889 | .flags = shdrToPhdrFlags(first.sh_flags), | 3894 | phdr.p_align = @"align"; |
| 3890 | }); | | |
| 3891 | | 3895 | |
| 3892 | for (cover.items) |shndx| { | 3896 | for (cover.items) |shndx| { |
| 3893 | const shdr = &slice.items(.shdr)[shndx]; | 3897 | const shdr = &slice.items(.shdr)[shndx]; |
| ... | @@ -4102,6 +4106,7 @@ pub fn updateSymtabSize(self: *Elf) !void { | ... | @@ -4102,6 +4106,7 @@ pub fn updateSymtabSize(self: *Elf) !void { |
| 4102 | nlocals += @intCast(self.sections.slice().len); | 4106 | nlocals += @intCast(self.sections.slice().len); |
| 4103 | | 4107 | |
| 4104 | if (self.requiresThunks()) for (self.thunks.items) |*th| { | 4108 | if (self.requiresThunks()) for (self.thunks.items) |*th| { |
| | 4109 | th.output_symtab_ctx.reset(); |
| 4105 | th.output_symtab_ctx.ilocal = nlocals; | 4110 | th.output_symtab_ctx.ilocal = nlocals; |
| 4106 | th.calcSymtabSize(self); | 4111 | th.calcSymtabSize(self); |
| 4107 | nlocals += th.output_symtab_ctx.nlocals; | 4112 | nlocals += th.output_symtab_ctx.nlocals; |
| ... | @@ -4113,6 +4118,7 @@ pub fn updateSymtabSize(self: *Elf) !void { | ... | @@ -4113,6 +4118,7 @@ pub fn updateSymtabSize(self: *Elf) !void { |
| 4113 | const ctx = switch (file_ptr) { | 4118 | const ctx = switch (file_ptr) { |
| 4114 | inline else => |x| &x.output_symtab_ctx, | 4119 | inline else => |x| &x.output_symtab_ctx, |
| 4115 | }; | 4120 | }; |
| | 4121 | ctx.reset(); |
| 4116 | ctx.ilocal = nlocals; | 4122 | ctx.ilocal = nlocals; |
| 4117 | ctx.iglobal = nglobals; | 4123 | ctx.iglobal = nglobals; |
| 4118 | try file_ptr.updateSymtabSize(self); | 4124 | try file_ptr.updateSymtabSize(self); |
| ... | @@ -4122,6 +4128,7 @@ pub fn updateSymtabSize(self: *Elf) !void { | ... | @@ -4122,6 +4128,7 @@ pub fn updateSymtabSize(self: *Elf) !void { |
| 4122 | } | 4128 | } |
| 4123 | | 4129 | |
| 4124 | if (self.got_section_index) |_| { | 4130 | if (self.got_section_index) |_| { |
| | 4131 | self.got.output_symtab_ctx.reset(); |
| 4125 | self.got.output_symtab_ctx.ilocal = nlocals; | 4132 | self.got.output_symtab_ctx.ilocal = nlocals; |
| 4126 | self.got.updateSymtabSize(self); | 4133 | self.got.updateSymtabSize(self); |
| 4127 | nlocals += self.got.output_symtab_ctx.nlocals; | 4134 | nlocals += self.got.output_symtab_ctx.nlocals; |
| ... | @@ -4129,6 +4136,7 @@ pub fn updateSymtabSize(self: *Elf) !void { | ... | @@ -4129,6 +4136,7 @@ pub fn updateSymtabSize(self: *Elf) !void { |
| 4129 | } | 4136 | } |
| 4130 | | 4137 | |
| 4131 | if (self.plt_section_index) |_| { | 4138 | if (self.plt_section_index) |_| { |
| | 4139 | self.plt.output_symtab_ctx.reset(); |
| 4132 | self.plt.output_symtab_ctx.ilocal = nlocals; | 4140 | self.plt.output_symtab_ctx.ilocal = nlocals; |
| 4133 | self.plt.updateSymtabSize(self); | 4141 | self.plt.updateSymtabSize(self); |
| 4134 | nlocals += self.plt.output_symtab_ctx.nlocals; | 4142 | nlocals += self.plt.output_symtab_ctx.nlocals; |
| ... | @@ -4136,6 +4144,7 @@ pub fn updateSymtabSize(self: *Elf) !void { | ... | @@ -4136,6 +4144,7 @@ pub fn updateSymtabSize(self: *Elf) !void { |
| 4136 | } | 4144 | } |
| 4137 | | 4145 | |
| 4138 | if (self.plt_got_section_index) |_| { | 4146 | if (self.plt_got_section_index) |_| { |
| | 4147 | self.plt_got.output_symtab_ctx.reset(); |
| 4139 | self.plt_got.output_symtab_ctx.ilocal = nlocals; | 4148 | self.plt_got.output_symtab_ctx.ilocal = nlocals; |
| 4140 | self.plt_got.updateSymtabSize(self); | 4149 | self.plt_got.updateSymtabSize(self); |
| 4141 | nlocals += self.plt_got.output_symtab_ctx.nlocals; | 4150 | nlocals += self.plt_got.output_symtab_ctx.nlocals; |
| ... | @@ -4334,6 +4343,9 @@ pub fn writeSymtab(self: *Elf) !void { | ... | @@ -4334,6 +4343,9 @@ pub fn writeSymtab(self: *Elf) !void { |
| 4334 | | 4343 | |
| 4335 | try self.symtab.resize(gpa, nsyms); | 4344 | try self.symtab.resize(gpa, nsyms); |
| 4336 | const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow; | 4345 | const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow; |
| | 4346 | // TODO we could resize instead and in ZigObject/Object always access as slice |
| | 4347 | self.strtab.clearRetainingCapacity(); |
| | 4348 | self.strtab.appendAssumeCapacity(0); |
| 4337 | try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size); | 4349 | try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size); |
| 4338 | | 4350 | |
| 4339 | for (slice.items(.shdr), 0..) |shdr, shndx| { | 4351 | for (slice.items(.shdr), 0..) |shdr, shndx| { |
| ... | @@ -4714,7 +4726,20 @@ pub fn isEffectivelyDynLib(self: Elf) bool { | ... | @@ -4714,7 +4726,20 @@ pub fn isEffectivelyDynLib(self: Elf) bool { |
| 4714 | }; | 4726 | }; |
| 4715 | } | 4727 | } |
| 4716 | | 4728 | |
| 4717 | pub fn addPhdr(self: *Elf, opts: struct { | 4729 | fn getPhdr(self: *Elf, opts: struct { |
| | 4730 | type: u32 = 0, |
| | 4731 | flags: u32 = 0, |
| | 4732 | }) ?u16 { |
| | 4733 | for (self.phdrs.items, 0..) |phdr, phndx| { |
| | 4734 | if (self.phdr_table_load_index) |index| { |
| | 4735 | if (phndx == index) continue; |
| | 4736 | } |
| | 4737 | if (phdr.p_type == opts.type and phdr.p_flags == opts.flags) return @intCast(phndx); |
| | 4738 | } |
| | 4739 | return null; |
| | 4740 | } |
| | 4741 | |
| | 4742 | fn addPhdr(self: *Elf, opts: struct { |
| 4718 | type: u32 = 0, | 4743 | type: u32 = 0, |
| 4719 | flags: u32 = 0, | 4744 | flags: u32 = 0, |
| 4720 | @"align": u64 = 0, | 4745 | @"align": u64 = 0, |
| ... | @@ -5305,7 +5330,7 @@ fn fmtDumpState( | ... | @@ -5305,7 +5330,7 @@ fn fmtDumpState( |
| 5305 | { | 5330 | { |
| 5306 | try writer.writeAll("atom lists\n"); | 5331 | try writer.writeAll("atom lists\n"); |
| 5307 | for (slice.items(.shdr), slice.items(.atom_list_2), 0..) |shdr, atom_list, shndx| { | 5332 | for (slice.items(.shdr), slice.items(.atom_list_2), 0..) |shdr, atom_list, shndx| { |
| 5308 | try writer.print("shdr({d}) : {s} : {}", .{ shndx, self.getShString(shdr.sh_name), atom_list.fmt(self) }); | 5333 | try writer.print("shdr({d}) : {s} : {}\n", .{ shndx, self.getShString(shdr.sh_name), atom_list.fmt(self) }); |
| 5309 | } | 5334 | } |
| 5310 | } | 5335 | } |
| 5311 | | 5336 | |
| ... | @@ -5437,6 +5462,14 @@ pub const SymtabCtx = struct { | ... | @@ -5437,6 +5462,14 @@ pub const SymtabCtx = struct { |
| 5437 | nlocals: u32 = 0, | 5462 | nlocals: u32 = 0, |
| 5438 | nglobals: u32 = 0, | 5463 | nglobals: u32 = 0, |
| 5439 | strsize: u32 = 0, | 5464 | strsize: u32 = 0, |
| | 5465 | |
| | 5466 | pub fn reset(ctx: *SymtabCtx) void { |
| | 5467 | ctx.ilocal = 0; |
| | 5468 | ctx.iglobal = 0; |
| | 5469 | ctx.nlocals = 0; |
| | 5470 | ctx.nglobals = 0; |
| | 5471 | ctx.strsize = 0; |
| | 5472 | } |
| 5440 | }; | 5473 | }; |
| 5441 | | 5474 | |
| 5442 | pub const null_sym = elf.Elf64_Sym{ | 5475 | pub const null_sym = elf.Elf64_Sym{ |