| author | |
| committer | |
| log | d328140858ab7f0f3eeb5d53b50bae32ab331686 |
| tree | 63881cfb19195a7629ae5ae891837bb96eebbffc |
| parent | 4c2b34e8abd1fc2091eeb10798658bd9bb3910f5 |
8 files changed, 30 insertions(+), 438 deletions(-)
src/arch/x86_64/Emit.zig+12-33| ... | ... | @@ -110,21 +110,11 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 110 | 110 | }); |
| 111 | 111 | }, |
| 112 | 112 | .linker_reloc => |data| if (emit.lower.bin_file.cast(.elf)) |elf_file| { |
| 113 | const is_obj_or_static_lib = switch (emit.lower.output_mode) { | |
| 114 | .Exe => false, | |
| 115 | .Obj => true, | |
| 116 | .Lib => emit.lower.link_mode == .static, | |
| 117 | }; | |
| 118 | 113 | const zo = elf_file.zigObjectPtr().?; |
| 119 | 114 | const atom = zo.symbol(data.atom_index).atom(elf_file).?; |
| 120 | 115 | const sym = zo.symbol(data.sym_index); |
| 121 | if (sym.flags.needs_zig_got and !is_obj_or_static_lib) { | |
| 122 | _ = try sym.getOrCreateZigGotEntry(data.sym_index, elf_file); | |
| 123 | } | |
| 124 | 116 | if (emit.lower.pic) { |
| 125 | const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj_or_static_lib) | |
| 126 | link.File.Elf.R_ZIG_GOTPCREL | |
| 127 | else if (sym.flags.needs_got) | |
| 117 | const r_type: u32 = if (sym.flags.needs_got) | |
| 128 | 118 | @intFromEnum(std.elf.R_X86_64.GOTPCREL) |
| 129 | 119 | else |
| 130 | 120 | @intFromEnum(std.elf.R_X86_64.PC32); |
| ... | ... | @@ -134,28 +124,17 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 134 | 124 | .r_addend = -4, |
| 135 | 125 | }); |
| 136 | 126 | } else { |
| 137 | if (lowered_inst.encoding.mnemonic == .call and sym.flags.needs_zig_got and is_obj_or_static_lib) { | |
| 138 | const r_type = @intFromEnum(std.elf.R_X86_64.PC32); | |
| 139 | try atom.addReloc(elf_file, .{ | |
| 140 | .r_offset = end_offset - 4, | |
| 141 | .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type, | |
| 142 | .r_addend = -4, | |
| 143 | }); | |
| 144 | } else { | |
| 145 | const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj_or_static_lib) | |
| 146 | link.File.Elf.R_ZIG_GOT32 | |
| 147 | else if (sym.flags.needs_got) | |
| 148 | @intFromEnum(std.elf.R_X86_64.GOT32) | |
| 149 | else if (sym.flags.is_tls) | |
| 150 | @intFromEnum(std.elf.R_X86_64.TPOFF32) | |
| 151 | else | |
| 152 | @intFromEnum(std.elf.R_X86_64.@"32"); | |
| 153 | try atom.addReloc(elf_file, .{ | |
| 154 | .r_offset = end_offset - 4, | |
| 155 | .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type, | |
| 156 | .r_addend = 0, | |
| 157 | }); | |
| 158 | } | |
| 127 | const r_type: u32 = if (sym.flags.needs_got) | |
| 128 | @intFromEnum(std.elf.R_X86_64.GOT32) | |
| 129 | else if (sym.flags.is_tls) | |
| 130 | @intFromEnum(std.elf.R_X86_64.TPOFF32) | |
| 131 | else | |
| 132 | @intFromEnum(std.elf.R_X86_64.@"32"); | |
| 133 | try atom.addReloc(elf_file, .{ | |
| 134 | .r_offset = end_offset - 4, | |
| 135 | .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type, | |
| 136 | .r_addend = 0, | |
| 137 | }); | |
| 159 | 138 | } |
| 160 | 139 | } else if (emit.lower.bin_file.cast(.macho)) |macho_file| { |
| 161 | 140 | const is_obj_or_static_lib = switch (emit.lower.output_mode) { |
src/arch/x86_64/Lower.zig+6-16| ... | ... | @@ -398,30 +398,20 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) |
| 398 | 398 | |
| 399 | 399 | _ = lower.reloc(.{ .linker_reloc = sym }); |
| 400 | 400 | break :op if (lower.pic) switch (mnemonic) { |
| 401 | .lea => { | |
| 402 | break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; | |
| 403 | }, | |
| 404 | .mov => { | |
| 405 | if (is_obj_or_static_lib and elf_sym.flags.needs_zig_got) emit_mnemonic = .lea; | |
| 406 | break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }; | |
| 407 | }, | |
| 401 | .lea => break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }, | |
| 402 | .mov => break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) }, | |
| 408 | 403 | else => unreachable, |
| 409 | 404 | } else switch (mnemonic) { |
| 410 | .call => break :op if (is_obj_or_static_lib and elf_sym.flags.needs_zig_got) .{ | |
| 411 | .imm = Immediate.s(0), | |
| 412 | } else .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ | |
| 405 | .call => break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ | |
| 413 | 406 | .base = .{ .reg = .ds }, |
| 414 | 407 | }) }, |
| 415 | 408 | .lea => { |
| 416 | 409 | emit_mnemonic = .mov; |
| 417 | 410 | break :op .{ .imm = Immediate.s(0) }; |
| 418 | 411 | }, |
| 419 | .mov => { | |
| 420 | if (is_obj_or_static_lib and elf_sym.flags.needs_zig_got) emit_mnemonic = .lea; | |
| 421 | break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ | |
| 422 | .base = .{ .reg = .ds }, | |
| 423 | }) }; | |
| 424 | }, | |
| 412 | .mov => break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{ | |
| 413 | .base = .{ .reg = .ds }, | |
| 414 | }) }, | |
| 425 | 415 | else => unreachable, |
| 426 | 416 | }; |
| 427 | 417 | } else if (lower.bin_file.cast(.macho)) |macho_file| { |
src/link/Elf.zig+3-75| ... | ... | @@ -64,9 +64,6 @@ phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{}, |
| 64 | 64 | /// Tracked loadable segments during incremental linking. |
| 65 | 65 | /// The index into the program headers of a PT_LOAD program header with Read and Execute flags |
| 66 | 66 | phdr_zig_load_re_index: ?u16 = null, |
| 67 | /// The index into the program headers of the global offset table. | |
| 68 | /// It needs PT_LOAD and Read flags. | |
| 69 | phdr_zig_got_index: ?u16 = null, | |
| 70 | 67 | /// The index into the program headers of a PT_LOAD program header with Read flag |
| 71 | 68 | phdr_zig_load_ro_index: ?u16 = null, |
| 72 | 69 | /// The index into the program headers of a PT_LOAD program header with Write flag |
| ... | ... | @@ -130,8 +127,6 @@ plt_got: PltGotSection = .{}, |
| 130 | 127 | copy_rel: CopyRelSection = .{}, |
| 131 | 128 | /// .rela.plt section |
| 132 | 129 | rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{}, |
| 133 | /// .got.zig section | |
| 134 | zig_got: ZigGotSection = .{}, | |
| 135 | 130 | /// SHT_GROUP sections |
| 136 | 131 | /// Applies only to a relocatable. |
| 137 | 132 | comdat_group_sections: std.ArrayListUnmanaged(ComdatGroupSection) = .{}, |
| ... | ... | @@ -142,7 +137,6 @@ zig_text_section_index: ?u32 = null, |
| 142 | 137 | zig_data_rel_ro_section_index: ?u32 = null, |
| 143 | 138 | zig_data_section_index: ?u32 = null, |
| 144 | 139 | zig_bss_section_index: ?u32 = null, |
| 145 | zig_got_section_index: ?u32 = null, | |
| 146 | 140 | |
| 147 | 141 | debug_info_section_index: ?u32 = null, |
| 148 | 142 | debug_abbrev_section_index: ?u32 = null, |
| ... | ... | @@ -474,7 +468,6 @@ pub fn deinit(self: *Elf) void { |
| 474 | 468 | self.copy_rel.deinit(gpa); |
| 475 | 469 | self.rela_dyn.deinit(gpa); |
| 476 | 470 | self.rela_plt.deinit(gpa); |
| 477 | self.zig_got.deinit(gpa); | |
| 478 | 471 | self.comdat_group_sections.deinit(gpa); |
| 479 | 472 | } |
| 480 | 473 | |
| ... | ... | @@ -618,21 +611,6 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { |
| 618 | 611 | }); |
| 619 | 612 | } |
| 620 | 613 | |
| 621 | if (self.phdr_zig_got_index == null) { | |
| 622 | const alignment = self.page_size; | |
| 623 | const filesz = @as(u64, ptr_size) * options.symbol_count_hint; | |
| 624 | const off = self.findFreeSpace(filesz, alignment); | |
| 625 | self.phdr_zig_got_index = try self.addPhdr(.{ | |
| 626 | .type = elf.PT_LOAD, | |
| 627 | .offset = off, | |
| 628 | .filesz = filesz, | |
| 629 | .addr = if (ptr_bit_width >= 32) 0x4000000 else 0x4000, | |
| 630 | .memsz = filesz, | |
| 631 | .@"align" = alignment, | |
| 632 | .flags = elf.PF_R | elf.PF_W, | |
| 633 | }); | |
| 634 | } | |
| 635 | ||
| 636 | 614 | if (self.phdr_zig_load_ro_index == null) { |
| 637 | 615 | const alignment = self.page_size; |
| 638 | 616 | const filesz: u64 = 1024; |
| ... | ... | @@ -701,27 +679,6 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { |
| 701 | 679 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_text_section_index.?, .{}); |
| 702 | 680 | } |
| 703 | 681 | |
| 704 | if (self.zig_got_section_index == null and !self.base.isRelocatable()) { | |
| 705 | self.zig_got_section_index = try self.addSection(.{ | |
| 706 | .name = try self.insertShString(".got.zig"), | |
| 707 | .type = elf.SHT_PROGBITS, | |
| 708 | .addralign = ptr_size, | |
| 709 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | |
| 710 | .offset = std.math.maxInt(u64), | |
| 711 | }); | |
| 712 | const shdr = &self.shdrs.items[self.zig_got_section_index.?]; | |
| 713 | const phndx = self.phdr_zig_got_index.?; | |
| 714 | const phdr = self.phdrs.items[phndx]; | |
| 715 | shdr.sh_addr = phdr.p_vaddr; | |
| 716 | shdr.sh_offset = phdr.p_offset; | |
| 717 | shdr.sh_size = phdr.p_memsz; | |
| 718 | try self.phdr_to_shdr_table.putNoClobber( | |
| 719 | gpa, | |
| 720 | self.zig_got_section_index.?, | |
| 721 | self.phdr_zig_got_index.?, | |
| 722 | ); | |
| 723 | } | |
| 724 | ||
| 725 | 682 | if (self.zig_data_rel_ro_section_index == null) { |
| 726 | 683 | self.zig_data_rel_ro_section_index = try self.addSection(.{ |
| 727 | 684 | .name = try self.insertShString(".data.rel.ro.zig"), |
| ... | ... | @@ -3156,8 +3113,8 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3156 | 3113 | }); |
| 3157 | 3114 | |
| 3158 | 3115 | const needs_rela_dyn = blk: { |
| 3159 | if (self.got.flags.needs_rela or self.got.flags.needs_tlsld or | |
| 3160 | self.zig_got.flags.needs_rela or self.copy_rel.symbols.items.len > 0) break :blk true; | |
| 3116 | if (self.got.flags.needs_rela or self.got.flags.needs_tlsld or self.copy_rel.symbols.items.len > 0) | |
| 3117 | break :blk true; | |
| 3161 | 3118 | if (self.zigObjectPtr()) |zig_object| { |
| 3162 | 3119 | if (zig_object.num_dynrelocs > 0) break :blk true; |
| 3163 | 3120 | } |
| ... | ... | @@ -3562,7 +3519,6 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void { |
| 3562 | 3519 | |
| 3563 | 3520 | for (&[_]*?u16{ |
| 3564 | 3521 | &self.phdr_zig_load_re_index, |
| 3565 | &self.phdr_zig_got_index, | |
| 3566 | 3522 | &self.phdr_zig_load_ro_index, |
| 3567 | 3523 | &self.phdr_zig_load_zerofill_index, |
| 3568 | 3524 | &self.phdr_table_index, |
| ... | ... | @@ -3694,7 +3650,6 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) !void { |
| 3694 | 3650 | &self.versym_section_index, |
| 3695 | 3651 | &self.verneed_section_index, |
| 3696 | 3652 | &self.zig_text_section_index, |
| 3697 | &self.zig_got_section_index, | |
| 3698 | 3653 | &self.zig_data_rel_ro_section_index, |
| 3699 | 3654 | &self.zig_data_section_index, |
| 3700 | 3655 | &self.zig_bss_section_index, |
| ... | ... | @@ -3893,7 +3848,7 @@ fn updateSectionSizes(self: *Elf) !void { |
| 3893 | 3848 | } |
| 3894 | 3849 | |
| 3895 | 3850 | if (self.rela_dyn_section_index) |shndx| { |
| 3896 | var num = self.got.numRela(self) + self.copy_rel.numRela() + self.zig_got.numRela(); | |
| 3851 | var num = self.got.numRela(self) + self.copy_rel.numRela(); | |
| 3897 | 3852 | if (self.zigObjectPtr()) |zig_object| { |
| 3898 | 3853 | num += zig_object.num_dynrelocs; |
| 3899 | 3854 | } |
| ... | ... | @@ -4431,15 +4386,6 @@ pub fn updateSymtabSize(self: *Elf) !void { |
| 4431 | 4386 | strsize += ctx.strsize; |
| 4432 | 4387 | } |
| 4433 | 4388 | |
| 4434 | if (self.zigObjectPtr()) |_| { | |
| 4435 | if (self.zig_got_section_index) |_| { | |
| 4436 | self.zig_got.output_symtab_ctx.ilocal = nlocals + 1; | |
| 4437 | self.zig_got.updateSymtabSize(self); | |
| 4438 | nlocals += self.zig_got.output_symtab_ctx.nlocals; | |
| 4439 | strsize += self.zig_got.output_symtab_ctx.strsize; | |
| 4440 | } | |
| 4441 | } | |
| 4442 | ||
| 4443 | 4389 | if (self.got_section_index) |_| { |
| 4444 | 4390 | self.got.output_symtab_ctx.ilocal = nlocals + 1; |
| 4445 | 4391 | self.got.updateSymtabSize(self); |
| ... | ... | @@ -4576,9 +4522,6 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4576 | 4522 | const shdr = self.shdrs.items[shndx]; |
| 4577 | 4523 | try self.got.addRela(self); |
| 4578 | 4524 | try self.copy_rel.addRela(self); |
| 4579 | if (self.zigObjectPtr()) |_| { | |
| 4580 | try self.zig_got.addRela(self); | |
| 4581 | } | |
| 4582 | 4525 | self.sortRelaDyn(); |
| 4583 | 4526 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_dyn.items), shdr.sh_offset); |
| 4584 | 4527 | } |
| ... | ... | @@ -4674,10 +4617,6 @@ pub fn writeSymtab(self: *Elf) !void { |
| 4674 | 4617 | obj.asFile().writeSymtab(self); |
| 4675 | 4618 | } |
| 4676 | 4619 | |
| 4677 | if (self.zig_got_section_index) |_| { | |
| 4678 | self.zig_got.writeSymtab(self); | |
| 4679 | } | |
| 4680 | ||
| 4681 | 4620 | if (self.got_section_index) |_| { |
| 4682 | 4621 | self.got.writeSymtab(self); |
| 4683 | 4622 | } |
| ... | ... | @@ -5085,7 +5024,6 @@ pub fn isZigSection(self: Elf, shndx: u32) bool { |
| 5085 | 5024 | self.zig_data_rel_ro_section_index, |
| 5086 | 5025 | self.zig_data_section_index, |
| 5087 | 5026 | self.zig_bss_section_index, |
| 5088 | self.zig_got_section_index, | |
| 5089 | 5027 | }) |maybe_index| { |
| 5090 | 5028 | if (maybe_index) |index| { |
| 5091 | 5029 | if (index == shndx) return true; |
| ... | ... | @@ -5704,7 +5642,6 @@ fn fmtDumpState( |
| 5704 | 5642 | } |
| 5705 | 5643 | } |
| 5706 | 5644 | |
| 5707 | try writer.print("{}\n", .{self.zig_got.fmt(self)}); | |
| 5708 | 5645 | try writer.print("{}\n", .{self.got.fmt(self)}); |
| 5709 | 5646 | try writer.print("{}\n", .{self.plt.fmt(self)}); |
| 5710 | 5647 | |
| ... | ... | @@ -5995,20 +5932,12 @@ const RelaSection = struct { |
| 5995 | 5932 | }; |
| 5996 | 5933 | const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection); |
| 5997 | 5934 | |
| 5998 | pub const R_ZIG_GOT32: u32 = 0xff00; | |
| 5999 | pub const R_ZIG_GOTPCREL: u32 = 0xff01; | |
| 6000 | pub const R_ZIG_GOT_HI20: u32 = 0xff02; | |
| 6001 | pub const R_ZIG_GOT_LO12: u32 = 0xff03; | |
| 6002 | 5935 | pub const R_GOT_HI20_STATIC: u32 = 0xff04; |
| 6003 | 5936 | pub const R_GOT_LO12_I_STATIC: u32 = 0xff05; |
| 6004 | 5937 | |
| 6005 | 5938 | // Comptime asserts that no Zig relocs overlap with another ISA's reloc number |
| 6006 | 5939 | comptime { |
| 6007 | 5940 | const zig_relocs = .{ |
| 6008 | R_ZIG_GOT32, | |
| 6009 | R_ZIG_GOT_HI20, | |
| 6010 | R_ZIG_GOT_LO12, | |
| 6011 | R_ZIG_GOTPCREL, | |
| 6012 | 5941 | R_GOT_HI20_STATIC, |
| 6013 | 5942 | R_GOT_LO12_I_STATIC, |
| 6014 | 5943 | }; |
| ... | ... | @@ -6099,6 +6028,5 @@ const StringTable = @import("StringTable.zig"); |
| 6099 | 6028 | const Thunk = thunks.Thunk; |
| 6100 | 6029 | const Value = @import("../Value.zig"); |
| 6101 | 6030 | const VerneedSection = synthetic_sections.VerneedSection; |
| 6102 | const ZigGotSection = synthetic_sections.ZigGotSection; | |
| 6103 | 6031 | const ZigObject = @import("Elf/ZigObject.zig"); |
| 6104 | 6032 | const riscv = @import("riscv.zig"); |
src/link/Elf/Atom.zig+8-41| ... | ... | @@ -750,8 +750,8 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi |
| 750 | 750 | const S = target.address(.{}, elf_file); |
| 751 | 751 | // Address of the global offset table. |
| 752 | 752 | const GOT = elf_file.gotAddress(); |
| 753 | // Address of the .zig.got table entry if any. | |
| 754 | const ZIG_GOT = target.zigGotAddress(elf_file); | |
| 753 | // Address of the offset table entry if any. | |
| 754 | const ZIG_GOT = target.zigOffsetTableAddress(elf_file); | |
| 755 | 755 | // Relative offset to the start of the global offset table. |
| 756 | 756 | const G = target.gotAddress(elf_file) - GOT; |
| 757 | 757 | // // Address of the thread pointer. |
| ... | ... | @@ -759,14 +759,13 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi |
| 759 | 759 | // Address of the dynamic thread pointer. |
| 760 | 760 | const DTP = elf_file.dtpAddress(); |
| 761 | 761 | |
| 762 | relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ZG({x}) ZG2({x}) ({s})", .{ | |
| 762 | relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ZG({x}) ({s})", .{ | |
| 763 | 763 | relocation.fmtRelocType(rel.r_type(), cpu_arch), |
| 764 | 764 | r_offset, |
| 765 | 765 | P, |
| 766 | 766 | S + A, |
| 767 | 767 | G + GOT + A, |
| 768 | 768 | ZIG_GOT + A, |
| 769 | target.zigOffsetTableAddress(elf_file) + A, | |
| 770 | 769 | target.name(elf_file), |
| 771 | 770 | }); |
| 772 | 771 | |
| ... | ... | @@ -1181,16 +1180,7 @@ const x86_64 = struct { |
| 1181 | 1180 | .TLSDESC_CALL, |
| 1182 | 1181 | => {}, |
| 1183 | 1182 | |
| 1184 | else => |x| switch (@intFromEnum(x)) { | |
| 1185 | // Zig custom relocations | |
| 1186 | Elf.R_ZIG_GOT32, | |
| 1187 | Elf.R_ZIG_GOTPCREL, | |
| 1188 | => { | |
| 1189 | assert(symbol.flags.has_zig_got); | |
| 1190 | }, | |
| 1191 | ||
| 1192 | else => try atom.reportUnhandledRelocError(rel, elf_file), | |
| 1193 | }, | |
| 1183 | else => try atom.reportUnhandledRelocError(rel, elf_file), | |
| 1194 | 1184 | } |
| 1195 | 1185 | } |
| 1196 | 1186 | |
| ... | ... | @@ -1228,7 +1218,7 @@ const x86_64 = struct { |
| 1228 | 1218 | .PLT32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little), |
| 1229 | 1219 | |
| 1230 | 1220 | .PC32 => { |
| 1231 | const S_ = if (target.flags.zig_offset_table) target.zigOffsetTableAddress(elf_file) else S; | |
| 1221 | const S_ = if (target.flags.zig_offset_table) ZIG_GOT else S; | |
| 1232 | 1222 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); |
| 1233 | 1223 | }, |
| 1234 | 1224 | |
| ... | ... | @@ -1255,7 +1245,7 @@ const x86_64 = struct { |
| 1255 | 1245 | }, |
| 1256 | 1246 | |
| 1257 | 1247 | .@"32" => { |
| 1258 | const S_ = if (target.flags.zig_offset_table) target.zigOffsetTableAddress(elf_file) else S; | |
| 1248 | const S_ = if (target.flags.zig_offset_table) ZIG_GOT else S; | |
| 1259 | 1249 | try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S_ + A)))), .little); |
| 1260 | 1250 | }, |
| 1261 | 1251 | .@"32S" => try cwriter.writeInt(i32, @as(i32, @truncate(S + A)), .little), |
| ... | ... | @@ -1336,13 +1326,7 @@ const x86_64 = struct { |
| 1336 | 1326 | |
| 1337 | 1327 | .GOT32 => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A)), .little), |
| 1338 | 1328 | |
| 1339 | else => |x| switch (@intFromEnum(x)) { | |
| 1340 | // Zig custom relocations | |
| 1341 | Elf.R_ZIG_GOT32 => try cwriter.writeInt(u32, @as(u32, @intCast(ZIG_GOT + A)), .little), | |
| 1342 | Elf.R_ZIG_GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(ZIG_GOT + A - P)), .little), | |
| 1343 | ||
| 1344 | else => try atom.reportUnhandledRelocError(rel, elf_file), | |
| 1345 | }, | |
| 1329 | else => try atom.reportUnhandledRelocError(rel, elf_file), | |
| 1346 | 1330 | } |
| 1347 | 1331 | } |
| 1348 | 1332 | |
| ... | ... | @@ -2006,12 +1990,6 @@ const riscv = struct { |
| 2006 | 1990 | => {}, |
| 2007 | 1991 | |
| 2008 | 1992 | else => |x| switch (@intFromEnum(x)) { |
| 2009 | Elf.R_ZIG_GOT_HI20, | |
| 2010 | Elf.R_ZIG_GOT_LO12, | |
| 2011 | => { | |
| 2012 | assert(symbol.flags.has_zig_got); | |
| 2013 | }, | |
| 2014 | ||
| 2015 | 1993 | Elf.R_GOT_HI20_STATIC, |
| 2016 | 1994 | Elf.R_GOT_LO12_I_STATIC, |
| 2017 | 1995 | => symbol.flags.needs_got = true, |
| ... | ... | @@ -2038,6 +2016,7 @@ const riscv = struct { |
| 2038 | 2016 | const P, const A, const S, const GOT, const G, const TP, const DTP, const ZIG_GOT = args; |
| 2039 | 2017 | _ = TP; |
| 2040 | 2018 | _ = DTP; |
| 2019 | _ = ZIG_GOT; | |
| 2041 | 2020 | |
| 2042 | 2021 | switch (r_type) { |
| 2043 | 2022 | .NONE => unreachable, |
| ... | ... | @@ -2156,18 +2135,6 @@ const riscv = struct { |
| 2156 | 2135 | |
| 2157 | 2136 | else => |x| switch (@intFromEnum(x)) { |
| 2158 | 2137 | // Zig custom relocations |
| 2159 | Elf.R_ZIG_GOT_HI20 => { | |
| 2160 | assert(target.flags.has_zig_got); | |
| 2161 | const disp: u32 = @bitCast(math.cast(i32, ZIG_GOT + A) orelse return error.Overflow); | |
| 2162 | riscv_util.writeInstU(code[r_offset..][0..4], disp); | |
| 2163 | }, | |
| 2164 | ||
| 2165 | Elf.R_ZIG_GOT_LO12 => { | |
| 2166 | assert(target.flags.has_zig_got); | |
| 2167 | const value: u32 = @bitCast(math.cast(i32, ZIG_GOT + A) orelse return error.Overflow); | |
| 2168 | riscv_util.writeInstI(code[r_offset..][0..4], value); | |
| 2169 | }, | |
| 2170 | ||
| 2171 | 2138 | Elf.R_GOT_HI20_STATIC => { |
| 2172 | 2139 | assert(target.flags.has_got); |
| 2173 | 2140 | const disp: u32 = @bitCast(math.cast(i32, G + GOT + A) orelse return error.Overflow); |
src/link/Elf/Symbol.zig-25| ... | ... | @@ -217,25 +217,6 @@ pub fn tlsDescAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 217 | 217 | return entry.address(elf_file); |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | const GetOrCreateZigGotEntryResult = struct { | |
| 221 | found_existing: bool, | |
| 222 | index: ZigGotSection.Index, | |
| 223 | }; | |
| 224 | ||
| 225 | pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, elf_file: *Elf) !GetOrCreateZigGotEntryResult { | |
| 226 | assert(!elf_file.base.isRelocatable()); | |
| 227 | assert(symbol.flags.needs_zig_got); | |
| 228 | if (symbol.flags.has_zig_got) return .{ .found_existing = true, .index = symbol.extra(elf_file).zig_got }; | |
| 229 | const index = try elf_file.zig_got.addSymbol(symbol_index, elf_file); | |
| 230 | return .{ .found_existing = false, .index = index }; | |
| 231 | } | |
| 232 | ||
| 233 | pub fn zigGotAddress(symbol: Symbol, elf_file: *Elf) i64 { | |
| 234 | if (!symbol.flags.has_zig_got) return 0; | |
| 235 | const extras = symbol.extra(elf_file); | |
| 236 | return elf_file.zig_got.entryAddress(extras.zig_got, elf_file); | |
| 237 | } | |
| 238 | ||
| 239 | 220 | pub fn zigOffsetTableAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 240 | 221 | if (!symbol.flags.zig_offset_table) return 0; |
| 241 | 222 | const zo = elf_file.zigObjectPtr().?; |
| ... | ... | @@ -267,7 +248,6 @@ const AddExtraOpts = struct { |
| 267 | 248 | tlsgd: ?u32 = null, |
| 268 | 249 | gottp: ?u32 = null, |
| 269 | 250 | tlsdesc: ?u32 = null, |
| 270 | zig_got: ?u32 = null, | |
| 271 | 251 | zig_offset_table: ?u32 = null, |
| 272 | 252 | }; |
| 273 | 253 | |
| ... | ... | @@ -465,10 +445,6 @@ pub const Flags = packed struct { |
| 465 | 445 | needs_tlsdesc: bool = false, |
| 466 | 446 | has_tlsdesc: bool = false, |
| 467 | 447 | |
| 468 | /// Whether the symbol contains .zig.got indirection. | |
| 469 | needs_zig_got: bool = false, | |
| 470 | has_zig_got: bool = false, | |
| 471 | ||
| 472 | 448 | /// Whether the symbol is a TLS variable. |
| 473 | 449 | /// TODO this is really not needed if only we operated on esyms between |
| 474 | 450 | /// codegen and ZigObject. |
| ... | ... | @@ -491,7 +467,6 @@ pub const Extra = struct { |
| 491 | 467 | tlsgd: u32 = 0, |
| 492 | 468 | gottp: u32 = 0, |
| 493 | 469 | tlsdesc: u32 = 0, |
| 494 | zig_got: u32 = 0, | |
| 495 | 470 | merge_section: u32 = 0, |
| 496 | 471 | zig_offset_table: u32 = 0, |
| 497 | 472 | }; |
src/link/Elf/ZigObject.zig+1-35| ... | ... | @@ -756,15 +756,7 @@ pub fn getOrCreateMetadataForLazySymbol( |
| 756 | 756 | .const_data => .{ &gop.value_ptr.rodata_symbol_index, &gop.value_ptr.rodata_state }, |
| 757 | 757 | }; |
| 758 | 758 | switch (state_ptr.*) { |
| 759 | .unused => { | |
| 760 | const gpa = elf_file.base.comp.gpa; | |
| 761 | const symbol_index = try self.newSymbolWithAtom(gpa, 0); | |
| 762 | const sym = self.symbol(symbol_index); | |
| 763 | if (lazy_sym.kind != .code) { | |
| 764 | sym.flags.needs_zig_got = true; | |
| 765 | } | |
| 766 | symbol_index_ptr.* = symbol_index; | |
| 767 | }, | |
| 759 | .unused => symbol_index_ptr.* = try self.newSymbolWithAtom(pt.zcu.gpa, 0), | |
| 768 | 760 | .pending_flush => return symbol_index_ptr.*, |
| 769 | 761 | .flushed => {}, |
| 770 | 762 | } |
| ... | ... | @@ -818,9 +810,6 @@ pub fn getOrCreateMetadataForNav( |
| 818 | 810 | sym.flags.is_tls = true; |
| 819 | 811 | } |
| 820 | 812 | } |
| 821 | if (!sym.flags.is_tls and nav_val.typeOf(zcu).zigTypeTag(zcu) != .Fn) { | |
| 822 | sym.flags.needs_zig_got = true; | |
| 823 | } | |
| 824 | 813 | gop.value_ptr.* = .{ .symbol_index = symbol_index }; |
| 825 | 814 | } |
| 826 | 815 | return gop.value_ptr.symbol_index; |
| ... | ... | @@ -921,14 +910,6 @@ fn updateNavCode( |
| 921 | 910 | sym.value = 0; |
| 922 | 911 | esym.st_value = 0; |
| 923 | 912 | |
| 924 | if (stt_bits != elf.STT_FUNC) { | |
| 925 | if (!elf_file.base.isRelocatable()) { | |
| 926 | log.debug(" (writing new offset table entry)", .{}); | |
| 927 | assert(sym.flags.has_zig_got); | |
| 928 | const extra = sym.extra(elf_file); | |
| 929 | try elf_file.zig_got.writeOne(elf_file, extra.zig_got); | |
| 930 | } | |
| 931 | } | |
| 932 | 913 | if (stt_bits == elf.STT_FUNC) { |
| 933 | 914 | const extra = sym.extra(elf_file); |
| 934 | 915 | const offset_table = self.offsetTablePtr().?; |
| ... | ... | @@ -944,13 +925,6 @@ fn updateNavCode( |
| 944 | 925 | |
| 945 | 926 | sym.value = 0; |
| 946 | 927 | esym.st_value = 0; |
| 947 | if (stt_bits != elf.STT_FUNC) { | |
| 948 | sym.flags.needs_zig_got = true; | |
| 949 | if (!elf_file.base.isRelocatable()) { | |
| 950 | const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file); | |
| 951 | try elf_file.zig_got.writeOne(elf_file, gop.index); | |
| 952 | } | |
| 953 | } | |
| 954 | 928 | } |
| 955 | 929 | |
| 956 | 930 | if (elf_file.base.child_pid) |pid| { |
| ... | ... | @@ -1278,16 +1252,8 @@ fn updateLazySymbol( |
| 1278 | 1252 | errdefer self.freeNavMetadata(elf_file, symbol_index); |
| 1279 | 1253 | |
| 1280 | 1254 | local_sym.value = 0; |
| 1281 | if (sym.kind != .code) { | |
| 1282 | local_sym.flags.needs_zig_got = true; | |
| 1283 | } | |
| 1284 | 1255 | local_esym.st_value = 0; |
| 1285 | 1256 | |
| 1286 | if (!elf_file.base.isRelocatable()) { | |
| 1287 | const gop = try local_sym.getOrCreateZigGotEntry(symbol_index, elf_file); | |
| 1288 | try elf_file.zig_got.writeOne(elf_file, gop.index); | |
| 1289 | } | |
| 1290 | ||
| 1291 | 1257 | const shdr = elf_file.shdrs.items[output_section_index]; |
| 1292 | 1258 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); |
| 1293 | 1259 | try elf_file.base.file.?.pwriteAll(code, file_offset); |
src/link/Elf/relocation.zig-4| ... | ... | @@ -113,10 +113,6 @@ fn formatRelocType( |
| 113 | 113 | _ = options; |
| 114 | 114 | const r_type = ctx.r_type; |
| 115 | 115 | switch (r_type) { |
| 116 | Elf.R_ZIG_GOT32 => try writer.writeAll("R_ZIG_GOT32"), | |
| 117 | Elf.R_ZIG_GOTPCREL => try writer.writeAll("R_ZIG_GOTPCREL"), | |
| 118 | Elf.R_ZIG_GOT_HI20 => try writer.writeAll("R_ZIG_GOT_HI20"), | |
| 119 | Elf.R_ZIG_GOT_LO12 => try writer.writeAll("R_ZIG_GOT_LO12"), | |
| 120 | 116 | Elf.R_GOT_HI20_STATIC => try writer.writeAll("R_GOT_HI20_STATIC"), |
| 121 | 117 | Elf.R_GOT_LO12_I_STATIC => try writer.writeAll("R_GOT_LO12_I_STATIC"), |
| 122 | 118 | else => switch (ctx.cpu_arch) { |
src/link/Elf/synthetic_sections.zig-209| ... | ... | @@ -223,215 +223,6 @@ pub const DynamicSection = struct { |
| 223 | 223 | } |
| 224 | 224 | }; |
| 225 | 225 | |
| 226 | pub const ZigGotSection = struct { | |
| 227 | entries: std.ArrayListUnmanaged(Symbol.Index) = .{}, | |
| 228 | output_symtab_ctx: Elf.SymtabCtx = .{}, | |
| 229 | flags: Flags = .{}, | |
| 230 | ||
| 231 | const Flags = packed struct { | |
| 232 | needs_rela: bool = false, | |
| 233 | dirty: bool = false, | |
| 234 | }; | |
| 235 | ||
| 236 | pub const Index = u32; | |
| 237 | ||
| 238 | pub fn deinit(zig_got: *ZigGotSection, allocator: Allocator) void { | |
| 239 | zig_got.entries.deinit(allocator); | |
| 240 | } | |
| 241 | ||
| 242 | fn allocateEntry(zig_got: *ZigGotSection, allocator: Allocator) !Index { | |
| 243 | try zig_got.entries.ensureUnusedCapacity(allocator, 1); | |
| 244 | // TODO add free list | |
| 245 | const index = @as(Index, @intCast(zig_got.entries.items.len)); | |
| 246 | _ = zig_got.entries.addOneAssumeCapacity(); | |
| 247 | zig_got.flags.dirty = true; | |
| 248 | return index; | |
| 249 | } | |
| 250 | ||
| 251 | pub fn addSymbol(zig_got: *ZigGotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index { | |
| 252 | const comp = elf_file.base.comp; | |
| 253 | const gpa = comp.gpa; | |
| 254 | const zo = elf_file.zigObjectPtr().?; | |
| 255 | const index = try zig_got.allocateEntry(gpa); | |
| 256 | const entry = &zig_got.entries.items[index]; | |
| 257 | entry.* = sym_index; | |
| 258 | const symbol = zo.symbol(sym_index); | |
| 259 | symbol.flags.has_zig_got = true; | |
| 260 | if (elf_file.isEffectivelyDynLib() or (elf_file.base.isExe() and comp.config.pie)) { | |
| 261 | zig_got.flags.needs_rela = true; | |
| 262 | } | |
| 263 | symbol.addExtra(.{ .zig_got = index }, elf_file); | |
| 264 | return index; | |
| 265 | } | |
| 266 | ||
| 267 | pub fn entryOffset(zig_got: ZigGotSection, index: Index, elf_file: *Elf) u64 { | |
| 268 | _ = zig_got; | |
| 269 | const entry_size = elf_file.archPtrWidthBytes(); | |
| 270 | const shdr = elf_file.shdrs.items[elf_file.zig_got_section_index.?]; | |
| 271 | return shdr.sh_offset + @as(u64, entry_size) * index; | |
| 272 | } | |
| 273 | ||
| 274 | pub fn entryAddress(zig_got: ZigGotSection, index: Index, elf_file: *Elf) i64 { | |
| 275 | _ = zig_got; | |
| 276 | const entry_size = elf_file.archPtrWidthBytes(); | |
| 277 | const shdr = elf_file.shdrs.items[elf_file.zig_got_section_index.?]; | |
| 278 | return @as(i64, @intCast(shdr.sh_addr)) + entry_size * index; | |
| 279 | } | |
| 280 | ||
| 281 | pub fn size(zig_got: ZigGotSection, elf_file: *Elf) usize { | |
| 282 | return elf_file.archPtrWidthBytes() * zig_got.entries.items.len; | |
| 283 | } | |
| 284 | ||
| 285 | pub fn writeOne(zig_got: *ZigGotSection, elf_file: *Elf, index: Index) !void { | |
| 286 | const zo = elf_file.zigObjectPtr().?; | |
| 287 | if (zig_got.flags.dirty) { | |
| 288 | const needed_size = zig_got.size(elf_file); | |
| 289 | try elf_file.growAllocSection(elf_file.zig_got_section_index.?, needed_size); | |
| 290 | zig_got.flags.dirty = false; | |
| 291 | } | |
| 292 | const entry_size: u16 = elf_file.archPtrWidthBytes(); | |
| 293 | const target = elf_file.getTarget(); | |
| 294 | const endian = target.cpu.arch.endian(); | |
| 295 | const off = zig_got.entryOffset(index, elf_file); | |
| 296 | const vaddr: u64 = @intCast(zig_got.entryAddress(index, elf_file)); | |
| 297 | const entry = zig_got.entries.items[index]; | |
| 298 | const value = zo.symbol(entry).address(.{}, elf_file); | |
| 299 | switch (entry_size) { | |
| 300 | 2 => { | |
| 301 | var buf: [2]u8 = undefined; | |
| 302 | std.mem.writeInt(u16, &buf, @intCast(value), endian); | |
| 303 | try elf_file.base.file.?.pwriteAll(&buf, off); | |
| 304 | }, | |
| 305 | 4 => { | |
| 306 | var buf: [4]u8 = undefined; | |
| 307 | std.mem.writeInt(u32, &buf, @intCast(value), endian); | |
| 308 | try elf_file.base.file.?.pwriteAll(&buf, off); | |
| 309 | }, | |
| 310 | 8 => { | |
| 311 | var buf: [8]u8 = undefined; | |
| 312 | std.mem.writeInt(u64, &buf, @intCast(value), endian); | |
| 313 | try elf_file.base.file.?.pwriteAll(&buf, off); | |
| 314 | ||
| 315 | if (elf_file.base.child_pid) |pid| { | |
| 316 | switch (builtin.os.tag) { | |
| 317 | .linux => { | |
| 318 | var local_vec: [1]std.posix.iovec_const = .{.{ | |
| 319 | .base = &buf, | |
| 320 | .len = buf.len, | |
| 321 | }}; | |
| 322 | var remote_vec: [1]std.posix.iovec_const = .{.{ | |
| 323 | .base = @as([*]u8, @ptrFromInt(@as(usize, @intCast(vaddr)))), | |
| 324 | .len = buf.len, | |
| 325 | }}; | |
| 326 | const rc = std.os.linux.process_vm_writev(pid, &local_vec, &remote_vec, 0); | |
| 327 | switch (std.os.linux.E.init(rc)) { | |
| 328 | .SUCCESS => assert(rc == buf.len), | |
| 329 | else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}), | |
| 330 | } | |
| 331 | }, | |
| 332 | else => return error.HotSwapUnavailableOnHostOperatingSystem, | |
| 333 | } | |
| 334 | } | |
| 335 | }, | |
| 336 | else => unreachable, | |
| 337 | } | |
| 338 | } | |
| 339 | ||
| 340 | pub fn writeAll(zig_got: ZigGotSection, elf_file: *Elf, writer: anytype) !void { | |
| 341 | const zo = elf_file.zigObjectPtr().?; | |
| 342 | for (zig_got.entries.items) |entry| { | |
| 343 | const symbol = zo.symbol(entry); | |
| 344 | const value = symbol.address(.{ .plt = false }, elf_file); | |
| 345 | try writeInt(value, elf_file, writer); | |
| 346 | } | |
| 347 | } | |
| 348 | ||
| 349 | pub fn numRela(zig_got: ZigGotSection) usize { | |
| 350 | return zig_got.entries.items.len; | |
| 351 | } | |
| 352 | ||
| 353 | pub fn addRela(zig_got: ZigGotSection, elf_file: *Elf) !void { | |
| 354 | const comp = elf_file.base.comp; | |
| 355 | const gpa = comp.gpa; | |
| 356 | const cpu_arch = elf_file.getTarget().cpu.arch; | |
| 357 | const zo = elf_file.zigObjectPtr().?; | |
| 358 | try elf_file.rela_dyn.ensureUnusedCapacity(gpa, zig_got.numRela()); | |
| 359 | for (zig_got.entries.items) |entry| { | |
| 360 | const symbol = zo.symbol(entry); | |
| 361 | const offset = symbol.zigGotAddress(elf_file); | |
| 362 | elf_file.addRelaDynAssumeCapacity(.{ | |
| 363 | .offset = @intCast(offset), | |
| 364 | .type = relocation.encode(.rel, cpu_arch), | |
| 365 | .addend = symbol.address(.{ .plt = false }, elf_file), | |
| 366 | }); | |
| 367 | } | |
| 368 | } | |
| 369 | ||
| 370 | pub fn updateSymtabSize(zig_got: *ZigGotSection, elf_file: *Elf) void { | |
| 371 | const zo = elf_file.zigObjectPtr().?; | |
| 372 | zig_got.output_symtab_ctx.nlocals = @as(u32, @intCast(zig_got.entries.items.len)); | |
| 373 | for (zig_got.entries.items) |entry| { | |
| 374 | const name = zo.symbol(entry).name(elf_file); | |
| 375 | zig_got.output_symtab_ctx.strsize += @as(u32, @intCast(name.len + "$ziggot".len)) + 1; | |
| 376 | } | |
| 377 | } | |
| 378 | ||
| 379 | pub fn writeSymtab(zig_got: ZigGotSection, elf_file: *Elf) void { | |
| 380 | const zo = elf_file.zigObjectPtr().?; | |
| 381 | for (zig_got.entries.items, zig_got.output_symtab_ctx.ilocal.., 0..) |entry, ilocal, index| { | |
| 382 | const symbol = zo.symbol(entry); | |
| 383 | const symbol_name = symbol.name(elf_file); | |
| 384 | const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); | |
| 385 | elf_file.strtab.appendSliceAssumeCapacity(symbol_name); | |
| 386 | elf_file.strtab.appendSliceAssumeCapacity("$ziggot"); | |
| 387 | elf_file.strtab.appendAssumeCapacity(0); | |
| 388 | const st_value = zig_got.entryAddress(@intCast(index), elf_file); | |
| 389 | const st_size = elf_file.archPtrWidthBytes(); | |
| 390 | elf_file.symtab.items[ilocal] = .{ | |
| 391 | .st_name = st_name, | |
| 392 | .st_info = elf.STT_OBJECT, | |
| 393 | .st_other = 0, | |
| 394 | .st_shndx = @intCast(elf_file.zig_got_section_index.?), | |
| 395 | .st_value = @intCast(st_value), | |
| 396 | .st_size = st_size, | |
| 397 | }; | |
| 398 | } | |
| 399 | } | |
| 400 | ||
| 401 | const FormatCtx = struct { | |
| 402 | zig_got: ZigGotSection, | |
| 403 | elf_file: *Elf, | |
| 404 | }; | |
| 405 | ||
| 406 | pub fn fmt(zig_got: ZigGotSection, elf_file: *Elf) std.fmt.Formatter(format2) { | |
| 407 | return .{ .data = .{ .zig_got = zig_got, .elf_file = elf_file } }; | |
| 408 | } | |
| 409 | ||
| 410 | pub fn format2( | |
| 411 | ctx: FormatCtx, | |
| 412 | comptime unused_fmt_string: []const u8, | |
| 413 | options: std.fmt.FormatOptions, | |
| 414 | writer: anytype, | |
| 415 | ) !void { | |
| 416 | _ = options; | |
| 417 | _ = unused_fmt_string; | |
| 418 | const zig_got = ctx.zig_got; | |
| 419 | const elf_file = ctx.elf_file; | |
| 420 | try writer.writeAll(".zig.got\n"); | |
| 421 | for (zig_got.entries.items, 0..) |entry, index| { | |
| 422 | const zo = elf_file.zigObjectPtr().?; | |
| 423 | const symbol = zo.symbol(entry); | |
| 424 | try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{ | |
| 425 | index, | |
| 426 | zig_got.entryAddress(@intCast(index), elf_file), | |
| 427 | entry, | |
| 428 | symbol.address(.{}, elf_file), | |
| 429 | symbol.name(elf_file), | |
| 430 | }); | |
| 431 | } | |
| 432 | } | |
| 433 | }; | |
| 434 | ||
| 435 | 226 | pub const GotSection = struct { |
| 436 | 227 | entries: std.ArrayListUnmanaged(Entry) = .{}, |
| 437 | 228 | output_symtab_ctx: Elf.SymtabCtx = .{}, |