| ... | ... | @@ -1387,10 +1387,9 @@ const SymbolReloc = struct { |
| 1387 | 1387 | illegal_dynamic_section, |
| 1388 | 1388 | }, |
| 1389 | 1389 | |
| 1390 | | /// ~~mystery bits~~ |
| 1391 | | /// what will MLUGG use them for? |
| 1392 | | /// nobody knows |
| 1393 | | _: u11 = 0, |
| 1390 | relaxation: Relaxation, |
| 1391 | |
| 1392 | _: u10 = 0, |
| 1394 | 1393 | }, |
| 1395 | 1394 | /// Forms a linked list of all symbol relocations with the same `target`. This list exists so |
| 1396 | 1395 | /// that all relocations targeting a particular symbol can be re-applied if that symbol moves. |
| ... | ... | @@ -1439,6 +1438,19 @@ const SymbolReloc = struct { |
| 1439 | 1438 | }, |
| 1440 | 1439 | }; |
| 1441 | 1440 | |
| 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 | |
| 1442 | 1454 | /// Instead of using the ELF relocation enums, we have our own internal representation for |
| 1443 | 1455 | /// relocation types. This representation is more compact (requiring only 16 bits), and allows |
| 1444 | 1456 | /// sharing a lot of relocation handling between multiple relocs and target architectures. |
| ... | ... | @@ -2332,7 +2344,8 @@ const SymbolReloc = struct { |
| 2332 | 2344 | reloc.rela_index = .none; |
| 2333 | 2345 | } |
| 2334 | 2346 | |
| 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 { |
| 2336 | 2349 | assert(elf.ehdrType() != .REL); |
| 2337 | 2350 | const reloc_node = reloc.node.unwrap().?; // deleted |
| 2338 | 2351 | |
| ... | ... | @@ -2351,6 +2364,30 @@ const SymbolReloc = struct { |
| 2351 | 2364 | }, |
| 2352 | 2365 | } |
| 2353 | 2366 | |
| 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 | |
| 2354 | 2391 | assert(reloc.rela_index == .none); |
| 2355 | 2392 | |
| 2356 | 2393 | const symbol_class = elf.classifySymbolValue(reloc.target_symbol); |
| ... | ... | @@ -4345,7 +4382,7 @@ const Symbol = struct { |
| 4345 | 4382 | while (ri != .none) { |
| 4346 | 4383 | const reloc = ri.get(elf); |
| 4347 | 4384 | assert(reloc.target_symbol == sym_id); |
| 4348 | | try reloc.updateDynamicReloc(elf); |
| 4385 | try reloc.updateDynamicReloc(elf, ri); |
| 4349 | 4386 | ri = reloc.next; |
| 4350 | 4387 | } |
| 4351 | 4388 | |
| ... | ... | @@ -10000,6 +10037,7 @@ fn addSymbolRelocAssumeCapacityInner( |
| 10000 | 10037 | .bits = .{ |
| 10001 | 10038 | .type = @"type", |
| 10002 | 10039 | .result = .ok, |
| 10040 | .relaxation = .none, |
| 10003 | 10041 | }, |
| 10004 | 10042 | .next = next, |
| 10005 | 10043 | .prev = .none, |
| ... | ... | @@ -10011,7 +10049,7 @@ fn addSymbolRelocAssumeCapacityInner( |
| 10011 | 10049 | if (@"type".dependsOnGotAddress()) { |
| 10012 | 10050 | try elf.got_relocs.put(gpa, ri, {}); |
| 10013 | 10051 | } |
| 10014 | | try ri.get(elf).updateDynamicReloc(elf); |
| 10052 | try ri.get(elf).updateDynamicReloc(elf, ri); |
| 10015 | 10053 | |
| 10016 | 10054 | // Actually apply the new relocation! |
| 10017 | 10055 | ri.get(elf).apply(elf); |