| ... | ... | @@ -92,6 +92,8 @@ lazy: std.EnumArray(link.File.LazySymbol.Kind, struct { |
| 92 | 92 | }), |
| 93 | 93 | pending_uavs: std.ArrayList(Node.UavMapIndex), |
| 94 | 94 | relocs: std.ArrayList(Reloc), |
| 95 | /// Index matches the index into `shdrs`. |
| 96 | section_by_name: std.array_hash_map.Auto(String(.shstrtab), void), |
| 95 | 97 | |
| 96 | 98 | /// Key is the name of a global symbol which has been moved to a new symtab index. Any relocation |
| 97 | 99 | /// entries which target that symbol must be updated to reference the correct symbol index. |
| ... | ... | @@ -361,11 +363,10 @@ const Section = struct { |
| 361 | 363 | return &elf.shdrs.items[@intFromEnum(s)]; |
| 362 | 364 | } |
| 363 | 365 | |
| 364 | | fn name(s: Index, elf: *Elf) [:0]const u8 { |
| 365 | | const str: String(.shstrtab) = switch (elf.shdrPtr(s)) { |
| 366 | fn name(s: Index, elf: *Elf) String(.shstrtab) { |
| 367 | return switch (elf.shdrPtr(s)) { |
| 366 | 368 | inline else => |shdr| @enumFromInt(elf.targetLoad(&shdr.name)), |
| 367 | 369 | }; |
| 368 | | return str.slice(elf); |
| 369 | 370 | } |
| 370 | 371 | |
| 371 | 372 | fn vaddr(s: Index, elf: *Elf) u64 { |
| ... | ... | @@ -1372,7 +1373,7 @@ pub fn navSymbol(elf: *Elf, nav_index: InternPool.Nav.Index) !link.File.SymbolId |
| 1372 | 1373 | return elf.externSymbol(.{ |
| 1373 | 1374 | .name = @"extern".name.toSlice(ip), |
| 1374 | 1375 | .lib_name = @"extern".lib_name.toSlice(ip), |
| 1375 | | .type = navType(ip, nav.resolved.?, elf.base.comp.config.any_non_single_threaded), |
| 1376 | .type = elf.navType(nav.resolved.?), |
| 1376 | 1377 | .linkage = @"extern".linkage, |
| 1377 | 1378 | .visibility = @"extern".visibility, |
| 1378 | 1379 | }); |
| ... | ... | @@ -1956,6 +1957,7 @@ fn create( |
| 1956 | 1957 | }), |
| 1957 | 1958 | .pending_uavs = .empty, |
| 1958 | 1959 | .relocs = .empty, |
| 1960 | .section_by_name = .empty, |
| 1959 | 1961 | .changed_symtab_index = .empty, |
| 1960 | 1962 | .const_prog_node = .none, |
| 1961 | 1963 | .synth_prog_node = .none, |
| ... | ... | @@ -1992,6 +1994,7 @@ pub fn deinit(elf: *Elf) void { |
| 1992 | 1994 | for (&elf.lazy.values) |*lazy| lazy.map.deinit(gpa); |
| 1993 | 1995 | elf.pending_uavs.deinit(gpa); |
| 1994 | 1996 | elf.relocs.deinit(gpa); |
| 1997 | elf.section_by_name.deinit(gpa); |
| 1995 | 1998 | elf.changed_symtab_index.deinit(gpa); |
| 1996 | 1999 | elf.* = undefined; |
| 1997 | 2000 | } |
| ... | ... | @@ -2561,6 +2564,12 @@ fn initHeaders( |
| 2561 | 2564 | .addralign = elf.mf.flags.block_size, |
| 2562 | 2565 | }); |
| 2563 | 2566 | assert(elf.nodes.len == expected_nodes_len); |
| 2567 | |
| 2568 | try elf.section_by_name.ensureUnusedCapacity(gpa, elf.shdrs.items.len); |
| 2569 | for (0..elf.shdrs.items.len) |shndx_raw| { |
| 2570 | const shndx: Section.Index = @enumFromInt(shndx_raw); |
| 2571 | elf.section_by_name.putAssumeCapacityNoClobber(shndx.name(elf), {}); |
| 2572 | } |
| 2564 | 2573 | } |
| 2565 | 2574 | |
| 2566 | 2575 | pub fn startProgress(elf: *Elf, prog_node: std.Progress.Node) void { |
| ... | ... | @@ -2810,28 +2819,129 @@ fn dynsymPtr(elf: *Elf, index: u32) SymPtr { |
| 2810 | 2819 | } |
| 2811 | 2820 | } |
| 2812 | 2821 | |
| 2813 | | fn navType( |
| 2814 | | ip: *const InternPool, |
| 2815 | | nav_resolved: @typeInfo(@FieldType(InternPool.Nav, "resolved")).optional.child, |
| 2816 | | any_non_single_threaded: bool, |
| 2817 | | ) std.elf.STT { |
| 2822 | fn navType(elf: *const Elf, nav_resolved: InternPool.Nav.Resolved) std.elf.STT { |
| 2823 | const any_non_single_threaded = elf.base.comp.config.any_non_single_threaded; |
| 2818 | 2824 | return if (any_non_single_threaded and nav_resolved.@"threadlocal") |
| 2819 | 2825 | .TLS |
| 2820 | | else if (ip.isFunctionType(nav_resolved.type)) |
| 2826 | else if (elf.base.comp.zcu.?.intern_pool.isFunctionType(nav_resolved.type)) |
| 2821 | 2827 | .FUNC |
| 2822 | 2828 | else |
| 2823 | 2829 | .OBJECT; |
| 2824 | 2830 | } |
| 2825 | | fn namedSection(elf: *const Elf, name: []const u8) ?Section.Index { |
| 2826 | | if (std.mem.eql(u8, name, ".rodata") or |
| 2827 | | std.mem.startsWith(u8, name, ".rodata.")) return .rodata; |
| 2828 | | if (std.mem.eql(u8, name, ".text") or |
| 2829 | | std.mem.startsWith(u8, name, ".text.")) return .text; |
| 2830 | | if (std.mem.eql(u8, name, ".data") or |
| 2831 | | std.mem.startsWith(u8, name, ".data.")) return .data; |
| 2832 | | if (std.mem.eql(u8, name, ".tdata") or |
| 2833 | | std.mem.startsWith(u8, name, ".tdata.")) return elf.shndx.tdata; |
| 2834 | | return null; |
| 2831 | fn mapInputSection(elf: *Elf, opts: struct { |
| 2832 | name: []const u8, |
| 2833 | flags: std.elf.SHF, |
| 2834 | addralign: std.elf.Xword, |
| 2835 | entsize: std.elf.Xword, |
| 2836 | }) !Section.Index { |
| 2837 | const gpa = elf.base.comp.gpa; |
| 2838 | if (opts.flags.INFO_LINK or |
| 2839 | opts.flags.LINK_ORDER or |
| 2840 | opts.flags.OS_NONCONFORMING or |
| 2841 | (opts.flags.EXECINSTR and opts.flags.WRITE) or |
| 2842 | (opts.flags.EXECINSTR and opts.flags.TLS)) |
| 2843 | { |
| 2844 | return error.UnsupportedSectionFlags; |
| 2845 | } |
| 2846 | if (opts.flags.TLS and elf.ni.tls == .none) { |
| 2847 | assert(!elf.base.comp.config.any_non_single_threaded); |
| 2848 | return error.TlsSectionUnavailable; |
| 2849 | } |
| 2850 | const name: []const u8 = switch (elf.ehdrField(.type)) { |
| 2851 | .NONE, .CORE, _ => unreachable, |
| 2852 | .REL => opts.name, |
| 2853 | .EXEC, .DYN => name: { |
| 2854 | if (std.mem.startsWith(u8, opts.name, ".text.")) break :name ".text"; |
| 2855 | if (std.mem.startsWith(u8, opts.name, ".rodata.")) break :name ".rodata"; |
| 2856 | if (std.mem.startsWith(u8, opts.name, ".data.")) break :name ".data"; |
| 2857 | if (std.mem.startsWith(u8, opts.name, ".data.rel.ro.")) break :name ".data.rel.ro"; |
| 2858 | if (std.mem.startsWith(u8, opts.name, ".tdata.")) break :name ".tdata"; |
| 2859 | if (std.mem.startsWith(u8, opts.name, ".gcc_except_table.")) break :name ".gcc_except_table"; |
| 2860 | // TODO: actually generate a bss section! |
| 2861 | if (std.mem.eql(u8, opts.name, ".bss")) break :name ".data"; |
| 2862 | if (std.mem.startsWith(u8, opts.name, ".bss.")) break :name ".data"; |
| 2863 | // TODO: actually generate a tbss section! |
| 2864 | if (std.mem.eql(u8, opts.name, ".tbss")) break :name ".tdata"; |
| 2865 | if (std.mem.startsWith(u8, opts.name, ".tbss.")) break :name ".tdata"; |
| 2866 | break :name opts.name; |
| 2867 | }, |
| 2868 | }; |
| 2869 | const existing_shndx: Section.Index = existing: { |
| 2870 | const name_shstrtab = try elf.string(.shstrtab, name); |
| 2871 | const gop = try elf.section_by_name.getOrPut(gpa, name_shstrtab); |
| 2872 | if (gop.found_existing) { |
| 2873 | break :existing @enumFromInt(gop.index); |
| 2874 | } |
| 2875 | errdefer assert(elf.section_by_name.pop().?.key == name_shstrtab); |
| 2876 | const parent_node: MappedFile.Node.Index = parent: { |
| 2877 | if (!opts.flags.ALLOC) break :parent elf.ni.file; |
| 2878 | if (opts.flags.EXECINSTR) break :parent elf.ni.text; |
| 2879 | if (opts.flags.TLS) break :parent elf.ni.tls; |
| 2880 | if (opts.flags.WRITE) break :parent elf.ni.data; |
| 2881 | break :parent elf.ni.rodata; |
| 2882 | }; |
| 2883 | assert(gop.index == elf.shdrs.items.len); |
| 2884 | return elf.addSection(parent_node, .{ |
| 2885 | .name = name, |
| 2886 | .type = .NULL, // because initial size is 0 |
| 2887 | .flags = flags: { |
| 2888 | // We need to decompress the section for linking. |
| 2889 | var flags = opts.flags; |
| 2890 | flags.COMPRESSED = false; |
| 2891 | break :flags flags; |
| 2892 | }, |
| 2893 | .node_align = .fromByteUnits(std.math.ceilPowerOfTwoAssert( |
| 2894 | usize, |
| 2895 | @intCast(@max(opts.addralign, 1)), |
| 2896 | )), |
| 2897 | .entsize = std.math.lossyCast(u32, opts.entsize), |
| 2898 | }); |
| 2899 | }; |
| 2900 | // Validate that the input is compatible with this section... |
| 2901 | switch (elf.shdrPtr(existing_shndx)) { |
| 2902 | inline else => |shdr| { |
| 2903 | const cur_flags = elf.targetLoad(&shdr.flags).shf; |
| 2904 | if (cur_flags.EXECINSTR != opts.flags.EXECINSTR or |
| 2905 | cur_flags.WRITE != opts.flags.WRITE or |
| 2906 | cur_flags.TLS != opts.flags.TLS) |
| 2907 | { |
| 2908 | return error.SectionFlagsConflict; |
| 2909 | } |
| 2910 | |
| 2911 | switch (elf.targetLoad(&shdr.type)) { |
| 2912 | .NULL, .PROGBITS => {}, |
| 2913 | else => return error.SectionTypeConflict, |
| 2914 | } |
| 2915 | }, |
| 2916 | } |
| 2917 | // ...then realign the section's node if necessary... |
| 2918 | if (opts.addralign > existing_shndx.get(elf).ni.alignment(&elf.mf).toByteUnits()) { |
| 2919 | const new_alignment: std.mem.Alignment = .fromByteUnits( |
| 2920 | std.math.ceilPowerOfTwoAssert(usize, @intCast(opts.addralign)), |
| 2921 | ); |
| 2922 | try existing_shndx.get(elf).ni.realign(&elf.mf, gpa, new_alignment); |
| 2923 | } |
| 2924 | // ...and update the shdr as needed. |
| 2925 | switch (elf.shdrPtr(existing_shndx)) { |
| 2926 | inline else => |shdr| { |
| 2927 | // Combine the section flags. |
| 2928 | const cur_flags = elf.targetLoad(&shdr.flags).shf; |
| 2929 | elf.targetStore(&shdr.flags, .{ .shf = .{ |
| 2930 | .EXECINSTR = cur_flags.EXECINSTR, |
| 2931 | .WRITE = cur_flags.WRITE, |
| 2932 | .TLS = cur_flags.TLS, |
| 2933 | .ALLOC = cur_flags.ALLOC or opts.flags.ALLOC, |
| 2934 | .STRINGS = cur_flags.STRINGS and opts.flags.STRINGS, |
| 2935 | .MERGE = cur_flags.MERGE and opts.flags.MERGE, |
| 2936 | } }); |
| 2937 | // Increase addralign to the maximum of the current value and the new value---the node |
| 2938 | // alignment was already increased above. |
| 2939 | if (opts.addralign > elf.targetLoad(&shdr.addralign)) { |
| 2940 | elf.targetStore(&shdr.addralign, @intCast(opts.addralign)); |
| 2941 | } |
| 2942 | }, |
| 2943 | } |
| 2944 | return existing_shndx; |
| 2835 | 2945 | } |
| 2836 | 2946 | fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavMapIndex { |
| 2837 | 2947 | const gpa = zcu.gpa; |
| ... | ... | @@ -2845,17 +2955,40 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavM |
| 2845 | 2955 | const nav_gop = elf.navs.getOrPutAssumeCapacity(nav_index); |
| 2846 | 2956 | const nmi: Node.NavMapIndex = @enumFromInt(nav_gop.index); |
| 2847 | 2957 | if (!nav_gop.found_existing) { |
| 2848 | | const sym_type = navType(ip, nav.resolved.?, elf.base.comp.config.any_non_single_threaded); |
| 2849 | 2958 | const shndx: Section.Index = section: { |
| 2850 | 2959 | if (nav.resolved.?.@"linksection".toSlice(ip)) |@"linksection"| { |
| 2851 | | if (elf.namedSection(@"linksection")) |shndx| break :section shndx; |
| 2960 | if (elf.mapInputSection(.{ |
| 2961 | .name = @"linksection", |
| 2962 | .flags = .{ |
| 2963 | .ALLOC = true, |
| 2964 | .EXECINSTR = ip.isFunctionType(nav.resolved.?.type), |
| 2965 | .WRITE = !nav.resolved.?.@"const", |
| 2966 | .TLS = elf.base.comp.config.any_non_single_threaded and |
| 2967 | nav.resolved.?.@"threadlocal", |
| 2968 | }, |
| 2969 | .addralign = 1, |
| 2970 | .entsize = 0, |
| 2971 | })) |shndx| { |
| 2972 | break :section shndx; |
| 2973 | } else |err| switch (err) { |
| 2974 | error.TlsSectionUnavailable, |
| 2975 | error.UnsupportedSectionFlags, |
| 2976 | error.SectionTypeConflict, |
| 2977 | error.SectionFlagsConflict, |
| 2978 | => {}, // fall back to default behavior below |
| 2979 | |
| 2980 | else => |e| return e, |
| 2981 | } |
| 2982 | } |
| 2983 | if (elf.base.comp.config.any_non_single_threaded and nav.resolved.?.@"threadlocal") { |
| 2984 | break :section elf.shndx.tdata; |
| 2985 | } else if (!nav.resolved.?.@"const") { |
| 2986 | break :section .data; |
| 2987 | } else if (ip.isFunctionType(nav.resolved.?.type)) { |
| 2988 | break :section .text; |
| 2989 | } else { |
| 2990 | break :section .rodata; |
| 2852 | 2991 | } |
| 2853 | | break :section switch (sym_type) { |
| 2854 | | else => unreachable, |
| 2855 | | .FUNC => .text, |
| 2856 | | .OBJECT => .data, |
| 2857 | | .TLS => elf.shndx.tdata, |
| 2858 | | }; |
| 2859 | 2992 | }; |
| 2860 | 2993 | const alignment: InternPool.Alignment = switch (Type.fromInterned(nav.resolved.?.type).zigTypeTag(zcu)) { |
| 2861 | 2994 | .@"fn" => a: { |
| ... | ... | @@ -2887,7 +3020,7 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavM |
| 2887 | 3020 | .name = try elf.string(.strtab, nav.fqn.toSlice(ip)), |
| 2888 | 3021 | .value = 0, |
| 2889 | 3022 | .size = 0, |
| 2890 | | .type = sym_type, |
| 3023 | .type = elf.navType(nav.resolved.?), |
| 2891 | 3024 | .shndx = shndx, |
| 2892 | 3025 | }), |
| 2893 | 3026 | .first_reloc = .none, |
| ... | ... | @@ -3131,26 +3264,69 @@ fn loadObject( |
| 3131 | 3264 | node_fixed: bool, |
| 3132 | 3265 | } = switch (section.shdr.type) { |
| 3133 | 3266 | else => continue, |
| 3134 | | .PROGBITS => .{ |
| 3135 | | .shndx = elf.namedSection(name) orelse continue, |
| 3136 | | .has_file_bits = true, |
| 3137 | | .node_fixed = false, |
| 3138 | | }, |
| 3139 | | .NOBITS => .{ |
| 3140 | | .shndx = shndx: { |
| 3141 | | // TODO: actually generate a .bss section. For now, just throw it into `.data`. |
| 3142 | | if (std.mem.eql(u8, name, ".bss") or std.mem.startsWith(u8, name, ".bss.")) { |
| 3143 | | break :shndx .data; |
| 3144 | | } |
| 3145 | | if (elf.shndx.tdata != .UNDEF and |
| 3146 | | (std.mem.eql(u8, name, ".tbss") or std.mem.startsWith(u8, name, ".tbss."))) |
| 3147 | | { |
| 3148 | | break :shndx elf.shndx.tdata; |
| 3149 | | } |
| 3267 | .PROGBITS, .NOBITS => opts: { |
| 3268 | const shndx = elf.mapInputSection(.{ |
| 3269 | .name = name, |
| 3270 | .flags = section.shdr.flags.shf, |
| 3271 | .addralign = section.shdr.addralign, |
| 3272 | .entsize = section.shdr.entsize, |
| 3273 | }) catch |err| switch (err) { |
| 3274 | error.TlsSectionUnavailable => return diags.failParse( |
| 3275 | path, |
| 3276 | "thread-local storage section '{s}' is incompatible with '-fsingle-threaded'", |
| 3277 | .{name}, |
| 3278 | ), |
| 3279 | error.UnsupportedSectionFlags => if (!section.shdr.flags.shf.ALLOC) { |
| 3280 | // It probably doesn't matter, just skip this section. |
| 3281 | continue; |
| 3282 | } else return diags.failParse( |
| 3283 | path, |
| 3284 | "unsupported flags for section '{s}'", |
| 3285 | .{name}, |
| 3286 | ), |
| 3287 | error.SectionTypeConflict => if (!section.shdr.flags.shf.ALLOC) { |
| 3288 | // It probably doesn't matter, just skip this section. |
| 3289 | continue; |
| 3290 | } else return diags.failParse( |
| 3291 | path, |
| 3292 | "type of section '{s}' conflicts with other inputs", |
| 3293 | .{name}, |
| 3294 | ), |
| 3295 | error.SectionFlagsConflict => if (!section.shdr.flags.shf.ALLOC) { |
| 3296 | // It probably doesn't matter, just skip this section. |
| 3297 | continue; |
| 3298 | } else return diags.failParse( |
| 3299 | path, |
| 3300 | "flags of section '{s}' conflict with other inputs", |
| 3301 | .{name}, |
| 3302 | ), |
| 3303 | else => |e| return e, |
| 3304 | }; |
| 3305 | if (section.shdr.flags.shf.COMPRESSED) { |
| 3306 | // SHF_COMPRESSED is only allowed on non-alloc sections. |
| 3307 | if (section.shdr.flags.shf.ALLOC) return diags.failParse( |
| 3308 | path, |
| 3309 | "section '{s}' has conflicting flags SHF_ALLOC and SHF_COMPRESSED", |
| 3310 | .{name}, |
| 3311 | ); |
| 3312 | // TODO: handle compressed input sections. We'll need to set a flag to |
| 3313 | // indicate that `flushInputSection` needs to decompress the section. |
| 3314 | // But because this section isn't SHF_ALLOC, it's probably okay to just |
| 3315 | // skip it for now. |
| 3150 | 3316 | continue; |
| 3151 | | }, |
| 3152 | | .has_file_bits = false, |
| 3153 | | .node_fixed = false, |
| 3317 | } |
| 3318 | break :opts .{ |
| 3319 | .shndx = shndx, |
| 3320 | .has_file_bits = section.shdr.type == .PROGBITS, |
| 3321 | // For well-known sections, we know that it's fine to have e.g. random |
| 3322 | // padding, so there's no need to make the sections fixed. For custom |
| 3323 | // sections, however, we do want fixed nodes to avoid padding. |
| 3324 | .node_fixed = shndx != .text and |
| 3325 | shndx != .rodata and |
| 3326 | shndx != .data and |
| 3327 | shndx != .data_rel_ro and |
| 3328 | shndx != elf.shndx.tdata, |
| 3329 | }; |
| 3154 | 3330 | }, |
| 3155 | 3331 | inline .INIT_ARRAY, .FINI_ARRAY, .PREINIT_ARRAY => |@"type"| .{ |
| 3156 | 3332 | .shndx = shndx: { |
| ... | ... | @@ -3372,11 +3548,17 @@ fn loadObject( |
| 3372 | 3548 | .{rel.info.sym}, |
| 3373 | 3549 | ); |
| 3374 | 3550 | const target = symmap.items[rel.info.sym - 1]; |
| 3375 | | if (target == Symbol.Id.null) return diags.failParse( |
| 3376 | | path, |
| 3377 | | "unsupported symbol at index {d} required for relocation", |
| 3378 | | .{rel.info.sym}, |
| 3379 | | ); |
| 3551 | if (target == Symbol.Id.null) { |
| 3552 | // If this is not an SHF_ALLOC section, then let's let this |
| 3553 | // slide for now, because it probably doesn't affect the final |
| 3554 | // binary's functionality for this section to be a bit broken. |
| 3555 | if (!loc_sec.shdr.flags.shf.ALLOC) continue; |
| 3556 | return diags.failParse( |
| 3557 | path, |
| 3558 | "unsupported symbol at index {d} required for relocation", |
| 3559 | .{rel.info.sym}, |
| 3560 | ); |
| 3561 | } |
| 3380 | 3562 | elf.addRelocAssumeCapacity( |
| 3381 | 3563 | loc_node, |
| 3382 | 3564 | rel.offset - loc_sec.shdr.addr, |
| ... | ... | @@ -3531,17 +3713,21 @@ fn createInitFiniArraySection( |
| 3531 | 3713 | @"type": std.elf.SHT, |
| 3532 | 3714 | ) !void { |
| 3533 | 3715 | assert(shndx.* == .UNDEF); |
| 3716 | const gpa = elf.base.comp.gpa; |
| 3534 | 3717 | const addr_align: std.mem.Alignment = switch (elf.identClass()) { |
| 3535 | 3718 | .NONE, _ => unreachable, |
| 3536 | 3719 | .@"32" => .@"4", |
| 3537 | 3720 | .@"64" => .@"8", |
| 3538 | 3721 | }; |
| 3722 | assert(elf.section_by_name.count() == elf.shdrs.items.len); |
| 3723 | try elf.section_by_name.ensureUnusedCapacity(gpa, 1); |
| 3539 | 3724 | shndx.* = try elf.addSection(elf.ni.data_rel_ro, .{ |
| 3540 | 3725 | .name = "." ++ name, |
| 3541 | 3726 | .type = @"type", |
| 3542 | 3727 | .flags = .{ .WRITE = true, .ALLOC = true }, |
| 3543 | 3728 | .node_align = addr_align, |
| 3544 | 3729 | }); |
| 3730 | elf.section_by_name.putAssumeCapacityNoClobber(shndx.name(elf), {}); |
| 3545 | 3731 | try elf.ensureUnusedSymbolCapacity(2, .maybe_global); |
| 3546 | 3732 | _ = elf.addGlobalSymbolAssumeCapacity(.{ |
| 3547 | 3733 | .node = shndx.get(elf).ni, |
| ... | ... | @@ -3879,9 +4065,11 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) |
| 3879 | 4065 | var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, gpa); |
| 3880 | 4066 | const allocator = bfa.allocator(); |
| 3881 | 4067 | |
| 3882 | | const rela_name = try std.fmt.allocPrint(allocator, ".rela{s}", .{shndx.name(elf)}); |
| 4068 | const rela_name = try std.fmt.allocPrint(allocator, ".rela{s}", .{shndx.name(elf).slice(elf)}); |
| 3883 | 4069 | defer allocator.free(rela_name); |
| 3884 | 4070 | |
| 4071 | assert(elf.section_by_name.count() == elf.shdrs.items.len); |
| 4072 | try elf.section_by_name.ensureUnusedCapacity(gpa, 1); |
| 3885 | 4073 | const rela_shndx = try elf.addSection(.none, .{ |
| 3886 | 4074 | .name = rela_name, |
| 3887 | 4075 | .type = .RELA, |
| ... | ... | @@ -3898,6 +4086,7 @@ fn ensureUnusedRelocCapacity(elf: *Elf, node: MappedFile.Node.Index, len: usize) |
| 3898 | 4086 | }, |
| 3899 | 4087 | .node_align = elf.mf.flags.block_size, |
| 3900 | 4088 | }); |
| 4089 | elf.section_by_name.putAssumeCapacityNoClobber(rela_shndx.name(elf), {}); |
| 3901 | 4090 | shndx.get(elf).rela_shndx = rela_shndx; |
| 3902 | 4091 | } |
| 3903 | 4092 | break :rela .{ shndx.get(elf).rela_shndx, len }; |
| ... | ... | @@ -4272,7 +4461,7 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) !bool { |
| 4272 | 4461 | return comp.link_diags.fail( |
| 4273 | 4462 | "linker failed to read input section '{s}' from \"{f}{f}\": {t}", |
| 4274 | 4463 | .{ |
| 4275 | | elf.getNode(isi.node(elf).parent(&elf.mf)).section.name(elf), |
| 4464 | elf.getNode(isi.node(elf).parent(&elf.mf)).section.name(elf).slice(elf), |
| 4276 | 4465 | ii.path(elf).fmtEscapeString(), |
| 4277 | 4466 | fmtMemberString(ii.member(elf)), |
| 4278 | 4467 | e, |
| ... | ... | @@ -4325,13 +4514,13 @@ fn idleProgNode( |
| 4325 | 4514 | var name: [std.Progress.Node.max_name_len]u8 = undefined; |
| 4326 | 4515 | return prog_node.start(name: switch (node) { |
| 4327 | 4516 | else => |tag| @tagName(tag), |
| 4328 | | .section => |shndx| shndx.name(elf), |
| 4517 | .section => |shndx| shndx.name(elf).slice(elf), |
| 4329 | 4518 | .input_section => |isi| { |
| 4330 | 4519 | const ii = isi.input(elf); |
| 4331 | 4520 | break :name std.fmt.bufPrint(&name, "{f}{f} {s}", .{ |
| 4332 | 4521 | ii.path(elf).fmtEscapeString(), |
| 4333 | 4522 | fmtMemberString(ii.member(elf)), |
| 4334 | | elf.getNode(isi.node(elf).parent(&elf.mf)).section.name(elf), |
| 4523 | elf.getNode(isi.node(elf).parent(&elf.mf)).section.name(elf).slice(elf), |
| 4335 | 4524 | }) catch &name; |
| 4336 | 4525 | }, |
| 4337 | 4526 | .nav => |nmi| { |
| ... | ... | @@ -4885,7 +5074,7 @@ fn updateExportsInner( |
| 4885 | 5074 | const exported_lsi: Symbol.LocalIndex, const @"type": std.elf.STT = switch (exported) { |
| 4886 | 5075 | .nav => |nav| .{ |
| 4887 | 5076 | (try elf.navMapIndex(zcu, nav)).symbol(elf), |
| 4888 | | navType(ip, ip.getNav(nav).resolved.?, elf.base.comp.config.any_non_single_threaded), |
| 5077 | elf.navType(ip.getNav(nav).resolved.?), |
| 4889 | 5078 | }, |
| 4890 | 5079 | .uav => |uav| .{ (try elf.uavMapIndex(uav, .none)).symbol(elf), .OBJECT }, |
| 4891 | 5080 | }; |
| ... | ... | @@ -4987,13 +5176,13 @@ pub fn printNode( |
| 4987 | 5176 | try w.writeByte(')'); |
| 4988 | 5177 | }, |
| 4989 | 5178 | }, |
| 4990 | | .section => |shndx| try w.print("({s})", .{shndx.name(elf)}), |
| 5179 | .section => |shndx| try w.print("({s})", .{shndx.name(elf).slice(elf)}), |
| 4991 | 5180 | .input_section => |isi| { |
| 4992 | 5181 | const ii = isi.input(elf); |
| 4993 | 5182 | try w.print("({f}{f}, {s})", .{ |
| 4994 | 5183 | ii.path(elf).fmtEscapeString(), |
| 4995 | 5184 | fmtMemberString(ii.member(elf)), |
| 4996 | | elf.getNode(isi.node(elf).parent(&elf.mf)).section.name(elf), |
| 5185 | elf.getNode(isi.node(elf).parent(&elf.mf)).section.name(elf).slice(elf), |
| 4997 | 5186 | }); |
| 4998 | 5187 | }, |
| 4999 | 5188 | .nav => |nmi| { |