mirror of
https://github.com/intel/llvm.git
synced 2026-01-20 10:58:11 +08:00
[LinkerScript] Process program header in PHDRS command
Add PT_PHDR segment depending on its availability in linker script's PHDRS command, fallback if no linker script is given. Handle FILEHDR, PHDRS and FLAGS attributes of program header. Differential Revision: http://reviews.llvm.org/D11589 llvm-svn: 244743
This commit is contained in:
@@ -38,6 +38,9 @@ enum class LinkerScriptReaderError {
|
||||
unknown_symbol_in_expr,
|
||||
unrecognized_function_in_expr,
|
||||
unknown_phdr_ids,
|
||||
extra_program_phdr,
|
||||
misplaced_program_phdr,
|
||||
program_phdr_wrong_phdrs,
|
||||
};
|
||||
|
||||
inline std::error_code make_error_code(LinkerScriptReaderError e) {
|
||||
|
||||
@@ -79,7 +79,9 @@ public:
|
||||
kw_entry,
|
||||
kw_exclude_file,
|
||||
kw_extern,
|
||||
kw_filehdr,
|
||||
kw_fill,
|
||||
kw_flags,
|
||||
kw_group,
|
||||
kw_hidden,
|
||||
kw_input,
|
||||
@@ -818,6 +820,8 @@ public:
|
||||
|
||||
StringRef name() const { return _name; }
|
||||
uint64_t type() const { return _type; }
|
||||
bool hasFileHdr() const { return _includeFileHdr; }
|
||||
bool hasPHDRs() const { return _includePHDRs; }
|
||||
uint64_t flags() const { return _flags; }
|
||||
bool isNone() const;
|
||||
|
||||
@@ -1284,7 +1288,7 @@ public:
|
||||
/// Prepare our data structures according to the linker scripts currently in
|
||||
/// our control (control given via addLinkerScript()). Called once all linker
|
||||
/// scripts have been parsed.
|
||||
void perform();
|
||||
std::error_code perform();
|
||||
|
||||
/// Answer if we have layout commands (section mapping rules). If we don't,
|
||||
/// the output file writer can assume there is no linker script special rule
|
||||
@@ -1326,12 +1330,14 @@ public:
|
||||
/// has been performed (by calling evalExpr() for all expressions).
|
||||
uint64_t getLinkerScriptExprValue(StringRef name) const;
|
||||
|
||||
/// Check if there are custom headers available.
|
||||
bool hasPHDRs() const;
|
||||
|
||||
/// Retrieve all the headers the given output section is assigned to.
|
||||
/// Error is returned if the output section is assigned to headers with
|
||||
/// missing declarations.
|
||||
std::error_code
|
||||
getPHDRsForOutputSection(StringRef name,
|
||||
std::vector<const PHDR *> &phdrs) const;
|
||||
std::vector<const PHDR *> getPHDRsForOutputSection(StringRef name) const;
|
||||
|
||||
/// Retrieve program header if available.
|
||||
const PHDR *getProgramPHDR() const;
|
||||
|
||||
void dump() const;
|
||||
|
||||
@@ -1374,9 +1380,14 @@ private:
|
||||
bool localCompare(int order, const SectionKey &lhs,
|
||||
const SectionKey &rhs) const;
|
||||
|
||||
/// Convert the PHDRS command into map of names to headers.
|
||||
/// Determine program header during processing.
|
||||
std::error_code collectPHDRs(const PHDRS *ph,
|
||||
llvm::StringMap<const PHDR *> &phdrs);
|
||||
|
||||
/// Build map that matches output section names to segments they should be
|
||||
/// put into.
|
||||
std::error_code buildSectionToPHDR();
|
||||
std::error_code buildSectionToPHDR(llvm::StringMap<const PHDR *> &phdrs);
|
||||
|
||||
/// Our goal with all linearizeAST overloaded functions is to
|
||||
/// traverse the linker script AST while putting nodes in a vector and
|
||||
@@ -1433,8 +1444,6 @@ private:
|
||||
void linearizeAST(const InputSectionsCmd *inputSections);
|
||||
void linearizeAST(const InputSection *inputSection);
|
||||
|
||||
void perform(const LinkerScript *ls);
|
||||
|
||||
std::vector<std::unique_ptr<Parser>> _scripts;
|
||||
std::vector<const Command *> _layoutCommands;
|
||||
std::unordered_multimap<std::string, int> _memberToLayoutOrder;
|
||||
@@ -1444,8 +1453,8 @@ private:
|
||||
llvm::DenseSet<int> _deliveredExprs;
|
||||
mutable llvm::StringSet<> _definedSymbols;
|
||||
|
||||
bool _parsedPHDRS;
|
||||
llvm::StringMap<llvm::SmallVector<const PHDR *, 2>> _sectionToPHDR;
|
||||
const PHDR *_programPHDR;
|
||||
|
||||
Expression::SymbolTableTy _symbolTable;
|
||||
};
|
||||
|
||||
@@ -58,6 +58,12 @@ public:
|
||||
"expression";
|
||||
case LinkerScriptReaderError::unknown_phdr_ids:
|
||||
return "Unknown header identifiers (missing in PHDRS command) are used";
|
||||
case LinkerScriptReaderError::extra_program_phdr:
|
||||
return "Extra program header is found";
|
||||
case LinkerScriptReaderError::misplaced_program_phdr:
|
||||
return "Program header must precede load segments";
|
||||
case LinkerScriptReaderError::program_phdr_wrong_phdrs:
|
||||
return "Program header has invalid PHDRS attribute";
|
||||
}
|
||||
llvm_unreachable("An enumerator of LinkerScriptReaderError does not have a "
|
||||
"message defined.");
|
||||
|
||||
@@ -748,7 +748,10 @@ bool GnuLdDriver::parse(llvm::ArrayRef<const char *> args,
|
||||
return false;
|
||||
|
||||
// Perform linker script semantic actions
|
||||
ctx->linkerScriptSema().perform();
|
||||
if (auto ec = ctx->linkerScriptSema().perform()) {
|
||||
diag << "Error in the linker script's semantics: " << ec.message() << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
context.swap(ctx);
|
||||
return true;
|
||||
|
||||
@@ -423,7 +423,7 @@ template <class ELFT> int64_t Segment<ELFT>::flags() const {
|
||||
}
|
||||
|
||||
template <class ELFT> void Segment<ELFT>::setSegmentFlags(uint64_t flags) {
|
||||
assert(!_segmentFlags && !_flags && "Flags has already been set");
|
||||
assert(!_segmentFlags && "Segment flags have already been set");
|
||||
_segmentFlags = true;
|
||||
_flags = flags;
|
||||
_atomflags = toAtomPermsSegment(flags);
|
||||
|
||||
@@ -330,12 +330,7 @@ template <class ELFT> void TargetLayout<ELFT>::createOutputSections() {
|
||||
template <class ELFT>
|
||||
std::vector<const script::PHDR *>
|
||||
TargetLayout<ELFT>::getCustomSegments(const OutputSection<ELFT> *sec) const {
|
||||
std::vector<const script::PHDR *> phdrs;
|
||||
if (_linkerScriptSema.getPHDRsForOutputSection(sec->name(), phdrs)) {
|
||||
llvm::report_fatal_error(
|
||||
"Linker script has wrong segments set for output sections");
|
||||
}
|
||||
return phdrs;
|
||||
return _linkerScriptSema.getPHDRsForOutputSection(sec->name());
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@@ -466,11 +461,36 @@ template <class ELFT> void TargetLayout<ELFT>::assignSectionsToSegments() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_ctx.isDynamic() && !_ctx.isDynamicLibrary()) {
|
||||
|
||||
// Default values if no linker script is available
|
||||
bool hasProgramSegment = _ctx.isDynamic() && !_ctx.isDynamicLibrary();
|
||||
bool hasElfHeader = true;
|
||||
bool hasProgramHeader = true;
|
||||
uint64_t segmentFlags = 0;
|
||||
|
||||
// Check if linker script has PHDRS and program segment defined
|
||||
if (_linkerScriptSema.hasPHDRs()) {
|
||||
if (auto p = _linkerScriptSema.getProgramPHDR()) {
|
||||
hasProgramSegment = true;
|
||||
hasElfHeader = p->hasFileHdr();
|
||||
hasProgramHeader = p->hasPHDRs();
|
||||
segmentFlags = p->flags();
|
||||
} else {
|
||||
hasProgramSegment = false;
|
||||
hasElfHeader = false;
|
||||
hasProgramHeader = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasProgramSegment) {
|
||||
Segment<ELFT> *segment = new (_allocator) ProgramHeaderSegment<ELFT>(_ctx);
|
||||
_segments.push_back(segment);
|
||||
segment->append(_elfHeader);
|
||||
segment->append(_programHeader);
|
||||
if (segmentFlags)
|
||||
segment->setSegmentFlags(segmentFlags);
|
||||
if (hasElfHeader)
|
||||
segment->append(_elfHeader);
|
||||
if (hasProgramHeader)
|
||||
segment->append(_programHeader);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,9 @@ void Token::dump(raw_ostream &os) const {
|
||||
CASE(kw_entry)
|
||||
CASE(kw_exclude_file)
|
||||
CASE(kw_extern)
|
||||
CASE(kw_filehdr)
|
||||
CASE(kw_fill)
|
||||
CASE(kw_flags)
|
||||
CASE(kw_group)
|
||||
CASE(kw_hidden)
|
||||
CASE(kw_input)
|
||||
@@ -476,7 +478,9 @@ void Lexer::lex(Token &tok) {
|
||||
.Case("ENTRY", Token::kw_entry)
|
||||
.Case("EXCLUDE_FILE", Token::kw_exclude_file)
|
||||
.Case("EXTERN", Token::kw_extern)
|
||||
.Case("FILEHDR", Token::kw_filehdr)
|
||||
.Case("FILL", Token::kw_fill)
|
||||
.Case("FLAGS", Token::kw_flags)
|
||||
.Case("GROUP", Token::kw_group)
|
||||
.Case("HIDDEN", Token::kw_hidden)
|
||||
.Case("INPUT", Token::kw_input)
|
||||
@@ -2126,26 +2130,57 @@ const PHDR *Parser::parsePHDR() {
|
||||
}
|
||||
|
||||
uint64_t flags = 0;
|
||||
const Expression *flagsExpr = nullptr;
|
||||
bool includeFileHdr = false;
|
||||
bool includePHDRs = false;
|
||||
|
||||
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 )"))
|
||||
while (_tok._kind != Token::semicolon) {
|
||||
switch (_tok._kind) {
|
||||
case Token::kw_filehdr:
|
||||
if (includeFileHdr) {
|
||||
error(_tok, "Duplicate FILEHDR attribute");
|
||||
return nullptr;
|
||||
}
|
||||
includeFileHdr = true;
|
||||
consumeToken();
|
||||
break;
|
||||
case Token::kw_phdrs:
|
||||
if (includePHDRs) {
|
||||
error(_tok, "Duplicate PHDRS attribute");
|
||||
return nullptr;
|
||||
}
|
||||
includePHDRs = true;
|
||||
consumeToken();
|
||||
break;
|
||||
case Token::kw_flags: {
|
||||
if (flagsExpr) {
|
||||
error(_tok, "Duplicate FLAGS attribute");
|
||||
return nullptr;
|
||||
}
|
||||
consumeToken();
|
||||
if (!expectAndConsume(Token::l_paren, "Expected ("))
|
||||
return nullptr;
|
||||
flagsExpr = parseExpression();
|
||||
if (!flagsExpr)
|
||||
return nullptr;
|
||||
auto f = flagsExpr->evalExpr();
|
||||
if (!f)
|
||||
return nullptr;
|
||||
flags = *f;
|
||||
if (!expectAndConsume(Token::r_paren, "Expected )"))
|
||||
return nullptr;
|
||||
} break;
|
||||
default:
|
||||
error(_tok, "Unexpected token");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!expectAndConsume(Token::semicolon, "Expected ;"))
|
||||
return nullptr;
|
||||
|
||||
return new (getAllocator()) PHDR(name, type, false, false, nullptr, flags);
|
||||
return new (getAllocator())
|
||||
PHDR(name, type, includeFileHdr, includePHDRs, nullptr, flags);
|
||||
}
|
||||
|
||||
PHDRS *Parser::parsePHDRS() {
|
||||
@@ -2360,11 +2395,22 @@ Extern *Parser::parseExtern() {
|
||||
}
|
||||
|
||||
// Sema member functions
|
||||
Sema::Sema() : _parsedPHDRS(false) {}
|
||||
Sema::Sema() : _programPHDR(nullptr) {}
|
||||
|
||||
void Sema::perform() {
|
||||
for (auto &parser : _scripts)
|
||||
perform(parser->get());
|
||||
std::error_code Sema::perform() {
|
||||
llvm::StringMap<const PHDR *> phdrs;
|
||||
|
||||
for (auto &parser : _scripts) {
|
||||
for (const Command *c : parser->get()->_commands) {
|
||||
if (const auto *sec = dyn_cast<Sections>(c)) {
|
||||
linearizeAST(sec);
|
||||
} else if (const auto *ph = dyn_cast<PHDRS>(c)) {
|
||||
if (auto ec = collectPHDRs(ph, phdrs))
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
}
|
||||
return buildSectionToPHDR(phdrs);
|
||||
}
|
||||
|
||||
bool Sema::less(const SectionKey &lhs, const SectionKey &rhs) const {
|
||||
@@ -2469,18 +2515,15 @@ uint64_t Sema::getLinkerScriptExprValue(StringRef name) const {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::error_code
|
||||
Sema::getPHDRsForOutputSection(StringRef name,
|
||||
std::vector<const PHDR *> &phdrs) const {
|
||||
// Cache results if not done yet.
|
||||
if (auto ec = const_cast<Sema *>(this)->buildSectionToPHDR())
|
||||
return ec;
|
||||
bool Sema::hasPHDRs() const { return !_sectionToPHDR.empty(); }
|
||||
|
||||
std::vector<const PHDR *> Sema::getPHDRsForOutputSection(StringRef name) const {
|
||||
auto vec = _sectionToPHDR.lookup(name);
|
||||
std::copy(std::begin(vec), std::end(vec), std::back_inserter(phdrs));
|
||||
return std::error_code();
|
||||
return std::vector<const PHDR *>(std::begin(vec), std::end(vec));
|
||||
}
|
||||
|
||||
const PHDR *Sema::getProgramPHDR() const { return _programPHDR; }
|
||||
|
||||
void Sema::dump() const {
|
||||
raw_ostream &os = llvm::outs();
|
||||
os << "Linker script semantics dump\n";
|
||||
@@ -2717,25 +2760,35 @@ bool Sema::localCompare(int order, const SectionKey &lhs,
|
||||
return false;
|
||||
}
|
||||
|
||||
std::error_code Sema::buildSectionToPHDR() {
|
||||
if (_parsedPHDRS)
|
||||
return std::error_code();
|
||||
_parsedPHDRS = true;
|
||||
std::error_code Sema::collectPHDRs(const PHDRS *ph,
|
||||
llvm::StringMap<const PHDR *> &phdrs) {
|
||||
bool loadFound = false;
|
||||
for (auto *p : *ph) {
|
||||
phdrs[p->name()] = p;
|
||||
|
||||
// No scripts - nothing to do.
|
||||
if (_scripts.empty() || _layoutCommands.empty())
|
||||
return std::error_code();
|
||||
|
||||
// Collect all header declarations.
|
||||
llvm::StringMap<const PHDR *> phdrs;
|
||||
for (auto &parser : _scripts) {
|
||||
for (auto *cmd : parser->get()->_commands) {
|
||||
if (auto *ph = dyn_cast<PHDRS>(cmd)) {
|
||||
for (auto *p : *ph)
|
||||
phdrs[p->name()] = p;
|
||||
}
|
||||
switch (p->type()) {
|
||||
case llvm::ELF::PT_PHDR:
|
||||
if (_programPHDR != nullptr)
|
||||
return LinkerScriptReaderError::extra_program_phdr;
|
||||
if (loadFound)
|
||||
return LinkerScriptReaderError::misplaced_program_phdr;
|
||||
if (!p->hasPHDRs())
|
||||
return LinkerScriptReaderError::program_phdr_wrong_phdrs;
|
||||
_programPHDR = p;
|
||||
break;
|
||||
case llvm::ELF::PT_LOAD:
|
||||
// Program header, if available, should have program header table
|
||||
// mapped in the first loadable segment.
|
||||
if (!loadFound && _programPHDR && !p->hasPHDRs())
|
||||
return LinkerScriptReaderError::program_phdr_wrong_phdrs;
|
||||
loadFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
std::error_code Sema::buildSectionToPHDR(llvm::StringMap<const PHDR *> &phdrs) {
|
||||
const bool noPhdrs = phdrs.empty();
|
||||
|
||||
// Add NONE header to the map provided there's no user-defined
|
||||
@@ -2838,12 +2891,5 @@ void Sema::linearizeAST(const Sections *sections) {
|
||||
}
|
||||
}
|
||||
|
||||
void Sema::perform(const LinkerScript *ls) {
|
||||
for (const Command *c : ls->_commands) {
|
||||
if (const Sections *sec = dyn_cast<Sections>(c))
|
||||
linearizeAST(sec);
|
||||
}
|
||||
}
|
||||
|
||||
} // End namespace script
|
||||
} // end namespace lld
|
||||
|
||||
27
lld/test/elf/linkerscript/phdrs-extra-program.test
Normal file
27
lld/test/elf/linkerscript/phdrs-extra-program.test
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Test extra program header generates error.
|
||||
|
||||
RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
|
||||
|
||||
RUN: not lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1 &> %t1-error
|
||||
RUN: FileCheck -check-prefix EXTRA-PROGRAM-PHDR %s < %t1-error
|
||||
*/
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
header PT_PHDR PHDRS;
|
||||
header2 PT_PHDR PHDRS;
|
||||
text PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : { *(.text) } :NONE
|
||||
.data : { *(.data) }
|
||||
}
|
||||
|
||||
/*
|
||||
EXTRA-PROGRAM-PHDR: Extra program header is found
|
||||
*/
|
||||
33
lld/test/elf/linkerscript/phdrs-has-program.test
Normal file
33
lld/test/elf/linkerscript/phdrs-has-program.test
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Test when program segment is set it's generated.
|
||||
|
||||
RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
|
||||
|
||||
RUN: lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1
|
||||
RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix PROGRAM-PHDR %s
|
||||
*/
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
header PT_PHDR FILEHDR PHDRS;
|
||||
text PT_LOAD PHDRS;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : { *(.text) } :text
|
||||
.data : { *(.data) }
|
||||
}
|
||||
|
||||
/*
|
||||
PROGRAM-PHDR: ProgramHeader {
|
||||
PROGRAM-PHDR: Type: PT_PHDR (0x6)
|
||||
PROGRAM-PHDR: VirtualAddress: 0x400040
|
||||
PROGRAM-PHDR: Flags [ (0x5)
|
||||
PROGRAM-PHDR: PF_R (0x4)
|
||||
PROGRAM-PHDR: PF_X (0x1)
|
||||
PROGRAM-PHDR: ]
|
||||
PROGRAM-PHDR: }
|
||||
*/
|
||||
@@ -41,7 +41,7 @@ Test undefined header used when no PHDRS defined.
|
||||
RUN: not lld -flavor gnu -target x86_64 -T %p/phdrs/undef-no-phdrs.script %t.o -static -o %t1 &> %t1-error
|
||||
RUN: FileCheck -check-prefix UNDEF-NO-PHDRS %s < %t1-error
|
||||
|
||||
UNDEF-NO-PHDRS: Linker script has wrong segments set for output sections
|
||||
UNDEF-NO-PHDRS: Unknown header identifiers (missing in PHDRS command) are used
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -50,7 +50,7 @@ Test undefined header used when PHDRS is empty.
|
||||
RUN: not lld -flavor gnu -target x86_64 -T %p/phdrs/undef-empty-phdrs.script %t.o -static -o %t2 &> %t2-error
|
||||
RUN: FileCheck -check-prefix UNDEF-EMPTY-PHDRS %s < %t2-error
|
||||
|
||||
UNDEF-EMPTY-PHDRS: Linker script has wrong segments set for output sections
|
||||
UNDEF-EMPTY-PHDRS: Unknown header identifiers (missing in PHDRS command) are used
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -59,5 +59,5 @@ Test undefined header used when PHDRS contains definitions.
|
||||
RUN: not lld -flavor gnu -target x86_64 -T %p/phdrs/undef-id-phdrs.script %t.o -static -o %t3 &> %t3-error
|
||||
RUN: FileCheck -check-prefix UNDEF-ID-PHDRS %s < %t3-error
|
||||
|
||||
UNDEF-ID-PHDRS: Linker script has wrong segments set for output sections
|
||||
UNDEF-ID-PHDRS: Unknown header identifiers (missing in PHDRS command) are used
|
||||
*/
|
||||
|
||||
26
lld/test/elf/linkerscript/phdrs-misplaced-program.test
Normal file
26
lld/test/elf/linkerscript/phdrs-misplaced-program.test
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Test misplaced program header generates error.
|
||||
|
||||
RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
|
||||
|
||||
RUN: not lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1 &> %t1-error
|
||||
RUN: FileCheck -check-prefix MISPLACED-PROGRAM-PHDR %s < %t1-error
|
||||
*/
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD;
|
||||
header PT_PHDR PHDRS;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : { *(.text) } :NONE
|
||||
.data : { *(.data) }
|
||||
}
|
||||
|
||||
/*
|
||||
MISPLACED-PROGRAM-PHDR: Program header must precede load segments
|
||||
*/
|
||||
25
lld/test/elf/linkerscript/phdrs-no-program.test
Normal file
25
lld/test/elf/linkerscript/phdrs-no-program.test
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Test when no program segment set it's not generated.
|
||||
|
||||
RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
|
||||
|
||||
RUN: lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1
|
||||
RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix PROGRAM-PHDR %s
|
||||
*/
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : { *(.text) } :text
|
||||
.data : { *(.data) }
|
||||
}
|
||||
|
||||
/*
|
||||
PROGRAM-PHDR-NOT: Type: PT_PHDR (0x6)
|
||||
*/
|
||||
33
lld/test/elf/linkerscript/phdrs-program-flags.test
Normal file
33
lld/test/elf/linkerscript/phdrs-program-flags.test
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Test when program segment contains only FLAGS attribute.
|
||||
|
||||
RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
|
||||
|
||||
RUN: lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1
|
||||
RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix PROGRAM-FLAGS-PHDR %s
|
||||
*/
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
header PT_PHDR PHDRS FLAGS(0x7);
|
||||
text PT_LOAD FILEHDR PHDRS;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : { *(.text) } :text
|
||||
.data : { *(.data) }
|
||||
}
|
||||
|
||||
/*
|
||||
PROGRAM-FLAGS-PHDR: ProgramHeader {
|
||||
PROGRAM-FLAGS-PHDR: Type: PT_PHDR (0x6)
|
||||
PROGRAM-FLAGS-PHDR: Flags [ (0x7)
|
||||
PROGRAM-FLAGS-PHDR: PF_R (0x4)
|
||||
PROGRAM-FLAGS-PHDR: PF_W (0x2)
|
||||
PROGRAM-FLAGS-PHDR: PF_X (0x1)
|
||||
PROGRAM-FLAGS-PHDR: ]
|
||||
PROGRAM-FLAGS-PHDR: }
|
||||
*/
|
||||
34
lld/test/elf/linkerscript/phdrs-program-good-phdrs.test
Normal file
34
lld/test/elf/linkerscript/phdrs-program-good-phdrs.test
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Test when program segment contains only PHDRS attribute.
|
||||
|
||||
RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
|
||||
|
||||
RUN: lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1
|
||||
RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix PROGRAM-PHDRS-PHDR %s
|
||||
*/
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
header PT_PHDR PHDRS;
|
||||
text PT_LOAD PHDRS;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : { *(.text) } :text
|
||||
.data : { *(.data) }
|
||||
}
|
||||
|
||||
/*
|
||||
PROGRAM-PHDRS-PHDR: ProgramHeader {
|
||||
PROGRAM-PHDRS-PHDR: Type: PT_PHDR (0x6)
|
||||
PROGRAM-PHDRS-PHDR: VirtualAddress: 0x400040
|
||||
PROGRAM-PHDRS-PHDR: MemSize: 168
|
||||
PROGRAM-PHDRS-PHDR: Flags [ (0x5)
|
||||
PROGRAM-PHDRS-PHDR: PF_R (0x4)
|
||||
PROGRAM-PHDRS-PHDR: PF_X (0x1)
|
||||
PROGRAM-PHDRS-PHDR: ]
|
||||
PROGRAM-PHDRS-PHDR: }
|
||||
*/
|
||||
26
lld/test/elf/linkerscript/phdrs-program-no-phdrs.test
Normal file
26
lld/test/elf/linkerscript/phdrs-program-no-phdrs.test
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Test when program segment doesn't contain PHDRS attribute.
|
||||
|
||||
RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
|
||||
|
||||
RUN: not lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1 &> %t1-error
|
||||
RUN: FileCheck -check-prefix PROGRAM-PHDR-NO-PHDRS %s < %t1-error
|
||||
*/
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
header PT_PHDR;
|
||||
text PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : { *(.text) } :text
|
||||
.data : { *(.data) }
|
||||
}
|
||||
|
||||
/*
|
||||
PROGRAM-PHDR-NO-PHDRS: Program header has invalid PHDRS attribute
|
||||
*/
|
||||
26
lld/test/elf/linkerscript/phdrs-program-wrong-phdrs.test
Normal file
26
lld/test/elf/linkerscript/phdrs-program-wrong-phdrs.test
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Test when program segment contains PHDRS attribute not mapped to load segment.
|
||||
|
||||
RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o
|
||||
|
||||
RUN: not lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1 &> %t1-error
|
||||
RUN: FileCheck -check-prefix PROGRAM-PHDR-WRONG-PHDRS %s < %t1-error
|
||||
*/
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
header PT_PHDR PHDRS;
|
||||
text PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : { *(.text) } :text
|
||||
.data : { *(.data) }
|
||||
}
|
||||
|
||||
/*
|
||||
PROGRAM-PHDR-WRONG-PHDRS: Program header has invalid PHDRS attribute
|
||||
*/
|
||||
Reference in New Issue
Block a user