| ... | ... | @@ -203,6 +203,8 @@ const Node = union(enum) { |
| 203 | 203 | archive, |
| 204 | 204 | /// This includes the archive magic and long file member. |
| 205 | 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 | 208 | elf, |
| 207 | 209 | ehdr, |
| 208 | 210 | shdr, |
| ... | ... | @@ -2952,6 +2954,7 @@ pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId { |
| 2952 | 2954 | const lsi: Symbol.LocalIndex = switch (elf.getNode(Node.fromAtom(atom))) { |
| 2953 | 2955 | .archive, |
| 2954 | 2956 | .archive_header, |
| 2957 | .archive_elf_footer, |
| 2955 | 2958 | .elf, |
| 2956 | 2959 | .ehdr, |
| 2957 | 2960 | .shdr, |
| ... | ... | @@ -3599,8 +3602,8 @@ fn initHeaders( |
| 3599 | 3602 | }, phnum }; |
| 3600 | 3603 | }; |
| 3601 | 3604 | |
| 3602 | | const expected_nodes_len = @as(usize, if (is_archive) 2 else 0) + // .archive, .archive_header |
| 3603 | | 3 + // `.file`, `.ehdr`, and `.shdr` nodes |
| 3605 | const expected_nodes_len = @as(usize, if (is_archive) 3 else 0) + // .archive, .archive_header, .archive_elf_footer |
| 3606 | 3 + // `.elf`, `.ehdr`, and `.shdr` nodes |
| 3604 | 3607 | (shnum - 1) + // -1 because the SHN_UNDEF shdr does not have a `.section` node |
| 3605 | 3608 | (phnum -| 1); // -1 because the GNU_STACK phdr does not have a `.segment` node |
| 3606 | 3609 | |
| ... | ... | @@ -3643,6 +3646,12 @@ fn initHeaders( |
| 3643 | 3646 | .enable_next_moved = true, |
| 3644 | 3647 | }); |
| 3645 | 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 | 3655 | } else { |
| 3647 | 3656 | elf.ni.elf = .root; |
| 3648 | 3657 | elf.nodes.appendAssumeCapacity(.elf); |
| ... | ... | @@ -3729,6 +3738,14 @@ fn initHeaders( |
| 3729 | 3738 | } |
| 3730 | 3739 | |
| 3731 | 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 | 3751 | switch (class) { |
| ... | ... | @@ -4522,8 +4539,6 @@ fn initHeaders( |
| 4522 | 4539 | break :str try elf.string(.dynstr, slice); |
| 4523 | 4540 | }, |
| 4524 | 4541 | }; |
| 4525 | | |
| 4526 | | try elf.ensureElfNodeSize(); |
| 4527 | 4542 | } |
| 4528 | 4543 | |
| 4529 | 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 | 4573 | return switch (elf.getNode(ni)) { |
| 4559 | 4574 | .archive, |
| 4560 | 4575 | .archive_header, |
| 4576 | .archive_elf_footer, |
| 4561 | 4577 | .elf, |
| 4562 | 4578 | .ehdr, |
| 4563 | 4579 | .shdr, |
| ... | ... | @@ -4578,6 +4594,7 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 4578 | 4594 | return switch (elf.getNode(ni)) { |
| 4579 | 4595 | .archive, |
| 4580 | 4596 | .archive_header, |
| 4597 | .archive_elf_footer, |
| 4581 | 4598 | .elf, |
| 4582 | 4599 | .ehdr, |
| 4583 | 4600 | .shdr, |
| ... | ... | @@ -4596,7 +4613,7 @@ fn getNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 4596 | 4613 | } |
| 4597 | 4614 | fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 4598 | 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 | 4617 | .elf => return 0, |
| 4601 | 4618 | .ehdr, .shdr => unreachable, |
| 4602 | 4619 | .segment => |phndx| switch (elf.phdrSlice()) { |
| ... | ... | @@ -4622,6 +4639,7 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 4622 | 4639 | const symbol_relocs: *SymbolReloc.Index, const got_relocs: ?*GotReloc.Index = switch (elf.getNode(ni)) { |
| 4623 | 4640 | .archive, |
| 4624 | 4641 | .archive_header, |
| 4642 | .archive_elf_footer, |
| 4625 | 4643 | .elf, |
| 4626 | 4644 | .ehdr, |
| 4627 | 4645 | .shdr, |
| ... | ... | @@ -6255,8 +6273,6 @@ fn prelinkInner(elf: *Elf) Error!void { |
| 6255 | 6273 | }; |
| 6256 | 6274 | elf.input_pending_index += 1; |
| 6257 | 6275 | } |
| 6258 | | |
| 6259 | | try elf.ensureElfNodeSize(); |
| 6260 | 6276 | } |
| 6261 | 6277 | |
| 6262 | 6278 | fn prepareDynamic(elf: *Elf) Error!void { |
| ... | ... | @@ -7056,6 +7072,7 @@ fn addGotRelocAssumeCapacity( |
| 7056 | 7072 | switch (elf.getNode(node)) { |
| 7057 | 7073 | .archive, |
| 7058 | 7074 | .archive_header, |
| 7075 | .archive_elf_footer, |
| 7059 | 7076 | .elf, |
| 7060 | 7077 | .ehdr, |
| 7061 | 7078 | .shdr, |
| ... | ... | @@ -7485,7 +7502,6 @@ fn flushInner( |
| 7485 | 7502 | |
| 7486 | 7503 | try elf.prepareDynamic(); |
| 7487 | 7504 | |
| 7488 | | try elf.ensureElfNodeSize(); |
| 7489 | 7505 | while (try elf.idle(tid)) {} |
| 7490 | 7506 | |
| 7491 | 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 | 7754 | }; |
| 7739 | 7755 | break; |
| 7740 | 7756 | } |
| 7741 | | |
| 7742 | | try elf.ensureElfNodeSize(); |
| 7743 | 7757 | } |
| 7744 | 7758 | |
| 7745 | 7759 | fn genUav( |
| ... | ... | @@ -7922,7 +7936,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 7922 | 7936 | |
| 7923 | 7937 | switch (elf.getNode(ni)) { |
| 7924 | 7938 | .archive, .archive_header => unreachable, |
| 7925 | | .elf => {}, |
| 7939 | .archive_elf_footer, .elf => {}, |
| 7926 | 7940 | .ehdr, .shdr => elf.flushElfOffset(ni), |
| 7927 | 7941 | .segment => |phndx| { |
| 7928 | 7942 | elf.flushElfOffset(ni); |
| ... | ... | @@ -8216,7 +8230,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo |
| 8216 | 8230 | } |
| 8217 | 8231 | }, |
| 8218 | 8232 | .archive_header, .elf => {}, |
| 8219 | | .ehdr => unreachable, |
| 8233 | .ehdr, .archive_elf_footer => unreachable, |
| 8220 | 8234 | .shdr => {}, |
| 8221 | 8235 | .segment => |phndx| switch (elf.phdrSlice()) { |
| 8222 | 8236 | inline else => |phdr| { |
| ... | ... | @@ -8301,6 +8315,7 @@ fn flushNextMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error! |
| 8301 | 8315 | |
| 8302 | 8316 | switch (elf.getNode(ni)) { |
| 8303 | 8317 | .archive, |
| 8318 | .archive_elf_footer, |
| 8304 | 8319 | .ehdr, |
| 8305 | 8320 | .shdr, |
| 8306 | 8321 | .segment, |
| ... | ... | @@ -8746,8 +8761,6 @@ fn updateExportInner( |
| 8746 | 8761 | .uav => |uav| (try elf.uavMapIndex(uav, .none)).symbol(elf), |
| 8747 | 8762 | }; |
| 8748 | 8763 | |
| 8749 | | try elf.ensureElfNodeSize(); |
| 8750 | | |
| 8751 | 8764 | // Initialize the global symbol with the same values that the local one currently has. If the |
| 8752 | 8765 | // NAV/UAV is updated, then `updateNavInner` or `genUav` will update the global symbol sizes, |
| 8753 | 8766 | // and `flushMoved` will update their values. |
| ... | ... | @@ -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 | 8986 | /// If `sym` has a PLT entry, returns the address of that entry (specifically, the address which a |
| 8986 | 8987 | /// branch to the PLT should target). If `sym` does not have a PLT entry, returns `null`. |
| 8987 | 8988 | fn pltEntryTargetAddr(elf: *Elf, sym: Symbol.Id) ?u64 { |