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