| ... | ... | @@ -34,6 +34,10 @@ shndx: struct { |
| 34 | 34 | dynstr: Section.Index, |
| 35 | 35 | dynamic: Section.Index, |
| 36 | 36 | tdata: Section.Index, |
| 37 | // These sections are created only as needed, and are initially `.UNDEF`. |
| 38 | init_array: Section.Index, |
| 39 | fini_array: Section.Index, |
| 40 | preinit_array: Section.Index, |
| 37 | 41 | }, |
| 38 | 42 | symtab: std.ArrayList(Symbol), |
| 39 | 43 | globals: struct { |
| ... | ... | @@ -1113,7 +1117,7 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void |
| 1113 | 1117 | const Symbol = struct { |
| 1114 | 1118 | /// The node which this symbol's value is defined relative to. Possible values are: |
| 1115 | 1119 | /// * `.none` for a SHN_ABS or SHN_UNDEF symbol |
| 1116 | | /// * A section (the symbol's value is that section's vaddr) |
| 1120 | /// * A section (the symbol's value is some vaddr in that section) |
| 1117 | 1121 | /// * An input section (the symbol's value is some vaddr in that input section) |
| 1118 | 1122 | /// * A NAV, UAV, or lazy code/data (the symbol's value is exactly the vaddr of that node) |
| 1119 | 1123 | node: MappedFile.Node.Index, |
| ... | ... | @@ -1918,6 +1922,9 @@ fn create( |
| 1918 | 1922 | .dynstr = .UNDEF, |
| 1919 | 1923 | .dynamic = .UNDEF, |
| 1920 | 1924 | .tdata = .UNDEF, |
| 1925 | .init_array = .UNDEF, |
| 1926 | .fini_array = .UNDEF, |
| 1927 | .preinit_array = .UNDEF, |
| 1921 | 1928 | }, |
| 1922 | 1929 | .symtab = .empty, |
| 1923 | 1930 | .globals = .{ |
| ... | ... | @@ -3109,47 +3116,100 @@ fn loadObject( |
| 3109 | 3116 | defer gpa.free(shstrtab); |
| 3110 | 3117 | try elf.nodes.ensureUnusedCapacity(gpa, ehdr.shnum - 1); |
| 3111 | 3118 | try elf.input_sections.ensureUnusedCapacity(gpa, ehdr.shnum - 1); |
| 3112 | | for (sections[1..]) |*section| switch (section.shdr.type) { |
| 3113 | | else => {}, |
| 3114 | | .PROGBITS, .NOBITS => { |
| 3115 | | if (section.shdr.name >= shstrtab.len) continue; |
| 3116 | | const name = std.mem.sliceTo(shstrtab[section.shdr.name..], 0); |
| 3117 | | const shndx: Section.Index = elf.namedSection(name) orelse shndx: { |
| 3118 | | // TODO: actually generate a .bss section. For now, just throw it into `.data`. |
| 3119 | | if (std.mem.eql(u8, name, ".bss") or |
| 3120 | | std.mem.startsWith(u8, name, ".bss.")) break :shndx .data; |
| 3121 | | if (std.mem.eql(u8, name, ".tbss") or |
| 3122 | | std.mem.startsWith(u8, name, ".tbss.")) break :shndx elf.shndx.tdata; |
| 3123 | | break :shndx .UNDEF; |
| 3124 | | }; |
| 3125 | | if (shndx == .UNDEF) continue; |
| 3126 | | const ni = try elf.mf.addLastChildNode(gpa, shndx.get(elf).ni, .{ |
| 3127 | | .size = section.shdr.size, |
| 3128 | | .alignment = .fromByteUnits(std.math.ceilPowerOfTwoAssert( |
| 3129 | | usize, |
| 3130 | | @intCast(@max(section.shdr.addralign, 1)), |
| 3131 | | )), |
| 3132 | | .moved = true, // see assert at end of `flushInputSection` |
| 3133 | | }); |
| 3134 | | elf.nodes.appendAssumeCapacity(.{ |
| 3135 | | .input_section = @enumFromInt(elf.input_sections.items.len), |
| 3136 | | }); |
| 3137 | | section.isi = @enumFromInt(elf.input_sections.items.len); |
| 3138 | | elf.input_sections.addOneAssumeCapacity().* = .{ |
| 3139 | | .input = input_index, |
| 3140 | | .file_location = .{ |
| 3141 | | .offset = fl.offset + section.shdr.offset, |
| 3142 | | .size = if (section.shdr.type == .NOBITS) 0 else section.shdr.size, |
| 3119 | for (sections[1..]) |*section| { |
| 3120 | if (section.shdr.name >= shstrtab.len) continue; |
| 3121 | const name = std.mem.sliceTo(shstrtab[section.shdr.name..], 0); |
| 3122 | const opts: struct { |
| 3123 | shndx: Section.Index, |
| 3124 | has_file_bits: bool, |
| 3125 | node_fixed: bool, |
| 3126 | } = switch (section.shdr.type) { |
| 3127 | else => continue, |
| 3128 | .PROGBITS => .{ |
| 3129 | .shndx = elf.namedSection(name) orelse continue, |
| 3130 | .has_file_bits = true, |
| 3131 | .node_fixed = false, |
| 3132 | }, |
| 3133 | .NOBITS => .{ |
| 3134 | .shndx = shndx: { |
| 3135 | // TODO: actually generate a .bss section. For now, just throw it into `.data`. |
| 3136 | if (std.mem.eql(u8, name, ".bss") or std.mem.startsWith(u8, name, ".bss.")) { |
| 3137 | break :shndx .data; |
| 3138 | } |
| 3139 | if (elf.shndx.tdata != .UNDEF and |
| 3140 | (std.mem.eql(u8, name, ".tbss") or std.mem.startsWith(u8, name, ".tbss."))) |
| 3141 | { |
| 3142 | break :shndx elf.shndx.tdata; |
| 3143 | } |
| 3144 | continue; |
| 3143 | 3145 | }, |
| 3144 | | // The section vaddr is initially 0, because the symbol addresses are |
| 3145 | | // zero-based. This will eventually be updated by `flushMoved`. |
| 3146 | | .vaddr = 0, |
| 3147 | | .node = ni, |
| 3148 | | .first_reloc = .none, |
| 3149 | | }; |
| 3150 | | elf.synth_prog_node.increaseEstimatedTotalItems(1); |
| 3151 | | }, |
| 3152 | | }; |
| 3146 | .has_file_bits = false, |
| 3147 | .node_fixed = false, |
| 3148 | }, |
| 3149 | inline .INIT_ARRAY, .FINI_ARRAY, .PREINIT_ARRAY => |@"type"| .{ |
| 3150 | .shndx = shndx: { |
| 3151 | // TODO: the input section name may include a "priority" value between 1 |
| 3152 | // and 65535 which should affect the order we assemble input sections in |
| 3153 | const init_fini_section_name: []const u8 = switch (@"type") { |
| 3154 | .INIT_ARRAY => "init_array", |
| 3155 | .FINI_ARRAY => "fini_array", |
| 3156 | .PREINIT_ARRAY => "preinit_array", |
| 3157 | else => comptime unreachable, |
| 3158 | }; |
| 3159 | const shndx: *Section.Index = &@field(elf.shndx, init_fini_section_name); |
| 3160 | const need_addralign: u8 = switch (class) { |
| 3161 | .NONE, _ => unreachable, |
| 3162 | .@"32" => 4, |
| 3163 | .@"64" => 8, |
| 3164 | }; |
| 3165 | if (section.shdr.addralign != need_addralign) { |
| 3166 | return diags.failParse(path, "bad addralign on {t} shdr", .{@"type"}); |
| 3167 | } |
| 3168 | if (shndx.* == .UNDEF) { |
| 3169 | try elf.createInitFiniArraySection(shndx, init_fini_section_name, @"type"); |
| 3170 | } |
| 3171 | switch (elf.shdrPtr(shndx.*)) { |
| 3172 | inline else => |shdr| { |
| 3173 | const old_size = elf.targetLoad(&shdr.size); |
| 3174 | elf.targetStore(&shdr.size, @intCast(old_size + section.shdr.size)); |
| 3175 | }, |
| 3176 | } |
| 3177 | try shndx.get(elf).ni.resized(gpa, &elf.mf); |
| 3178 | break :shndx shndx.*; |
| 3179 | }, |
| 3180 | .has_file_bits = true, |
| 3181 | // This node must be fixed to prevent padding from being added between different |
| 3182 | // INIT_ARRAY/FINI_ARRAY/PREINIT_ARRAY input sections. |
| 3183 | .node_fixed = true, |
| 3184 | }, |
| 3185 | }; |
| 3186 | const ni = try elf.mf.addLastChildNode(gpa, opts.shndx.get(elf).ni, .{ |
| 3187 | .size = section.shdr.size, |
| 3188 | .alignment = .fromByteUnits(std.math.ceilPowerOfTwoAssert( |
| 3189 | usize, |
| 3190 | @intCast(@max(section.shdr.addralign, 1)), |
| 3191 | )), |
| 3192 | .moved = true, // see assert at end of `flushInputSection` |
| 3193 | .fixed = opts.node_fixed, |
| 3194 | }); |
| 3195 | elf.nodes.appendAssumeCapacity(.{ |
| 3196 | .input_section = @enumFromInt(elf.input_sections.items.len), |
| 3197 | }); |
| 3198 | section.isi = @enumFromInt(elf.input_sections.items.len); |
| 3199 | elf.input_sections.addOneAssumeCapacity().* = .{ |
| 3200 | .input = input_index, |
| 3201 | .file_location = .{ |
| 3202 | .offset = fl.offset + section.shdr.offset, |
| 3203 | .size = if (opts.has_file_bits) section.shdr.size else 0, |
| 3204 | }, |
| 3205 | // The section vaddr is initially 0, because the symbol addresses are |
| 3206 | // zero-based. This will eventually be updated by `flushMoved`. |
| 3207 | .vaddr = 0, |
| 3208 | .node = ni, |
| 3209 | .first_reloc = .none, |
| 3210 | }; |
| 3211 | elf.synth_prog_node.increaseEstimatedTotalItems(1); |
| 3212 | } |
| 3153 | 3213 | var symmap: std.ArrayList(Symbol.Id) = .empty; |
| 3154 | 3214 | defer symmap.deinit(gpa); |
| 3155 | 3215 | for (sections[1..], 1..) |*symtab, symtab_shndx| switch (symtab.shdr.type) { |
| ... | ... | @@ -3450,6 +3510,57 @@ fn checkInputIdent( |
| 3450 | 3510 | ); |
| 3451 | 3511 | } |
| 3452 | 3512 | |
| 3513 | fn createInitFiniArraySection( |
| 3514 | elf: *Elf, |
| 3515 | shndx: *Section.Index, |
| 3516 | comptime name: []const u8, |
| 3517 | @"type": std.elf.SHT, |
| 3518 | ) !void { |
| 3519 | assert(shndx.* == .UNDEF); |
| 3520 | const addr_align: std.mem.Alignment = switch (elf.identClass()) { |
| 3521 | .NONE, _ => unreachable, |
| 3522 | .@"32" => .@"4", |
| 3523 | .@"64" => .@"8", |
| 3524 | }; |
| 3525 | shndx.* = try elf.addSection(elf.ni.data_rel_ro, .{ |
| 3526 | .name = "." ++ name, |
| 3527 | .type = @"type", |
| 3528 | .flags = .{ .WRITE = true, .ALLOC = true }, |
| 3529 | .node_align = addr_align, |
| 3530 | }); |
| 3531 | try elf.ensureUnusedSymbolCapacity(2, .maybe_global); |
| 3532 | _ = elf.addGlobalSymbolAssumeCapacity(.{ |
| 3533 | .node = shndx.get(elf).ni, |
| 3534 | .name = try .string(elf, "__" ++ name ++ "_start"), |
| 3535 | .value = shndx.vaddr(elf), |
| 3536 | .size = 0, |
| 3537 | .type = .NOTYPE, |
| 3538 | .bind = .strong, |
| 3539 | .visibility = .HIDDEN, |
| 3540 | .shndx = shndx.*, |
| 3541 | }) catch |err| switch (err) { |
| 3542 | error.MultipleDefinitions => return elf.base.comp.link_diags.fail( |
| 3543 | "multiple definitions of '{s}'", |
| 3544 | .{"__" ++ name ++ "_start"}, |
| 3545 | ), |
| 3546 | }; |
| 3547 | _ = elf.addGlobalSymbolAssumeCapacity(.{ |
| 3548 | .node = shndx.get(elf).ni, |
| 3549 | .name = try .string(elf, "__" ++ name ++ "_end"), |
| 3550 | .value = shndx.vaddr(elf), |
| 3551 | .size = 0, |
| 3552 | .type = .NOTYPE, |
| 3553 | .bind = .strong, |
| 3554 | .visibility = .HIDDEN, |
| 3555 | .shndx = shndx.*, |
| 3556 | }) catch |err| switch (err) { |
| 3557 | error.MultipleDefinitions => return elf.base.comp.link_diags.fail( |
| 3558 | "multiple definitions of '{s}'", |
| 3559 | .{"__" ++ name ++ "_end"}, |
| 3560 | ), |
| 3561 | }; |
| 3562 | } |
| 3563 | |
| 3453 | 3564 | pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) !void { |
| 3454 | 3565 | _ = prog_node; |
| 3455 | 3566 | elf.prelinkInner() catch |err| switch (err) { |
| ... | ... | @@ -3489,6 +3600,9 @@ fn prelinkInner(elf: *Elf) !void { |
| 3489 | 3600 | const needed_len = elf.needed.count(); |
| 3490 | 3601 | const dynamic_len = needed_len + @intFromBool(elf.options.soname != null) + |
| 3491 | 3602 | @intFromBool(flags != 0) + @intFromBool(flags_1 != 0) + |
| 3603 | @as(usize, @intFromBool(elf.shndx.init_array != .UNDEF)) * 2 + |
| 3604 | @as(usize, @intFromBool(elf.shndx.fini_array != .UNDEF)) * 2 + |
| 3605 | @as(usize, @intFromBool(elf.shndx.preinit_array != .UNDEF)) * 2 + |
| 3492 | 3606 | @intFromBool(comp.config.output_mode == .Exe) + 12; |
| 3493 | 3607 | const dynamic_size: u32 = @intCast(@sizeOf(ElfN.Addr) * 2 * dynamic_len); |
| 3494 | 3608 | const dynamic_ni = elf.shndx.dynamic.get(elf).ni; |
| ... | ... | @@ -3520,23 +3634,74 @@ fn prelinkInner(elf: *Elf) !void { |
| 3520 | 3634 | dynamic_entries[dynamic_index] = .{ std.elf.DT_DEBUG, 0 }; |
| 3521 | 3635 | dynamic_index += 1; |
| 3522 | 3636 | } |
| 3637 | if (elf.shndx.init_array != .UNDEF) { |
| 3638 | dynamic_entries[dynamic_index..][0..2].* = .{ |
| 3639 | .{ std.elf.DT_INIT_ARRAY, @intCast(elf.shndx.init_array.vaddr(elf)) }, |
| 3640 | .{ std.elf.DT_INIT_ARRAYSZ, elf.targetLoad( |
| 3641 | &@field(elf.shdrPtr(elf.shndx.init_array), @tagName(ct_class)).size, |
| 3642 | ) }, |
| 3643 | }; |
| 3644 | try elf.ensureUnusedRelocCapacity(dynamic_ni, 1); |
| 3645 | elf.addRelocAssumeCapacity( |
| 3646 | dynamic_ni, |
| 3647 | @sizeOf(ElfN.Addr) * (2 * dynamic_index + 1), |
| 3648 | .local(elf.shndx.init_array.get(elf).lsi), |
| 3649 | 0, |
| 3650 | .absAddr(elf), |
| 3651 | ); |
| 3652 | dynamic_index += 2; |
| 3653 | } |
| 3654 | if (elf.shndx.fini_array != .UNDEF) { |
| 3655 | dynamic_entries[dynamic_index..][0..2].* = .{ |
| 3656 | .{ std.elf.DT_FINI_ARRAY, @intCast(elf.shndx.fini_array.vaddr(elf)) }, |
| 3657 | .{ std.elf.DT_FINI_ARRAYSZ, elf.targetLoad( |
| 3658 | &@field(elf.shdrPtr(elf.shndx.fini_array), @tagName(ct_class)).size, |
| 3659 | ) }, |
| 3660 | }; |
| 3661 | try elf.ensureUnusedRelocCapacity(dynamic_ni, 1); |
| 3662 | elf.addRelocAssumeCapacity( |
| 3663 | dynamic_ni, |
| 3664 | @sizeOf(ElfN.Addr) * (2 * dynamic_index + 1), |
| 3665 | .local(elf.shndx.fini_array.get(elf).lsi), |
| 3666 | 0, |
| 3667 | .absAddr(elf), |
| 3668 | ); |
| 3669 | dynamic_index += 2; |
| 3670 | } |
| 3671 | if (elf.shndx.preinit_array != .UNDEF) { |
| 3672 | dynamic_entries[dynamic_index..][0..2].* = .{ |
| 3673 | .{ std.elf.DT_PREINIT_ARRAY, @intCast(elf.shndx.preinit_array.vaddr(elf)) }, |
| 3674 | .{ std.elf.DT_PREINIT_ARRAYSZ, elf.targetLoad( |
| 3675 | &@field(elf.shdrPtr(elf.shndx.preinit_array), @tagName(ct_class)).size, |
| 3676 | ) }, |
| 3677 | }; |
| 3678 | try elf.ensureUnusedRelocCapacity(dynamic_ni, 1); |
| 3679 | elf.addRelocAssumeCapacity( |
| 3680 | dynamic_ni, |
| 3681 | @sizeOf(ElfN.Addr) * (2 * dynamic_index + 1), |
| 3682 | .local(elf.shndx.preinit_array.get(elf).lsi), |
| 3683 | 0, |
| 3684 | .absAddr(elf), |
| 3685 | ); |
| 3686 | dynamic_index += 2; |
| 3687 | } |
| 3523 | 3688 | const rela_dyn_shndx = elf.shndx.got.get(elf).rela_shndx; |
| 3524 | 3689 | const rela_plt_shndx = elf.shndx.got_plt.get(elf).rela_shndx; |
| 3525 | 3690 | dynamic_entries[dynamic_index..][0..12].* = .{ |
| 3526 | | .{ std.elf.DT_RELA, @intCast(elf.computeNodeVAddr(rela_dyn_shndx.get(elf).ni)) }, |
| 3691 | .{ std.elf.DT_RELA, @intCast(rela_dyn_shndx.vaddr(elf)) }, |
| 3527 | 3692 | .{ std.elf.DT_RELASZ, elf.targetLoad( |
| 3528 | 3693 | &@field(elf.shdrPtr(rela_dyn_shndx), @tagName(ct_class)).size, |
| 3529 | 3694 | ) }, |
| 3530 | 3695 | .{ std.elf.DT_RELAENT, @sizeOf(ElfN.Rela) }, |
| 3531 | | .{ std.elf.DT_JMPREL, @intCast(elf.computeNodeVAddr(rela_plt_shndx.get(elf).ni)) }, |
| 3696 | .{ std.elf.DT_JMPREL, @intCast(rela_plt_shndx.vaddr(elf)) }, |
| 3532 | 3697 | .{ std.elf.DT_PLTRELSZ, elf.targetLoad( |
| 3533 | 3698 | &@field(elf.shdrPtr(rela_plt_shndx), @tagName(ct_class)).size, |
| 3534 | 3699 | ) }, |
| 3535 | | .{ std.elf.DT_PLTGOT, @intCast(elf.computeNodeVAddr(elf.shndx.got_plt.get(elf).ni)) }, |
| 3700 | .{ std.elf.DT_PLTGOT, @intCast(elf.shndx.got_plt.vaddr(elf)) }, |
| 3536 | 3701 | .{ std.elf.DT_PLTREL, std.elf.DT_RELA }, |
| 3537 | | .{ std.elf.DT_SYMTAB, @intCast(elf.computeNodeVAddr(elf.shndx.dynsym.get(elf).ni)) }, |
| 3702 | .{ std.elf.DT_SYMTAB, @intCast(elf.shndx.dynsym.vaddr(elf)) }, |
| 3538 | 3703 | .{ std.elf.DT_SYMENT, @sizeOf(ElfN.Sym) }, |
| 3539 | | .{ std.elf.DT_STRTAB, @intCast(elf.computeNodeVAddr(elf.shndx.dynstr.get(elf).ni)) }, |
| 3704 | .{ std.elf.DT_STRTAB, @intCast(elf.shndx.dynstr.vaddr(elf)) }, |
| 3540 | 3705 | .{ std.elf.DT_STRSZ, elf.targetLoad( |
| 3541 | 3706 | &@field(elf.shdrPtr(elf.shndx.dynstr), @tagName(ct_class)).size, |
| 3542 | 3707 | ) }, |
| ... | ... | @@ -4414,6 +4579,22 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void { |
| 4414 | 4579 | } |
| 4415 | 4580 | } |
| 4416 | 4581 | } |
| 4582 | |
| 4583 | // Update global symbols targeting this section |
| 4584 | if (elf.node_global_symbols.get(ni)) |first_name| { |
| 4585 | assert(first_name != .empty); |
| 4586 | const old_addr = elf.targetLoad(&shdr.addr); |
| 4587 | var name = first_name; |
| 4588 | while (name != .empty) { |
| 4589 | const global = elf.globalByName(name).?; |
| 4590 | const old_sym_addr: u64 = switch (elf.symPtr(global.symtab_index)) { |
| 4591 | inline else => |sym| elf.targetLoad(&sym.value), |
| 4592 | }; |
| 4593 | global.flushMoved(elf, old_sym_addr - old_addr + addr); |
| 4594 | name = global.next_in_node; |
| 4595 | } |
| 4596 | } |
| 4597 | |
| 4417 | 4598 | elf.targetStore(&shdr.addr, @intCast(addr)); |
| 4418 | 4599 | shndx.get(elf).lsi.index().flushMoved(elf, addr); |
| 4419 | 4600 | } |
| ... | ... | @@ -4547,6 +4728,63 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void { |
| 4547 | 4728 | .NULL => if (size > 0) elf.targetStore(&shdr.type, .PROGBITS), |
| 4548 | 4729 | .PROGBITS => if (size == 0) elf.targetStore(&shdr.type, .NULL), |
| 4549 | 4730 | .SYMTAB, .DYNAMIC, .REL, .DYNSYM => return, |
| 4731 | .INIT_ARRAY => { |
| 4732 | assert(shndx == elf.shndx.init_array); |
| 4733 | if (elf.shndx.dynamic != .UNDEF) { |
| 4734 | const dynamic_entries: [][2]class.ElfN().Addr = @ptrCast(@alignCast( |
| 4735 | elf.shndx.dynamic.get(elf).ni.slice(&elf.mf), |
| 4736 | )); |
| 4737 | for (dynamic_entries) |*dynamic_entry| |
| 4738 | switch (elf.targetLoad(&dynamic_entry[0])) { |
| 4739 | else => {}, |
| 4740 | std.elf.DT_INIT_ARRAYSZ => dynamic_entry[1] = shdr.size, |
| 4741 | }; |
| 4742 | } |
| 4743 | const end_sym_index = elf.globalByName(elf.string(.strtab, "__init_array_end") catch unreachable).?.symtab_index; |
| 4744 | const end_sym_ptr = @field(elf.symPtr(end_sym_index), @tagName(class)); |
| 4745 | const end_vaddr = shndx.vaddr(elf) + elf.targetLoad(&shdr.size); |
| 4746 | elf.targetStore(&end_sym_ptr.value, @intCast(end_vaddr)); |
| 4747 | end_sym_index.flushMoved(elf, end_vaddr); |
| 4748 | return; |
| 4749 | }, |
| 4750 | .FINI_ARRAY => { |
| 4751 | assert(shndx == elf.shndx.fini_array); |
| 4752 | if (elf.shndx.dynamic != .UNDEF) { |
| 4753 | const dynamic_entries: [][2]class.ElfN().Addr = @ptrCast(@alignCast( |
| 4754 | elf.shndx.dynamic.get(elf).ni.slice(&elf.mf), |
| 4755 | )); |
| 4756 | for (dynamic_entries) |*dynamic_entry| |
| 4757 | switch (elf.targetLoad(&dynamic_entry[0])) { |
| 4758 | else => {}, |
| 4759 | std.elf.DT_FINI_ARRAYSZ => dynamic_entry[1] = shdr.size, |
| 4760 | }; |
| 4761 | } |
| 4762 | const end_sym_index = elf.globalByName(elf.string(.strtab, "__fini_array_end") catch unreachable).?.symtab_index; |
| 4763 | const end_sym_ptr = @field(elf.symPtr(end_sym_index), @tagName(class)); |
| 4764 | const end_vaddr = shndx.vaddr(elf) + elf.targetLoad(&shdr.size); |
| 4765 | elf.targetStore(&end_sym_ptr.value, @intCast(end_vaddr)); |
| 4766 | end_sym_index.flushMoved(elf, end_vaddr); |
| 4767 | return; |
| 4768 | }, |
| 4769 | .PREINIT_ARRAY => { |
| 4770 | assert(shndx == elf.shndx.preinit_array); |
| 4771 | if (elf.shndx.dynamic != .UNDEF) { |
| 4772 | const dynamic_entries: [][2]class.ElfN().Addr = @ptrCast(@alignCast( |
| 4773 | elf.shndx.dynamic.get(elf).ni.slice(&elf.mf), |
| 4774 | )); |
| 4775 | for (dynamic_entries) |*dynamic_entry| |
| 4776 | switch (elf.targetLoad(&dynamic_entry[0])) { |
| 4777 | else => {}, |
| 4778 | std.elf.DT_PREINIT_ARRAYSZ => dynamic_entry[1] = shdr.size, |
| 4779 | }; |
| 4780 | } |
| 4781 | const end_sym_index = elf.globalByName(elf.string(.strtab, "__preinit_array_end") catch unreachable).?.symtab_index; |
| 4782 | const end_sym_ptr = @field(elf.symPtr(end_sym_index), @tagName(class)); |
| 4783 | const end_vaddr = shndx.vaddr(elf) + elf.targetLoad(&shdr.size); |
| 4784 | elf.targetStore(&end_sym_ptr.value, @intCast(end_vaddr)); |
| 4785 | end_sym_index.flushMoved(elf, end_vaddr); |
| 4786 | return; |
| 4787 | }, |
| 4550 | 4788 | .STRTAB => { |
| 4551 | 4789 | if (elf.shndx.dynamic != .UNDEF) { |
| 4552 | 4790 | if (shndx == elf.shndx.dynstr) { |