diff options
author | Shoaib Meenai <smeenai@fb.com> | 2024-08-06 12:58:04 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-06 12:58:04 -0700 |
commit | 0371dff99529e93b8650281801e89bc015dc2703 (patch) | |
tree | 0fe5963596572d43ca0f2e702945e4a482794ef0 /clang/lib/CodeGen/CGVTables.cpp | |
parent | 2601d6f189cf1d4e4e77a7cba83e5d32c87bf079 (diff) | |
download | llvm-0371dff99529e93b8650281801e89bc015dc2703.zip llvm-0371dff99529e93b8650281801e89bc015dc2703.tar.gz llvm-0371dff99529e93b8650281801e89bc015dc2703.tar.bz2 |
[CodeGen] Make non-COMDAT relative vtable internal instead of private (#102056)
When using the relative vtable ABI, if a vtable is not dso_local, it's
given private linkage (if not COMDAT) or hidden visibility (if COMDAT)
to make it dso_local (to place it in rodata instead of data.rel.ro), and
an alias generated with the original linkage and visibility. This alias
could later be removed from the symbol table, e.g. if using a version
script, at which point we lose all symbol information about the vtable.
Use internal linkage instead of private linkage to avoid this.
While I'm here, clarify the comment about why COMDAT vtables can't use
internal (or private) linkage, and associate it with the else block
where hidden visibility is applied instead of internal linkage.
Diffstat (limited to 'clang/lib/CodeGen/CGVTables.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGVTables.cpp | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 7f729d3..def8c4a 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -1013,7 +1013,7 @@ void CodeGenVTables::RemoveHwasanMetadata(llvm::GlobalValue *GV) const { // the VTable does not need a relocation and move into rodata. A frequent // time this can occur is for classes that should be made public from a DSO // (like in libc++). For cases like these, we can make the vtable hidden or -// private and create a public alias with the same visibility and linkage as +// internal and create a public alias with the same visibility and linkage as // the original vtable type. void CodeGenVTables::GenerateRelativeVTableAlias(llvm::GlobalVariable *VTable, llvm::StringRef AliasNameRef) { @@ -1050,15 +1050,18 @@ void CodeGenVTables::GenerateRelativeVTableAlias(llvm::GlobalVariable *VTable, VTableAlias->setVisibility(VTable->getVisibility()); VTableAlias->setUnnamedAddr(VTable->getUnnamedAddr()); - // Both of these imply dso_local for the vtable. + // Both of these will now imply dso_local for the vtable. if (!VTable->hasComdat()) { - // If this is in a comdat, then we shouldn't make the linkage private due to - // an issue in lld where private symbols can be used as the key symbol when - // choosing the prevelant group. This leads to "relocation refers to a - // symbol in a discarded section". - VTable->setLinkage(llvm::GlobalValue::PrivateLinkage); + VTable->setLinkage(llvm::GlobalValue::InternalLinkage); } else { - // We should at least make this hidden since we don't want to expose it. + // If a relocation targets an internal linkage symbol, MC will generate the + // relocation against the symbol's section instead of the symbol itself + // (see ELFObjectWriter::shouldRelocateWithSymbol). If an internal symbol is + // in a COMDAT section group, that section might be discarded, and then the + // relocation to that section will generate a linker error. We therefore + // make COMDAT vtables hidden instead of internal: they'll still not be + // public, but relocations will reference the symbol instead of the section + // and COMDAT deduplication will thus work as expected. VTable->setVisibility(llvm::GlobalValue::HiddenVisibility); } |