authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-05 01:55:35-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-23 00:26:56-04:00
log8781abd79b5d8c8ce155b065c874d09076491e26
tree674bf71cb32dc71720a10c0f4e0105a4075009f8
parentdc8dd5c08a4715c39de2e6ca8f4d4c6c4aa1f96b

Coff: track the exports of a symbol so they can be updated

Globals created as exports of other symbols were not being updated when the original symbol moved. Since we discover the entrypoint after exports are updated, nodes can move as a result of the entrypoint logic pulling in an input object.

1 files changed, 21 insertions(+), 1 deletions(-)

src/link/Coff.zig+21-1
......@@ -912,7 +912,8 @@ pub const Symbol = struct {
912912 dll_storage_class: DllStorageClass,
913913 // Only defined for .alias_si and .alias_name
914914 weak_external_strat: WeakExternalStrat,
915 _: u8 = 0,
915 has_exports: bool,
916 _: u7 = 0,
916917 },
917918 /// Relocations contained within this symbol
918919 loc_relocs: Reloc.Index,
......@@ -924,7 +925,11 @@ pub const Symbol = struct {
924925 /// Only valid when outputting objects
925926 sti: SymbolTable.Index,
926927 /// Only valid when .ni == .input_section and .value_tag == .node_offset
928 /// TODO: This is only used for name lookups, could just be String?
927929 isli: Node.InputSection.LocalIndex,
930 /// Only valid if flags.has_exports is set. The first in a contiguous
931 /// list of symbols that are exports of this symbol.
932 first_export_si: Symbol.Index,
928933 },
929934
930935 pub const DllStorageClass = enum(u2) {
......@@ -1063,6 +1068,15 @@ pub const Symbol = struct {
10631068 sym.rva = coff.computeNodeRva(sym.ni) + sym.nodeOffset(coff);
10641069 si.applyLocationRelocs(coff);
10651070 si.applyTargetRelocs(coff, .none);
1071
1072 if (sym.flags.has_exports) {
1073 for (coff.symbols.items[@intFromEnum(sym.extra.first_export_si)..]) |*export_sym| {
1074 if (export_sym.ni != sym.ni) break;
1075 export_sym.rva = sym.rva;
1076 const export_si: Symbol.Index = @enumFromInt(export_sym - coff.symbols.items.ptr);
1077 export_si.applyTargetRelocs(coff, .none);
1078 }
1079 }
10661080 }
10671081
10681082 pub fn flushSymbolTableIndex(si: Symbol.Index, coff: *Coff) void {
......@@ -2547,6 +2561,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {
25472561 .type = .unknown,
25482562 .dll_storage_class = .default,
25492563 .weak_external_strat = undefined,
2564 .has_exports = false,
25502565 },
25512566 .loc_relocs = .none,
25522567 .target_relocs = .none,
......@@ -7063,9 +7078,14 @@ fn updateExportsInner(
70637078 const machine = coff.targetLoad(&coff.headerPtr().machine);
70647079 const exported_ni = exported_si.node(coff);
70657080 const exported_sym = exported_si.get(coff);
7081 exported_sym.extra = .{ .first_export_si = @enumFromInt(coff.symbols.items.len) };
7082 exported_sym.flags.has_exports = true;
7083
70667084 for (export_indices) |export_index| {
70677085 const @"export" = export_index.ptr(zcu);
70687086 const name = @"export".opts.name.toSlice(ip);
7087 // TODO: Add an errMsg if this conflicts with an existing global from an input
7088 // first_export_si relies on this being a new symbol.
70697089 const export_si = try coff.globalSymbol(.{
70707090 .name = name,
70717091 .lib_name = null,