1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 12:12:47 +01:00

[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@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.
This commit is contained in:
Fangrui Song 2021-03-06 15:23:02 -08:00
parent 2cc01b071e
commit 7517775e7d
11 changed files with 80 additions and 33 deletions

View File

@ -212,9 +212,11 @@ private:
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;

View File

@ -52,8 +52,8 @@ public:
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;

View File

@ -611,10 +611,8 @@ public:
///
/// 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.

View File

@ -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("@@") &&

View File

@ -141,8 +141,8 @@ public:
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();
}

View File

@ -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,

View File

@ -790,8 +790,8 @@ bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
/// ParseDirectiveSymver
/// ::= .symver foo, bar2@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;
}

View File

@ -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,

View File

@ -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>

View File

@ -63,8 +63,8 @@ public:
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.

View File

@ -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@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@v1, remove
# ASM-NEXT: .symver def2, def2@@v2{{$}}
# ASM-NEXT: def2:
# CHECK: 1: 0000000000000000 0 NOTYPE GLOBAL DEFAULT [[#]] nondef@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@v1
# CHECK-NEXT: 5: 0000000000000000 0 NOTYPE GLOBAL DEFAULT [[#]] def2@@v2
# CHECK-NOT: {{.}}
.globl nondef
.symver nondef, nondef@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@v1, remove
.symver def2, def2@@v2
def2: