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 {...@@ -912,7 +912,8 @@ pub const Symbol = struct {
912 dll_storage_class: DllStorageClass,912 dll_storage_class: DllStorageClass,
913 // Only defined for .alias_si and .alias_name913 // Only defined for .alias_si and .alias_name
914 weak_external_strat: WeakExternalStrat,914 weak_external_strat: WeakExternalStrat,
915 _: u8 = 0,915 has_exports: bool,
916 _: u7 = 0,
916 },917 },
917 /// Relocations contained within this symbol918 /// Relocations contained within this symbol
918 loc_relocs: Reloc.Index,919 loc_relocs: Reloc.Index,
...@@ -924,7 +925,11 @@ pub const Symbol = struct {...@@ -924,7 +925,11 @@ pub const Symbol = struct {
924 /// Only valid when outputting objects925 /// Only valid when outputting objects
925 sti: SymbolTable.Index,926 sti: SymbolTable.Index,
926 /// Only valid when .ni == .input_section and .value_tag == .node_offset927 /// Only valid when .ni == .input_section and .value_tag == .node_offset
928 /// TODO: This is only used for name lookups, could just be String?
927 isli: Node.InputSection.LocalIndex,929 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,
928 },933 },
929934
930 pub const DllStorageClass = enum(u2) {935 pub const DllStorageClass = enum(u2) {
...@@ -1063,6 +1068,15 @@ pub const Symbol = struct {...@@ -1063,6 +1068,15 @@ pub const Symbol = struct {
1063 sym.rva = coff.computeNodeRva(sym.ni) + sym.nodeOffset(coff);1068 sym.rva = coff.computeNodeRva(sym.ni) + sym.nodeOffset(coff);
1064 si.applyLocationRelocs(coff);1069 si.applyLocationRelocs(coff);
1065 si.applyTargetRelocs(coff, .none);1070 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 }
1066 }1080 }
10671081
1068 pub fn flushSymbolTableIndex(si: Symbol.Index, coff: *Coff) void {1082 pub fn flushSymbolTableIndex(si: Symbol.Index, coff: *Coff) void {
...@@ -2547,6 +2561,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {...@@ -2547,6 +2561,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {
2547 .type = .unknown,2561 .type = .unknown,
2548 .dll_storage_class = .default,2562 .dll_storage_class = .default,
2549 .weak_external_strat = undefined,2563 .weak_external_strat = undefined,
2564 .has_exports = false,
2550 },2565 },
2551 .loc_relocs = .none,2566 .loc_relocs = .none,
2552 .target_relocs = .none,2567 .target_relocs = .none,
...@@ -7063,9 +7078,14 @@ fn updateExportsInner(...@@ -7063,9 +7078,14 @@ fn updateExportsInner(
7063 const machine = coff.targetLoad(&coff.headerPtr().machine);7078 const machine = coff.targetLoad(&coff.headerPtr().machine);
7064 const exported_ni = exported_si.node(coff);7079 const exported_ni = exported_si.node(coff);
7065 const exported_sym = exported_si.get(coff);7080 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
7066 for (export_indices) |export_index| {7084 for (export_indices) |export_index| {
7067 const @"export" = export_index.ptr(zcu);7085 const @"export" = export_index.ptr(zcu);
7068 const name = @"export".opts.name.toSlice(ip);7086 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.
7069 const export_si = try coff.globalSymbol(.{7089 const export_si = try coff.globalSymbol(.{
7070 .name = name,7090 .name = name,
7071 .lib_name = null,7091 .lib_name = null,