| ... | ... | @@ -2884,51 +2884,99 @@ fn initHeaders( |
| 2884 | 2884 | .@"64" => .@"8", |
| 2885 | 2885 | }; |
| 2886 | 2886 | |
| 2887 | | const shnum: u32 = 1; |
| 2888 | | var phnum: u32 = 0; |
| 2889 | | const phdr_phndx = phnum; |
| 2890 | | phnum += 1; |
| 2891 | | const interp_phndx = if (maybe_interp) |_| phndx: { |
| 2892 | | defer phnum += 1; |
| 2893 | | break :phndx phnum; |
| 2894 | | } else undefined; |
| 2895 | | const rodata_phndx = phnum; |
| 2896 | | phnum += 1; |
| 2897 | | const text_phndx = phnum; |
| 2898 | | phnum += 1; |
| 2899 | | const data_phndx = phnum; |
| 2900 | | phnum += 1; |
| 2901 | | const tls_phndx = if (comp.config.any_non_single_threaded) phndx: { |
| 2902 | | defer phnum += 1; |
| 2903 | | break :phndx phnum; |
| 2904 | | } else undefined; |
| 2905 | | const dynamic_phndx = if (have_dynamic_section) phndx: { |
| 2906 | | defer phnum += 1; |
| 2907 | | break :phndx phnum; |
| 2908 | | } else undefined; |
| 2909 | | const relro_phndx = phnum; |
| 2910 | | phnum += 1; |
| 2911 | | |
| 2912 | 2887 | const init_plt_size: std.elf.Xword, const plt_align: std.mem.Alignment, const plt_sec = |
| 2913 | 2888 | switch (machine) { |
| 2914 | 2889 | else => @panic(@tagName(machine)), |
| 2915 | 2890 | .X86_64 => .{ 16, .@"16", true }, |
| 2916 | 2891 | .LOONGARCH => .{ 32, .@"4", false }, |
| 2917 | 2892 | }; |
| 2918 | | const expected_nodes_len = expected_nodes_len: switch (@"type") { |
| 2919 | | .NONE, .CORE, _ => unreachable, |
| 2920 | | .REL => { |
| 2921 | | // Each phdr is actually going to be an shdr. |
| 2922 | | defer phnum = 0; |
| 2923 | | break :expected_nodes_len 5 + phnum; |
| 2924 | | }, |
| 2925 | | .EXEC, .DYN => break :expected_nodes_len 9 + |
| 2926 | | phnum * 2 - 1 + // each phdr also has a matching shdr, except for the PT_PHDR phdr |
| 2927 | | @as(usize, 4) * @intFromBool(have_dynamic_section) + // .dynstr, .dynsym, .rela.dyn, .rela.plt |
| 2928 | | @intFromBool(plt_sec), |
| 2893 | |
| 2894 | const shnum: u32 = shnum: { |
| 2895 | var shnum: u32 = 1; // reserved ("null") shdr |
| 2896 | shnum += 1; // .symtab |
| 2897 | shnum += 1; // .shstrtab |
| 2898 | shnum += 1; // .strtab |
| 2899 | shnum += @intFromBool(maybe_interp != null); // .interp |
| 2900 | shnum += 1; // .rodata |
| 2901 | shnum += 1; // .text |
| 2902 | shnum += 1; // .data |
| 2903 | shnum += @intFromBool(comp.config.any_non_single_threaded); // .tdata |
| 2904 | shnum += 1; // .data.rel.ro |
| 2905 | if (have_dynamic_section) { |
| 2906 | shnum += 1; // .dynamic |
| 2907 | shnum += 1; // .dynstr |
| 2908 | shnum += 1; // .dynsym |
| 2909 | shnum += 1; // .rela.dyn |
| 2910 | shnum += 1; // .rela.plt |
| 2911 | } |
| 2912 | if (@"type" != .REL) { |
| 2913 | shnum += 1; // .got |
| 2914 | shnum += 1; // .got.plt |
| 2915 | shnum += 1; // .plt |
| 2916 | shnum += @intFromBool(plt_sec); // .plt_sec |
| 2917 | } |
| 2918 | break :shnum shnum; |
| 2929 | 2919 | }; |
| 2920 | |
| 2921 | const phndx: struct { |
| 2922 | phdr: u32, |
| 2923 | interp: u32, |
| 2924 | rodata: u32, |
| 2925 | text: u32, |
| 2926 | data: u32, |
| 2927 | tls: u32, |
| 2928 | dynamic: u32, |
| 2929 | relro: u32, |
| 2930 | }, const phnum: u32 = ph: { |
| 2931 | switch (@"type") { |
| 2932 | .NONE, .CORE, _ => unreachable, |
| 2933 | .REL => break :ph .{ undefined, 0 }, |
| 2934 | .EXEC, .DYN => {}, |
| 2935 | } |
| 2936 | var phnum: u32 = 0; |
| 2937 | break :ph .{ .{ |
| 2938 | .phdr = phndx: { |
| 2939 | defer phnum += 1; |
| 2940 | break :phndx phnum; |
| 2941 | }, |
| 2942 | .interp = if (maybe_interp) |_| phndx: { |
| 2943 | defer phnum += 1; |
| 2944 | break :phndx phnum; |
| 2945 | } else undefined, |
| 2946 | .rodata = phndx: { |
| 2947 | defer phnum += 1; |
| 2948 | break :phndx phnum; |
| 2949 | }, |
| 2950 | .text = phndx: { |
| 2951 | defer phnum += 1; |
| 2952 | break :phndx phnum; |
| 2953 | }, |
| 2954 | .data = phndx: { |
| 2955 | defer phnum += 1; |
| 2956 | break :phndx phnum; |
| 2957 | }, |
| 2958 | .tls = if (comp.config.any_non_single_threaded) phndx: { |
| 2959 | defer phnum += 1; |
| 2960 | break :phndx phnum; |
| 2961 | } else undefined, |
| 2962 | .dynamic = if (have_dynamic_section) phndx: { |
| 2963 | defer phnum += 1; |
| 2964 | break :phndx phnum; |
| 2965 | } else undefined, |
| 2966 | .relro = phndx: { |
| 2967 | defer phnum += 1; |
| 2968 | break :phndx phnum; |
| 2969 | }, |
| 2970 | }, phnum }; |
| 2971 | }; |
| 2972 | |
| 2973 | const expected_nodes_len = 3 + // `.file`, `.ehdr`, and `.shdr` nodes |
| 2974 | (shnum - 1) + // -1 because the null shdr does not have a `.section` node |
| 2975 | phnum; |
| 2976 | |
| 2930 | 2977 | try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len); |
| 2931 | 2978 | try elf.shdrs.ensureTotalCapacity(gpa, shnum); |
| 2979 | try elf.section_by_name.ensureUnusedCapacity(gpa, shnum); |
| 2932 | 2980 | try elf.phdrs.resize(gpa, phnum); |
| 2933 | 2981 | try elf.symtab.ensureTotalCapacity(gpa, 1); |
| 2934 | 2982 | elf.nodes.appendAssumeCapacity(.file); |
| ... | ... | @@ -2980,7 +3028,7 @@ fn initHeaders( |
| 2980 | 3028 | ehdr.phentsize = @sizeOf(ElfN.Phdr); |
| 2981 | 3029 | ehdr.phnum = @min(phnum, std.elf.PN_XNUM); |
| 2982 | 3030 | ehdr.shentsize = @sizeOf(ElfN.Shdr); |
| 2983 | | ehdr.shnum = if (shnum < std.elf.SHN_LORESERVE) shnum else 0; |
| 3031 | ehdr.shnum = 1; // Only the null shdr initially---will be incremented by `addSection` |
| 2984 | 3032 | ehdr.shstrndx = std.elf.SHN_UNDEF; |
| 2985 | 3033 | if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(ElfN.Ehdr, ehdr); |
| 2986 | 3034 | }, |
| ... | ... | @@ -3000,8 +3048,8 @@ fn initHeaders( |
| 3000 | 3048 | .moved = true, |
| 3001 | 3049 | .bubbles_moved = false, |
| 3002 | 3050 | })); |
| 3003 | | elf.nodes.appendAssumeCapacity(.{ .segment = rodata_phndx }); |
| 3004 | | elf.phdrs.items[rodata_phndx] = elf.ni.rodata; |
| 3051 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.rodata }); |
| 3052 | elf.phdrs.items[phndx.rodata] = elf.ni.rodata; |
| 3005 | 3053 | |
| 3006 | 3054 | assert(elf.ni.phdr == try elf.mf.addOnlyChildNode(gpa, elf.ni.rodata, .{ |
| 3007 | 3055 | .size = elf.ehdrField(.phentsize) * elf.ehdrField(.phnum), |
| ... | ... | @@ -3010,32 +3058,32 @@ fn initHeaders( |
| 3010 | 3058 | .resized = true, |
| 3011 | 3059 | .bubbles_moved = false, |
| 3012 | 3060 | })); |
| 3013 | | elf.nodes.appendAssumeCapacity(.{ .segment = phdr_phndx }); |
| 3014 | | elf.phdrs.items[phdr_phndx] = elf.ni.phdr; |
| 3061 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.phdr }); |
| 3062 | elf.phdrs.items[phndx.phdr] = elf.ni.phdr; |
| 3015 | 3063 | |
| 3016 | 3064 | assert(elf.ni.text == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{ |
| 3017 | 3065 | .alignment = elf.mf.flags.block_size, |
| 3018 | 3066 | .moved = true, |
| 3019 | 3067 | .bubbles_moved = false, |
| 3020 | 3068 | })); |
| 3021 | | elf.nodes.appendAssumeCapacity(.{ .segment = text_phndx }); |
| 3022 | | elf.phdrs.items[text_phndx] = elf.ni.text; |
| 3069 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.text }); |
| 3070 | elf.phdrs.items[phndx.text] = elf.ni.text; |
| 3023 | 3071 | |
| 3024 | 3072 | assert(elf.ni.data == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{ |
| 3025 | 3073 | .alignment = elf.mf.flags.block_size, |
| 3026 | 3074 | .moved = true, |
| 3027 | 3075 | .bubbles_moved = false, |
| 3028 | 3076 | })); |
| 3029 | | elf.nodes.appendAssumeCapacity(.{ .segment = data_phndx }); |
| 3030 | | elf.phdrs.items[data_phndx] = elf.ni.data; |
| 3077 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.data }); |
| 3078 | elf.phdrs.items[phndx.data] = elf.ni.data; |
| 3031 | 3079 | |
| 3032 | 3080 | assert(elf.ni.data_rel_ro == try elf.mf.addOnlyChildNode(gpa, elf.ni.data, .{ |
| 3033 | 3081 | .alignment = elf.mf.flags.block_size, |
| 3034 | 3082 | .moved = true, |
| 3035 | 3083 | .bubbles_moved = false, |
| 3036 | 3084 | })); |
| 3037 | | elf.nodes.appendAssumeCapacity(.{ .segment = relro_phndx }); |
| 3038 | | elf.phdrs.items[relro_phndx] = elf.ni.data_rel_ro; |
| 3085 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.relro }); |
| 3086 | elf.phdrs.items[phndx.relro] = elf.ni.data_rel_ro; |
| 3039 | 3087 | |
| 3040 | 3088 | break :ph_vaddr switch (elf.ehdrField(.type)) { |
| 3041 | 3089 | .NONE, .CORE, _ => unreachable, |
| ... | ... | @@ -3058,7 +3106,7 @@ fn initHeaders( |
| 3058 | 3106 | |
| 3059 | 3107 | if (@"type" != .REL) { |
| 3060 | 3108 | const phdr: []ElfN.Phdr = @ptrCast(@alignCast(elf.ni.phdr.slice(&elf.mf))); |
| 3061 | | const ph_phdr = &phdr[phdr_phndx]; |
| 3109 | const ph_phdr = &phdr[phndx.phdr]; |
| 3062 | 3110 | ph_phdr.* = .{ |
| 3063 | 3111 | .type = .PHDR, |
| 3064 | 3112 | .offset = 0, |
| ... | ... | @@ -3072,7 +3120,7 @@ fn initHeaders( |
| 3072 | 3120 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_phdr); |
| 3073 | 3121 | |
| 3074 | 3122 | if (maybe_interp) |_| { |
| 3075 | | const ph_interp = &phdr[interp_phndx]; |
| 3123 | const ph_interp = &phdr[phndx.interp]; |
| 3076 | 3124 | ph_interp.* = .{ |
| 3077 | 3125 | .type = .INTERP, |
| 3078 | 3126 | .offset = 0, |
| ... | ... | @@ -3087,7 +3135,7 @@ fn initHeaders( |
| 3087 | 3135 | } |
| 3088 | 3136 | |
| 3089 | 3137 | _, const rodata_size = elf.ni.rodata.location(&elf.mf).resolve(&elf.mf); |
| 3090 | | const ph_rodata = &phdr[rodata_phndx]; |
| 3138 | const ph_rodata = &phdr[phndx.rodata]; |
| 3091 | 3139 | ph_rodata.* = .{ |
| 3092 | 3140 | .type = if (rodata_size == 0) .NULL else .LOAD, |
| 3093 | 3141 | .offset = 0, |
| ... | ... | @@ -3102,7 +3150,7 @@ fn initHeaders( |
| 3102 | 3150 | ph_vaddr += @intCast(rodata_size); |
| 3103 | 3151 | |
| 3104 | 3152 | _, const text_size = elf.ni.text.location(&elf.mf).resolve(&elf.mf); |
| 3105 | | const ph_text = &phdr[text_phndx]; |
| 3153 | const ph_text = &phdr[phndx.text]; |
| 3106 | 3154 | ph_text.* = .{ |
| 3107 | 3155 | .type = if (text_size == 0) .NULL else .LOAD, |
| 3108 | 3156 | .offset = 0, |
| ... | ... | @@ -3117,7 +3165,7 @@ fn initHeaders( |
| 3117 | 3165 | ph_vaddr += @intCast(text_size); |
| 3118 | 3166 | |
| 3119 | 3167 | _, const data_size = elf.ni.data.location(&elf.mf).resolve(&elf.mf); |
| 3120 | | const ph_data = &phdr[data_phndx]; |
| 3168 | const ph_data = &phdr[phndx.data]; |
| 3121 | 3169 | ph_data.* = .{ |
| 3122 | 3170 | .type = if (data_size == 0) .NULL else .LOAD, |
| 3123 | 3171 | .offset = 0, |
| ... | ... | @@ -3132,7 +3180,7 @@ fn initHeaders( |
| 3132 | 3180 | ph_vaddr += @intCast(data_size); |
| 3133 | 3181 | |
| 3134 | 3182 | if (comp.config.any_non_single_threaded) { |
| 3135 | | const ph_tls = &phdr[tls_phndx]; |
| 3183 | const ph_tls = &phdr[phndx.tls]; |
| 3136 | 3184 | ph_tls.* = .{ |
| 3137 | 3185 | .type = .TLS, |
| 3138 | 3186 | .offset = 0, |
| ... | ... | @@ -3147,7 +3195,7 @@ fn initHeaders( |
| 3147 | 3195 | } |
| 3148 | 3196 | |
| 3149 | 3197 | if (have_dynamic_section) { |
| 3150 | | const ph_dynamic = &phdr[dynamic_phndx]; |
| 3198 | const ph_dynamic = &phdr[phndx.dynamic]; |
| 3151 | 3199 | ph_dynamic.* = .{ |
| 3152 | 3200 | .type = .DYNAMIC, |
| 3153 | 3201 | .offset = 0, |
| ... | ... | @@ -3161,7 +3209,7 @@ fn initHeaders( |
| 3161 | 3209 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_dynamic); |
| 3162 | 3210 | } |
| 3163 | 3211 | |
| 3164 | | const ph_relro = &phdr[relro_phndx]; |
| 3212 | const ph_relro = &phdr[phndx.relro]; |
| 3165 | 3213 | ph_relro.* = .{ |
| 3166 | 3214 | .type = .GNU_RELRO, |
| 3167 | 3215 | .offset = 0, |
| ... | ... | @@ -3312,8 +3360,8 @@ fn initHeaders( |
| 3312 | 3360 | .resized = true, |
| 3313 | 3361 | .bubbles_moved = false, |
| 3314 | 3362 | }); |
| 3315 | | elf.nodes.appendAssumeCapacity(.{ .segment = interp_phndx }); |
| 3316 | | elf.phdrs.items[interp_phndx] = interp_ni; |
| 3363 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.interp }); |
| 3364 | elf.phdrs.items[phndx.interp] = interp_ni; |
| 3317 | 3365 | |
| 3318 | 3366 | const sec_interp_shndx = try elf.addSection(interp_ni, .{ |
| 3319 | 3367 | .name = ".interp", |
| ... | ... | @@ -3331,8 +3379,8 @@ fn initHeaders( |
| 3331 | 3379 | .moved = true, |
| 3332 | 3380 | .bubbles_moved = false, |
| 3333 | 3381 | }); |
| 3334 | | elf.nodes.appendAssumeCapacity(.{ .segment = dynamic_phndx }); |
| 3335 | | elf.phdrs.items[dynamic_phndx] = dynamic_ni; |
| 3382 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.dynamic }); |
| 3383 | elf.phdrs.items[phndx.dynamic] = dynamic_ni; |
| 3336 | 3384 | |
| 3337 | 3385 | const dynstr_shndx = try elf.addSection(elf.ni.rodata, .{ |
| 3338 | 3386 | .name = ".dynstr", |
| ... | ... | @@ -3473,8 +3521,8 @@ fn initHeaders( |
| 3473 | 3521 | .moved = true, |
| 3474 | 3522 | .bubbles_moved = false, |
| 3475 | 3523 | }); |
| 3476 | | elf.nodes.appendAssumeCapacity(.{ .segment = tls_phndx }); |
| 3477 | | elf.phdrs.items[tls_phndx] = elf.ni.tls; |
| 3524 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.tls }); |
| 3525 | elf.phdrs.items[phndx.tls] = elf.ni.tls; |
| 3478 | 3526 | } |
| 3479 | 3527 | |
| 3480 | 3528 | // Populate reserved GOT words. |
| ... | ... | @@ -3641,10 +3689,11 @@ fn initHeaders( |
| 3641 | 3689 | .flags = .{ .WRITE = true, .ALLOC = true, .TLS = true }, |
| 3642 | 3690 | .addralign = elf.mf.flags.block_size, |
| 3643 | 3691 | }); |
| 3692 | |
| 3644 | 3693 | assert(elf.nodes.len == expected_nodes_len); |
| 3694 | assert(elf.shdrs.items.len == shnum); |
| 3645 | 3695 | |
| 3646 | | try elf.section_by_name.ensureUnusedCapacity(gpa, elf.shdrs.items.len); |
| 3647 | | for (0..elf.shdrs.items.len) |shndx_raw| { |
| 3696 | for (0..shnum) |shndx_raw| { |
| 3648 | 3697 | const shndx: Section.Index = @enumFromInt(shndx_raw); |
| 3649 | 3698 | elf.section_by_name.putAssumeCapacityNoClobber(shndx.name(elf), {}); |
| 3650 | 3699 | } |