| ... | @@ -203,6 +203,8 @@ const Node = union(enum) { | ... | @@ -203,6 +203,8 @@ const Node = union(enum) { |
| 203 | archive, | 203 | archive, |
| 204 | /// This includes the archive magic and long file member. | 204 | /// This includes the archive magic and long file member. |
| 205 | archive_header, | 205 | archive_header, |
| | 206 | /// This is a footer of the `.elf` node, and contains the next archive entry's file header. |
| | 207 | archive_elf_footer, |
| 206 | elf, | 208 | elf, |
| 207 | ehdr, | 209 | ehdr, |
| 208 | shdr, | 210 | shdr, |
| ... | @@ -2952,6 +2954,7 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId { | ... | @@ -2952,6 +2954,7 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId { |
| 2952 | const lsi: Symbol.LocalIndex = switch (elf.getNode(Node.fromAtom(atom))) { | 2954 | const lsi: Symbol.LocalIndex = switch (elf.getNode(Node.fromAtom(atom))) { |
| 2953 | .archive, | 2955 | .archive, |
| 2954 | .archive_header, | 2956 | .archive_header, |
| | 2957 | .archive_elf_footer, |
| 2955 | .elf, | 2958 | .elf, |
| 2956 | .ehdr, | 2959 | .ehdr, |
| 2957 | .shdr, | 2960 | .shdr, |
| ... | @@ -3599,8 +3602,8 @@ fn initHeaders( | ... | @@ -3599,8 +3602,8 @@ fn initHeaders( |
| 3599 | }, phnum }; | 3602 | }, phnum }; |
| 3600 | }; | 3603 | }; |
| 3601 | | 3604 | |
| 3602 | const expected_nodes_len = @as(usize, if (is_archive) 2 else 0) + // .archive, .archive_header | 3605 | const expected_nodes_len = @as(usize, if (is_archive) 3 else 0) + // .archive, .archive_header, .archive_elf_footer |
| 3603 | 3 + // `.file`, `.ehdr`, and `.shdr` nodes | 3606 | 3 + // `.elf`, `.ehdr`, and `.shdr` nodes |
| 3604 | (shnum - 1) + // -1 because the SHN_UNDEF shdr does not have a `.section` node | 3607 | (shnum - 1) + // -1 because the SHN_UNDEF shdr does not have a `.section` node |
| 3605 | (phnum -| 1); // -1 because the GNU_STACK phdr does not have a `.segment` node | 3608 | (phnum -| 1); // -1 because the GNU_STACK phdr does not have a `.segment` node |
| 3606 | | 3609 | |
| ... | @@ -3643,6 +3646,12 @@ fn initHeaders( | ... | @@ -3643,6 +3646,12 @@ fn initHeaders( |
| 3643 | .enable_next_moved = true, | 3646 | .enable_next_moved = true, |
| 3644 | }); | 3647 | }); |
| 3645 | elf.nodes.appendAssumeCapacity(.elf); | 3648 | elf.nodes.appendAssumeCapacity(.elf); |
| | 3649 | |
| | 3650 | _ = try elf.ni.elf.addOnlyFooterChild(&elf.mf, gpa, .{ |
| | 3651 | .alignment = .@"2", |
| | 3652 | .size = @sizeOf(std.elf.ar_hdr), |
| | 3653 | }); |
| | 3654 | elf.nodes.appendAssumeCapacity(.archive_elf_footer); |
| 3646 | } else { | 3655 | } else { |
| 3647 | elf.ni.elf = .root; | 3656 | elf.ni.elf = .root; |
| 3648 | elf.nodes.appendAssumeCapacity(.elf); | 3657 | elf.nodes.appendAssumeCapacity(.elf); |
| ... | @@ -3729,6 +3738,14 @@ fn initHeaders( | ... | @@ -3729,6 +3738,14 @@ fn initHeaders( |
| 3729 | } | 3738 | } |
| 3730 | | 3739 | |
| 3731 | elf.phdrs.items[phndx.gnu_stack] = .none; | 3740 | elf.phdrs.items[phndx.gnu_stack] = .none; |
| | 3741 | } else { |
| | 3742 | elf.ni.rodata = elf.ni.elf; |
| | 3743 | elf.ni.text = elf.ni.elf; |
| | 3744 | elf.ni.data = elf.ni.elf; |
| | 3745 | elf.ni.data_rel_ro = elf.ni.elf; |
| | 3746 | if (comp.config.any_non_single_threaded) { |
| | 3747 | elf.ni.tls = .wrap(elf.ni.elf); |
| | 3748 | } |
| 3732 | } | 3749 | } |
| 3733 | | 3750 | |
| 3734 | switch (class) { | 3751 | switch (class) { |
| ... | @@ -4522,8 +4539,6 @@ fn initHeaders( | ... | @@ -4522,8 +4539,6 @@ fn initHeaders( |
| 4522 | break :str try elf.string(.dynstr, slice); | 4539 | break :str try elf.string(.dynstr, slice); |
| 4523 | }, | 4540 | }, |
| 4524 | }; | 4541 | }; |
| 4525 | | | |
| 4526 | try elf.ensureElfNodeSize(); | | |
| 4527 | } | 4542 | } |
| 4528 | | 4543 | |
| 4529 | pub fn startProgress(elf: *Elf, prog_node: std.Progress.Node) void { | 4544 | pub fn startProgress(elf: *Elf, prog_node: std.Progress.Node) void { |
| ... | @@ -4558,6 +4573,7 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index { | ... | @@ -4558,6 +4573,7 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index { |
| 4558 | return switch (elf.getNode(ni)) { | 4573 | return switch (elf.getNode(ni)) { |
| 4559 | .archive, | 4574 | .archive, |
| 4560 | .archive_header, | 4575 | .archive_header, |
| | 4576 | .archive_elf_footer, |
| 4561 | .elf, | 4577 | .elf, |
| 4562 | .ehdr, | 4578 | .ehdr, |
| 4563 | .shdr, | 4579 | .shdr, |
| ... | @@ -4578,6 +4594,7 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { | ... | @@ -4578,6 +4594,7 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 4578 | return switch (elf.getNode(ni)) { | 4594 | return switch (elf.getNode(ni)) { |
| 4579 | .archive, | 4595 | .archive, |
| 4580 | .archive_header, | 4596 | .archive_header, |
| | 4597 | .archive_elf_footer, |
| 4581 | .elf, | 4598 | .elf, |
| 4582 | .ehdr, | 4599 | .ehdr, |
| 4583 | .shdr, | 4600 | .shdr, |
| ... | @@ -4596,7 +4613,7 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { | ... | @@ -4596,7 +4613,7 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 4596 | } | 4613 | } |
| 4597 | fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { | 4614 | fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 4598 | const parent_vaddr = switch (elf.getNode(ni.parent(&elf.mf).unwrap().?)) { | 4615 | const parent_vaddr = switch (elf.getNode(ni.parent(&elf.mf).unwrap().?)) { |
| 4599 | .archive, .archive_header => unreachable, | 4616 | .archive, .archive_header, .archive_elf_footer => unreachable, |
| 4600 | .elf => return 0, | 4617 | .elf => return 0, |
| 4601 | .ehdr, .shdr => unreachable, | 4618 | .ehdr, .shdr => unreachable, |
| 4602 | .segment => |phndx| switch (elf.phdrSlice()) { | 4619 | .segment => |phndx| switch (elf.phdrSlice()) { |
| ... | @@ -4622,6 +4639,7 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { | ... | @@ -4622,6 +4639,7 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 4622 | const symbol_relocs: *SymbolReloc.Index, const got_relocs: ?*GotReloc.Index = switch (elf.getNode(ni)) { | 4639 | const symbol_relocs: *SymbolReloc.Index, const got_relocs: ?*GotReloc.Index = switch (elf.getNode(ni)) { |
| 4623 | .archive, | 4640 | .archive, |
| 4624 | .archive_header, | 4641 | .archive_header, |
| | 4642 | .archive_elf_footer, |
| 4625 | .elf, | 4643 | .elf, |
| 4626 | .ehdr, | 4644 | .ehdr, |
| 4627 | .shdr, | 4645 | .shdr, |
| ... | @@ -6255,8 +6273,6 @@ fn prelinkInner(elf: *Elf) Error!void { | ... | @@ -6255,8 +6273,6 @@ fn prelinkInner(elf: *Elf) Error!void { |
| 6255 | }; | 6273 | }; |
| 6256 | elf.input_pending_index += 1; | 6274 | elf.input_pending_index += 1; |
| 6257 | } | 6275 | } |
| 6258 | | | |
| 6259 | try elf.ensureElfNodeSize(); | | |
| 6260 | } | 6276 | } |
| 6261 | | 6277 | |
| 6262 | fn prepareDynamic(elf: *Elf) Error!void { | 6278 | fn prepareDynamic(elf: *Elf) Error!void { |
| ... | @@ -7056,6 +7072,7 @@ fn addGotRelocAssumeCapacity( | ... | @@ -7056,6 +7072,7 @@ fn addGotRelocAssumeCapacity( |
| 7056 | switch (elf.getNode(node)) { | 7072 | switch (elf.getNode(node)) { |
| 7057 | .archive, | 7073 | .archive, |
| 7058 | .archive_header, | 7074 | .archive_header, |
| | 7075 | .archive_elf_footer, |
| 7059 | .elf, | 7076 | .elf, |
| 7060 | .ehdr, | 7077 | .ehdr, |
| 7061 | .shdr, | 7078 | .shdr, |
| ... | @@ -7485,7 +7502,6 @@ fn flushInner( | ... | @@ -7485,7 +7502,6 @@ fn flushInner( |
| 7485 | | 7502 | |
| 7486 | try elf.prepareDynamic(); | 7503 | try elf.prepareDynamic(); |
| 7487 | | 7504 | |
| 7488 | try elf.ensureElfNodeSize(); | | |
| 7489 | while (try elf.idle(tid)) {} | 7505 | while (try elf.idle(tid)) {} |
| 7490 | | 7506 | |
| 7491 | // We've done the final `idle` loop, so everything is at its final place in the file. We have a | 7507 | // We've done the final `idle` loop, so everything is at its final place in the file. We have a |
| ... | @@ -7738,8 +7754,6 @@ fn genPending(elf: *Elf, pt: Zcu.PerThread) Error!void { | ... | @@ -7738,8 +7754,6 @@ fn genPending(elf: *Elf, pt: Zcu.PerThread) Error!void { |
| 7738 | }; | 7754 | }; |
| 7739 | break; | 7755 | break; |
| 7740 | } | 7756 | } |
| 7741 | | | |
| 7742 | try elf.ensureElfNodeSize(); | | |
| 7743 | } | 7757 | } |
| 7744 | | 7758 | |
| 7745 | fn genUav( | 7759 | fn genUav( |
| ... | @@ -7922,7 +7936,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void | ... | @@ -7922,7 +7936,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 7922 | | 7936 | |
| 7923 | switch (elf.getNode(ni)) { | 7937 | switch (elf.getNode(ni)) { |
| 7924 | .archive, .archive_header => unreachable, | 7938 | .archive, .archive_header => unreachable, |
| 7925 | .elf => {}, | 7939 | .archive_elf_footer, .elf => {}, |
| 7926 | .ehdr, .shdr => elf.flushElfOffset(ni), | 7940 | .ehdr, .shdr => elf.flushElfOffset(ni), |
| 7927 | .segment => |phndx| { | 7941 | .segment => |phndx| { |
| 7928 | elf.flushElfOffset(ni); | 7942 | elf.flushElfOffset(ni); |
| ... | @@ -8216,7 +8230,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo | ... | @@ -8216,7 +8230,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo |
| 8216 | } | 8230 | } |
| 8217 | }, | 8231 | }, |
| 8218 | .archive_header, .elf => {}, | 8232 | .archive_header, .elf => {}, |
| 8219 | .ehdr => unreachable, | 8233 | .ehdr, .archive_elf_footer => unreachable, |
| 8220 | .shdr => {}, | 8234 | .shdr => {}, |
| 8221 | .segment => |phndx| switch (elf.phdrSlice()) { | 8235 | .segment => |phndx| switch (elf.phdrSlice()) { |
| 8222 | inline else => |phdr| { | 8236 | inline else => |phdr| { |
| ... | @@ -8301,6 +8315,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error! | ... | @@ -8301,6 +8315,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error! |
| 8301 | | 8315 | |
| 8302 | switch (elf.getNode(ni)) { | 8316 | switch (elf.getNode(ni)) { |
| 8303 | .archive, | 8317 | .archive, |
| | 8318 | .archive_elf_footer, |
| 8304 | .ehdr, | 8319 | .ehdr, |
| 8305 | .shdr, | 8320 | .shdr, |
| 8306 | .segment, | 8321 | .segment, |
| ... | @@ -8746,8 +8761,6 @@ fn updateExportInner( | ... | @@ -8746,8 +8761,6 @@ fn updateExportInner( |
| 8746 | .uav => |uav| (try elf.uavMapIndex(uav, .none)).symbol(elf), | 8761 | .uav => |uav| (try elf.uavMapIndex(uav, .none)).symbol(elf), |
| 8747 | }; | 8762 | }; |
| 8748 | | 8763 | |
| 8749 | try elf.ensureElfNodeSize(); | | |
| 8750 | | | |
| 8751 | // Initialize the global symbol with the same values that the local one currently has. If the | 8764 | // Initialize the global symbol with the same values that the local one currently has. If the |
| 8752 | // NAV/UAV is updated, then `updateNavInner` or `genUav` will update the global symbol sizes, | 8765 | // NAV/UAV is updated, then `updateNavInner` or `genUav` will update the global symbol sizes, |
| 8753 | // and `flushMoved` will update their values. | 8766 | // and `flushMoved` will update their values. |
| ... | @@ -8970,18 +8983,6 @@ fn ensureSegmentAligned(elf: *Elf, start_phndx: u32, min_align: Alignment) Error | ... | @@ -8970,18 +8983,6 @@ fn ensureSegmentAligned(elf: *Elf, start_phndx: u32, min_align: Alignment) Error |
| 8970 | } | 8983 | } |
| 8971 | } | 8984 | } |
| 8972 | | 8985 | |
| 8973 | /// Must be called deterministically after any call to `MappedFile.Node.Index.resize` | | |
| 8974 | /// (of `elf.ni.elf` or one of its children) before any possible calls to `idle`. | | |
| 8975 | fn ensureElfNodeSize(elf: *Elf) MappedFile.Error!void { | | |
| 8976 | if (elf.ni.elf == .root) return; | | |
| 8977 | var child_it = elf.ni.elf.reverseChildren(&elf.mf); | | |
| 8978 | const last_end = if (child_it.next()) |last_ni| last_end: { | | |
| 8979 | const last_offset, const last_size = last_ni.location(&elf.mf).resolve(&elf.mf); | | |
| 8980 | break :last_end last_offset + last_size; | | |
| 8981 | } else 0; | | |
| 8982 | try elf.ni.elf.ensureMinimumSize(&elf.mf, elf.base.comp.gpa, last_end + @sizeOf(std.elf.ar_hdr)); | | |
| 8983 | } | | |
| 8984 | | | |
| 8985 | /// If `sym` has a PLT entry, returns the address of that entry (specifically, the address which a | 8986 | /// If `sym` has a PLT entry, returns the address of that entry (specifically, the address which a |
| 8986 | /// branch to the PLT should target). If `sym` does not have a PLT entry, returns `null`. | 8987 | /// branch to the PLT should target). If `sym` does not have a PLT entry, returns `null`. |
| 8987 | fn pltEntryTargetAddr(elf: *Elf, sym: Symbol.Id) ?u64 { | 8988 | fn pltEntryTargetAddr(elf: *Elf, sym: Symbol.Id) ?u64 { |