| ... | @@ -34,6 +34,10 @@ shndx: struct { | ... | @@ -34,6 +34,10 @@ shndx: struct { |
| 34 | dynstr: Section.Index, | 34 | dynstr: Section.Index, |
| 35 | dynamic: Section.Index, | 35 | dynamic: Section.Index, |
| 36 | tdata: Section.Index, | 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 | symtab: std.ArrayList(Symbol), | 42 | symtab: std.ArrayList(Symbol), |
| 39 | globals: struct { | 43 | globals: struct { |
| ... | @@ -1113,7 +1117,7 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void | ... | @@ -1113,7 +1117,7 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void |
| 1113 | const Symbol = struct { | 1117 | const Symbol = struct { |
| 1114 | /// The node which this symbol's value is defined relative to. Possible values are: | 1118 | /// The node which this symbol's value is defined relative to. Possible values are: |
| 1115 | /// * `.none` for a SHN_ABS or SHN_UNDEF symbol | 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 | /// * An input section (the symbol's value is some vaddr in that input section) | 1121 | /// * An input section (the symbol's value is some vaddr in that input section) |
| 1118 | /// * A NAV, UAV, or lazy code/data (the symbol's value is exactly the vaddr of that node) | 1122 | /// * A NAV, UAV, or lazy code/data (the symbol's value is exactly the vaddr of that node) |
| 1119 | node: MappedFile.Node.Index, | 1123 | node: MappedFile.Node.Index, |
| ... | @@ -1918,6 +1922,9 @@ fn create( | ... | @@ -1918,6 +1922,9 @@ fn create( |
| 1918 | .dynstr = .UNDEF, | 1922 | .dynstr = .UNDEF, |
| 1919 | .dynamic = .UNDEF, | 1923 | .dynamic = .UNDEF, |
| 1920 | .tdata = .UNDEF, | 1924 | .tdata = .UNDEF, |
| | 1925 | .init_array = .UNDEF, |
| | 1926 | .fini_array = .UNDEF, |
| | 1927 | .preinit_array = .UNDEF, |
| 1921 | }, | 1928 | }, |
| 1922 | .symtab = .empty, | 1929 | .symtab = .empty, |
| 1923 | .globals = .{ | 1930 | .globals = .{ |
| ... | @@ -3109,47 +3116,100 @@ fn loadObject( | ... | @@ -3109,47 +3116,100 @@ fn loadObject( |
| 3109 | defer gpa.free(shstrtab); | 3116 | defer gpa.free(shstrtab); |
| 3110 | try elf.nodes.ensureUnusedCapacity(gpa, ehdr.shnum - 1); | 3117 | try elf.nodes.ensureUnusedCapacity(gpa, ehdr.shnum - 1); |
| 3111 | try elf.input_sections.ensureUnusedCapacity(gpa, ehdr.shnum - 1); | 3118 | try elf.input_sections.ensureUnusedCapacity(gpa, ehdr.shnum - 1); |
| 3112 | for (sections[1..]) |*section| switch (section.shdr.type) { | 3119 | for (sections[1..]) |*section| { |
| 3113 | else => {}, | 3120 | if (section.shdr.name >= shstrtab.len) continue; |
| 3114 | .PROGBITS, .NOBITS => { | 3121 | const name = std.mem.sliceTo(shstrtab[section.shdr.name..], 0); |
| 3115 | if (section.shdr.name >= shstrtab.len) continue; | 3122 | const opts: struct { |
| 3116 | const name = std.mem.sliceTo(shstrtab[section.shdr.name..], 0); | 3123 | shndx: Section.Index, |
| 3117 | const shndx: Section.Index = elf.namedSection(name) orelse shndx: { | 3124 | has_file_bits: bool, |
| 3118 | // TODO: actually generate a .bss section. For now, just throw it into `.data`. | 3125 | node_fixed: bool, |
| 3119 | if (std.mem.eql(u8, name, ".bss") or | 3126 | } = switch (section.shdr.type) { |
| 3120 | std.mem.startsWith(u8, name, ".bss.")) break :shndx .data; | 3127 | else => continue, |
| 3121 | if (std.mem.eql(u8, name, ".tbss") or | 3128 | .PROGBITS => .{ |
| 3122 | std.mem.startsWith(u8, name, ".tbss.")) break :shndx elf.shndx.tdata; | 3129 | .shndx = elf.namedSection(name) orelse continue, |
| 3123 | break :shndx .UNDEF; | 3130 | .has_file_bits = true, |
| 3124 | }; | 3131 | .node_fixed = false, |
| 3125 | if (shndx == .UNDEF) continue; | 3132 | }, |
| 3126 | const ni = try elf.mf.addLastChildNode(gpa, shndx.get(elf).ni, .{ | 3133 | .NOBITS => .{ |
| 3127 | .size = section.shdr.size, | 3134 | .shndx = shndx: { |
| 3128 | .alignment = .fromByteUnits(std.math.ceilPowerOfTwoAssert( | 3135 | // TODO: actually generate a .bss section. For now, just throw it into `.data`. |
| 3129 | usize, | 3136 | if (std.mem.eql(u8, name, ".bss") or std.mem.startsWith(u8, name, ".bss.")) { |
| 3130 | @intCast(@max(section.shdr.addralign, 1)), | 3137 | break :shndx .data; |
| 3131 | )), | 3138 | } |
| 3132 | .moved = true, // see assert at end of `flushInputSection` | 3139 | if (elf.shndx.tdata != .UNDEF and |
| 3133 | }); | 3140 | (std.mem.eql(u8, name, ".tbss") or std.mem.startsWith(u8, name, ".tbss."))) |
| 3134 | elf.nodes.appendAssumeCapacity(.{ | 3141 | { |
| 3135 | .input_section = @enumFromInt(elf.input_sections.items.len), | 3142 | break :shndx elf.shndx.tdata; |
| 3136 | }); | 3143 | } |
| 3137 | section.isi = @enumFromInt(elf.input_sections.items.len); | 3144 | continue; |
| 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, | | |
| 3143 | }, | 3145 | }, |
| 3144 | // The section vaddr is initially 0, because the symbol addresses are | 3146 | .has_file_bits = false, |
| 3145 | // zero-based. This will eventually be updated by `flushMoved`. | 3147 | .node_fixed = false, |
| 3146 | .vaddr = 0, | 3148 | }, |
| 3147 | .node = ni, | 3149 | inline .INIT_ARRAY, .FINI_ARRAY, .PREINIT_ARRAY => |@"type"| .{ |
| 3148 | .first_reloc = .none, | 3150 | .shndx = shndx: { |
| 3149 | }; | 3151 | // TODO: the input section name may include a "priority" value between 1 |
| 3150 | elf.synth_prog_node.increaseEstimatedTotalItems(1); | 3152 | // and 65535 which should affect the order we assemble input sections in |
| 3151 | }, | 3153 | const init_fini_section_name: []const u8 = switch (@"type") { |
| 3152 | }; | 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 | var symmap: std.ArrayList(Symbol.Id) = .empty; | 3213 | var symmap: std.ArrayList(Symbol.Id) = .empty; |
| 3154 | defer symmap.deinit(gpa); | 3214 | defer symmap.deinit(gpa); |
| 3155 | for (sections[1..], 1..) |*symtab, symtab_shndx| switch (symtab.shdr.type) { | 3215 | for (sections[1..], 1..) |*symtab, symtab_shndx| switch (symtab.shdr.type) { |
| ... | @@ -3450,6 +3510,57 @@ fn checkInputIdent( | ... | @@ -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 | pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) !void { | 3564 | pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) !void { |
| 3454 | _ = prog_node; | 3565 | _ = prog_node; |
| 3455 | elf.prelinkInner() catch |err| switch (err) { | 3566 | elf.prelinkInner() catch |err| switch (err) { |
| ... | @@ -3489,6 +3600,9 @@ fn prelinkInner(elf: *Elf) !void { | ... | @@ -3489,6 +3600,9 @@ fn prelinkInner(elf: *Elf) !void { |
| 3489 | const needed_len = elf.needed.count(); | 3600 | const needed_len = elf.needed.count(); |
| 3490 | const dynamic_len = needed_len + @intFromBool(elf.options.soname != null) + | 3601 | const dynamic_len = needed_len + @intFromBool(elf.options.soname != null) + |
| 3491 | @intFromBool(flags != 0) + @intFromBool(flags_1 != 0) + | 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 | @intFromBool(comp.config.output_mode == .Exe) + 12; | 3606 | @intFromBool(comp.config.output_mode == .Exe) + 12; |
| 3493 | const dynamic_size: u32 = @intCast(@sizeOf(ElfN.Addr) * 2 * dynamic_len); | 3607 | const dynamic_size: u32 = @intCast(@sizeOf(ElfN.Addr) * 2 * dynamic_len); |
| 3494 | const dynamic_ni = elf.shndx.dynamic.get(elf).ni; | 3608 | const dynamic_ni = elf.shndx.dynamic.get(elf).ni; |
| ... | @@ -3520,23 +3634,74 @@ fn prelinkInner(elf: *Elf) !void { | ... | @@ -3520,23 +3634,74 @@ fn prelinkInner(elf: *Elf) !void { |
| 3520 | dynamic_entries[dynamic_index] = .{ std.elf.DT_DEBUG, 0 }; | 3634 | dynamic_entries[dynamic_index] = .{ std.elf.DT_DEBUG, 0 }; |
| 3521 | dynamic_index += 1; | 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 | const rela_dyn_shndx = elf.shndx.got.get(elf).rela_shndx; | 3688 | const rela_dyn_shndx = elf.shndx.got.get(elf).rela_shndx; |
| 3524 | const rela_plt_shndx = elf.shndx.got_plt.get(elf).rela_shndx; | 3689 | const rela_plt_shndx = elf.shndx.got_plt.get(elf).rela_shndx; |
| 3525 | dynamic_entries[dynamic_index..][0..12].* = .{ | 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 | .{ std.elf.DT_RELASZ, elf.targetLoad( | 3692 | .{ std.elf.DT_RELASZ, elf.targetLoad( |
| 3528 | &@field(elf.shdrPtr(rela_dyn_shndx), @tagName(ct_class)).size, | 3693 | &@field(elf.shdrPtr(rela_dyn_shndx), @tagName(ct_class)).size, |
| 3529 | ) }, | 3694 | ) }, |
| 3530 | .{ std.elf.DT_RELAENT, @sizeOf(ElfN.Rela) }, | 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 | .{ std.elf.DT_PLTRELSZ, elf.targetLoad( | 3697 | .{ std.elf.DT_PLTRELSZ, elf.targetLoad( |
| 3533 | &@field(elf.shdrPtr(rela_plt_shndx), @tagName(ct_class)).size, | 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 | .{ std.elf.DT_PLTREL, std.elf.DT_RELA }, | 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 | .{ std.elf.DT_SYMENT, @sizeOf(ElfN.Sym) }, | 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 | .{ std.elf.DT_STRSZ, elf.targetLoad( | 3705 | .{ std.elf.DT_STRSZ, elf.targetLoad( |
| 3541 | &@field(elf.shdrPtr(elf.shndx.dynstr), @tagName(ct_class)).size, | 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,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 | elf.targetStore(&shdr.addr, @intCast(addr)); | 4598 | elf.targetStore(&shdr.addr, @intCast(addr)); |
| 4418 | shndx.get(elf).lsi.index().flushMoved(elf, addr); | 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,6 +4728,63 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void { |
| 4547 | .NULL => if (size > 0) elf.targetStore(&shdr.type, .PROGBITS), | 4728 | .NULL => if (size > 0) elf.targetStore(&shdr.type, .PROGBITS), |
| 4548 | .PROGBITS => if (size == 0) elf.targetStore(&shdr.type, .NULL), | 4729 | .PROGBITS => if (size == 0) elf.targetStore(&shdr.type, .NULL), |
| 4549 | .SYMTAB, .DYNAMIC, .REL, .DYNSYM => return, | 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 | .STRTAB => { | 4788 | .STRTAB => { |
| 4551 | if (elf.shndx.dynamic != .UNDEF) { | 4789 | if (elf.shndx.dynamic != .UNDEF) { |
| 4552 | if (shndx == elf.shndx.dynstr) { | 4790 | if (shndx == elf.shndx.dynstr) { |