authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-10-21 13:07:43+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-10-25 00:21:55+01:00
logd74e9a786f96af052065c0d3a6c22ab38e9b697f
treef6e34da8396ea5e301dea73c69e219728b6a3ecb
parent7cc50a4fb3f8184742abe7a6939ae920c648ebab
signature Commit is signed but in an unrecognized format.

Elf2: prepare to support simple relaxations


1 files changed, 45 insertions(+), 7 deletions(-)

src/link/Elf2.zig+45-7
......@@ -1387,10 +1387,9 @@ const SymbolReloc = struct {
13871387 illegal_dynamic_section,
13881388 },
13891389
1390 /// ~~mystery bits~~
1391 /// what will MLUGG use them for?
1392 /// nobody knows
1393 _: u11 = 0,
1390 relaxation: Relaxation,
1391
1392 _: u10 = 0,
13941393 },
13951394 /// Forms a linked list of all symbol relocations with the same `target`. This list exists so
13961395 /// that all relocations targeting a particular symbol can be re-applied if that symbol moves.
......@@ -1439,6 +1438,19 @@ const SymbolReloc = struct {
14391438 },
14401439 };
14411440
1441 const Relaxation = enum(u1) {
1442 none,
1443 };
1444 /// Updates `reloc.type` and `reloc.offset` as needed based on `reloc.bits.relaxation`. It is
1445 /// possible that `reloc` is already relaxed, and may need to be un-relaxed due to a change in
1446 /// the symbol definition.
1447 fn processRelaxation(reloc: *SymbolReloc, elf: *Elf) void {
1448 _ = elf;
1449 switch (reloc.bits.relaxation) {
1450 .none => return,
1451 }
1452 }
1453
14421454 /// Instead of using the ELF relocation enums, we have our own internal representation for
14431455 /// relocation types. This representation is more compact (requiring only 16 bits), and allows
14441456 /// sharing a lot of relocation handling between multiple relocs and target architectures.
......@@ -2332,7 +2344,8 @@ const SymbolReloc = struct {
23322344 reloc.rela_index = .none;
23332345 }
23342346
2335 fn updateDynamicReloc(reloc: *SymbolReloc, elf: *Elf) Error!void {
2347 /// Called when the classification of the target symbol changes.
2348 fn updateDynamicReloc(reloc: *SymbolReloc, elf: *Elf, ri: SymbolReloc.Index) Error!void {
23362349 assert(elf.ehdrType() != .REL);
23372350 const reloc_node = reloc.node.unwrap().?; // deleted
23382351
......@@ -2351,6 +2364,30 @@ const SymbolReloc = struct {
23512364 },
23522365 }
23532366
2367 {
2368 const gpa = elf.base.comp.gpa;
2369
2370 const old_depends_on_got_address = reloc.bits.type.dependsOnGotAddress();
2371 const old_depends_on_tls_size = reloc.bits.type.dependsOnTlsSize(elf);
2372
2373 reloc.processRelaxation(elf);
2374
2375 const new_depends_on_got_address = reloc.bits.type.dependsOnGotAddress();
2376 const new_depends_on_tls_size = reloc.bits.type.dependsOnTlsSize(elf);
2377
2378 if (old_depends_on_got_address and !new_depends_on_got_address) {
2379 assert(elf.got_relocs.swapRemove(ri));
2380 } else if (!old_depends_on_got_address and new_depends_on_got_address) {
2381 try elf.got_relocs.putNoClobber(gpa, ri, {});
2382 }
2383
2384 if (old_depends_on_tls_size and !new_depends_on_tls_size) {
2385 assert(elf.tls_size_symbol_relocs.swapRemove(ri));
2386 } else if (!old_depends_on_tls_size and new_depends_on_tls_size) {
2387 try elf.tls_size_symbol_relocs.putNoClobber(gpa, ri, {});
2388 }
2389 }
2390
23542391 assert(reloc.rela_index == .none);
23552392
23562393 const symbol_class = elf.classifySymbolValue(reloc.target_symbol);
......@@ -4345,7 +4382,7 @@ const Symbol = struct {
43454382 while (ri != .none) {
43464383 const reloc = ri.get(elf);
43474384 assert(reloc.target_symbol == sym_id);
4348 try reloc.updateDynamicReloc(elf);
4385 try reloc.updateDynamicReloc(elf, ri);
43494386 ri = reloc.next;
43504387 }
43514388
......@@ -10000,6 +10037,7 @@ fn addSymbolRelocAssumeCapacityInner(
1000010037 .bits = .{
1000110038 .type = @"type",
1000210039 .result = .ok,
10040 .relaxation = .none,
1000310041 },
1000410042 .next = next,
1000510043 .prev = .none,
......@@ -10011,7 +10049,7 @@ fn addSymbolRelocAssumeCapacityInner(
1001110049 if (@"type".dependsOnGotAddress()) {
1001210050 try elf.got_relocs.put(gpa, ri, {});
1001310051 }
10014 try ri.get(elf).updateDynamicReloc(elf);
10052 try ri.get(elf).updateDynamicReloc(elf, ri);
1001510053
1001610054 // Actually apply the new relocation!
1001710055 ri.get(elf).apply(elf);