authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-23 22:05:25-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-23 22:05:25-04:00
logd94b3e7691f15b8bc6993cc6999d0f439255ed80
tree989a2e168ad321000989343a45ccafbab933def6
parentbe7b9dec521f36909643c7084c16c284968a7db3

Coff: fix incorrect section offset calculations when writing section relocation tables


2 files changed, 22 insertions(+), 11 deletions(-)

src/link/Coff.zig+21-10
...@@ -1110,7 +1110,7 @@ pub const Symbol = struct {...@@ -1110,7 +1110,7 @@ pub const Symbol = struct {
1110 if (reloc.loc != si) break;1110 if (reloc.loc != si) break;
1111 if (reloc.sri.entry(coff, sym.section_number)) |entry| coff.targetStore(1111 if (reloc.sri.entry(coff, sym.section_number)) |entry| coff.targetStore(
1112 &entry.virtual_address,1112 &entry.virtual_address,
1113 @intCast(coff.computeSymbolSectionOffset(sym) + reloc.offset),1113 @intCast(coff.computeSymbolSectionOffset(sym, .image) + reloc.offset),
1114 );1114 );
1115 try reloc.apply(coff);1115 try reloc.apply(coff);
1116 }1116 }
...@@ -1442,7 +1442,7 @@ pub const Reloc = extern struct {...@@ -1442,7 +1442,7 @@ pub const Reloc = extern struct {
1442 .SECREL => std.mem.writeInt(1442 .SECREL => std.mem.writeInt(
1443 u32,1443 u32,
1444 loc_slice[0..4],1444 loc_slice[0..4],
1445 @intCast(coff.computeSymbolSectionOffset(target_sym) + reloc.addend),1445 @intCast(coff.computeSymbolSectionOffset(target_sym, .pseudo) + reloc.addend),
1446 target_endian,1446 target_endian,
1447 ),1447 ),
1448 },1448 },
...@@ -1482,7 +1482,7 @@ pub const Reloc = extern struct {...@@ -1482,7 +1482,7 @@ pub const Reloc = extern struct {
1482 .SECREL => std.mem.writeInt(1482 .SECREL => std.mem.writeInt(
1483 u32,1483 u32,
1484 loc_slice[0..4],1484 loc_slice[0..4],
1485 @intCast(coff.computeSymbolSectionOffset(target_sym) + reloc.addend),1485 @intCast(coff.computeSymbolSectionOffset(target_sym, .pseudo) + reloc.addend),
1486 target_endian,1486 target_endian,
1487 ),1487 ),
1488 },1488 },
...@@ -1496,7 +1496,7 @@ pub const Reloc = extern struct {...@@ -1496,7 +1496,7 @@ pub const Reloc = extern struct {
1496 // TODO: If this was the last reloc causing something to be in the symbol table, we should remove1496 // TODO: If this was the last reloc causing something to be in the symbol table, we should remove
1497 // the symbol table entry (and unset sti). That will require flushSymbolTableIndex on the1497 // the symbol table entry (and unset sti). That will require flushSymbolTableIndex on the
1498 // swapped symbol if we exchange indices1498 // swapped symbol if we exchange indices
1499 unreachable;1499 @panic("TODO implement symbol table reloc deletions");
1500 }1500 }
15011501
1502 switch (reloc.prev) {1502 switch (reloc.prev) {
...@@ -2443,7 +2443,12 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 {...@@ -2443,7 +2443,12 @@ fn computeNodeRva(coff: *Coff, ni: MappedFile.Node.Index) u32 {
2443 const offset, _ = ni.location(&coff.mf).resolve(&coff.mf);2443 const offset, _ = ni.location(&coff.mf).resolve(&coff.mf);
2444 return @intCast(parent_rva + offset);2444 return @intCast(parent_rva + offset);
2445}2445}
2446fn computeSymbolSectionOffset(coff: *Coff, sym: *const Symbol) u32 {2446
2447fn computeSymbolSectionOffset(
2448 coff: *Coff,
2449 sym: *const Symbol,
2450 relative_to: enum { image, pseudo },
2451) u32 {
2447 var section_offset: u32 = sym.nodeOffset(coff);2452 var section_offset: u32 = sym.nodeOffset(coff);
2448 var parent_ni = sym.ni;2453 var parent_ni = sym.ni;
2449 while (true) {2454 while (true) {
...@@ -2452,10 +2457,14 @@ fn computeSymbolSectionOffset(coff: *Coff, sym: *const Symbol) u32 {...@@ -2452,10 +2457,14 @@ fn computeSymbolSectionOffset(coff: *Coff, sym: *const Symbol) u32 {
2452 parent_ni = parent_ni.parent(&coff.mf);2457 parent_ni = parent_ni.parent(&coff.mf);
2453 switch (coff.getNode(parent_ni)) {2458 switch (coff.getNode(parent_ni)) {
2454 else => unreachable,2459 else => unreachable,
2455 .image_section, .pseudo_section => return section_offset,2460 .image_section => break,
2456 .object_section => {},2461 .pseudo_section => if (relative_to == .pseudo) break,
2462 .object_section,
2463 => {},
2457 }2464 }
2458 }2465 }
2466
2467 return section_offset;
2459}2468}
24602469
2461pub inline fn targetEndian(_: *const Coff) std.lang.Endian {2470pub inline fn targetEndian(_: *const Coff) std.lang.Endian {
...@@ -3279,7 +3288,7 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32, pt: Zcu.PerThread) !void {...@@ -3279,7 +3288,7 @@ fn flushSymbolTableEntry(coff: *Coff, index: u32, pt: Zcu.PerThread) !void {
3279 => unreachable,3288 => unreachable,
3280 else => switch (coff.getNode(sym.ni)) {3289 else => switch (coff.getNode(sym.ni)) {
3281 .image_section => 0,3290 .image_section => 0,
3282 else => coff.computeSymbolSectionOffset(sym),3291 else => coff.computeSymbolSectionOffset(sym, .image),
3283 },3292 },
3284 });3293 });
32853294
...@@ -3328,10 +3337,12 @@ fn flushInputSection(coff: *Coff, isi: Node.InputSection.Index) !void {...@@ -3328,10 +3337,12 @@ fn flushInputSection(coff: *Coff, isi: Node.InputSection.Index) !void {
3328 const si = isi.symbol(coff);3337 const si = isi.symbol(coff);
3329 si.node(coff).writer(&coff.mf, gpa, &nw);3338 si.node(coff).writer(&coff.mf, gpa, &nw);
3330 defer nw.deinit();3339 defer nw.deinit();
3331 log.debug("flushInputSection({f}{f}, {s})", .{3340 log.debug("flushInputSection({f}{f}, {s}, {d}, n{d})", .{
3332 path,3341 path,
3333 fmtMemberNameString(ioi.memberName(coff)),3342 fmtMemberNameString(ioi.memberName(coff)),
3334 isi.symbol(coff).get(coff).section_number.name(coff).toSlice(coff),3343 si.get(coff).section_number.name(coff).toSlice(coff),
3344 si,
3345 si.node(coff),
3335 });3346 });
3336 if (try nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) != file_loc.size)3347 if (try nw.interface.sendFileAll(&fr, .limited(@intCast(file_loc.size))) != file_loc.size)
3337 return error.EndOfStream;3348 return error.EndOfStream;
test/link/snapshots/.gitattributes+1-1
...@@ -1 +1 @@...@@ -1 +1 @@
1* -text 1*.dmp eol=lf