[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