diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index b781fe4bc1c070be7d775bf6da3737457cd8d0f1..e05e9796c4e6b2c059427fa17003cd185cbb04f5 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -128,7 +128,7 @@ section_by_name: std.array_hash_map.Auto(String(.shstrtab), void), changed_symtab_index: std.array_hash_map.Auto(String(.strtab), void), /// Counts how many relocations are currently in `.rela.dyn` which would require a `DT_TEXTREL` /// entry in the `.dynamic` section. This allows adding `DT_TEXTREL` to the output `.dynamic` -/// section in `flush` only when it is actually necessary. See also `nodeRequiresTextrel`. +/// section in `flush` only when it is actually necessary. See also `nodeWantsDsoRelocation`. textrel_count: u32, const_prog_node: std.Progress.Node, @@ -1128,8 +1128,10 @@ const SymbolReloc = struct { } if (reloc.rela_index.unwrap()) |rela_index| { reloc.relaSection(elf).relaDeleteOne(elf, rela_index); - if (elf.nodeRequiresTextrel(reloc.node)) { - elf.textrel_count -= 1; + switch (elf.nodeWantsDsoRelocation(reloc.node)) { + .no => unreachable, // there *was* a dynamic relocation! + .yes => {}, + .yes_textrel => elf.textrel_count -= 1, } } if (reloc.type.dependsOnTlsSize()) { @@ -1672,8 +1674,10 @@ fn setGlobalSymbolValue( assert(reloc.target == Symbol.Id.global(global_name)); if (reloc.rela_index.unwrap()) |rela_index| { reloc.relaSection(elf).relaDeleteOne(elf, rela_index); - if (elf.nodeRequiresTextrel(reloc.node)) { - elf.textrel_count -= 1; + switch (elf.nodeWantsDsoRelocation(reloc.node)) { + .no => unreachable, // there *was* a dynamic relocation! + .yes => {}, + .yes_textrel => elf.textrel_count -= 1, } reloc.rela_index = .none; } @@ -5108,8 +5112,10 @@ fn addSymbolRelocAssumeCapacity( } else elf.globalByName(name).?.dynsym_index, }; - if (elf.nodeRequiresTextrel(node)) { - elf.textrel_count += 1; + switch (elf.nodeWantsDsoRelocation(node)) { + .no => break :r .none, + .yes => {}, + .yes_textrel => elf.textrel_count += 1, } // It currently looks like we need a runtime relocation for this. @@ -5383,13 +5389,18 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { }; } -/// Returns whether a `DT_TEXTREL` dynamic entry is needed to have a runtime relocation in `node`. -fn nodeRequiresTextrel(elf: *Elf, node: MappedFile.Node.Index) bool { +/// If `node` cannot contain runtime relocations, returns `.no`. +/// +/// If `node` can contain runtime relocations, `returns `.yes_textrel` if such a relocation requires +/// the presence of a `DT_TEXTREL` dynamic entry, or `.yes` otherwise. +fn nodeWantsDsoRelocation(elf: *Elf, node: MappedFile.Node.Index) enum { yes, yes_textrel, no } { const shndx = elf.getNodeShndx(node); const shf: std.elf.SHF = switch (elf.shdrPtr(shndx)) { inline else => |shdr| elf.targetLoad(&shdr.flags).shf, }; - return shf.ALLOC and !shf.WRITE; + if (!shf.ALLOC) return .no; + if (!shf.WRITE) return .yes_textrel; + return .yes; } pub fn updateNav(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {