[ELF] Fix TLS GD against non-preemptible dynamic symbols in DSOs (#207881) Consider a DSO that uses TLS GD against a dynamic non-preemptible symbol (e.g. protected, or linked with -Bsymbolic). The expected meaning of this is to always reference the DSO's own TLS segment for that symbol, regardless of any attempts to preempt it at load time, and LLD will indeed emit a constant offset rather than a symbolic DTPOFF relocation for the second GOT word. However, for the first GOT word, because we currently only treat the isLocalInExecutable case as special (where the module index is 1), we end up creating a symbolic DTPMOD relocation, rather than a non-symbolic (i.e. against the null symbol) one to get this DSO's index, and so any load-time preemption will cause us to use a different module's TLS block. As a result, not only do we have symbol preemption when we shouldn't, but also the two halves of the TLS GD GOT entry end up inconsistent, using the offset of the symbol in this module's TLS block for a different module's. Fix this by breaking down the two !isLocalInExecutable cases, emitting the expected non-symbolic DTPMOD relocation for any non-preemptible symbol references in a DSO. Whilst here, combine the DTPMOD and DTPOFF code rather than have two different if statements, so it's clearer what the three cases are and they don't get out of sync. Note that although, for the existing code, local symbols take the exact same code paths in postScanRelocations, they do not end up with symbolic DTPMOD relocations in the output, despite creating them. DynamicReloc::getSymIndex has the quirk of silently squashing the symbol index to 0 for symbolic relocations against non-dynamic symbols, which applies to local symbols but not other non-preemptible symbols, i.e. the case relevant in the first paragraph. This quirky behaviour of DynamicReloc::getSymIndex is probably something that should be retired; I can't see a good reason for it, and any case that it squashes could be hiding similar bugs like this. I take the view that a request to create a symbolic relocation against a symbol that won't be in the dynamic symbol table is a strong sign that the code is confused and doing something wrong, even if it happens to work out.
Welcome to the LLVM project!
This repository contains the source code for LLVM, a toolkit for the construction of highly optimized compilers, optimizers, and run-time environments.
The LLVM project has multiple components. The core of the project is itself called “LLVM”. This contains all of the tools, libraries, and header files needed to process intermediate representations and convert them into object files. Tools include an assembler, disassembler, bitcode analyzer, and bitcode optimizer.
C-like languages use the Clang frontend. This component compiles C, C++, Objective-C, and Objective-C++ code into LLVM bitcode -- and from there into object files, using LLVM.
Other components include: the libc++ C++ standard library, the LLD linker, and more.
Consult the Getting Started with LLVM page for information on building and running LLVM.
For information on how to contribute to the LLVM project, please take a look at the Contributing to LLVM guide.
Join the LLVM Discourse forums, Discord chat, LLVM Office Hours or Regular sync-ups.
The LLVM project has adopted a code of conduct for participants to all modes of communication within the project.