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:
parent
2cc01b071e
commit
7517775e7d
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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("@@") &&
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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>
|
||||
|
@ -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.
|
||||
|
36
test/MC/ELF/symver-remove.s
Normal file
36
test/MC/ELF/symver-remove.s
Normal 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:
|
Loading…
Reference in New Issue
Block a user