2010-07-13 05:23:32 +08:00
|
|
|
//===- ELFAsmParser.cpp - ELF Assembly Parser -----------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-02-08 07:02:00 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
2017-06-07 11:48:56 +08:00
|
|
|
#include "llvm/BinaryFormat/ELF.h"
|
2010-07-17 12:29:04 +08:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
2010-07-13 05:23:32 +08:00
|
|
|
#include "llvm/MC/MCContext.h"
|
2017-02-08 07:02:00 +08:00
|
|
|
#include "llvm/MC/MCDirectives.h"
|
2010-10-27 23:18:17 +08:00
|
|
|
#include "llvm/MC/MCExpr.h"
|
2010-07-13 05:23:32 +08:00
|
|
|
#include "llvm/MC/MCParser/MCAsmLexer.h"
|
2017-02-08 07:02:00 +08:00
|
|
|
#include "llvm/MC/MCParser/MCAsmParser.h"
|
|
|
|
#include "llvm/MC/MCParser/MCAsmParserExtension.h"
|
|
|
|
#include "llvm/MC/MCSection.h"
|
2010-07-17 12:29:04 +08:00
|
|
|
#include "llvm/MC/MCSectionELF.h"
|
|
|
|
#include "llvm/MC/MCStreamer.h"
|
2017-02-08 07:02:00 +08:00
|
|
|
#include "llvm/MC/MCSymbol.h"
|
2015-06-02 08:25:12 +08:00
|
|
|
#include "llvm/MC/MCSymbolELF.h"
|
2017-02-08 07:02:00 +08:00
|
|
|
#include "llvm/MC/SectionKind.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/MathExtras.h"
|
|
|
|
#include "llvm/Support/SMLoc.h"
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <utility>
|
|
|
|
|
2010-07-13 05:23:32 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
class ELFAsmParser : public MCAsmParserExtension {
|
2013-01-16 08:50:52 +08:00
|
|
|
template<bool (ELFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
|
2013-02-21 06:21:35 +08:00
|
|
|
void addDirectiveHandler(StringRef Directive) {
|
2013-01-16 08:50:52 +08:00
|
|
|
MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
|
|
|
|
this, HandleDirective<ELFAsmParser, HandlerMethod>);
|
|
|
|
|
2013-02-21 06:21:35 +08:00
|
|
|
getParser().addDirectiveHandler(Directive, Handler);
|
2010-07-19 06:22:07 +08:00
|
|
|
}
|
|
|
|
|
2013-10-16 09:05:45 +08:00
|
|
|
bool ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags,
|
|
|
|
SectionKind Kind);
|
2010-07-13 05:23:32 +08:00
|
|
|
|
|
|
|
public:
|
2013-10-16 09:05:45 +08:00
|
|
|
ELFAsmParser() { BracketExpressionsSupported = true; }
|
2010-07-13 05:23:32 +08:00
|
|
|
|
2014-03-08 15:14:16 +08:00
|
|
|
void Initialize(MCAsmParser &Parser) override {
|
2010-07-13 05:23:32 +08:00
|
|
|
// Call the base implementation.
|
|
|
|
this->MCAsmParserExtension::Initialize(Parser);
|
|
|
|
|
2013-02-21 06:21:35 +08:00
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data");
|
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text");
|
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss");
|
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata");
|
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata");
|
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss");
|
|
|
|
addDirectiveHandler<
|
2011-07-26 01:11:29 +08:00
|
|
|
&ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel");
|
2013-02-21 06:21:35 +08:00
|
|
|
addDirectiveHandler<
|
2011-07-26 01:11:29 +08:00
|
|
|
&ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro");
|
2013-02-21 06:21:35 +08:00
|
|
|
addDirectiveHandler<
|
2011-07-26 01:11:29 +08:00
|
|
|
&ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame");
|
2013-02-21 06:21:35 +08:00
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section");
|
|
|
|
addDirectiveHandler<
|
2011-07-26 01:11:29 +08:00
|
|
|
&ELFAsmParser::ParseDirectivePushSection>(".pushsection");
|
2013-02-21 06:21:35 +08:00
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection");
|
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size");
|
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous");
|
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type");
|
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident");
|
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver");
|
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseDirectiveVersion>(".version");
|
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref");
|
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
|
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local");
|
|
|
|
addDirectiveHandler<
|
2011-07-26 01:55:35 +08:00
|
|
|
&ELFAsmParser::ParseDirectiveSymbolAttribute>(".protected");
|
2013-02-21 06:21:35 +08:00
|
|
|
addDirectiveHandler<
|
2011-07-26 01:55:35 +08:00
|
|
|
&ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal");
|
2013-02-21 06:21:35 +08:00
|
|
|
addDirectiveHandler<
|
2011-07-26 01:55:35 +08:00
|
|
|
&ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden");
|
2013-04-18 05:18:16 +08:00
|
|
|
addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection");
|
2010-07-13 05:23:32 +08:00
|
|
|
}
|
|
|
|
|
2010-09-16 05:48:40 +08:00
|
|
|
// FIXME: Part of this logic is duplicated in the MCELFStreamer. What is
|
|
|
|
// the best way for us to get access to it?
|
2010-07-13 05:23:32 +08:00
|
|
|
bool ParseSectionDirectiveData(StringRef, SMLoc) {
|
2011-01-23 12:28:49 +08:00
|
|
|
return ParseSectionSwitch(".data", ELF::SHT_PROGBITS,
|
2015-11-18 14:02:15 +08:00
|
|
|
ELF::SHF_WRITE | ELF::SHF_ALLOC,
|
|
|
|
SectionKind::getData());
|
2010-07-13 05:23:32 +08:00
|
|
|
}
|
|
|
|
bool ParseSectionDirectiveText(StringRef, SMLoc) {
|
2011-01-23 12:28:49 +08:00
|
|
|
return ParseSectionSwitch(".text", ELF::SHT_PROGBITS,
|
2011-01-23 12:43:11 +08:00
|
|
|
ELF::SHF_EXECINSTR |
|
|
|
|
ELF::SHF_ALLOC, SectionKind::getText());
|
2010-07-13 05:23:32 +08:00
|
|
|
}
|
2010-07-21 05:12:46 +08:00
|
|
|
bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
|
2011-01-23 12:28:49 +08:00
|
|
|
return ParseSectionSwitch(".bss", ELF::SHT_NOBITS,
|
2011-01-23 12:43:11 +08:00
|
|
|
ELF::SHF_WRITE |
|
|
|
|
ELF::SHF_ALLOC, SectionKind::getBSS());
|
2010-07-21 05:12:46 +08:00
|
|
|
}
|
|
|
|
bool ParseSectionDirectiveRoData(StringRef, SMLoc) {
|
2011-01-23 12:28:49 +08:00
|
|
|
return ParseSectionSwitch(".rodata", ELF::SHT_PROGBITS,
|
2011-01-23 12:43:11 +08:00
|
|
|
ELF::SHF_ALLOC,
|
2010-07-21 05:12:46 +08:00
|
|
|
SectionKind::getReadOnly());
|
|
|
|
}
|
|
|
|
bool ParseSectionDirectiveTData(StringRef, SMLoc) {
|
2011-01-23 12:28:49 +08:00
|
|
|
return ParseSectionSwitch(".tdata", ELF::SHT_PROGBITS,
|
2011-01-23 12:43:11 +08:00
|
|
|
ELF::SHF_ALLOC |
|
|
|
|
ELF::SHF_TLS | ELF::SHF_WRITE,
|
2010-07-21 05:12:46 +08:00
|
|
|
SectionKind::getThreadData());
|
|
|
|
}
|
|
|
|
bool ParseSectionDirectiveTBSS(StringRef, SMLoc) {
|
2011-01-23 12:28:49 +08:00
|
|
|
return ParseSectionSwitch(".tbss", ELF::SHT_NOBITS,
|
2011-01-23 12:43:11 +08:00
|
|
|
ELF::SHF_ALLOC |
|
|
|
|
ELF::SHF_TLS | ELF::SHF_WRITE,
|
2010-07-21 05:12:46 +08:00
|
|
|
SectionKind::getThreadBSS());
|
|
|
|
}
|
|
|
|
bool ParseSectionDirectiveDataRel(StringRef, SMLoc) {
|
2011-01-23 12:28:49 +08:00
|
|
|
return ParseSectionSwitch(".data.rel", ELF::SHT_PROGBITS,
|
2015-11-18 14:02:15 +08:00
|
|
|
ELF::SHF_ALLOC | ELF::SHF_WRITE,
|
|
|
|
SectionKind::getData());
|
2010-07-21 05:12:46 +08:00
|
|
|
}
|
|
|
|
bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) {
|
2011-01-23 12:28:49 +08:00
|
|
|
return ParseSectionSwitch(".data.rel.ro", ELF::SHT_PROGBITS,
|
2011-01-23 12:43:11 +08:00
|
|
|
ELF::SHF_ALLOC |
|
|
|
|
ELF::SHF_WRITE,
|
2010-07-21 05:12:46 +08:00
|
|
|
SectionKind::getReadOnlyWithRel());
|
|
|
|
}
|
|
|
|
bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) {
|
2011-01-23 12:28:49 +08:00
|
|
|
return ParseSectionSwitch(".eh_frame", ELF::SHT_PROGBITS,
|
2015-11-18 14:02:15 +08:00
|
|
|
ELF::SHF_ALLOC | ELF::SHF_WRITE,
|
|
|
|
SectionKind::getData());
|
2010-07-21 05:12:46 +08:00
|
|
|
}
|
2011-02-16 09:08:29 +08:00
|
|
|
bool ParseDirectivePushSection(StringRef, SMLoc);
|
|
|
|
bool ParseDirectivePopSection(StringRef, SMLoc);
|
2010-07-17 12:29:04 +08:00
|
|
|
bool ParseDirectiveSection(StringRef, SMLoc);
|
|
|
|
bool ParseDirectiveSize(StringRef, SMLoc);
|
2010-09-03 02:53:37 +08:00
|
|
|
bool ParseDirectivePrevious(StringRef, SMLoc);
|
2010-10-09 11:47:55 +08:00
|
|
|
bool ParseDirectiveType(StringRef, SMLoc);
|
2010-10-27 03:35:47 +08:00
|
|
|
bool ParseDirectiveIdent(StringRef, SMLoc);
|
2010-10-27 23:18:17 +08:00
|
|
|
bool ParseDirectiveSymver(StringRef, SMLoc);
|
2012-05-12 22:30:47 +08:00
|
|
|
bool ParseDirectiveVersion(StringRef, SMLoc);
|
2010-11-01 22:28:48 +08:00
|
|
|
bool ParseDirectiveWeakref(StringRef, SMLoc);
|
2011-07-26 01:55:35 +08:00
|
|
|
bool ParseDirectiveSymbolAttribute(StringRef, SMLoc);
|
2013-04-18 05:18:16 +08:00
|
|
|
bool ParseDirectiveSubsection(StringRef, SMLoc);
|
2010-09-17 01:05:55 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
bool ParseSectionName(StringRef &SectionName);
|
2014-06-19 23:52:37 +08:00
|
|
|
bool ParseSectionArguments(bool IsPush, SMLoc loc);
|
2014-03-01 14:21:00 +08:00
|
|
|
unsigned parseSunStyleSectionFlags();
|
2017-02-01 07:07:08 +08:00
|
|
|
bool maybeParseSectionType(StringRef &TypeName);
|
2017-02-01 07:26:32 +08:00
|
|
|
bool parseMergeSize(int64_t &Size);
|
|
|
|
bool parseGroup(StringRef &GroupName);
|
2017-03-15 03:28:51 +08:00
|
|
|
bool parseMetadataSym(MCSymbolELF *&Associated);
|
2017-02-01 07:26:32 +08:00
|
|
|
bool maybeParseUniqueID(int64_t &UniqueID);
|
2010-07-13 05:23:32 +08:00
|
|
|
};
|
|
|
|
|
2017-02-08 07:02:00 +08:00
|
|
|
} // end anonymous namespace
|
2010-07-13 05:23:32 +08:00
|
|
|
|
2011-07-26 01:55:35 +08:00
|
|
|
/// ParseDirectiveSymbolAttribute
|
|
|
|
/// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ]
|
|
|
|
bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
|
|
|
|
MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
|
|
|
|
.Case(".weak", MCSA_Weak)
|
|
|
|
.Case(".local", MCSA_Local)
|
|
|
|
.Case(".hidden", MCSA_Hidden)
|
|
|
|
.Case(".internal", MCSA_Internal)
|
|
|
|
.Case(".protected", MCSA_Protected)
|
|
|
|
.Default(MCSA_Invalid);
|
|
|
|
assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
|
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
2017-02-08 07:02:00 +08:00
|
|
|
while (true) {
|
2011-07-26 01:55:35 +08:00
|
|
|
StringRef Name;
|
|
|
|
|
2013-02-21 06:21:35 +08:00
|
|
|
if (getParser().parseIdentifier(Name))
|
2011-07-26 01:55:35 +08:00
|
|
|
return TokError("expected identifier in directive");
|
|
|
|
|
2015-05-19 02:43:14 +08:00
|
|
|
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
|
2011-07-26 01:55:35 +08:00
|
|
|
|
|
|
|
getStreamer().EmitSymbolAttribute(Sym, Attr);
|
|
|
|
|
|
|
|
if (getLexer().is(AsmToken::EndOfStatement))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (getLexer().isNot(AsmToken::Comma))
|
|
|
|
return TokError("unexpected token in directive");
|
|
|
|
Lex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Lex();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-07-13 05:23:32 +08:00
|
|
|
bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type,
|
|
|
|
unsigned Flags, SectionKind Kind) {
|
2014-04-24 14:44:33 +08:00
|
|
|
const MCExpr *Subsection = nullptr;
|
2013-04-18 05:18:16 +08:00
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
|
|
|
if (getParser().parseExpression(Subsection))
|
|
|
|
return true;
|
|
|
|
}
|
2016-07-11 20:42:14 +08:00
|
|
|
Lex();
|
2010-07-13 05:23:32 +08:00
|
|
|
|
2015-01-30 01:33:21 +08:00
|
|
|
getStreamer().SwitchSection(getContext().getELFSection(Section, Type, Flags),
|
2013-04-18 05:18:16 +08:00
|
|
|
Subsection);
|
2010-07-13 05:23:32 +08:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-07-17 12:29:04 +08:00
|
|
|
bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) {
|
2010-07-17 11:09:18 +08:00
|
|
|
StringRef Name;
|
2013-02-21 06:21:35 +08:00
|
|
|
if (getParser().parseIdentifier(Name))
|
2010-07-17 11:09:18 +08:00
|
|
|
return TokError("expected identifier in directive");
|
2015-06-02 08:25:12 +08:00
|
|
|
MCSymbolELF *Sym = cast<MCSymbolELF>(getContext().getOrCreateSymbol(Name));
|
2010-07-17 11:09:18 +08:00
|
|
|
|
|
|
|
if (getLexer().isNot(AsmToken::Comma))
|
|
|
|
return TokError("unexpected token in directive");
|
|
|
|
Lex();
|
|
|
|
|
|
|
|
const MCExpr *Expr;
|
2013-02-21 06:21:35 +08:00
|
|
|
if (getParser().parseExpression(Expr))
|
2010-07-17 11:09:18 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement))
|
|
|
|
return TokError("unexpected token in directive");
|
2016-07-18 23:24:03 +08:00
|
|
|
Lex();
|
2010-07-17 11:09:18 +08:00
|
|
|
|
2015-06-02 08:25:12 +08:00
|
|
|
getStreamer().emitELFSize(Sym, Expr);
|
2010-07-17 11:09:18 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-09-17 01:05:55 +08:00
|
|
|
bool ELFAsmParser::ParseSectionName(StringRef &SectionName) {
|
|
|
|
// A section name can contain -, so we cannot just use
|
2013-02-21 06:21:35 +08:00
|
|
|
// parseIdentifier.
|
2010-09-17 01:05:55 +08:00
|
|
|
SMLoc FirstLoc = getLexer().getLoc();
|
|
|
|
unsigned Size = 0;
|
|
|
|
|
2011-01-25 02:02:54 +08:00
|
|
|
if (getLexer().is(AsmToken::String)) {
|
|
|
|
SectionName = getTok().getIdentifier();
|
|
|
|
Lex();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-02-08 07:02:00 +08:00
|
|
|
while (true) {
|
2010-09-17 01:05:55 +08:00
|
|
|
SMLoc PrevLoc = getLexer().getLoc();
|
2016-03-22 19:23:15 +08:00
|
|
|
if (getLexer().is(AsmToken::Comma) ||
|
|
|
|
getLexer().is(AsmToken::EndOfStatement))
|
|
|
|
break;
|
|
|
|
|
|
|
|
unsigned CurSize;
|
|
|
|
if (getLexer().is(AsmToken::String)) {
|
2011-01-25 02:02:54 +08:00
|
|
|
CurSize = getTok().getIdentifier().size() + 2;
|
|
|
|
Lex();
|
|
|
|
} else if (getLexer().is(AsmToken::Identifier)) {
|
|
|
|
CurSize = getTok().getIdentifier().size();
|
|
|
|
Lex();
|
|
|
|
} else {
|
2016-03-22 19:23:15 +08:00
|
|
|
CurSize = getTok().getString().size();
|
|
|
|
Lex();
|
2011-01-25 02:02:54 +08:00
|
|
|
}
|
2010-09-17 01:05:55 +08:00
|
|
|
Size += CurSize;
|
|
|
|
SectionName = StringRef(FirstLoc.getPointer(), Size);
|
|
|
|
|
|
|
|
// Make sure the following token is adjacent.
|
|
|
|
if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer())
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (Size == 0)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-09-16 03:53:20 +08:00
|
|
|
static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) {
|
|
|
|
unsigned flags = 0;
|
2010-11-25 23:32:56 +08:00
|
|
|
|
2016-12-15 15:59:15 +08:00
|
|
|
// If a valid numerical value is set for the section flag, use it verbatim
|
|
|
|
if (!flagsStr.getAsInteger(0, flags))
|
|
|
|
return flags;
|
|
|
|
|
2016-06-26 22:49:00 +08:00
|
|
|
for (char i : flagsStr) {
|
|
|
|
switch (i) {
|
2010-11-25 23:32:56 +08:00
|
|
|
case 'a':
|
2011-01-23 12:43:11 +08:00
|
|
|
flags |= ELF::SHF_ALLOC;
|
2010-11-25 23:32:56 +08:00
|
|
|
break;
|
2013-09-16 03:53:20 +08:00
|
|
|
case 'e':
|
|
|
|
flags |= ELF::SHF_EXCLUDE;
|
|
|
|
break;
|
2010-11-25 23:32:56 +08:00
|
|
|
case 'x':
|
2011-01-23 12:43:11 +08:00
|
|
|
flags |= ELF::SHF_EXECINSTR;
|
2010-11-25 23:32:56 +08:00
|
|
|
break;
|
|
|
|
case 'w':
|
2011-01-23 12:43:11 +08:00
|
|
|
flags |= ELF::SHF_WRITE;
|
2010-11-25 23:32:56 +08:00
|
|
|
break;
|
2017-04-05 06:35:08 +08:00
|
|
|
case 'o':
|
2017-02-09 22:59:20 +08:00
|
|
|
flags |= ELF::SHF_LINK_ORDER;
|
|
|
|
break;
|
2010-11-25 23:32:56 +08:00
|
|
|
case 'M':
|
2011-01-23 12:43:11 +08:00
|
|
|
flags |= ELF::SHF_MERGE;
|
2010-11-25 23:32:56 +08:00
|
|
|
break;
|
|
|
|
case 'S':
|
2011-01-23 12:43:11 +08:00
|
|
|
flags |= ELF::SHF_STRINGS;
|
2010-11-25 23:32:56 +08:00
|
|
|
break;
|
|
|
|
case 'T':
|
2011-01-23 12:43:11 +08:00
|
|
|
flags |= ELF::SHF_TLS;
|
2010-11-25 23:32:56 +08:00
|
|
|
break;
|
|
|
|
case 'c':
|
2011-01-23 12:43:11 +08:00
|
|
|
flags |= ELF::XCORE_SHF_CP_SECTION;
|
2010-11-25 23:32:56 +08:00
|
|
|
break;
|
|
|
|
case 'd':
|
2011-01-23 12:43:11 +08:00
|
|
|
flags |= ELF::XCORE_SHF_DP_SECTION;
|
2010-11-25 23:32:56 +08:00
|
|
|
break;
|
2016-12-15 15:59:08 +08:00
|
|
|
case 'y':
|
|
|
|
flags |= ELF::SHF_ARM_PURECODE;
|
|
|
|
break;
|
2010-11-25 23:32:56 +08:00
|
|
|
case 'G':
|
2011-01-23 12:43:11 +08:00
|
|
|
flags |= ELF::SHF_GROUP;
|
2010-11-25 23:32:56 +08:00
|
|
|
break;
|
2013-09-16 03:24:16 +08:00
|
|
|
case '?':
|
|
|
|
*UseLastGroup = true;
|
|
|
|
break;
|
2010-11-25 23:32:56 +08:00
|
|
|
default:
|
2013-09-16 03:53:20 +08:00
|
|
|
return -1U;
|
2010-11-25 23:32:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
2014-03-01 14:21:00 +08:00
|
|
|
unsigned ELFAsmParser::parseSunStyleSectionFlags() {
|
|
|
|
unsigned flags = 0;
|
|
|
|
while (getLexer().is(AsmToken::Hash)) {
|
|
|
|
Lex(); // Eat the #.
|
|
|
|
|
|
|
|
if (!getLexer().is(AsmToken::Identifier))
|
|
|
|
return -1U;
|
|
|
|
|
|
|
|
StringRef flagId = getTok().getIdentifier();
|
|
|
|
if (flagId == "alloc")
|
|
|
|
flags |= ELF::SHF_ALLOC;
|
|
|
|
else if (flagId == "execinstr")
|
|
|
|
flags |= ELF::SHF_EXECINSTR;
|
|
|
|
else if (flagId == "write")
|
|
|
|
flags |= ELF::SHF_WRITE;
|
|
|
|
else if (flagId == "tls")
|
|
|
|
flags |= ELF::SHF_TLS;
|
|
|
|
else
|
|
|
|
return -1U;
|
|
|
|
|
|
|
|
Lex(); // Eat the flag.
|
|
|
|
|
|
|
|
if (!getLexer().is(AsmToken::Comma))
|
|
|
|
break;
|
|
|
|
Lex(); // Eat the comma.
|
|
|
|
}
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-16 09:08:29 +08:00
|
|
|
bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) {
|
|
|
|
getStreamer().PushSection();
|
|
|
|
|
2014-06-19 23:52:37 +08:00
|
|
|
if (ParseSectionArguments(/*IsPush=*/true, loc)) {
|
2011-02-16 09:08:29 +08:00
|
|
|
getStreamer().PopSection();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) {
|
|
|
|
if (!getStreamer().PopSection())
|
|
|
|
return TokError(".popsection without corresponding .pushsection");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-07-17 12:29:04 +08:00
|
|
|
// FIXME: This is a work in progress.
|
2014-06-19 23:52:37 +08:00
|
|
|
bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) {
|
|
|
|
return ParseSectionArguments(/*IsPush=*/false, loc);
|
2013-04-18 05:18:16 +08:00
|
|
|
}
|
|
|
|
|
2017-02-01 07:07:08 +08:00
|
|
|
bool ELFAsmParser::maybeParseSectionType(StringRef &TypeName) {
|
|
|
|
MCAsmLexer &L = getLexer();
|
|
|
|
if (L.isNot(AsmToken::Comma))
|
|
|
|
return false;
|
|
|
|
Lex();
|
|
|
|
if (L.isNot(AsmToken::At) && L.isNot(AsmToken::Percent) &&
|
2017-03-17 19:10:17 +08:00
|
|
|
L.isNot(AsmToken::String)) {
|
|
|
|
if (L.getAllowAtInIdentifier())
|
|
|
|
return TokError("expected '@<type>', '%<type>' or \"<type>\"");
|
|
|
|
else
|
|
|
|
return TokError("expected '%<type>' or \"<type>\"");
|
|
|
|
}
|
2017-02-01 07:07:08 +08:00
|
|
|
if (!L.is(AsmToken::String))
|
|
|
|
Lex();
|
2017-03-10 16:22:13 +08:00
|
|
|
if (L.is(AsmToken::Integer)) {
|
|
|
|
TypeName = getTok().getString();
|
|
|
|
Lex();
|
|
|
|
} else if (getParser().parseIdentifier(TypeName))
|
2017-02-01 07:07:08 +08:00
|
|
|
return TokError("expected identifier in directive");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-02-01 07:26:32 +08:00
|
|
|
bool ELFAsmParser::parseMergeSize(int64_t &Size) {
|
|
|
|
if (getLexer().isNot(AsmToken::Comma))
|
|
|
|
return TokError("expected the entry size");
|
|
|
|
Lex();
|
|
|
|
if (getParser().parseAbsoluteExpression(Size))
|
|
|
|
return true;
|
|
|
|
if (Size <= 0)
|
|
|
|
return TokError("entry size must be positive");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ELFAsmParser::parseGroup(StringRef &GroupName) {
|
|
|
|
MCAsmLexer &L = getLexer();
|
|
|
|
if (L.isNot(AsmToken::Comma))
|
|
|
|
return TokError("expected group name");
|
|
|
|
Lex();
|
|
|
|
if (getParser().parseIdentifier(GroupName))
|
|
|
|
return true;
|
|
|
|
if (L.is(AsmToken::Comma)) {
|
|
|
|
Lex();
|
|
|
|
StringRef Linkage;
|
|
|
|
if (getParser().parseIdentifier(Linkage))
|
|
|
|
return true;
|
|
|
|
if (Linkage != "comdat")
|
|
|
|
return TokError("Linkage must be 'comdat'");
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-03-15 03:28:51 +08:00
|
|
|
bool ELFAsmParser::parseMetadataSym(MCSymbolELF *&Associated) {
|
2017-02-09 22:59:20 +08:00
|
|
|
MCAsmLexer &L = getLexer();
|
|
|
|
if (L.isNot(AsmToken::Comma))
|
|
|
|
return TokError("expected metadata symbol");
|
|
|
|
Lex();
|
|
|
|
StringRef Name;
|
|
|
|
if (getParser().parseIdentifier(Name))
|
|
|
|
return true;
|
2017-03-15 03:28:51 +08:00
|
|
|
Associated = dyn_cast_or_null<MCSymbolELF>(getContext().lookupSymbol(Name));
|
|
|
|
if (!Associated || !Associated->isInSection())
|
2017-02-09 22:59:20 +08:00
|
|
|
return TokError("symbol is not in a section: " + Name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-02-01 07:26:32 +08:00
|
|
|
bool ELFAsmParser::maybeParseUniqueID(int64_t &UniqueID) {
|
|
|
|
MCAsmLexer &L = getLexer();
|
|
|
|
if (L.isNot(AsmToken::Comma))
|
|
|
|
return false;
|
|
|
|
Lex();
|
|
|
|
StringRef UniqueStr;
|
|
|
|
if (getParser().parseIdentifier(UniqueStr))
|
|
|
|
return TokError("expected identifier in directive");
|
|
|
|
if (UniqueStr != "unique")
|
|
|
|
return TokError("expected 'unique'");
|
|
|
|
if (L.isNot(AsmToken::Comma))
|
|
|
|
return TokError("expected commma");
|
|
|
|
Lex();
|
|
|
|
if (getParser().parseAbsoluteExpression(UniqueID))
|
|
|
|
return true;
|
|
|
|
if (UniqueID < 0)
|
|
|
|
return TokError("unique id must be positive");
|
|
|
|
if (!isUInt<32>(UniqueID) || UniqueID == ~0U)
|
|
|
|
return TokError("unique id is too large");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-03-22 21:35:41 +08:00
|
|
|
static bool hasPrefix(StringRef SectionName, StringRef Prefix) {
|
|
|
|
return SectionName.startswith(Prefix) || SectionName == Prefix.drop_back();
|
|
|
|
}
|
|
|
|
|
2014-06-19 23:52:37 +08:00
|
|
|
bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
|
2010-07-17 12:29:04 +08:00
|
|
|
StringRef SectionName;
|
2010-09-17 01:05:55 +08:00
|
|
|
|
|
|
|
if (ParseSectionName(SectionName))
|
2010-07-17 12:29:04 +08:00
|
|
|
return TokError("expected identifier in directive");
|
|
|
|
|
|
|
|
StringRef TypeName;
|
|
|
|
int64_t Size = 0;
|
2010-11-12 02:13:52 +08:00
|
|
|
StringRef GroupName;
|
2010-11-25 23:32:56 +08:00
|
|
|
unsigned Flags = 0;
|
2014-04-24 14:44:33 +08:00
|
|
|
const MCExpr *Subsection = nullptr;
|
2013-09-16 03:24:16 +08:00
|
|
|
bool UseLastGroup = false;
|
2015-02-18 04:48:01 +08:00
|
|
|
StringRef UniqueStr;
|
2017-03-15 03:28:51 +08:00
|
|
|
MCSymbolELF *Associated = nullptr;
|
2015-04-05 02:02:01 +08:00
|
|
|
int64_t UniqueID = ~0;
|
2010-11-25 23:32:56 +08:00
|
|
|
|
|
|
|
// Set the defaults first.
|
[MC] Set defaults based on section names and support name suffixes
Set correct default flags and section type based on its name for .text,
.data, .bss, .init_array, .fini_array, .preinit_array, .tdata, and .tbss
and support section name suffixes for .data.*, .rodata.*, .text.*,
.bss.*, .tdata.* and .tbss.* which matches the behavior of GAS.
Fixes PR31888.
Differential Revision: https://reviews.llvm.org/D30229
llvm-svn: 299484
2017-04-05 07:32:45 +08:00
|
|
|
if (hasPrefix(SectionName, ".rodata.") || SectionName == ".rodata1")
|
2011-01-23 12:43:11 +08:00
|
|
|
Flags |= ELF::SHF_ALLOC;
|
[MC] Set defaults based on section names and support name suffixes
Set correct default flags and section type based on its name for .text,
.data, .bss, .init_array, .fini_array, .preinit_array, .tdata, and .tbss
and support section name suffixes for .data.*, .rodata.*, .text.*,
.bss.*, .tdata.* and .tbss.* which matches the behavior of GAS.
Fixes PR31888.
Differential Revision: https://reviews.llvm.org/D30229
llvm-svn: 299484
2017-04-05 07:32:45 +08:00
|
|
|
if (SectionName == ".fini" || SectionName == ".init" ||
|
|
|
|
hasPrefix(SectionName, ".text."))
|
|
|
|
Flags |= ELF::SHF_ALLOC | ELF::SHF_EXECINSTR;
|
|
|
|
if (hasPrefix(SectionName, ".data.") || SectionName == ".data1" ||
|
|
|
|
hasPrefix(SectionName, ".bss.") ||
|
|
|
|
hasPrefix(SectionName, ".init_array.") ||
|
|
|
|
hasPrefix(SectionName, ".fini_array.") ||
|
|
|
|
hasPrefix(SectionName, ".preinit_array."))
|
|
|
|
Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE;
|
|
|
|
if (hasPrefix(SectionName, ".tdata.") ||
|
|
|
|
hasPrefix(SectionName, ".tbss."))
|
|
|
|
Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS;
|
2010-11-25 23:32:56 +08:00
|
|
|
|
2010-07-17 12:29:04 +08:00
|
|
|
if (getLexer().is(AsmToken::Comma)) {
|
|
|
|
Lex();
|
|
|
|
|
2013-04-18 05:18:16 +08:00
|
|
|
if (IsPush && getLexer().isNot(AsmToken::String)) {
|
|
|
|
if (getParser().parseExpression(Subsection))
|
|
|
|
return true;
|
|
|
|
if (getLexer().isNot(AsmToken::Comma))
|
|
|
|
goto EndStmt;
|
|
|
|
Lex();
|
|
|
|
}
|
2010-07-17 12:29:04 +08:00
|
|
|
|
2014-03-01 14:21:00 +08:00
|
|
|
unsigned extraFlags;
|
|
|
|
|
|
|
|
if (getLexer().isNot(AsmToken::String)) {
|
|
|
|
if (!getContext().getAsmInfo()->usesSunStyleELFSectionSwitchSyntax()
|
|
|
|
|| getLexer().isNot(AsmToken::Hash))
|
|
|
|
return TokError("expected string in directive");
|
|
|
|
extraFlags = parseSunStyleSectionFlags();
|
|
|
|
} else {
|
|
|
|
StringRef FlagsStr = getTok().getStringContents();
|
|
|
|
Lex();
|
|
|
|
extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup);
|
|
|
|
}
|
2010-07-17 12:29:04 +08:00
|
|
|
|
2013-09-16 03:53:20 +08:00
|
|
|
if (extraFlags == -1U)
|
2010-11-25 23:32:56 +08:00
|
|
|
return TokError("unknown flag");
|
|
|
|
Flags |= extraFlags;
|
|
|
|
|
2011-01-23 12:43:11 +08:00
|
|
|
bool Mergeable = Flags & ELF::SHF_MERGE;
|
|
|
|
bool Group = Flags & ELF::SHF_GROUP;
|
2013-09-16 03:24:16 +08:00
|
|
|
if (Group && UseLastGroup)
|
|
|
|
return TokError("Section cannot specifiy a group name while also acting "
|
|
|
|
"as a member of the last group");
|
2010-10-29 05:33:33 +08:00
|
|
|
|
2017-02-01 07:07:08 +08:00
|
|
|
if (maybeParseSectionType(TypeName))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
MCAsmLexer &L = getLexer();
|
|
|
|
if (TypeName.empty()) {
|
2010-10-29 05:33:33 +08:00
|
|
|
if (Mergeable)
|
|
|
|
return TokError("Mergeable section must specify the type");
|
|
|
|
if (Group)
|
|
|
|
return TokError("Group section must specify the type");
|
2017-02-01 07:07:08 +08:00
|
|
|
if (L.isNot(AsmToken::EndOfStatement))
|
|
|
|
return TokError("unexpected token in directive");
|
|
|
|
}
|
2010-10-29 05:33:33 +08:00
|
|
|
|
2017-02-01 07:26:32 +08:00
|
|
|
if (Mergeable)
|
|
|
|
if (parseMergeSize(Size))
|
2017-02-01 07:07:08 +08:00
|
|
|
return true;
|
2017-02-01 07:26:32 +08:00
|
|
|
if (Group)
|
|
|
|
if (parseGroup(GroupName))
|
2017-02-01 07:07:08 +08:00
|
|
|
return true;
|
2017-02-09 22:59:20 +08:00
|
|
|
if (Flags & ELF::SHF_LINK_ORDER)
|
|
|
|
if (parseMetadataSym(Associated))
|
|
|
|
return true;
|
2017-02-01 07:26:32 +08:00
|
|
|
if (maybeParseUniqueID(UniqueID))
|
|
|
|
return true;
|
2010-07-17 12:29:04 +08:00
|
|
|
}
|
|
|
|
|
2013-04-18 05:18:16 +08:00
|
|
|
EndStmt:
|
2010-07-17 12:29:04 +08:00
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement))
|
|
|
|
return TokError("unexpected token in directive");
|
2016-07-18 23:24:03 +08:00
|
|
|
Lex();
|
2010-07-17 12:29:04 +08:00
|
|
|
|
2011-01-23 12:28:49 +08:00
|
|
|
unsigned Type = ELF::SHT_PROGBITS;
|
2010-07-17 12:29:04 +08:00
|
|
|
|
2013-02-16 08:32:53 +08:00
|
|
|
if (TypeName.empty()) {
|
|
|
|
if (SectionName.startswith(".note"))
|
|
|
|
Type = ELF::SHT_NOTE;
|
2017-03-22 21:35:41 +08:00
|
|
|
else if (hasPrefix(SectionName, ".init_array."))
|
2013-02-16 08:32:53 +08:00
|
|
|
Type = ELF::SHT_INIT_ARRAY;
|
2017-03-22 21:57:16 +08:00
|
|
|
else if (hasPrefix(SectionName, ".bss."))
|
|
|
|
Type = ELF::SHT_NOBITS;
|
2017-03-22 22:04:19 +08:00
|
|
|
else if (hasPrefix(SectionName, ".tbss."))
|
|
|
|
Type = ELF::SHT_NOBITS;
|
[MC] Set defaults based on section names and support name suffixes
Set correct default flags and section type based on its name for .text,
.data, .bss, .init_array, .fini_array, .preinit_array, .tdata, and .tbss
and support section name suffixes for .data.*, .rodata.*, .text.*,
.bss.*, .tdata.* and .tbss.* which matches the behavior of GAS.
Fixes PR31888.
Differential Revision: https://reviews.llvm.org/D30229
llvm-svn: 299484
2017-04-05 07:32:45 +08:00
|
|
|
else if (hasPrefix(SectionName, ".fini_array."))
|
2013-02-16 08:32:53 +08:00
|
|
|
Type = ELF::SHT_FINI_ARRAY;
|
[MC] Set defaults based on section names and support name suffixes
Set correct default flags and section type based on its name for .text,
.data, .bss, .init_array, .fini_array, .preinit_array, .tdata, and .tbss
and support section name suffixes for .data.*, .rodata.*, .text.*,
.bss.*, .tdata.* and .tbss.* which matches the behavior of GAS.
Fixes PR31888.
Differential Revision: https://reviews.llvm.org/D30229
llvm-svn: 299484
2017-04-05 07:32:45 +08:00
|
|
|
else if (hasPrefix(SectionName, ".preinit_array."))
|
2013-02-16 08:32:53 +08:00
|
|
|
Type = ELF::SHT_PREINIT_ARRAY;
|
|
|
|
} else {
|
2010-07-17 12:29:04 +08:00
|
|
|
if (TypeName == "init_array")
|
2011-01-23 12:28:49 +08:00
|
|
|
Type = ELF::SHT_INIT_ARRAY;
|
2010-07-17 12:29:04 +08:00
|
|
|
else if (TypeName == "fini_array")
|
2011-01-23 12:28:49 +08:00
|
|
|
Type = ELF::SHT_FINI_ARRAY;
|
2010-07-17 12:29:04 +08:00
|
|
|
else if (TypeName == "preinit_array")
|
2011-01-23 12:28:49 +08:00
|
|
|
Type = ELF::SHT_PREINIT_ARRAY;
|
2010-07-17 12:29:04 +08:00
|
|
|
else if (TypeName == "nobits")
|
2011-01-23 12:28:49 +08:00
|
|
|
Type = ELF::SHT_NOBITS;
|
2010-07-17 12:29:04 +08:00
|
|
|
else if (TypeName == "progbits")
|
2011-01-23 12:28:49 +08:00
|
|
|
Type = ELF::SHT_PROGBITS;
|
2010-12-27 05:30:59 +08:00
|
|
|
else if (TypeName == "note")
|
2011-01-23 12:28:49 +08:00
|
|
|
Type = ELF::SHT_NOTE;
|
2011-01-23 13:43:40 +08:00
|
|
|
else if (TypeName == "unwind")
|
|
|
|
Type = ELF::SHT_X86_64_UNWIND;
|
2017-03-10 16:22:13 +08:00
|
|
|
else if (TypeName.getAsInteger(0, Type))
|
2010-07-17 12:29:04 +08:00
|
|
|
return TokError("unknown section type");
|
|
|
|
}
|
|
|
|
|
2013-09-16 03:24:16 +08:00
|
|
|
if (UseLastGroup) {
|
|
|
|
MCSectionSubPair CurrentSection = getStreamer().getCurrentSection();
|
|
|
|
if (const MCSectionELF *Section =
|
|
|
|
cast_or_null<MCSectionELF>(CurrentSection.first))
|
|
|
|
if (const MCSymbol *Group = Section->getGroup()) {
|
|
|
|
GroupName = Group->getName();
|
|
|
|
Flags |= ELF::SHF_GROUP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-15 03:28:51 +08:00
|
|
|
MCSection *ELFSection =
|
|
|
|
getContext().getELFSection(SectionName, Type, Flags, Size, GroupName,
|
|
|
|
UniqueID, Associated);
|
2014-06-19 23:52:37 +08:00
|
|
|
getStreamer().SwitchSection(ELFSection, Subsection);
|
|
|
|
|
|
|
|
if (getContext().getGenDwarfForAssembly()) {
|
2015-05-22 00:52:32 +08:00
|
|
|
bool InsertResult = getContext().addGenDwarfSection(ELFSection);
|
|
|
|
if (InsertResult) {
|
2014-06-19 23:52:37 +08:00
|
|
|
if (getContext().getDwarfVersion() <= 2)
|
2014-09-22 18:45:16 +08:00
|
|
|
Warning(loc, "DWARF2 only supports one section per compilation unit");
|
2014-06-19 23:52:37 +08:00
|
|
|
|
2015-05-28 04:52:32 +08:00
|
|
|
if (!ELFSection->getBeginSymbol()) {
|
|
|
|
MCSymbol *SectionStartSymbol = getContext().createTempSymbol();
|
|
|
|
getStreamer().EmitLabel(SectionStartSymbol);
|
|
|
|
ELFSection->setBeginSymbol(SectionStartSymbol);
|
|
|
|
}
|
2014-06-19 23:52:37 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-17 12:29:04 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-09-03 02:53:37 +08:00
|
|
|
bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) {
|
2013-04-18 05:18:16 +08:00
|
|
|
MCSectionSubPair PreviousSection = getStreamer().getPreviousSection();
|
2014-04-24 14:44:33 +08:00
|
|
|
if (PreviousSection.first == nullptr)
|
2011-02-16 09:08:29 +08:00
|
|
|
return TokError(".previous without corresponding .section");
|
2013-04-18 05:18:16 +08:00
|
|
|
getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second);
|
2010-09-03 02:53:37 +08:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-06-08 08:34:34 +08:00
|
|
|
static MCSymbolAttr MCAttrForString(StringRef Type) {
|
|
|
|
return StringSwitch<MCSymbolAttr>(Type)
|
|
|
|
.Cases("STT_FUNC", "function", MCSA_ELF_TypeFunction)
|
|
|
|
.Cases("STT_OBJECT", "object", MCSA_ELF_TypeObject)
|
|
|
|
.Cases("STT_TLS", "tls_object", MCSA_ELF_TypeTLS)
|
|
|
|
.Cases("STT_COMMON", "common", MCSA_ELF_TypeCommon)
|
|
|
|
.Cases("STT_NOTYPE", "notype", MCSA_ELF_TypeNoType)
|
|
|
|
.Cases("STT_GNU_IFUNC", "gnu_indirect_function",
|
|
|
|
MCSA_ELF_TypeIndFunction)
|
|
|
|
.Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject)
|
|
|
|
.Default(MCSA_Invalid);
|
|
|
|
}
|
|
|
|
|
2010-10-09 11:47:55 +08:00
|
|
|
/// ParseDirectiveELFType
|
2013-09-21 13:25:12 +08:00
|
|
|
/// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE>
|
|
|
|
/// ::= .type identifier , #attribute
|
2010-10-09 11:47:55 +08:00
|
|
|
/// ::= .type identifier , @attribute
|
2013-09-21 13:25:12 +08:00
|
|
|
/// ::= .type identifier , %attribute
|
|
|
|
/// ::= .type identifier , "attribute"
|
2010-10-09 11:47:55 +08:00
|
|
|
bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
|
|
|
|
StringRef Name;
|
2013-02-21 06:21:35 +08:00
|
|
|
if (getParser().parseIdentifier(Name))
|
2010-10-09 11:47:55 +08:00
|
|
|
return TokError("expected identifier in directive");
|
|
|
|
|
|
|
|
// Handle the identifier as the key symbol.
|
2015-05-19 02:43:14 +08:00
|
|
|
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
|
2010-10-09 11:47:55 +08:00
|
|
|
|
2014-06-08 08:34:34 +08:00
|
|
|
// NOTE the comma is optional in all cases. It is only documented as being
|
|
|
|
// optional in the first case, however, GAS will silently treat the comma as
|
|
|
|
// optional in all cases. Furthermore, although the documentation states that
|
|
|
|
// the first form only accepts STT_<TYPE_IN_UPPER_CASE>, in reality, GAS
|
|
|
|
// accepts both the upper case name as well as the lower case aliases.
|
|
|
|
if (getLexer().is(AsmToken::Comma))
|
|
|
|
Lex();
|
2010-10-09 11:47:55 +08:00
|
|
|
|
2014-06-08 08:34:34 +08:00
|
|
|
if (getLexer().isNot(AsmToken::Identifier) &&
|
2015-07-01 16:58:49 +08:00
|
|
|
getLexer().isNot(AsmToken::Hash) &&
|
|
|
|
getLexer().isNot(AsmToken::Percent) &&
|
|
|
|
getLexer().isNot(AsmToken::String)) {
|
|
|
|
if (!getLexer().getAllowAtInIdentifier())
|
|
|
|
return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', "
|
|
|
|
"'%<type>' or \"<type>\"");
|
|
|
|
else if (getLexer().isNot(AsmToken::At))
|
|
|
|
return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', "
|
|
|
|
"'%<type>' or \"<type>\"");
|
|
|
|
}
|
2010-10-09 11:47:55 +08:00
|
|
|
|
2014-06-08 08:34:34 +08:00
|
|
|
if (getLexer().isNot(AsmToken::String) &&
|
|
|
|
getLexer().isNot(AsmToken::Identifier))
|
|
|
|
Lex();
|
|
|
|
|
|
|
|
SMLoc TypeLoc = getLexer().getLoc();
|
|
|
|
|
|
|
|
StringRef Type;
|
|
|
|
if (getParser().parseIdentifier(Type))
|
|
|
|
return TokError("expected symbol type in directive");
|
|
|
|
|
|
|
|
MCSymbolAttr Attr = MCAttrForString(Type);
|
2010-10-09 11:47:55 +08:00
|
|
|
if (Attr == MCSA_Invalid)
|
|
|
|
return Error(TypeLoc, "unsupported attribute in '.type' directive");
|
|
|
|
|
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement))
|
|
|
|
return TokError("unexpected token in '.type' directive");
|
|
|
|
Lex();
|
|
|
|
|
|
|
|
getStreamer().EmitSymbolAttribute(Sym, Attr);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-10-27 03:35:47 +08:00
|
|
|
/// ParseDirectiveIdent
|
|
|
|
/// ::= .ident string
|
|
|
|
bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
|
|
|
|
if (getLexer().isNot(AsmToken::String))
|
|
|
|
return TokError("unexpected token in '.ident' directive");
|
|
|
|
|
|
|
|
StringRef Data = getTok().getIdentifier();
|
|
|
|
|
|
|
|
Lex();
|
|
|
|
|
2016-07-18 23:24:03 +08:00
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement))
|
|
|
|
return TokError("unexpected token in '.ident' directive");
|
|
|
|
Lex();
|
|
|
|
|
2013-10-16 09:05:45 +08:00
|
|
|
getStreamer().EmitIdent(Data);
|
2010-10-27 03:35:47 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-10-27 23:18:17 +08:00
|
|
|
/// ParseDirectiveSymver
|
|
|
|
/// ::= .symver foo, bar2@zed
|
|
|
|
bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) {
|
|
|
|
StringRef Name;
|
2013-02-21 06:21:35 +08:00
|
|
|
if (getParser().parseIdentifier(Name))
|
2010-10-27 23:18:17 +08:00
|
|
|
return TokError("expected identifier in directive");
|
|
|
|
|
|
|
|
if (getLexer().isNot(AsmToken::Comma))
|
|
|
|
return TokError("expected a comma");
|
|
|
|
|
2014-01-16 06:40:02 +08:00
|
|
|
// ARM assembly uses @ for a comment...
|
|
|
|
// except when parsing the second parameter of the .symver directive.
|
|
|
|
// Force the next symbol to allow @ in the identifier, which is
|
|
|
|
// required for this directive and then reset it to its initial state.
|
|
|
|
const bool AllowAtInIdentifier = getLexer().getAllowAtInIdentifier();
|
|
|
|
getLexer().setAllowAtInIdentifier(true);
|
2010-10-27 23:18:17 +08:00
|
|
|
Lex();
|
2014-01-16 06:40:02 +08:00
|
|
|
getLexer().setAllowAtInIdentifier(AllowAtInIdentifier);
|
2010-10-27 23:18:17 +08:00
|
|
|
|
|
|
|
StringRef AliasName;
|
2013-02-21 06:21:35 +08:00
|
|
|
if (getParser().parseIdentifier(AliasName))
|
2010-10-27 23:18:17 +08:00
|
|
|
return TokError("expected identifier in directive");
|
|
|
|
|
|
|
|
if (AliasName.find('@') == StringRef::npos)
|
|
|
|
return TokError("expected a '@' in the name");
|
|
|
|
|
2015-05-19 02:43:14 +08:00
|
|
|
MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);
|
|
|
|
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
|
2015-05-30 09:25:56 +08:00
|
|
|
const MCExpr *Value = MCSymbolRefExpr::create(Sym, getContext());
|
2010-10-27 23:18:17 +08:00
|
|
|
|
|
|
|
getStreamer().EmitAssignment(Alias, Value);
|
Perform symbol binding for .symver versioned symbols
Summary:
In a .symver assembler directive like:
.symver name, name2@@nodename
"name2@@nodename" should get the same symbol binding as "name".
While the ELF object writer is updating the symbol binding for .symver
aliases before emitting the object file, not doing so when the module
inline assembly is handled by the RecordStreamer is causing the wrong
behavior in *LTO mode.
E.g. when "name" is global, "name2@@nodename" must also be marked as
global. Otherwise, the symbol is skipped when iterating over the LTO
InputFile symbols (InputFile::Symbol::shouldSkip). So, for example,
when performing any *LTO via the gold-plugin, the versioned symbol
definition is not recorded by the plugin and passed back to the
linker. If the object was in an archive, and there were no other symbols
needed from that object, the object would not be included in the final
link and references to the versioned symbol are undefined.
The llvm-lto2 tests added will give an error about an unused symbol
resolution without the fix.
Reviewers: rafael, pcc
Reviewed By: pcc
Subscribers: mehdi_amini, llvm-commits
Differential Revision: https://reviews.llvm.org/D30485
llvm-svn: 297332
2017-03-09 08:19:49 +08:00
|
|
|
getStreamer().emitELFSymverDirective(Alias, Sym);
|
2010-10-27 23:18:17 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-05-12 22:30:47 +08:00
|
|
|
/// ParseDirectiveVersion
|
|
|
|
/// ::= .version string
|
|
|
|
bool ELFAsmParser::ParseDirectiveVersion(StringRef, SMLoc) {
|
|
|
|
if (getLexer().isNot(AsmToken::String))
|
|
|
|
return TokError("unexpected token in '.version' directive");
|
|
|
|
|
|
|
|
StringRef Data = getTok().getIdentifier();
|
|
|
|
|
|
|
|
Lex();
|
|
|
|
|
2015-05-22 03:20:38 +08:00
|
|
|
MCSection *Note = getContext().getELFSection(".note", ELF::SHT_NOTE, 0);
|
2012-05-12 22:30:47 +08:00
|
|
|
|
|
|
|
getStreamer().PushSection();
|
|
|
|
getStreamer().SwitchSection(Note);
|
|
|
|
getStreamer().EmitIntValue(Data.size()+1, 4); // namesz.
|
|
|
|
getStreamer().EmitIntValue(0, 4); // descsz = 0 (no description).
|
|
|
|
getStreamer().EmitIntValue(1, 4); // type = NT_VERSION.
|
2013-01-09 09:57:54 +08:00
|
|
|
getStreamer().EmitBytes(Data); // name.
|
2012-05-12 22:30:47 +08:00
|
|
|
getStreamer().EmitIntValue(0, 1); // terminate the string.
|
|
|
|
getStreamer().EmitValueToAlignment(4); // ensure 4 byte alignment.
|
|
|
|
getStreamer().PopSection();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-11-01 22:28:48 +08:00
|
|
|
/// ParseDirectiveWeakref
|
|
|
|
/// ::= .weakref foo, bar
|
|
|
|
bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) {
|
|
|
|
// FIXME: Share code with the other alias building directives.
|
|
|
|
|
|
|
|
StringRef AliasName;
|
2013-02-21 06:21:35 +08:00
|
|
|
if (getParser().parseIdentifier(AliasName))
|
2010-11-01 22:28:48 +08:00
|
|
|
return TokError("expected identifier in directive");
|
|
|
|
|
|
|
|
if (getLexer().isNot(AsmToken::Comma))
|
|
|
|
return TokError("expected a comma");
|
|
|
|
|
|
|
|
Lex();
|
|
|
|
|
|
|
|
StringRef Name;
|
2013-02-21 06:21:35 +08:00
|
|
|
if (getParser().parseIdentifier(Name))
|
2010-11-01 22:28:48 +08:00
|
|
|
return TokError("expected identifier in directive");
|
|
|
|
|
2015-05-19 02:43:14 +08:00
|
|
|
MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);
|
2010-11-01 22:28:48 +08:00
|
|
|
|
2015-05-19 02:43:14 +08:00
|
|
|
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
|
2010-11-01 22:28:48 +08:00
|
|
|
|
|
|
|
getStreamer().EmitWeakReference(Alias, Sym);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-04-18 05:18:16 +08:00
|
|
|
bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) {
|
2014-04-24 14:44:33 +08:00
|
|
|
const MCExpr *Subsection = nullptr;
|
2013-04-18 05:18:16 +08:00
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
|
|
|
if (getParser().parseExpression(Subsection))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement))
|
|
|
|
return TokError("unexpected token in directive");
|
|
|
|
|
2016-07-18 23:24:03 +08:00
|
|
|
Lex();
|
|
|
|
|
2013-04-18 05:18:16 +08:00
|
|
|
getStreamer().SubSection(Subsection);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-07-13 05:23:32 +08:00
|
|
|
namespace llvm {
|
|
|
|
|
|
|
|
MCAsmParserExtension *createELFAsmParser() {
|
|
|
|
return new ELFAsmParser;
|
|
|
|
}
|
|
|
|
|
2017-02-08 07:02:00 +08:00
|
|
|
} // end namespace llvm
|