[llvm] d96af2e - [MC] Support .symver *, *, remove
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sat Mar 6 15:23:08 PST 2021
Author: Fangrui Song
Date: 2021-03-06T15:23:02-08:00
New Revision: d96af2ed2d6cfaa227c82a79d85733bcca4d9084
URL: https://github.com/llvm/llvm-project/commit/d96af2ed2d6cfaa227c82a79d85733bcca4d9084
DIFF: https://github.com/llvm/llvm-project/commit/d96af2ed2d6cfaa227c82a79d85733bcca4d9084.diff
LOG: [MC] Support .symver *, *, remove
As a resolution to https://sourceware.org/bugzilla/show_bug.cgi?id=25295 , GNU as
from binutils 2.35 supports the optional third argument for the .symver directive.
'remove' for a non-default version is useful:
`.symver def_v1, def at v1, remove` => def_v1 is not retained in the symbol table.
Previously the user has to strip the original symbol or specify a `local:`
version node in a version script to localize the symbol.
`.symver def, def@@v1, remove` and `.symver def, def@@@v1, remove` are supported
as well, though they are identical to `.symver def, def@@@v1`.
local/hidden are not useful so this patch does not implement them.
Added:
llvm/test/MC/ELF/symver-remove.s
Modified:
llvm/include/llvm/MC/MCAssembler.h
llvm/include/llvm/MC/MCELFStreamer.h
llvm/include/llvm/MC/MCStreamer.h
llvm/lib/MC/ELFObjectWriter.cpp
llvm/lib/MC/MCAsmStreamer.cpp
llvm/lib/MC/MCELFStreamer.cpp
llvm/lib/MC/MCParser/ELFAsmParser.cpp
llvm/lib/MC/MCStreamer.cpp
llvm/lib/Object/RecordStreamer.cpp
llvm/lib/Object/RecordStreamer.h
Removed:
################################################################################
diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h
index 63b8c4b63bcf..1f670e3973ce 100644
--- a/llvm/include/llvm/MC/MCAssembler.h
+++ b/llvm/include/llvm/MC/MCAssembler.h
@@ -212,9 +212,11 @@ class MCAssembler {
public:
struct Symver {
- StringRef Name;
- const MCSymbol *Sym;
SMLoc Loc;
+ const MCSymbol *Sym;
+ StringRef Name;
+ // True if .symver *, *@@@* or .symver *, *, remove.
+ bool KeepOriginalSym;
};
std::vector<Symver> Symvers;
diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h
index f11629d94e90..280eb7ec92cf 100644
--- a/llvm/include/llvm/MC/MCELFStreamer.h
+++ b/llvm/include/llvm/MC/MCELFStreamer.h
@@ -52,8 +52,8 @@ class MCELFStreamer : public MCObjectStreamer {
unsigned ByteAlignment) override;
void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
- void emitELFSymverDirective(StringRef AliasName,
- const MCSymbol *Aliasee) override;
+ void emitELFSymverDirective(const MCSymbol *OriginalSym, StringRef Name,
+ bool KeepOriginalSym) override;
void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index 4156d69c4c02..084d3b643d39 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -611,10 +611,8 @@ class MCStreamer {
///
/// This corresponds to an assembler statement such as:
/// .symver _start, foo@@SOME_VERSION
- /// \param AliasName - The versioned alias (i.e. "foo@@SOME_VERSION")
- /// \param Aliasee - The aliased symbol (i.e. "_start")
- virtual void emitELFSymverDirective(StringRef AliasName,
- const MCSymbol *Aliasee);
+ virtual void emitELFSymverDirective(const MCSymbol *OriginalSym,
+ StringRef Name, bool KeepOriginalSym);
/// Emit a Linker Optimization Hint (LOH) directive.
/// \param Args - Arguments of the LOH.
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp
index f6b015f7c560..e635a47680da 100644
--- a/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/llvm/lib/MC/ELFObjectWriter.cpp
@@ -1259,7 +1259,7 @@ void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
Alias->setVisibility(Symbol.getVisibility());
Alias->setOther(Symbol.getOther());
- if (!Symbol.isUndefined() && !Rest.startswith("@@@"))
+ if (!Symbol.isUndefined() && S.KeepOriginalSym)
continue;
if (Symbol.isUndefined() && Rest.startswith("@@") &&
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index e82ad28da64e..0012c10bf83b 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -141,8 +141,8 @@ class MCAsmStreamer final : public MCStreamer {
void changeSection(MCSection *Section, const MCExpr *Subsection) override;
- void emitELFSymverDirective(StringRef AliasName,
- const MCSymbol *Aliasee) override;
+ void emitELFSymverDirective(const MCSymbol *OriginalSym, StringRef Name,
+ bool KeepOriginalSym) override;
void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
@@ -490,11 +490,14 @@ void MCAsmStreamer::changeSection(MCSection *Section,
}
}
-void MCAsmStreamer::emitELFSymverDirective(StringRef AliasName,
- const MCSymbol *Aliasee) {
+void MCAsmStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
+ StringRef Name,
+ bool KeepOriginalSym) {
OS << ".symver ";
- Aliasee->print(OS, MAI);
- OS << ", " << AliasName;
+ OriginalSym->print(OS, MAI);
+ OS << ", " << Name;
+ if (!KeepOriginalSym && !Name.contains("@@@"))
+ OS << ", remove";
EmitEOL();
}
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index f51f0997a4b4..384b4278c595 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -334,10 +334,11 @@ void MCELFStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
cast<MCSymbolELF>(Symbol)->setSize(Value);
}
-void MCELFStreamer::emitELFSymverDirective(StringRef AliasName,
- const MCSymbol *Aliasee) {
- getAssembler().Symvers.push_back(
- MCAssembler::Symver{AliasName, Aliasee, getStartTokLoc()});
+void MCELFStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
+ StringRef Name,
+ bool KeepOriginalSym) {
+ getAssembler().Symvers.push_back(MCAssembler::Symver{
+ getStartTokLoc(), OriginalSym, Name, KeepOriginalSym});
}
void MCELFStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
diff --git a/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/llvm/lib/MC/MCParser/ELFAsmParser.cpp
index 7de19a067a61..5b3f0225bba9 100644
--- a/llvm/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/ELFAsmParser.cpp
@@ -790,8 +790,8 @@ bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
/// ParseDirectiveSymver
/// ::= .symver foo, bar2 at zed
bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) {
- StringRef Name;
- if (getParser().parseIdentifier(Name))
+ StringRef OriginalName, Name, Action;
+ if (getParser().parseIdentifier(OriginalName))
return TokError("expected identifier in directive");
if (getLexer().isNot(AsmToken::Comma))
@@ -806,15 +806,21 @@ bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) {
Lex();
getLexer().setAllowAtInIdentifier(AllowAtInIdentifier);
- StringRef AliasName;
- if (getParser().parseIdentifier(AliasName))
+ if (getParser().parseIdentifier(Name))
return TokError("expected identifier in directive");
- if (AliasName.find('@') == StringRef::npos)
+ if (Name.find('@') == StringRef::npos)
return TokError("expected a '@' in the name");
+ bool KeepOriginalSym = !Name.contains("@@@");
+ if (parseOptionalToken(AsmToken::Comma)) {
+ if (getParser().parseIdentifier(Action) || Action != "remove")
+ return TokError("expected 'remove'");
+ KeepOriginalSym = false;
+ }
+ (void)parseOptionalToken(AsmToken::EndOfStatement);
- MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
- getStreamer().emitELFSymverDirective(AliasName, Sym);
+ getStreamer().emitELFSymverDirective(
+ getContext().getOrCreateSymbol(OriginalName), Name, KeepOriginalSym);
return false;
}
diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index afaa57005106..ee4cce0befd8 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -1160,8 +1160,8 @@ void MCStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
}
void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
-void MCStreamer::emitELFSymverDirective(StringRef AliasName,
- const MCSymbol *Aliasee) {}
+void MCStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
+ StringRef Name, bool KeepOriginalSym) {}
void MCStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) {}
void MCStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
diff --git a/llvm/lib/Object/RecordStreamer.cpp b/llvm/lib/Object/RecordStreamer.cpp
index b2f973eff361..2d07d34bbf97 100644
--- a/llvm/lib/Object/RecordStreamer.cpp
+++ b/llvm/lib/Object/RecordStreamer.cpp
@@ -123,9 +123,10 @@ RecordStreamer::State RecordStreamer::getSymbolState(const MCSymbol *Sym) {
return SI->second;
}
-void RecordStreamer::emitELFSymverDirective(StringRef AliasName,
- const MCSymbol *Aliasee) {
- SymverAliasMap[Aliasee].push_back(AliasName);
+void RecordStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
+ StringRef Name,
+ bool KeepOriginalSym) {
+ SymverAliasMap[OriginalSym].push_back(Name);
}
iterator_range<RecordStreamer::const_symver_iterator>
diff --git a/llvm/lib/Object/RecordStreamer.h b/llvm/lib/Object/RecordStreamer.h
index 99d15f790a15..957d80f33bf4 100644
--- a/llvm/lib/Object/RecordStreamer.h
+++ b/llvm/lib/Object/RecordStreamer.h
@@ -63,8 +63,8 @@ class RecordStreamer : public MCStreamer {
void EndCOFFSymbolDef() override {}
/// Record .symver aliases for later processing.
- void emitELFSymverDirective(StringRef AliasName,
- const MCSymbol *Aliasee) override;
+ void emitELFSymverDirective(const MCSymbol *OriginalSym, StringRef Name,
+ bool KeepOriginalSym) override;
// Emit ELF .symver aliases and ensure they have the same binding as the
// defined symbol they alias with.
diff --git a/llvm/test/MC/ELF/symver-remove.s b/llvm/test/MC/ELF/symver-remove.s
new file mode 100644
index 000000000000..81257b7ca959
--- /dev/null
+++ b/llvm/test/MC/ELF/symver-remove.s
@@ -0,0 +1,36 @@
+# RUN: llvm-mc -triple=x86_64 %s | FileCheck %s --check-prefix=ASM
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t
+# RUN: llvm-readelf -s %t | FileCheck %s
+
+# ASM: .symver nondef, nondef at v1, remove
+# ASM-NEXT: nondef:
+# ASM: .symver def0, def0@@v2, remove
+# ASM-NEXT: .symver def1, def1@@@v2{{$}}
+# ASM-NEXT: def0:
+# ASM-NEXT: def1:
+# ASM: .symver def2, def2 at v1, remove
+# ASM-NEXT: .symver def2, def2@@v2{{$}}
+# ASM-NEXT: def2:
+
+# CHECK: 1: 0000000000000000 0 NOTYPE GLOBAL DEFAULT [[#]] nondef at v1
+# CHECK-NEXT: 2: 0000000000000000 0 NOTYPE GLOBAL DEFAULT [[#]] def0@@v2
+# CHECK-NEXT: 3: 0000000000000000 0 NOTYPE GLOBAL DEFAULT [[#]] def1@@v2
+# CHECK-NEXT: 4: 0000000000000000 0 NOTYPE GLOBAL DEFAULT [[#]] def2 at v1
+# CHECK-NEXT: 5: 0000000000000000 0 NOTYPE GLOBAL DEFAULT [[#]] def2@@v2
+# CHECK-NOT: {{.}}
+
+.globl nondef
+.symver nondef, nondef at v1, remove
+nondef:
+
+.globl def0, def1, def2
+.symver def0, def0@@v2, remove
+.symver def1, def1@@@v2, remove
+def0:
+def1:
+
+## Giving multiple versions to the same original symbol is not useful.
+## This test just documents the behavior.
+.symver def2, def2 at v1, remove
+.symver def2, def2@@v2
+def2:
More information about the llvm-commits
mailing list