[lld] r238383 - Add PHDR and FILL parsing.
Michael J. Spencer
bigcheesegs at gmail.com
Wed May 27 17:14:59 PDT 2015
Author: mspencer
Date: Wed May 27 19:14:58 2015
New Revision: 238383
URL: http://llvm.org/viewvc/llvm-project?rev=238383&view=rev
Log:
Add PHDR and FILL parsing.
Added:
lld/trunk/test/LinkerScript/phdrs-sections.test
Modified:
lld/trunk/include/lld/ReaderWriter/LinkerScript.h
lld/trunk/lib/ReaderWriter/LinkerScript.cpp
lld/trunk/test/LinkerScript/sections.test
Modified: lld/trunk/include/lld/ReaderWriter/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/LinkerScript.h?rev=238383&r1=238382&r2=238383&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/LinkerScript.h (original)
+++ lld/trunk/include/lld/ReaderWriter/LinkerScript.h Wed May 27 19:14:58 2015
@@ -78,6 +78,7 @@ public:
kw_entry,
kw_exclude_file,
kw_extern,
+ kw_fill,
kw_group,
kw_hidden,
kw_input,
@@ -85,6 +86,7 @@ public:
kw_length,
kw_memory,
kw_origin,
+ kw_phdrs,
kw_provide,
kw_provide_hidden,
kw_only_if_ro,
@@ -160,6 +162,7 @@ public:
enum class Kind {
Entry,
Extern,
+ Fill,
Group,
Input,
InputSectionsCmd,
@@ -170,6 +173,7 @@ public:
OutputFormat,
OutputSectionDescription,
Overlay,
+ PHDRS,
SearchDir,
Sections,
SortedGroup,
@@ -191,6 +195,14 @@ private:
Kind _kind;
};
+template <class T>
+ArrayRef<T> save_array(llvm::BumpPtrAllocator &alloc, ArrayRef<T> array) {
+ size_t num = array.size();
+ T *start = alloc.Allocate<T>(num);
+ std::uninitialized_copy(std::begin(array), std::end(array), start);
+ return llvm::makeArrayRef(start, num);
+}
+
class Output : public Command {
public:
Output(Parser &ctx, StringRef outputFileName)
@@ -212,10 +224,7 @@ class OutputFormat : public Command {
public:
OutputFormat(Parser &ctx, const SmallVectorImpl<StringRef> &formats)
: Command(ctx, Kind::OutputFormat) {
- size_t numFormats = formats.size();
- StringRef *formatsStart = getAllocator().Allocate<StringRef>(numFormats);
- std::copy(std::begin(formats), std::end(formats), formatsStart);
- _formats = llvm::makeArrayRef(formatsStart, numFormats);
+ _formats = save_array<StringRef>(getAllocator(), formats);
}
static bool classof(const Command *c) {
@@ -274,10 +283,7 @@ class PathList : public Command {
public:
PathList(Parser &ctx, StringRef name, const SmallVectorImpl<Path> &paths)
: Command(ctx, K), _name(name) {
- size_t numPaths = paths.size();
- Path *pathsStart = getAllocator().template Allocate<Path>(numPaths);
- std::copy(std::begin(paths), std::end(paths), pathsStart);
- _paths = llvm::makeArrayRef(pathsStart, numPaths);
+ _paths = save_array<Path>(getAllocator(), paths);
}
static bool classof(const Command *c) { return c->getKind() == K; }
@@ -382,7 +388,8 @@ public:
Kind getKind() const { return _kind; }
inline llvm::BumpPtrAllocator &getAllocator() const;
virtual void dump(raw_ostream &os) const = 0;
- virtual ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const = 0;
+ virtual ErrorOr<int64_t>
+ evalExpr(const SymbolTableTy &symbolTable = SymbolTableTy()) const = 0;
virtual ~Expression() {}
protected:
@@ -406,7 +413,7 @@ public:
return c->getKind() == Kind::Constant;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
uint64_t _num;
@@ -422,7 +429,7 @@ public:
return c->getKind() == Kind::Symbol;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
StringRef _name;
@@ -433,11 +440,7 @@ public:
FunctionCall(Parser &ctx, StringRef name,
const SmallVectorImpl<const Expression *> &args)
: Expression(ctx, Kind::FunctionCall), _name(name) {
- size_t numArgs = args.size();
- const Expression **argsStart =
- getAllocator().Allocate<const Expression *>(numArgs);
- std::copy(std::begin(args), std::end(args), argsStart);
- _args = llvm::makeArrayRef(argsStart, numArgs);
+ _args = save_array<const Expression *>(getAllocator(), args);
}
void dump(raw_ostream &os) const override;
@@ -446,7 +449,7 @@ public:
return c->getKind() == Kind::FunctionCall;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
StringRef _name;
@@ -468,7 +471,7 @@ public:
return c->getKind() == Kind::Unary;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
Operation _op;
@@ -503,7 +506,7 @@ public:
return c->getKind() == Kind::BinOp;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
Operation _op;
@@ -538,7 +541,7 @@ public:
return c->getKind() == Kind::TernaryConditional;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
const Expression *_conditional;
@@ -647,11 +650,7 @@ public:
InputSectionSortedGroup(Parser &ctx, WildcardSortMode sort,
const SmallVectorImpl<const InputSection *> §ions)
: InputSection(ctx, Kind::SortedGroup), _sortMode(sort) {
- size_t numSections = sections.size();
- const InputSection **sectionsStart =
- getAllocator().Allocate<const InputSection *>(numSections);
- std::copy(std::begin(sections), std::end(sections), sectionsStart);
- _sections = llvm::makeArrayRef(sectionsStart, numSections);
+ _sections = save_array<const InputSection *>(getAllocator(), sections);
}
void dump(raw_ostream &os) const override;
@@ -691,11 +690,7 @@ public:
: Command(ctx, Kind::InputSectionsCmd), _memberName(memberName),
_archiveName(archiveName), _keep(keep), _fileSortMode(fileSortMode),
_archiveSortMode(archiveSortMode) {
- size_t numSections = sections.size();
- const InputSection **sectionsStart =
- getAllocator().Allocate<const InputSection *>(numSections);
- std::copy(std::begin(sections), std::end(sections), sectionsStart);
- _sections = llvm::makeArrayRef(sectionsStart, numSections);
+ _sections = save_array<const InputSection *>(getAllocator(), sections);
}
void dump(raw_ostream &os) const override;
@@ -720,6 +715,24 @@ private:
llvm::ArrayRef<const InputSection *> _sections;
};
+class FillCmd : public Command {
+public:
+ FillCmd(Parser &ctx, ArrayRef<uint8_t> bytes) : Command(ctx, Kind::Fill) {
+ _bytes = save_array<uint8_t>(getAllocator(), bytes);
+ }
+
+ void dump(raw_ostream &os) const override;
+
+ static bool classof(const Command *c) {
+ return c->getKind() == Kind::Fill;
+ }
+
+ ArrayRef<uint8_t> bytes() { return _bytes; }
+
+private:
+ ArrayRef<uint8_t> _bytes;
+};
+
/// A sections-command to specify which input sections and symbols compose a
/// given output section.
/// Example:
@@ -743,18 +756,16 @@ public:
const Expression *align, const Expression *subAlign, const Expression *at,
const Expression *fillExpr, StringRef fillStream, bool alignWithInput,
bool discard, Constraint constraint,
- const SmallVectorImpl<const Command *> &outputSectionCommands)
+ const SmallVectorImpl<const Command *> &outputSectionCommands,
+ ArrayRef<StringRef> phdrs)
: Command(ctx, Kind::OutputSectionDescription), _sectionName(sectionName),
_address(address), _align(align), _subAlign(subAlign), _at(at),
_fillExpr(fillExpr), _fillStream(fillStream),
_alignWithInput(alignWithInput), _discard(discard),
_constraint(constraint) {
- size_t numCommands = outputSectionCommands.size();
- const Command **commandsStart =
- getAllocator().Allocate<const Command *>(numCommands);
- std::copy(std::begin(outputSectionCommands),
- std::end(outputSectionCommands), commandsStart);
- _outputSectionCommands = llvm::makeArrayRef(commandsStart, numCommands);
+ _outputSectionCommands =
+ save_array<const Command *>(getAllocator(), outputSectionCommands);
+ _phdrs = save_array<StringRef>(getAllocator(), phdrs);
}
static bool classof(const Command *c) {
@@ -779,6 +790,7 @@ private:
bool _discard;
Constraint _constraint;
llvm::ArrayRef<const Command *> _outputSectionCommands;
+ ArrayRef<StringRef> _phdrs;
};
/// Represents an Overlay structure as documented in
@@ -794,6 +806,47 @@ public:
void dump(raw_ostream &os) const override { os << "Overlay description\n"; }
};
+class PHDR {
+public:
+ PHDR(StringRef name, uint64_t type, bool includeFileHdr, bool includePHDRs,
+ const Expression *at, uint64_t flags)
+ : _name(name), _type(type), _includeFileHdr(includeFileHdr),
+ _includePHDRs(includePHDRs), _at(at), _flags(flags) {}
+
+ ~PHDR() = delete;
+
+ void dump(raw_ostream &os) const;
+
+private:
+ StringRef _name;
+ uint64_t _type;
+ bool _includeFileHdr;
+ bool _includePHDRs;
+ const Expression *_at;
+ uint64_t _flags;
+};
+
+class PHDRS : public Command {
+public:
+ typedef ArrayRef<const PHDR *>::const_iterator const_iterator;
+
+ PHDRS(Parser &ctx, const SmallVectorImpl<const PHDR *> &phdrs)
+ : Command(ctx, Kind::PHDRS) {
+ _phdrs = save_array<const PHDR *>(getAllocator(), phdrs);
+ }
+
+ static bool classof(const Command *c) {
+ return c->getKind() == Kind::PHDRS;
+ }
+
+ void dump(raw_ostream &os) const override;
+ const_iterator begin() const { return _phdrs.begin(); }
+ const_iterator end() const { return _phdrs.end(); }
+
+private:
+ ArrayRef<const PHDR *> _phdrs;
+};
+
/// Represents all the contents of the SECTIONS {} construct.
class Sections : public Command {
public:
@@ -802,12 +855,8 @@ public:
Sections(Parser &ctx,
const SmallVectorImpl<const Command *> §ionsCommands)
: Command(ctx, Kind::Sections) {
- size_t numCommands = sectionsCommands.size();
- const Command **commandsStart =
- getAllocator().Allocate<const Command *>(numCommands);
- std::copy(std::begin(sectionsCommands), std::end(sectionsCommands),
- commandsStart);
- _sectionsCommands = llvm::makeArrayRef(commandsStart, numCommands);
+ _sectionsCommands =
+ save_array<const Command *>(getAllocator(), sectionsCommands);
}
static bool classof(const Command *c) {
@@ -844,11 +893,7 @@ public:
Memory(Parser &ctx,
const SmallVectorImpl<const MemoryBlock *> &blocks)
: Command(ctx, Kind::Memory) {
- size_t numBlocks = blocks.size();
- const MemoryBlock **blocksStart =
- getAllocator().Allocate<const MemoryBlock *>(numBlocks);
- std::copy(std::begin(blocks), std::end(blocks), blocksStart);
- _blocks = llvm::makeArrayRef(blocksStart, numBlocks);
+ _blocks = save_array<const MemoryBlock *>(getAllocator(), blocks);
}
static bool classof(const Command *c) {
@@ -869,11 +914,7 @@ public:
Extern(Parser &ctx,
const SmallVectorImpl<StringRef> &symbols)
: Command(ctx, Kind::Extern) {
- size_t numSymbols = symbols.size();
- StringRef *symbolsStart =
- getAllocator().Allocate<StringRef>(numSymbols);
- std::copy(std::begin(symbols), std::end(symbols), symbolsStart);
- _symbols = llvm::makeArrayRef(symbolsStart, numSymbols);
+ _symbols = save_array<StringRef>(getAllocator(), symbols);
}
static bool classof(const Command *c) {
@@ -1133,6 +1174,8 @@ private:
/// }
const InputSectionsCmd *parseInputSectionsCmd();
+ const FillCmd *parseFillCmd();
+
/// Parse output section description statements.
/// Example:
///
@@ -1145,6 +1188,10 @@ private:
/// Stub for parsing overlay commands. Currently unimplemented.
const Overlay *parseOverlay();
+ const PHDR *parsePHDR();
+
+ PHDRS *parsePHDRS();
+
/// Parse the SECTIONS linker script command.
/// Example:
///
Modified: lld/trunk/lib/ReaderWriter/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/LinkerScript.cpp?rev=238383&r1=238382&r2=238383&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/LinkerScript.cpp (original)
+++ lld/trunk/lib/ReaderWriter/LinkerScript.cpp Wed May 27 19:14:58 2015
@@ -14,6 +14,10 @@
#include "lld/ReaderWriter/LinkerScript.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ELF.h"
+
namespace lld {
namespace script {
void Token::dump(raw_ostream &os) const {
@@ -63,6 +67,7 @@ void Token::dump(raw_ostream &os) const
CASE(kw_entry)
CASE(kw_exclude_file)
CASE(kw_extern)
+ CASE(kw_fill)
CASE(kw_group)
CASE(kw_hidden)
CASE(kw_input)
@@ -70,6 +75,7 @@ void Token::dump(raw_ostream &os) const
CASE(kw_length)
CASE(kw_memory)
CASE(kw_origin)
+ CASE(kw_phdrs)
CASE(kw_provide)
CASE(kw_provide_hidden)
CASE(kw_only_if_ro)
@@ -469,6 +475,7 @@ void Lexer::lex(Token &tok) {
.Case("ENTRY", Token::kw_entry)
.Case("EXCLUDE_FILE", Token::kw_exclude_file)
.Case("EXTERN", Token::kw_extern)
+ .Case("FILL", Token::kw_fill)
.Case("GROUP", Token::kw_group)
.Case("HIDDEN", Token::kw_hidden)
.Case("INPUT", Token::kw_input)
@@ -486,6 +493,7 @@ void Lexer::lex(Token &tok) {
.Case("OUTPUT_ARCH", Token::kw_output_arch)
.Case("OUTPUT_FORMAT", Token::kw_output_format)
.Case("OVERLAY", Token::kw_overlay)
+ .Case("PHDRS", Token::kw_phdrs)
.Case("PROVIDE", Token::kw_provide)
.Case("PROVIDE_HIDDEN", Token::kw_provide_hidden)
.Case("SEARCH_DIR", Token::kw_search_dir)
@@ -544,14 +552,14 @@ void Lexer::skipWhitespace() {
// Constant functions
void Constant::dump(raw_ostream &os) const { os << _num; }
-ErrorOr<int64_t> Constant::evalExpr(SymbolTableTy &symbolTable) const {
+ErrorOr<int64_t> Constant::evalExpr(const SymbolTableTy &symbolTable) const {
return _num;
}
// Symbol functions
void Symbol::dump(raw_ostream &os) const { os << _name; }
-ErrorOr<int64_t> Symbol::evalExpr(SymbolTableTy &symbolTable) const {
+ErrorOr<int64_t> Symbol::evalExpr(const SymbolTableTy &symbolTable) const {
auto it = symbolTable.find(_name);
if (it == symbolTable.end())
return LinkerScriptReaderError::unknown_symbol_in_expr;
@@ -569,7 +577,8 @@ void FunctionCall::dump(raw_ostream &os)
os << ")";
}
-ErrorOr<int64_t> FunctionCall::evalExpr(SymbolTableTy &symbolTable) const {
+ErrorOr<int64_t>
+FunctionCall::evalExpr(const SymbolTableTy &symbolTable) const {
return LinkerScriptReaderError::unrecognized_function_in_expr;
}
@@ -584,7 +593,7 @@ void Unary::dump(raw_ostream &os) const
os << ")";
}
-ErrorOr<int64_t> Unary::evalExpr(SymbolTableTy &symbolTable) const {
+ErrorOr<int64_t> Unary::evalExpr(const SymbolTableTy &symbolTable) const {
auto child = _child->evalExpr(symbolTable);
if (child.getError())
return child.getError();
@@ -654,7 +663,7 @@ void BinOp::dump(raw_ostream &os) const
os << ")";
}
-ErrorOr<int64_t> BinOp::evalExpr(SymbolTableTy &symbolTable) const {
+ErrorOr<int64_t> BinOp::evalExpr(const SymbolTableTy &symbolTable) const {
auto lhs = _lhs->evalExpr(symbolTable);
if (lhs.getError())
return lhs.getError();
@@ -695,7 +704,7 @@ void TernaryConditional::dump(raw_ostrea
}
ErrorOr<int64_t>
-TernaryConditional::evalExpr(SymbolTableTy &symbolTable) const {
+TernaryConditional::evalExpr(const SymbolTableTy &symbolTable) const {
auto conditional = _conditional->evalExpr(symbolTable);
if (conditional.getError())
return conditional.getError();
@@ -857,6 +866,12 @@ void InputSectionsCmd::dump(raw_ostream
os << ")";
}
+void FillCmd::dump(raw_ostream &os) const {
+ os << "FILL(";
+ dumpByteStream(os, StringRef((const char *)_bytes.begin(), _bytes.size()));
+ os << ")";
+}
+
// OutputSectionDescription functions
void OutputSectionDescription::dump(raw_ostream &os) const {
if (_discard)
@@ -909,6 +924,9 @@ void OutputSectionDescription::dump(raw_
}
os << " }";
+ for (auto && phdr : _phdrs)
+ os << " : " << phdr;
+
if (_fillStream.size() > 0) {
os << " =";
dumpByteStream(os, _fillStream);
@@ -918,6 +936,21 @@ void OutputSectionDescription::dump(raw_
}
}
+void PHDR::dump(raw_ostream &os) const {
+ os << _name << " " << _type;
+ if (_flags)
+ os << " FLAGS (" << _flags << ")";
+ os << ";\n";
+}
+
+void PHDRS::dump(raw_ostream &os) const {
+ os << "PHDRS\n{\n";
+ for (auto &&phdr : _phdrs) {
+ phdr->dump(os);
+ }
+ os << "}\n";
+}
+
// Sections functions
void Sections::dump(raw_ostream &os) const {
os << "SECTIONS\n{\n";
@@ -1024,6 +1057,13 @@ std::error_code Parser::parse() {
_script._commands.push_back(entry);
break;
}
+ case Token::kw_phdrs: {
+ PHDRS *phdrs = parsePHDRS();
+ if (!phdrs)
+ return LinkerScriptReaderError::parse_error;
+ _script._commands.push_back(phdrs);
+ break;
+ }
case Token::kw_search_dir: {
SearchDir *searchDir = parseSearchDir();
if (!searchDir)
@@ -1793,6 +1833,46 @@ const InputSectionsCmd *Parser::parseInp
archiveSortMode, inputSections);
}
+const FillCmd *Parser::parseFillCmd() {
+ assert(_tok._kind == Token::kw_fill && "Expected FILL!");
+ consumeToken();
+ if (!expectAndConsume(Token::l_paren, "expected ("))
+ return nullptr;
+
+ SmallVector<uint8_t, 8> storage;
+
+ // If the expression is just a number, it's arbitrary length.
+ if (_tok._kind == Token::number && peek()._kind == Token::r_paren) {
+ if (_tok._range.size() > 2 && _tok._range.startswith("0x")) {
+ StringRef num = _tok._range.substr(2);
+ for (char c : num) {
+ unsigned nibble = llvm::hexDigitValue(c);
+ if (nibble == -1u)
+ goto not_simple_hex;
+ storage.push_back(nibble);
+ }
+
+ if (storage.size() % 2 != 0)
+ storage.insert(storage.begin(), 0);
+
+ // Collapse nibbles.
+ for (std::size_t i = 0, e = storage.size() / 2; i != e; ++i)
+ storage[i] = (storage[i * 2] << 4) + storage[(i * 2) + 1];
+
+ storage.resize(storage.size() / 2);
+ }
+ }
+not_simple_hex:
+
+ const Expression *expr = parseExpression();
+ if (!expr)
+ return nullptr;
+ if (!expectAndConsume(Token::r_paren, "expected )"))
+ return nullptr;
+
+ return new(getAllocator()) FillCmd(*this, storage);
+}
+
const OutputSectionDescription *Parser::parseOutputSectionDescription() {
assert((_tok._kind == Token::kw_discard || _tok._kind == Token::identifier) &&
"Expected /DISCARD/ or identifier!");
@@ -1892,6 +1972,12 @@ const OutputSectionDescription *Parser::
break;
}
break;
+ case Token::kw_fill:
+ if (const Command *cmd = parseFillCmd())
+ outputSectionCommands.push_back(cmd);
+ else
+ return nullptr;
+ break;
case Token::kw_keep:
case Token::star:
case Token::colon:
@@ -1921,6 +2007,17 @@ const OutputSectionDescription *Parser::
if (!expectAndConsume(Token::r_brace, "expected }"))
return nullptr;
+ SmallVector<StringRef, 2> phdrs;
+ while (_tok._kind == Token::colon) {
+ consumeToken();
+ if (_tok._kind != Token::identifier) {
+ error(_tok, "expected program header name");
+ return nullptr;
+ }
+ phdrs.push_back(_tok._range);
+ consumeToken();
+ }
+
if (_tok._kind == Token::equal) {
consumeToken();
if (_tok._kind != Token::number || !_tok._range.startswith_lower("0x")) {
@@ -1945,7 +2042,7 @@ const OutputSectionDescription *Parser::
return new (_alloc) OutputSectionDescription(
*this, sectionName, address, align, subAlign, at, fillExpr, fillStream,
- alignWithInput, discard, constraint, outputSectionCommands);
+ alignWithInput, discard, constraint, outputSectionCommands, phdrs);
}
const Overlay *Parser::parseOverlay() {
@@ -1954,6 +2051,110 @@ const Overlay *Parser::parseOverlay() {
return nullptr;
}
+const PHDR *Parser::parsePHDR() {
+ assert(_tok._kind == Token::identifier && "Expected identifier!");
+
+ StringRef name = _tok._range;
+ consumeToken();
+
+ uint64_t type;
+
+ switch (_tok._kind) {
+ case Token::identifier:
+ case Token::number:
+ case Token::l_paren: {
+ const Expression *expr = parseExpression();
+ if (!expr)
+ return nullptr;
+ Expression::SymbolTableTy PHDRTypes;
+#define PHDR_INSERT(x) PHDRTypes.insert(std::make_pair(#x, llvm::ELF::x))
+ PHDR_INSERT(PT_NULL);
+ PHDR_INSERT(PT_LOAD);
+ PHDR_INSERT(PT_DYNAMIC);
+ PHDR_INSERT(PT_INTERP);
+ PHDR_INSERT(PT_NOTE);
+ PHDR_INSERT(PT_SHLIB);
+ PHDR_INSERT(PT_PHDR);
+ PHDR_INSERT(PT_TLS);
+ PHDR_INSERT(PT_LOOS);
+ PHDR_INSERT(PT_GNU_EH_FRAME);
+ PHDR_INSERT(PT_GNU_STACK);
+ PHDR_INSERT(PT_GNU_RELRO);
+ PHDR_INSERT(PT_SUNW_EH_FRAME);
+ PHDR_INSERT(PT_SUNW_UNWIND);
+ PHDR_INSERT(PT_HIOS);
+ PHDR_INSERT(PT_LOPROC);
+ PHDR_INSERT(PT_ARM_ARCHEXT);
+ PHDR_INSERT(PT_ARM_EXIDX);
+ PHDR_INSERT(PT_ARM_UNWIND);
+ PHDR_INSERT(PT_MIPS_REGINFO);
+ PHDR_INSERT(PT_MIPS_RTPROC);
+ PHDR_INSERT(PT_MIPS_OPTIONS);
+ PHDR_INSERT(PT_MIPS_ABIFLAGS);
+ PHDR_INSERT(PT_HIPROC);
+#undef PHDR_INSERT
+ auto t = expr->evalExpr(PHDRTypes);
+ if (t == LinkerScriptReaderError::unknown_symbol_in_expr) {
+ error(_tok, "Unknown type");
+ return nullptr;
+ }
+ if (!t)
+ return nullptr;
+ type = *t;
+ break;
+ }
+ default:
+ error(_tok, "expected identifier or expression");
+ return nullptr;
+ }
+
+ uint64_t flags = 0;
+
+ if (_tok._kind == Token::identifier && _tok._range == "FLAGS") {
+ consumeToken();
+ if (!expectAndConsume(Token::l_paren, "Expected ("))
+ return nullptr;
+ const Expression *flagsExpr = parseExpression();
+ if (!flagsExpr)
+ return nullptr;
+ auto f = flagsExpr->evalExpr();
+ if (!f)
+ return nullptr;
+ flags = *f;
+ if (!expectAndConsume(Token::r_paren, "Expected )"))
+ return nullptr;
+ }
+
+ if (!expectAndConsume(Token::semicolon, "Expected ;"))
+ return nullptr;
+
+ return new (getAllocator()) PHDR(name, type, false, false, nullptr, flags);
+}
+
+PHDRS *Parser::parsePHDRS() {
+ assert(_tok._kind == Token::kw_phdrs && "Expected PHDRS!");
+ consumeToken();
+ if (!expectAndConsume(Token::l_brace, "expected {"))
+ return nullptr;
+
+ SmallVector<const PHDR *, 8> phdrs;
+
+ while (true) {
+ if (_tok._kind == Token::identifier) {
+ const PHDR *phdr = parsePHDR();
+ if (!phdr)
+ return nullptr;
+ phdrs.push_back(phdr);
+ } else
+ break;
+ }
+
+ if (!expectAndConsume(Token::r_brace, "expected }"))
+ return nullptr;
+
+ return new (getAllocator()) PHDRS(*this, phdrs);
+}
+
Sections *Parser::parseSections() {
assert(_tok._kind == Token::kw_sections && "Expected SECTIONS!");
consumeToken();
Added: lld/trunk/test/LinkerScript/phdrs-sections.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/LinkerScript/phdrs-sections.test?rev=238383&view=auto
==============================================================================
--- lld/trunk/test/LinkerScript/phdrs-sections.test (added)
+++ lld/trunk/test/LinkerScript/phdrs-sections.test Wed May 27 19:14:58 2015
@@ -0,0 +1,29 @@
+/*
+ Test PHDR parsing and section -> phdr mapping.
+ RUN: linker-script-test %s | FileCheck %s
+*/
+
+PHDRS
+{
+ ph_text PT_LOAD FLAGS (0x1 | 0x4);
+ ph_data PT_LOAD FLAGS (0x2 | 0x4);
+}
+
+SECTIONS
+{
+ .init : {} : ph_text
+}
+
+/*
+CHECK: PHDRS
+CHECK: {
+CHECK: ph_text 1 FLAGS (5);
+CHECK: ph_data 1 FLAGS (6);
+CHECK: }
+CHECK: SECTIONS
+CHECK: {
+CHECK: .init :
+CHECK: {
+CHECK: } : ph_text
+CHECK: }
+*/
Modified: lld/trunk/test/LinkerScript/sections.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/LinkerScript/sections.test?rev=238383&r1=238382&r2=238383&view=diff
==============================================================================
--- lld/trunk/test/LinkerScript/sections.test (original)
+++ lld/trunk/test/LinkerScript/sections.test Wed May 27 19:14:58 2015
@@ -26,6 +26,7 @@ SECTIONS
}
.init :
{
+ FILL (0x90909090)
KEEP (*(SORT_NONE(.init)))
} =0x909090909090909090909090
PROVIDE (__etext = .);
@@ -181,6 +182,10 @@ CHECK: r_brace: }
CHECK: identifier: .init
CHECK: colon: :
CHECK: l_brace: {
+CHECK: kw_fill: FILL
+CHECK: l_paren: (
+CHECK: number: 0x90909090
+CHECK: r_paren: )
CHECK: kw_keep: KEEP
CHECK: l_paren: (
CHECK: star: *
@@ -556,6 +561,7 @@ CHECK: PROVIDE_HIDDEN(__rela_iplt_en
CHECK: }
CHECK: .init :
CHECK: {
+CHECK: FILL(0x90909090)
CHECK: KEEP(*(SORT_NONE(.init)))
CHECK: } =0x909090909090909090909090
CHECK: PROVIDE(__etext = .)
More information about the llvm-commits
mailing list