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
log2f8a3eb4c8f2de68f9337978ab9b628087530c34
tree25dc6c28a670ef3943f77d60c9c8f9759b6c267c
parent2d3d3c042e99da64df53a533852bd0e27166b4f6

Coff: fixup alias list

- Change aliases to a linked list, as they aren't always contiguous

1 files changed, 34 insertions(+), 36 deletions(-)

src/link/Coff.zig+34-36
...@@ -912,7 +912,7 @@ pub const Symbol = struct {...@@ -912,7 +912,7 @@ 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 has_aliases: bool,915 has_alias: bool,
916 _: u7 = 0,916 _: u7 = 0,
917 },917 },
918 /// Relocations contained within this symbol918 /// Relocations contained within this symbol
...@@ -927,9 +927,9 @@ pub const Symbol = struct {...@@ -927,9 +927,9 @@ pub const Symbol = struct {
927 /// 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?928 /// TODO: This is only used for name lookups, could just be String?
929 isli: Node.InputSection.LocalIndex,929 isli: Node.InputSection.LocalIndex,
930 /// Only valid if flags.has_aliases is set. The first in a contiguous930 /// Only valid if flags.has_alias is set.
931 /// list of symbols that are aliases of this symbol.931 /// The next symbol in the list of aliases of this symbol.
932 first_alias_si: Symbol.Index,932 next_alias_si: Symbol.Index,
933 },933 },
934934
935 pub const DllStorageClass = enum(u2) {935 pub const DllStorageClass = enum(u2) {
...@@ -1069,13 +1069,13 @@ pub const Symbol = struct {...@@ -1069,13 +1069,13 @@ pub const Symbol = struct {
1069 si.applyLocationRelocs(coff);1069 si.applyLocationRelocs(coff);
1070 si.applyTargetRelocs(coff, .none);1070 si.applyTargetRelocs(coff, .none);
10711071
1072 if (sym.flags.has_aliases) {1072 var alias_sym = sym;
1073 for (coff.symbols.items[@intFromEnum(sym.extra.first_alias_si)..]) |*export_sym| {1073 while (alias_sym.flags.has_alias) {
1074 if (export_sym.ni != sym.ni) break;1074 const alias_si = alias_sym.extra.next_alias_si;
1075 export_sym.rva = sym.rva;1075 alias_sym = alias_si.get(coff);
1076 const export_si: Symbol.Index = @enumFromInt(export_sym - coff.symbols.items.ptr);1076 assert(alias_sym.ni == sym.ni);
1077 export_si.applyTargetRelocs(coff, .none);1077 alias_sym.rva = sym.rva;
1078 }1078 alias_si.applyTargetRelocs(coff, .none);
1079 }1079 }
1080 }1080 }
10811081
...@@ -2028,9 +2028,9 @@ fn initHeaders(...@@ -2028,9 +2028,9 @@ fn initHeaders(
2028 try coff.symbols.ensureTotalCapacity(gpa, Symbol.Index.known_count);2028 try coff.symbols.ensureTotalCapacity(gpa, Symbol.Index.known_count);
2029 assert(coff.addSymbolAssumeCapacity() == .null);2029 assert(coff.addSymbolAssumeCapacity() == .null);
20302030
2031 // TODO: How do we tell MappedFile not to allocate physical space for these?2031 // TODO: How do we tell MappedFile not to allocate physical space for .bss?
2032 // TODO: Could have a node flag 'virtual' that can never have slice* called on it or fileLocation2032 // TODO: Could have a node flag 'virtual' that can never have slice* or fileLocation called on it
2033 // TODO: Instead of it's own section, we can place .bss as a pseudo-section at the end of .text in the extra space2033 // TODO: Instead of it's own section, place .bss as a pseudo-section at the end of .text in the extra space
2034 assert(try coff.addSection(.@".bss", .{2034 assert(try coff.addSection(.@".bss", .{
2035 .CNT_UNINITIALIZED_DATA = true,2035 .CNT_UNINITIALIZED_DATA = true,
2036 .MEM_READ = true,2036 .MEM_READ = true,
...@@ -2203,9 +2203,6 @@ pub fn initBuiltins(coff: *Coff) !void {...@@ -2203,9 +2203,6 @@ pub fn initBuiltins(coff: *Coff) !void {
2203 );2203 );
22042204
2205 const start_sym = start_osmi.symbol(coff).get(coff);2205 const start_sym = start_osmi.symbol(coff).get(coff);
2206 start_sym.extra = .{ .first_alias_si = @enumFromInt(coff.symbols.items.len) };
2207 start_sym.flags.has_aliases = true;
2208
2209 try start_sym.ni.resize(&coff.mf, gpa, addr_info.size);2206 try start_sym.ni.resize(&coff.mf, gpa, addr_info.size);
2210 const start_slice = start_sym.ni.slice(&coff.mf);2207 const start_slice = start_sym.ni.slice(&coff.mf);
2211 switch (addr_info.magic) {2208 switch (addr_info.magic) {
...@@ -2229,6 +2226,9 @@ pub fn initBuiltins(coff: *Coff) !void {...@@ -2229,6 +2226,9 @@ pub fn initBuiltins(coff: *Coff) !void {
2229 const list_sym = list_si.get(coff);2226 const list_sym = list_si.get(coff);
2230 list_sym.ni = start_sym.ni;2227 list_sym.ni = start_sym.ni;
2231 list_sym.section_number = start_sym.section_number;2228 list_sym.section_number = start_sym.section_number;
2229
2230 start_sym.extra = .{ .next_alias_si = list_si };
2231 start_sym.flags.has_alias = true;
2232 }2232 }
2233 }2233 }
2234}2234}
...@@ -2564,7 +2564,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {...@@ -2564,7 +2564,7 @@ fn addSymbolAssumeCapacity(coff: *Coff) Symbol.Index {
2564 .type = .unknown,2564 .type = .unknown,
2565 .dll_storage_class = .default,2565 .dll_storage_class = .default,
2566 .weak_external_strat = undefined,2566 .weak_external_strat = undefined,
2567 .has_aliases = false,2567 .has_alias = false,
2568 },2568 },
2569 .loc_relocs = .none,2569 .loc_relocs = .none,
2570 .target_relocs = .none,2570 .target_relocs = .none,
...@@ -2692,10 +2692,6 @@ fn getDefinedGlobal(coff: *Coff, name: []const u8) Symbol.Index {...@@ -2692,10 +2692,6 @@ fn getDefinedGlobal(coff: *Coff, name: []const u8) Symbol.Index {
26922692
2693pub fn globalSymbol(coff: *Coff, opts: GlobalOptions) !Symbol.Index {2693pub fn globalSymbol(coff: *Coff, opts: GlobalOptions) !Symbol.Index {
2694 const gop = try coff.getOrPutGlobalSymbol(opts);2694 const gop = try coff.getOrPutGlobalSymbol(opts);
2695 if (gop.found_existing) {
2696 // TODO: Need to know if this is an export or extern, in order to decide if this is duplicate, add to opts
2697 }
2698
2699 return gop.value_ptr.*;2695 return gop.value_ptr.*;
2700}2696}
27012697
...@@ -3525,7 +3521,6 @@ pub fn addReloc(...@@ -3525,7 +3521,6 @@ pub fn addReloc(
3525 );3521 );
35263522
3527 // TODO: These need to allocate from a free list (once deleting relocs is supported) (or can we just remove swap?)3523 // TODO: These need to allocate from a free list (once deleting relocs is supported) (or can we just remove swap?)
3528
3529 const sri: Section.RelocationIndex = .wrap(old_num_relocations);3524 const sri: Section.RelocationIndex = .wrap(old_num_relocations);
3530 const entry = sri.entry(coff, loc_sn).?;3525 const entry = sri.entry(coff, loc_sn).?;
3531 if (sti.unwrap()) |index| coff.targetStore(&entry.symbol_table_index, index);3526 if (sti.unwrap()) |index| coff.targetStore(&entry.symbol_table_index, index);
...@@ -3826,7 +3821,7 @@ fn loadObject(...@@ -3826,7 +3821,7 @@ fn loadObject(
3826 try member.initHeader(coff, path_str, header.time_date_stamp);3821 try member.initHeader(coff, path_str, header.time_date_stamp);
38273822
3828 {3823 {
3829 // TODO: This could be deferred to an idle task?3824 // TODO: This should be deferred to an idle task
3830 var nw: MappedFile.Node.Writer = undefined;3825 var nw: MappedFile.Node.Writer = undefined;
3831 member.content_ni.writer(&coff.mf, gpa, &nw);3826 member.content_ni.writer(&coff.mf, gpa, &nw);
3832 defer nw.deinit();3827 defer nw.deinit();
...@@ -4101,7 +4096,7 @@ fn loadObject(...@@ -4101,7 +4096,7 @@ fn loadObject(
4101 if (arg.len == 0) continue;4096 if (arg.len == 0) continue;
41024097
4103 if (std.ascii.startsWithIgnoreCase(arg, "-exclude-symbols:")) {4098 if (std.ascii.startsWithIgnoreCase(arg, "-exclude-symbols:")) {
4104 // TODO: When implementing mingw auto-exports (if at all?), use this to not export this symbol4099 // TODO: When implementing mingw auto-exports (if at all?), track this to not export this symbol
4105 } else if (std.ascii.startsWithIgnoreCase(arg, "/include:")) {4100 } else if (std.ascii.startsWithIgnoreCase(arg, "/include:")) {
4106 _ = try coff.globalSymbol(.{ .name = arg["/include:".len..] });4101 _ = try coff.globalSymbol(.{ .name = arg["/include:".len..] });
4107 } else if (std.ascii.startsWithIgnoreCase(arg, "/alternatename:")) {4102 } else if (std.ascii.startsWithIgnoreCase(arg, "/alternatename:")) {
...@@ -4251,7 +4246,7 @@ fn loadObject(...@@ -4251,7 +4246,7 @@ fn loadObject(
4251 .lib_name = null,4246 .lib_name = null,
4252 });4247 });
42534248
4254 // TODO: What if the same symbol defined twice in this obj?4249 // TODO: What if the same symbol is incorrectly defined twice in this obj?
4255 // TODO: Would need to mark this global as pending, or notice it later when .ni != none4250 // TODO: Would need to mark this global as pending, or notice it later when .ni != none
4256 if (!global_gop.found_existing or global_gop.value_ptr.get(coff).ni == .none) {4251 if (!global_gop.found_existing or global_gop.value_ptr.get(coff).ni == .none) {
4257 symbol.si = global_gop.value_ptr.*;4252 symbol.si = global_gop.value_ptr.*;
...@@ -4319,7 +4314,7 @@ fn loadObject(...@@ -4319,7 +4314,7 @@ fn loadObject(
4319 .LARGEST => {4314 .LARGEST => {
4320 // TODO: Resize existing .ni and replace with this section's contents4315 // TODO: Resize existing .ni and replace with this section's contents
4321 // TODO: This will be tricky, what to do about existing InputSection?4316 // TODO: This will be tricky, what to do about existing InputSection?
4322 unreachable; // TODO4317 unreachable;
4323 },4318 },
4324 .NONE, .ASSOCIATIVE, _ => unreachable,4319 .NONE, .ASSOCIATIVE, _ => unreachable,
4325 }4320 }
...@@ -4504,7 +4499,7 @@ fn loadObject(...@@ -4504,7 +4499,7 @@ fn loadObject(
4504 symbol.si = coff.addSymbolAssumeCapacity();4499 symbol.si = coff.addSymbolAssumeCapacity();
4505 },4500 },
4506 .external => {4501 .external => {
4507 // TODO: Assert this is not the comdat leader4502 assert(index != section.comdat_psi.unwrap());
4508 const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name.toSlice(coff) });4503 const global_gop = try coff.getOrPutGlobalSymbol(.{ .name = symbol.name.toSlice(coff) });
4509 symbol.si = global_gop.value_ptr.*;4504 symbol.si = global_gop.value_ptr.*;
45104505
...@@ -5017,7 +5012,7 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !vo...@@ -5017,7 +5012,7 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) !vo
5017 } else {5012 } else {
5018 member.content.object.size = res.size;5013 member.content.object.size = res.size;
5019 // TODO: If .UNKNOWN assert later that it contains no non-undef symbols?5014 // TODO: If .UNKNOWN assert later that it contains no non-undef symbols?
5020 // Microsoft's CRT contains members that set .UNKNOWN but do have symbols5015 // Microsoft's CRT contains members that set .UNKNOWN but do have undef symbols
5021 if (machine != expected_machine and machine != .UNKNOWN) {5016 if (machine != expected_machine and machine != .UNKNOWN) {
5022 return diags.failParse(path, "machine mismatch in member header '{s}': expected {t}, found {t}", .{5017 return diags.failParse(path, "machine mismatch in member header '{s}': expected {t}, found {t}", .{
5023 res.name,5018 res.name,
...@@ -5192,7 +5187,6 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -5192,7 +5187,6 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
5192 si.applyLocationRelocs(coff);5187 si.applyLocationRelocs(coff);
5193 }5188 }
51945189
5195 // TODO: Did my MappedFile resize change affect this?
5196 if (nav.resolved.?.@"linksection".unwrap()) |_| {5190 if (nav.resolved.?.@"linksection".unwrap()) |_| {
5197 try ni.resize(&coff.mf, gpa, si.get(coff).value.size);5191 try ni.resize(&coff.mf, gpa, si.get(coff).value.size);
5198 var parent_ni = ni;5192 var parent_ni = ni;
...@@ -5746,7 +5740,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {...@@ -5746,7 +5740,7 @@ pub fn idle(coff: *Coff, tid: Zcu.PerThread.Id) !bool {
5746 };5740 };
5747 break :task;5741 break :task;
5748 }5742 }
5749 // TODO: Idle task for flushing obj into lib?5743 // TODO: Idle task for flushing obj into lib
5750 if (coff.input_section_pending_index < coff.input_sections.items.len) {5744 if (coff.input_section_pending_index < coff.input_sections.items.len) {
5751 const isi: Node.InputSection.Index = @enumFromInt(coff.input_section_pending_index);5745 const isi: Node.InputSection.Index = @enumFromInt(coff.input_section_pending_index);
5752 coff.input_section_pending_index += 1;5746 coff.input_section_pending_index += 1;
...@@ -7087,14 +7081,11 @@ fn updateExportsInner(...@@ -7087,14 +7081,11 @@ fn updateExportsInner(
7087 Type.fromInterned(ip.typeOf(uav)).abiAlignment(zcu),7081 Type.fromInterned(ip.typeOf(uav)).abiAlignment(zcu),
7088 ))),7082 ))),
7089 };7083 };
7090 while (try coff.idle(pt.tid)) {} // TODO: Is this necessary now that we handle exports moving via has_aliases?
70917084
7092 const machine = coff.targetLoad(&coff.headerPtr().machine);7085 const machine = coff.targetLoad(&coff.headerPtr().machine);
7093 const exported_ni = exported_si.node(coff);7086 const exported_ni = exported_si.node(coff);
7094 const exported_sym = exported_si.get(coff);7087 const exported_sym = exported_si.get(coff);
7095 exported_sym.extra = .{ .first_alias_si = @enumFromInt(coff.symbols.items.len) };7088 var prev_alias_si = exported_si;
7096 exported_sym.flags.has_aliases = true;
7097
7098 for (export_indices) |export_index| {7089 for (export_indices) |export_index| {
7099 const @"export" = export_index.ptr(zcu);7090 const @"export" = export_index.ptr(zcu);
7100 const name = @"export".opts.name.toSlice(ip);7091 const name = @"export".opts.name.toSlice(ip);
...@@ -7111,6 +7102,12 @@ fn updateExportsInner(...@@ -7111,6 +7102,12 @@ fn updateExportsInner(
7111 export_sym.section_number = exported_sym.section_number;7102 export_sym.section_number = exported_sym.section_number;
7112 defer export_si.applyTargetRelocs(coff, .none);7103 defer export_si.applyTargetRelocs(coff, .none);
71137104
7105 const prev_alias_sym = prev_alias_si.get(coff);
7106 assert(!prev_alias_sym.flags.has_alias);
7107 prev_alias_sym.extra = .{ .next_alias_si = export_si };
7108 prev_alias_sym.flags.has_alias = true;
7109 prev_alias_si = export_si;
7110
7114 if (!coff.isImage()) continue;7111 if (!coff.isImage()) continue;
71157112
7116 const entries_ctx = ExportTable.Adapter{ .coff = coff };7113 const entries_ctx = ExportTable.Adapter{ .coff = coff };
...@@ -7153,7 +7150,8 @@ fn updateExportsInner(...@@ -7153,7 +7150,8 @@ fn updateExportsInner(
7153 coff.targetStore(&edt.number_of_names, @intCast(export_count));7150 coff.targetStore(&edt.number_of_names, @intCast(export_count));
7154 edt.number_of_entries = edt.number_of_names;7151 edt.number_of_entries = edt.number_of_names;
71557152
7156 // TODO: These should all be resized ahead of time to fit all exports (after https://github.com/ziglang/zig/issues/23616)7153 // TODO: These should all be resized ahead of time to fit all exports
7154 // after https://github.com/ziglang/zig/issues/23616
7157 try coff.export_table.export_address_table_si.node(coff).resize(7155 try coff.export_table.export_address_table_si.node(coff).resize(
7158 &coff.mf,7156 &coff.mf,
7159 gpa,7157 gpa,