| ... | @@ -128,7 +128,7 @@ section_by_name: std.array_hash_map.Auto(String(.shstrtab), void), | ... | @@ -128,7 +128,7 @@ section_by_name: std.array_hash_map.Auto(String(.shstrtab), void), |
| 128 | changed_symtab_index: std.array_hash_map.Auto(String(.strtab), void), | 128 | changed_symtab_index: std.array_hash_map.Auto(String(.strtab), void), |
| 129 | /// Counts how many relocations are currently in `.rela.dyn` which would require a `DT_TEXTREL` | 129 | /// Counts how many relocations are currently in `.rela.dyn` which would require a `DT_TEXTREL` |
| 130 | /// entry in the `.dynamic` section. This allows adding `DT_TEXTREL` to the output `.dynamic` | 130 | /// entry in the `.dynamic` section. This allows adding `DT_TEXTREL` to the output `.dynamic` |
| 131 | /// section in `flush` only when it is actually necessary. See also `nodeRequiresTextrel`. | 131 | /// section in `flush` only when it is actually necessary. See also `nodeWantsDsoRelocation`. |
| 132 | textrel_count: u32, | 132 | textrel_count: u32, |
| 133 | | 133 | |
| 134 | const_prog_node: std.Progress.Node, | 134 | const_prog_node: std.Progress.Node, |
| ... | @@ -1128,8 +1128,10 @@ const SymbolReloc = struct { | ... | @@ -1128,8 +1128,10 @@ const SymbolReloc = struct { |
| 1128 | } | 1128 | } |
| 1129 | if (reloc.rela_index.unwrap()) |rela_index| { | 1129 | if (reloc.rela_index.unwrap()) |rela_index| { |
| 1130 | reloc.relaSection(elf).relaDeleteOne(elf, rela_index); | 1130 | reloc.relaSection(elf).relaDeleteOne(elf, rela_index); |
| 1131 | if (elf.nodeRequiresTextrel(reloc.node)) { | 1131 | switch (elf.nodeWantsDsoRelocation(reloc.node)) { |
| 1132 | elf.textrel_count -= 1; | 1132 | .no => unreachable, // there *was* a dynamic relocation! |
| | 1133 | .yes => {}, |
| | 1134 | .yes_textrel => elf.textrel_count -= 1, |
| 1133 | } | 1135 | } |
| 1134 | } | 1136 | } |
| 1135 | if (reloc.type.dependsOnTlsSize()) { | 1137 | if (reloc.type.dependsOnTlsSize()) { |
| ... | @@ -1672,8 +1674,10 @@ fn setGlobalSymbolValue( | ... | @@ -1672,8 +1674,10 @@ fn setGlobalSymbolValue( |
| 1672 | assert(reloc.target == Symbol.Id.global(global_name)); | 1674 | assert(reloc.target == Symbol.Id.global(global_name)); |
| 1673 | if (reloc.rela_index.unwrap()) |rela_index| { | 1675 | if (reloc.rela_index.unwrap()) |rela_index| { |
| 1674 | reloc.relaSection(elf).relaDeleteOne(elf, rela_index); | 1676 | reloc.relaSection(elf).relaDeleteOne(elf, rela_index); |
| 1675 | if (elf.nodeRequiresTextrel(reloc.node)) { | 1677 | switch (elf.nodeWantsDsoRelocation(reloc.node)) { |
| 1676 | elf.textrel_count -= 1; | 1678 | .no => unreachable, // there *was* a dynamic relocation! |
| | 1679 | .yes => {}, |
| | 1680 | .yes_textrel => elf.textrel_count -= 1, |
| 1677 | } | 1681 | } |
| 1678 | reloc.rela_index = .none; | 1682 | reloc.rela_index = .none; |
| 1679 | } | 1683 | } |
| ... | @@ -5108,8 +5112,10 @@ fn addSymbolRelocAssumeCapacity( | ... | @@ -5108,8 +5112,10 @@ fn addSymbolRelocAssumeCapacity( |
| 5108 | } else elf.globalByName(name).?.dynsym_index, | 5112 | } else elf.globalByName(name).?.dynsym_index, |
| 5109 | }; | 5113 | }; |
| 5110 | | 5114 | |
| 5111 | if (elf.nodeRequiresTextrel(node)) { | 5115 | switch (elf.nodeWantsDsoRelocation(node)) { |
| 5112 | elf.textrel_count += 1; | 5116 | .no => break :r .none, |
| | 5117 | .yes => {}, |
| | 5118 | .yes_textrel => elf.textrel_count += 1, |
| 5113 | } | 5119 | } |
| 5114 | | 5120 | |
| 5115 | // It currently looks like we need a runtime relocation for this. | 5121 | // It currently looks like we need a runtime relocation for this. |
| ... | @@ -5383,13 +5389,18 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { | ... | @@ -5383,13 +5389,18 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { |
| 5383 | }; | 5389 | }; |
| 5384 | } | 5390 | } |
| 5385 | | 5391 | |
| 5386 | /// Returns whether a `DT_TEXTREL` dynamic entry is needed to have a runtime relocation in `node`. | 5392 | /// If `node` cannot contain runtime relocations, returns `.no`. |
| 5387 | fn nodeRequiresTextrel(elf: *Elf, node: MappedFile.Node.Index) bool { | 5393 | /// |
| | 5394 | /// If `node` can contain runtime relocations, `returns `.yes_textrel` if such a relocation requires |
| | 5395 | /// the presence of a `DT_TEXTREL` dynamic entry, or `.yes` otherwise. |
| | 5396 | fn nodeWantsDsoRelocation(elf: *Elf, node: MappedFile.Node.Index) enum { yes, yes_textrel, no } { |
| 5388 | const shndx = elf.getNodeShndx(node); | 5397 | const shndx = elf.getNodeShndx(node); |
| 5389 | const shf: std.elf.SHF = switch (elf.shdrPtr(shndx)) { | 5398 | const shf: std.elf.SHF = switch (elf.shdrPtr(shndx)) { |
| 5390 | inline else => |shdr| elf.targetLoad(&shdr.flags).shf, | 5399 | inline else => |shdr| elf.targetLoad(&shdr.flags).shf, |
| 5391 | }; | 5400 | }; |
| 5392 | return shf.ALLOC and !shf.WRITE; | 5401 | if (!shf.ALLOC) return .no; |
| | 5402 | if (!shf.WRITE) return .yes_textrel; |
| | 5403 | return .yes; |
| 5393 | } | 5404 | } |
| 5394 | | 5405 | |
| 5395 | pub fn updateNav(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { | 5406 | pub fn updateNav(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { |