2015-10-01 01:23:26 +08:00
|
|
|
//===- LinkerScript.cpp ---------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Linker
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file contains the parser/evaluator of the linker script.
|
2016-07-22 03:45:22 +08:00
|
|
|
// It parses a linker script and write the result to Config or ScriptConfig
|
|
|
|
// objects.
|
|
|
|
//
|
|
|
|
// If SECTIONS command is used, a ScriptConfig contains an AST
|
|
|
|
// of the command which will later be consumed by createSections() and
|
|
|
|
// assignAddresses().
|
2015-10-01 01:23:26 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2016-02-12 05:17:59 +08:00
|
|
|
#include "LinkerScript.h"
|
2015-10-01 01:23:26 +08:00
|
|
|
#include "Config.h"
|
|
|
|
#include "Driver.h"
|
2016-02-13 05:47:28 +08:00
|
|
|
#include "InputSection.h"
|
2016-04-16 18:10:32 +08:00
|
|
|
#include "OutputSections.h"
|
2016-04-07 04:59:11 +08:00
|
|
|
#include "ScriptParser.h"
|
2016-06-29 16:01:32 +08:00
|
|
|
#include "Strings.h"
|
2016-07-12 14:39:48 +08:00
|
|
|
#include "Symbols.h"
|
2015-10-01 01:23:26 +08:00
|
|
|
#include "SymbolTable.h"
|
2016-07-01 18:27:36 +08:00
|
|
|
#include "Target.h"
|
2016-07-19 17:25:43 +08:00
|
|
|
#include "Writer.h"
|
2016-04-20 02:58:11 +08:00
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
2016-04-16 18:10:32 +08:00
|
|
|
#include "llvm/Support/ELF.h"
|
2015-10-01 01:23:26 +08:00
|
|
|
#include "llvm/Support/FileSystem.h"
|
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
2015-10-13 08:09:21 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
2015-10-11 09:53:04 +08:00
|
|
|
#include "llvm/Support/StringSaver.h"
|
2015-10-01 01:23:26 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
2016-04-16 18:10:32 +08:00
|
|
|
using namespace llvm::ELF;
|
2016-02-13 05:47:28 +08:00
|
|
|
using namespace llvm::object;
|
2015-10-01 01:23:26 +08:00
|
|
|
using namespace lld;
|
2016-02-28 08:25:54 +08:00
|
|
|
using namespace lld::elf;
|
2015-10-01 01:23:26 +08:00
|
|
|
|
2016-04-21 04:13:41 +08:00
|
|
|
ScriptConfiguration *elf::ScriptConfig;
|
2016-02-12 05:17:59 +08:00
|
|
|
|
2016-07-21 14:43:01 +08:00
|
|
|
bool SymbolAssignment::classof(const BaseCommand *C) {
|
|
|
|
return C->Kind == AssignmentKind;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OutputSectionCommand::classof(const BaseCommand *C) {
|
|
|
|
return C->Kind == OutputSectionKind;
|
|
|
|
}
|
|
|
|
|
2016-07-21 22:26:59 +08:00
|
|
|
bool InputSectionDescription::classof(const BaseCommand *C) {
|
|
|
|
return C->Kind == InputSectionKind;
|
|
|
|
}
|
|
|
|
|
2016-07-23 22:09:58 +08:00
|
|
|
template <class ELFT> static bool isDiscarded(InputSectionBase<ELFT> *S) {
|
2016-07-21 22:26:59 +08:00
|
|
|
return !S || !S->Live;
|
2016-02-12 05:17:59 +08:00
|
|
|
}
|
|
|
|
|
2016-04-21 04:13:41 +08:00
|
|
|
template <class ELFT>
|
|
|
|
bool LinkerScript<ELFT>::shouldKeep(InputSectionBase<ELFT> *S) {
|
2016-04-22 06:00:51 +08:00
|
|
|
for (StringRef Pat : Opt.KeptSections)
|
2016-06-29 13:32:09 +08:00
|
|
|
if (globMatch(Pat, S->getSectionName()))
|
2016-04-22 06:00:51 +08:00
|
|
|
return true;
|
|
|
|
return false;
|
2016-02-23 15:47:54 +08:00
|
|
|
}
|
|
|
|
|
2016-07-21 22:26:59 +08:00
|
|
|
static bool match(StringRef Pattern, ArrayRef<StringRef> Arr) {
|
|
|
|
for (StringRef S : Arr)
|
|
|
|
if (globMatch(S, Pattern))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-07-20 22:43:20 +08:00
|
|
|
template <class ELFT>
|
2016-07-21 01:19:03 +08:00
|
|
|
std::vector<OutputSectionBase<ELFT> *>
|
2016-07-20 22:43:20 +08:00
|
|
|
LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
|
2016-07-21 22:26:59 +08:00
|
|
|
typedef const std::unique_ptr<ObjectFile<ELFT>> ObjectFile;
|
2016-07-21 01:19:03 +08:00
|
|
|
std::vector<OutputSectionBase<ELFT> *> Result;
|
2016-07-24 10:05:09 +08:00
|
|
|
DenseSet<OutputSectionBase<ELFT> *> Removed;
|
2016-07-21 01:19:03 +08:00
|
|
|
|
2016-07-20 22:43:20 +08:00
|
|
|
// Add input section to output section. If there is no output section yet,
|
|
|
|
// then create it and add to output section list.
|
2016-07-24 10:05:09 +08:00
|
|
|
auto AddInputSec = [&](InputSectionBase<ELFT> *C, StringRef Name,
|
|
|
|
ConstraintKind Constraint) {
|
2016-07-20 22:43:20 +08:00
|
|
|
OutputSectionBase<ELFT> *Sec;
|
|
|
|
bool IsNew;
|
|
|
|
std::tie(Sec, IsNew) = Factory.create(C, Name);
|
|
|
|
if (IsNew)
|
2016-07-21 01:19:03 +08:00
|
|
|
Result.push_back(Sec);
|
2016-07-24 10:05:09 +08:00
|
|
|
if ((!(C->getSectionHdr()->sh_flags & SHF_WRITE)) &&
|
|
|
|
Constraint == ReadWrite) {
|
|
|
|
Removed.insert(Sec);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ((C->getSectionHdr()->sh_flags & SHF_WRITE) && Constraint == ReadOnly) {
|
|
|
|
Removed.insert(Sec);
|
|
|
|
return;
|
|
|
|
}
|
2016-07-20 22:43:20 +08:00
|
|
|
Sec->addSection(C);
|
|
|
|
};
|
|
|
|
|
|
|
|
// Select input sections matching rule and add them to corresponding
|
|
|
|
// output section. Section rules are processed in order they're listed
|
|
|
|
// in script, so correct input section order is maintained by design.
|
2016-07-21 22:26:59 +08:00
|
|
|
for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
|
|
|
|
auto *OutCmd = dyn_cast<OutputSectionCommand>(Base.get());
|
|
|
|
if (!OutCmd)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (const std::unique_ptr<BaseCommand> &Cmd : OutCmd->Commands) {
|
|
|
|
auto *InCmd = dyn_cast<InputSectionDescription>(Cmd.get());
|
|
|
|
if (!InCmd)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (ObjectFile &F : Symtab<ELFT>::X->getObjectFiles()) {
|
|
|
|
for (InputSectionBase<ELFT> *S : F->getSections()) {
|
|
|
|
if (isDiscarded(S) || S->OutSec)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (match(S->getSectionName(), InCmd->Patterns)) {
|
|
|
|
if (OutCmd->Name == "/DISCARD/")
|
|
|
|
S->Live = false;
|
|
|
|
else
|
2016-07-24 10:05:09 +08:00
|
|
|
AddInputSec(S, OutCmd->Name, OutCmd->Constraint);
|
2016-07-21 22:26:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-07-20 22:43:20 +08:00
|
|
|
|
|
|
|
// Add all other input sections, which are not listed in script.
|
2016-07-21 22:26:59 +08:00
|
|
|
for (ObjectFile &F : Symtab<ELFT>::X->getObjectFiles())
|
2016-07-22 02:39:28 +08:00
|
|
|
for (InputSectionBase<ELFT> *S : F->getSections()) {
|
2016-07-20 22:43:20 +08:00
|
|
|
if (!isDiscarded(S)) {
|
|
|
|
if (!S->OutSec)
|
2016-07-24 10:05:09 +08:00
|
|
|
AddInputSec(S, getOutputSectionName(S), NoConstraint);
|
2016-07-20 22:43:20 +08:00
|
|
|
} else
|
|
|
|
reportDiscarded(S, F);
|
2016-07-22 02:39:28 +08:00
|
|
|
}
|
2016-07-20 22:43:20 +08:00
|
|
|
|
2016-07-24 10:05:09 +08:00
|
|
|
// Remove from the output all the sections which did not met the constraints.
|
|
|
|
Result.erase(std::remove_if(Result.begin(), Result.end(),
|
|
|
|
[&](OutputSectionBase<ELFT> *Sec) {
|
|
|
|
return Removed.count(Sec);
|
|
|
|
}),
|
|
|
|
Result.end());
|
|
|
|
return Result;
|
2016-07-20 22:43:20 +08:00
|
|
|
}
|
|
|
|
|
2016-07-22 00:07:40 +08:00
|
|
|
template <class ELFT>
|
|
|
|
void LinkerScript<ELFT>::dispatchAssignment(SymbolAssignment *Cmd) {
|
Make readExpr return an Expr object instead of a vector of tokens.
Previously, we handled an expression as a vector of tokens. In other
words, an expression was a vector of uncooked raw StringRefs.
When we need a value of an expression, we used ExprParser to run
the expression.
The separation was needed essentially because parse time is too
early to evaluate an expression. In order to evaluate an expression,
we need to finalize section sizes. Because linker script parsing
is done at very early stage of the linking process, we can't
evaluate expressions while parsing.
The above mechanism worked fairly well, but there were a few
drawbacks.
One thing is that we sometimes have to parse the same expression
more than once in order to find the end of the expression.
In some contexts, linker script expressions have no clear end marker.
So, we needed to recognize balanced expressions and ternary operators.
The other is poor error reporting. Since expressions are parsed
basically twice, and some information that is available at the first
stage is lost in the second stage, it was hard to print out
apprpriate error messages.
This patch fixes the issues with a new approach.
Now the expression parsing is integrated into ScriptParser.
ExprParser class is removed. Expressions are represented as lambdas
instead of vectors of tokens. Lambdas captures information they
need to run themselves when they are created.
In this way, ends of expressions are naturally detected, and
errors are handled in the usual way. This patch also reduces
the amount of code.
Differential Revision: https://reviews.llvm.org/D22728
llvm-svn: 276574
2016-07-25 02:19:40 +08:00
|
|
|
uint64_t Val = Cmd->Expression(Dot);
|
2016-07-22 00:07:40 +08:00
|
|
|
if (Cmd->Name == ".") {
|
|
|
|
Dot = Val;
|
2016-07-22 15:38:40 +08:00
|
|
|
} else if (!Cmd->Ignore) {
|
2016-07-22 00:07:40 +08:00
|
|
|
auto *D = cast<DefinedRegular<ELFT>>(Symtab<ELFT>::X->find(Cmd->Name));
|
|
|
|
D->Value = Val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-19 05:00:40 +08:00
|
|
|
template <class ELFT>
|
2016-04-21 04:13:41 +08:00
|
|
|
void LinkerScript<ELFT>::assignAddresses(
|
2016-04-21 19:21:48 +08:00
|
|
|
ArrayRef<OutputSectionBase<ELFT> *> Sections) {
|
2016-04-16 18:10:32 +08:00
|
|
|
// Orphan sections are sections present in the input files which
|
2016-04-19 05:00:40 +08:00
|
|
|
// are not explicitly placed into the output file by the linker script.
|
|
|
|
// We place orphan sections at end of file.
|
|
|
|
// Other linkers places them using some heuristics as described in
|
2016-04-16 18:10:32 +08:00
|
|
|
// https://sourceware.org/binutils/docs/ld/Orphan-Sections.html#Orphan-Sections.
|
2016-04-19 05:00:40 +08:00
|
|
|
for (OutputSectionBase<ELFT> *Sec : Sections) {
|
2016-04-16 18:10:32 +08:00
|
|
|
StringRef Name = Sec->getName();
|
2016-04-22 04:30:00 +08:00
|
|
|
if (getSectionIndex(Name) == INT_MAX)
|
2016-07-21 14:43:01 +08:00
|
|
|
Opt.Commands.push_back(llvm::make_unique<OutputSectionCommand>(Name));
|
2016-04-16 18:10:32 +08:00
|
|
|
}
|
|
|
|
|
2016-04-19 05:00:40 +08:00
|
|
|
// Assign addresses as instructed by linker script SECTIONS sub-commands.
|
2016-07-01 18:42:25 +08:00
|
|
|
Dot = Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
|
2016-07-01 18:27:36 +08:00
|
|
|
uintX_t MinVA = std::numeric_limits<uintX_t>::max();
|
2016-04-16 18:10:32 +08:00
|
|
|
uintX_t ThreadBssOffset = 0;
|
|
|
|
|
2016-07-21 14:43:01 +08:00
|
|
|
for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
|
|
|
|
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base.get())) {
|
2016-07-22 00:07:40 +08:00
|
|
|
dispatchAssignment(Cmd);
|
2016-07-12 14:39:48 +08:00
|
|
|
continue;
|
|
|
|
}
|
2016-04-16 18:10:32 +08:00
|
|
|
|
2016-05-20 02:15:54 +08:00
|
|
|
// Find all the sections with required name. There can be more than
|
2016-07-19 15:39:07 +08:00
|
|
|
// one section with such name, if the alignment, flags or type
|
2016-05-20 02:15:54 +08:00
|
|
|
// attribute differs.
|
2016-07-21 14:43:01 +08:00
|
|
|
auto *Cmd = cast<OutputSectionCommand>(Base.get());
|
2016-05-20 02:15:54 +08:00
|
|
|
for (OutputSectionBase<ELFT> *Sec : Sections) {
|
2016-07-21 14:43:01 +08:00
|
|
|
if (Sec->getName() != Cmd->Name)
|
2016-05-20 02:15:54 +08:00
|
|
|
continue;
|
2016-04-16 18:10:32 +08:00
|
|
|
|
2016-05-20 02:15:54 +08:00
|
|
|
if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) {
|
|
|
|
uintX_t TVA = Dot + ThreadBssOffset;
|
2016-06-17 09:18:46 +08:00
|
|
|
TVA = alignTo(TVA, Sec->getAlignment());
|
2016-05-20 02:15:54 +08:00
|
|
|
Sec->setVA(TVA);
|
|
|
|
ThreadBssOffset = TVA - Dot + Sec->getSize();
|
|
|
|
continue;
|
|
|
|
}
|
2016-04-16 18:10:32 +08:00
|
|
|
|
2016-05-20 02:15:54 +08:00
|
|
|
if (Sec->getFlags() & SHF_ALLOC) {
|
2016-06-17 09:18:46 +08:00
|
|
|
Dot = alignTo(Dot, Sec->getAlignment());
|
2016-05-20 02:15:54 +08:00
|
|
|
Sec->setVA(Dot);
|
2016-07-01 18:42:25 +08:00
|
|
|
MinVA = std::min(MinVA, Dot);
|
2016-05-20 02:15:54 +08:00
|
|
|
Dot += Sec->getSize();
|
|
|
|
continue;
|
|
|
|
}
|
2016-04-16 18:10:32 +08:00
|
|
|
}
|
|
|
|
}
|
2016-07-01 18:42:25 +08:00
|
|
|
|
2016-07-07 22:28:47 +08:00
|
|
|
// ELF and Program headers need to be right before the first section in
|
2016-07-19 15:42:07 +08:00
|
|
|
// memory. Set their addresses accordingly.
|
2016-07-01 18:27:36 +08:00
|
|
|
MinVA = alignDown(MinVA - Out<ELFT>::ElfHeader->getSize() -
|
|
|
|
Out<ELFT>::ProgramHeaders->getSize(),
|
|
|
|
Target->PageSize);
|
|
|
|
Out<ELFT>::ElfHeader->setVA(MinVA);
|
|
|
|
Out<ELFT>::ProgramHeaders->setVA(Out<ELFT>::ElfHeader->getSize() + MinVA);
|
2016-04-16 18:10:32 +08:00
|
|
|
}
|
|
|
|
|
2016-07-19 17:25:43 +08:00
|
|
|
template <class ELFT>
|
2016-07-19 20:33:46 +08:00
|
|
|
std::vector<PhdrEntry<ELFT>>
|
2016-07-19 17:25:43 +08:00
|
|
|
LinkerScript<ELFT>::createPhdrs(ArrayRef<OutputSectionBase<ELFT> *> Sections) {
|
|
|
|
int TlsNum = -1;
|
|
|
|
int NoteNum = -1;
|
|
|
|
int RelroNum = -1;
|
2016-07-23 22:18:48 +08:00
|
|
|
PhdrEntry<ELFT> *Load = nullptr;
|
2016-07-19 17:25:43 +08:00
|
|
|
uintX_t Flags = PF_R;
|
2016-07-23 22:18:48 +08:00
|
|
|
std::vector<PhdrEntry<ELFT>> Phdrs;
|
2016-07-19 17:25:43 +08:00
|
|
|
|
|
|
|
for (const PhdrsCommand &Cmd : Opt.PhdrsCommands) {
|
2016-07-21 18:43:25 +08:00
|
|
|
Phdrs.emplace_back(Cmd.Type, Cmd.Flags == UINT_MAX ? PF_R : Cmd.Flags);
|
2016-07-23 22:18:48 +08:00
|
|
|
PhdrEntry<ELFT> &Phdr = Phdrs.back();
|
2016-07-19 17:25:43 +08:00
|
|
|
|
|
|
|
if (Cmd.HasFilehdr)
|
2016-07-23 22:18:48 +08:00
|
|
|
Phdr.add(Out<ELFT>::ElfHeader);
|
2016-07-19 17:25:43 +08:00
|
|
|
if (Cmd.HasPhdrs)
|
2016-07-23 22:18:48 +08:00
|
|
|
Phdr.add(Out<ELFT>::ProgramHeaders);
|
2016-07-19 17:25:43 +08:00
|
|
|
|
|
|
|
switch (Cmd.Type) {
|
|
|
|
case PT_INTERP:
|
2016-07-21 19:01:23 +08:00
|
|
|
if (Out<ELFT>::Interp)
|
2016-07-23 22:18:48 +08:00
|
|
|
Phdr.add(Out<ELFT>::Interp);
|
2016-07-19 17:25:43 +08:00
|
|
|
break;
|
|
|
|
case PT_DYNAMIC:
|
|
|
|
if (isOutputDynamic<ELFT>()) {
|
2016-07-23 22:18:48 +08:00
|
|
|
Phdr.H.p_flags = toPhdrFlags(Out<ELFT>::Dynamic->getFlags());
|
|
|
|
Phdr.add(Out<ELFT>::Dynamic);
|
2016-07-19 17:25:43 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PT_TLS:
|
|
|
|
TlsNum = Phdrs.size() - 1;
|
|
|
|
break;
|
|
|
|
case PT_NOTE:
|
|
|
|
NoteNum = Phdrs.size() - 1;
|
|
|
|
break;
|
|
|
|
case PT_GNU_RELRO:
|
|
|
|
RelroNum = Phdrs.size() - 1;
|
|
|
|
break;
|
|
|
|
case PT_GNU_EH_FRAME:
|
|
|
|
if (!Out<ELFT>::EhFrame->empty() && Out<ELFT>::EhFrameHdr) {
|
2016-07-23 22:18:48 +08:00
|
|
|
Phdr.H.p_flags = toPhdrFlags(Out<ELFT>::EhFrameHdr->getFlags());
|
|
|
|
Phdr.add(Out<ELFT>::EhFrameHdr);
|
2016-07-19 17:25:43 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (OutputSectionBase<ELFT> *Sec : Sections) {
|
|
|
|
if (!(Sec->getFlags() & SHF_ALLOC))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (TlsNum != -1 && (Sec->getFlags() & SHF_TLS))
|
2016-07-21 03:36:41 +08:00
|
|
|
Phdrs[TlsNum].add(Sec);
|
2016-07-19 17:25:43 +08:00
|
|
|
|
|
|
|
if (!needsPtLoad<ELFT>(Sec))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
const std::vector<size_t> &PhdrIds =
|
|
|
|
getPhdrIndicesForSection(Sec->getName());
|
|
|
|
if (!PhdrIds.empty()) {
|
|
|
|
// Assign headers specified by linker script
|
|
|
|
for (size_t Id : PhdrIds) {
|
2016-07-21 03:36:41 +08:00
|
|
|
Phdrs[Id].add(Sec);
|
2016-07-21 18:43:25 +08:00
|
|
|
if (Opt.PhdrsCommands[Id].Flags == UINT_MAX)
|
|
|
|
Phdrs[Id].H.p_flags |= toPhdrFlags(Sec->getFlags());
|
2016-07-19 17:25:43 +08:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// If we have no load segment or flags've changed then we want new load
|
|
|
|
// segment.
|
|
|
|
uintX_t NewFlags = toPhdrFlags(Sec->getFlags());
|
|
|
|
if (Load == nullptr || Flags != NewFlags) {
|
|
|
|
Load = &*Phdrs.emplace(Phdrs.end(), PT_LOAD, NewFlags);
|
|
|
|
Flags = NewFlags;
|
|
|
|
}
|
2016-07-21 03:36:41 +08:00
|
|
|
Load->add(Sec);
|
2016-07-19 17:25:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (RelroNum != -1 && isRelroSection(Sec))
|
2016-07-21 03:36:41 +08:00
|
|
|
Phdrs[RelroNum].add(Sec);
|
2016-07-19 17:25:43 +08:00
|
|
|
if (NoteNum != -1 && Sec->getType() == SHT_NOTE)
|
2016-07-21 03:36:41 +08:00
|
|
|
Phdrs[NoteNum].add(Sec);
|
2016-07-19 17:25:43 +08:00
|
|
|
}
|
|
|
|
return Phdrs;
|
|
|
|
}
|
|
|
|
|
2016-04-21 04:13:41 +08:00
|
|
|
template <class ELFT>
|
|
|
|
ArrayRef<uint8_t> LinkerScript<ELFT>::getFiller(StringRef Name) {
|
2016-07-21 15:48:54 +08:00
|
|
|
for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands)
|
|
|
|
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base.get()))
|
|
|
|
if (Cmd->Name == Name)
|
|
|
|
return Cmd->Filler;
|
|
|
|
return {};
|
2016-02-26 22:48:31 +08:00
|
|
|
}
|
|
|
|
|
2016-04-22 04:30:00 +08:00
|
|
|
// Returns the index of the given section name in linker script
|
|
|
|
// SECTIONS commands. Sections are laid out as the same order as they
|
|
|
|
// were in the script. If a given name did not appear in the script,
|
|
|
|
// it returns INT_MAX, so that it will be laid out at end of file.
|
2016-07-21 14:43:01 +08:00
|
|
|
template <class ELFT> int LinkerScript<ELFT>::getSectionIndex(StringRef Name) {
|
2016-04-21 18:22:02 +08:00
|
|
|
auto Begin = Opt.Commands.begin();
|
|
|
|
auto End = Opt.Commands.end();
|
2016-07-21 14:43:01 +08:00
|
|
|
auto I =
|
|
|
|
std::find_if(Begin, End, [&](const std::unique_ptr<BaseCommand> &Base) {
|
|
|
|
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base.get()))
|
|
|
|
if (Cmd->Name == Name)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
});
|
2016-04-22 04:30:00 +08:00
|
|
|
return I == End ? INT_MAX : (I - Begin);
|
2016-04-21 18:22:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// A compartor to sort output sections. Returns -1 or 1 if
|
|
|
|
// A or B are mentioned in linker script. Otherwise, returns 0.
|
2016-04-21 04:13:41 +08:00
|
|
|
template <class ELFT>
|
|
|
|
int LinkerScript<ELFT>::compareSections(StringRef A, StringRef B) {
|
2016-04-22 04:30:00 +08:00
|
|
|
int I = getSectionIndex(A);
|
|
|
|
int J = getSectionIndex(B);
|
|
|
|
if (I == INT_MAX && J == INT_MAX)
|
2016-02-12 05:17:59 +08:00
|
|
|
return 0;
|
|
|
|
return I < J ? -1 : 1;
|
|
|
|
}
|
|
|
|
|
2016-07-21 14:43:01 +08:00
|
|
|
template <class ELFT> void LinkerScript<ELFT>::addScriptedSymbols() {
|
2016-07-22 15:38:40 +08:00
|
|
|
for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
|
|
|
|
auto *Cmd = dyn_cast<SymbolAssignment>(Base.get());
|
|
|
|
if (!Cmd || Cmd->Name == ".")
|
|
|
|
continue;
|
|
|
|
|
2016-07-24 06:09:04 +08:00
|
|
|
SymbolBody *B = Symtab<ELFT>::X->find(Cmd->Name);
|
|
|
|
if (!B || B->isUndefined())
|
2016-07-22 15:38:40 +08:00
|
|
|
Symtab<ELFT>::X->addAbsolute(Cmd->Name,
|
|
|
|
Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT);
|
|
|
|
else
|
|
|
|
// Symbol already exists in symbol table. If it is provided
|
|
|
|
// then we can't override its value.
|
|
|
|
Cmd->Ignore = Cmd->Provide;
|
|
|
|
}
|
2016-07-12 14:39:48 +08:00
|
|
|
}
|
|
|
|
|
2016-07-19 17:25:43 +08:00
|
|
|
template <class ELFT> bool LinkerScript<ELFT>::hasPhdrsCommands() {
|
|
|
|
return !Opt.PhdrsCommands.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns indices of ELF headers containing specific section, identified
|
|
|
|
// by Name. Each index is a zero based number of ELF header listed within
|
|
|
|
// PHDRS {} script block.
|
|
|
|
template <class ELFT>
|
|
|
|
std::vector<size_t>
|
|
|
|
LinkerScript<ELFT>::getPhdrIndicesForSection(StringRef Name) {
|
2016-07-21 14:43:01 +08:00
|
|
|
for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
|
|
|
|
auto *Cmd = dyn_cast<OutputSectionCommand>(Base.get());
|
|
|
|
if (!Cmd || Cmd->Name != Name)
|
2016-07-21 00:43:03 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
std::vector<size_t> Indices;
|
2016-07-21 14:43:01 +08:00
|
|
|
for (StringRef PhdrName : Cmd->Phdrs) {
|
2016-07-21 00:43:03 +08:00
|
|
|
auto ItPhdr =
|
|
|
|
std::find_if(Opt.PhdrsCommands.rbegin(), Opt.PhdrsCommands.rend(),
|
2016-07-21 14:43:01 +08:00
|
|
|
[&](PhdrsCommand &P) { return P.Name == PhdrName; });
|
2016-07-19 17:25:43 +08:00
|
|
|
if (ItPhdr == Opt.PhdrsCommands.rend())
|
|
|
|
error("section header '" + PhdrName + "' is not listed in PHDRS");
|
|
|
|
else
|
|
|
|
Indices.push_back(std::distance(ItPhdr, Opt.PhdrsCommands.rend()) - 1);
|
|
|
|
}
|
2016-07-21 00:43:03 +08:00
|
|
|
return Indices;
|
2016-07-19 17:25:43 +08:00
|
|
|
}
|
2016-07-21 00:43:03 +08:00
|
|
|
return {};
|
2016-07-19 17:25:43 +08:00
|
|
|
}
|
|
|
|
|
2016-04-21 04:13:41 +08:00
|
|
|
class elf::ScriptParser : public ScriptParserBase {
|
2016-02-24 17:21:47 +08:00
|
|
|
typedef void (ScriptParser::*Handler)();
|
|
|
|
|
2015-10-01 01:23:26 +08:00
|
|
|
public:
|
2016-04-21 04:13:41 +08:00
|
|
|
ScriptParser(StringRef S, bool B) : ScriptParserBase(S), IsUnderSysroot(B) {}
|
2016-02-19 18:45:45 +08:00
|
|
|
|
2016-04-23 06:59:24 +08:00
|
|
|
void run();
|
2015-10-01 01:23:26 +08:00
|
|
|
|
|
|
|
private:
|
2015-10-11 11:28:42 +08:00
|
|
|
void addFile(StringRef Path);
|
|
|
|
|
2015-10-01 01:23:26 +08:00
|
|
|
void readAsNeeded();
|
2015-10-08 14:48:38 +08:00
|
|
|
void readEntry();
|
2015-10-20 01:35:12 +08:00
|
|
|
void readExtern();
|
2015-10-01 01:23:26 +08:00
|
|
|
void readGroup();
|
2015-10-11 09:31:55 +08:00
|
|
|
void readInclude();
|
2016-02-24 17:21:47 +08:00
|
|
|
void readNothing() {}
|
2015-10-07 08:25:09 +08:00
|
|
|
void readOutput();
|
2015-10-13 05:50:08 +08:00
|
|
|
void readOutputArch();
|
2015-10-01 01:23:26 +08:00
|
|
|
void readOutputFormat();
|
2016-07-19 17:25:43 +08:00
|
|
|
void readPhdrs();
|
2015-10-09 01:51:41 +08:00
|
|
|
void readSearchDir();
|
2015-11-12 17:52:08 +08:00
|
|
|
void readSections();
|
|
|
|
|
2016-07-25 07:05:57 +08:00
|
|
|
SymbolAssignment *readAssignment(StringRef Name);
|
2016-07-12 14:39:48 +08:00
|
|
|
void readOutputSectionDescription(StringRef OutSec);
|
2016-07-19 17:25:43 +08:00
|
|
|
std::vector<StringRef> readOutputSectionPhdrs();
|
|
|
|
unsigned readPhdrType();
|
2016-07-22 15:38:40 +08:00
|
|
|
void readProvide(bool Hidden);
|
Make readExpr return an Expr object instead of a vector of tokens.
Previously, we handled an expression as a vector of tokens. In other
words, an expression was a vector of uncooked raw StringRefs.
When we need a value of an expression, we used ExprParser to run
the expression.
The separation was needed essentially because parse time is too
early to evaluate an expression. In order to evaluate an expression,
we need to finalize section sizes. Because linker script parsing
is done at very early stage of the linking process, we can't
evaluate expressions while parsing.
The above mechanism worked fairly well, but there were a few
drawbacks.
One thing is that we sometimes have to parse the same expression
more than once in order to find the end of the expression.
In some contexts, linker script expressions have no clear end marker.
So, we needed to recognize balanced expressions and ternary operators.
The other is poor error reporting. Since expressions are parsed
basically twice, and some information that is available at the first
stage is lost in the second stage, it was hard to print out
apprpriate error messages.
This patch fixes the issues with a new approach.
Now the expression parsing is integrated into ScriptParser.
ExprParser class is removed. Expressions are represented as lambdas
instead of vectors of tokens. Lambdas captures information they
need to run themselves when they are created.
In this way, ends of expressions are naturally detected, and
errors are handled in the usual way. This patch also reduces
the amount of code.
Differential Revision: https://reviews.llvm.org/D22728
llvm-svn: 276574
2016-07-25 02:19:40 +08:00
|
|
|
|
|
|
|
Expr readExpr();
|
|
|
|
Expr readExpr1(Expr Lhs, int MinPrec);
|
|
|
|
Expr readPrimary();
|
|
|
|
Expr readTernary(Expr Cond);
|
|
|
|
Expr combine(StringRef Op, Expr Lhs, Expr Rhs);
|
2015-10-01 01:23:26 +08:00
|
|
|
|
2016-02-24 17:21:47 +08:00
|
|
|
const static StringMap<Handler> Cmd;
|
2016-04-21 04:13:41 +08:00
|
|
|
ScriptConfiguration &Opt = *ScriptConfig;
|
|
|
|
StringSaver Saver = {ScriptConfig->Alloc};
|
2015-11-26 13:53:00 +08:00
|
|
|
bool IsUnderSysroot;
|
2015-10-01 01:23:26 +08:00
|
|
|
};
|
|
|
|
|
2016-02-28 08:25:54 +08:00
|
|
|
const StringMap<elf::ScriptParser::Handler> elf::ScriptParser::Cmd = {
|
2016-02-24 17:21:47 +08:00
|
|
|
{"ENTRY", &ScriptParser::readEntry},
|
|
|
|
{"EXTERN", &ScriptParser::readExtern},
|
|
|
|
{"GROUP", &ScriptParser::readGroup},
|
|
|
|
{"INCLUDE", &ScriptParser::readInclude},
|
|
|
|
{"INPUT", &ScriptParser::readGroup},
|
|
|
|
{"OUTPUT", &ScriptParser::readOutput},
|
|
|
|
{"OUTPUT_ARCH", &ScriptParser::readOutputArch},
|
|
|
|
{"OUTPUT_FORMAT", &ScriptParser::readOutputFormat},
|
2016-07-19 17:25:43 +08:00
|
|
|
{"PHDRS", &ScriptParser::readPhdrs},
|
2016-02-24 17:21:47 +08:00
|
|
|
{"SEARCH_DIR", &ScriptParser::readSearchDir},
|
|
|
|
{"SECTIONS", &ScriptParser::readSections},
|
|
|
|
{";", &ScriptParser::readNothing}};
|
|
|
|
|
2016-02-12 05:17:59 +08:00
|
|
|
void ScriptParser::run() {
|
2015-10-01 01:23:26 +08:00
|
|
|
while (!atEOF()) {
|
|
|
|
StringRef Tok = next();
|
2016-02-24 17:21:47 +08:00
|
|
|
if (Handler Fn = Cmd.lookup(Tok))
|
|
|
|
(this->*Fn)();
|
|
|
|
else
|
2016-03-11 22:43:02 +08:00
|
|
|
setError("unknown directive: " + Tok);
|
2015-10-01 01:23:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-12 05:17:59 +08:00
|
|
|
void ScriptParser::addFile(StringRef S) {
|
2015-11-26 13:53:00 +08:00
|
|
|
if (IsUnderSysroot && S.startswith("/")) {
|
|
|
|
SmallString<128> Path;
|
|
|
|
(Config->Sysroot + S).toStringRef(Path);
|
|
|
|
if (sys::fs::exists(Path)) {
|
|
|
|
Driver->addFile(Saver.save(Path.str()));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-13 08:09:21 +08:00
|
|
|
if (sys::path::is_absolute(S)) {
|
2015-10-11 11:28:42 +08:00
|
|
|
Driver->addFile(S);
|
|
|
|
} else if (S.startswith("=")) {
|
|
|
|
if (Config->Sysroot.empty())
|
|
|
|
Driver->addFile(S.substr(1));
|
|
|
|
else
|
|
|
|
Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)));
|
|
|
|
} else if (S.startswith("-l")) {
|
2016-02-03 05:13:09 +08:00
|
|
|
Driver->addLibrary(S.substr(2));
|
2015-11-27 04:23:46 +08:00
|
|
|
} else if (sys::fs::exists(S)) {
|
|
|
|
Driver->addFile(S);
|
2015-10-11 11:28:42 +08:00
|
|
|
} else {
|
|
|
|
std::string Path = findFromSearchPaths(S);
|
|
|
|
if (Path.empty())
|
2016-03-12 16:31:34 +08:00
|
|
|
setError("unable to find " + S);
|
2016-02-03 04:27:59 +08:00
|
|
|
else
|
|
|
|
Driver->addFile(Saver.save(Path));
|
2015-10-11 11:28:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-12 05:17:59 +08:00
|
|
|
void ScriptParser::readAsNeeded() {
|
2015-10-01 01:23:26 +08:00
|
|
|
expect("(");
|
2015-10-12 04:59:12 +08:00
|
|
|
bool Orig = Config->AsNeeded;
|
|
|
|
Config->AsNeeded = true;
|
2016-02-03 04:27:59 +08:00
|
|
|
while (!Error) {
|
2015-10-01 01:23:26 +08:00
|
|
|
StringRef Tok = next();
|
|
|
|
if (Tok == ")")
|
2015-10-12 04:59:12 +08:00
|
|
|
break;
|
2015-10-11 11:28:42 +08:00
|
|
|
addFile(Tok);
|
2015-10-01 01:23:26 +08:00
|
|
|
}
|
2015-10-12 04:59:12 +08:00
|
|
|
Config->AsNeeded = Orig;
|
2015-10-01 01:23:26 +08:00
|
|
|
}
|
|
|
|
|
2016-02-12 05:17:59 +08:00
|
|
|
void ScriptParser::readEntry() {
|
2015-10-08 14:48:38 +08:00
|
|
|
// -e <symbol> takes predecence over ENTRY(<symbol>).
|
|
|
|
expect("(");
|
|
|
|
StringRef Tok = next();
|
|
|
|
if (Config->Entry.empty())
|
|
|
|
Config->Entry = Tok;
|
|
|
|
expect(")");
|
|
|
|
}
|
|
|
|
|
2016-02-12 05:17:59 +08:00
|
|
|
void ScriptParser::readExtern() {
|
2015-10-20 01:35:12 +08:00
|
|
|
expect("(");
|
2016-02-03 04:27:59 +08:00
|
|
|
while (!Error) {
|
2015-10-20 01:35:12 +08:00
|
|
|
StringRef Tok = next();
|
|
|
|
if (Tok == ")")
|
|
|
|
return;
|
|
|
|
Config->Undefined.push_back(Tok);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-12 05:17:59 +08:00
|
|
|
void ScriptParser::readGroup() {
|
2015-10-01 01:23:26 +08:00
|
|
|
expect("(");
|
2016-02-03 04:27:59 +08:00
|
|
|
while (!Error) {
|
2015-10-01 01:23:26 +08:00
|
|
|
StringRef Tok = next();
|
|
|
|
if (Tok == ")")
|
|
|
|
return;
|
|
|
|
if (Tok == "AS_NEEDED") {
|
|
|
|
readAsNeeded();
|
|
|
|
continue;
|
|
|
|
}
|
2015-10-11 11:28:42 +08:00
|
|
|
addFile(Tok);
|
2015-10-01 01:23:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-12 05:17:59 +08:00
|
|
|
void ScriptParser::readInclude() {
|
2015-10-11 09:31:55 +08:00
|
|
|
StringRef Tok = next();
|
|
|
|
auto MBOrErr = MemoryBuffer::getFile(Tok);
|
2016-02-03 04:27:59 +08:00
|
|
|
if (!MBOrErr) {
|
2016-03-11 22:43:02 +08:00
|
|
|
setError("cannot open " + Tok);
|
2016-02-03 04:27:59 +08:00
|
|
|
return;
|
|
|
|
}
|
2015-10-11 09:31:55 +08:00
|
|
|
std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
|
2015-10-11 09:53:04 +08:00
|
|
|
StringRef S = Saver.save(MB->getMemBufferRef().getBuffer());
|
|
|
|
std::vector<StringRef> V = tokenize(S);
|
2015-10-11 09:31:55 +08:00
|
|
|
Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end());
|
|
|
|
}
|
|
|
|
|
2016-02-12 05:17:59 +08:00
|
|
|
void ScriptParser::readOutput() {
|
2015-10-07 08:25:09 +08:00
|
|
|
// -o <file> takes predecence over OUTPUT(<file>).
|
|
|
|
expect("(");
|
|
|
|
StringRef Tok = next();
|
|
|
|
if (Config->OutputFile.empty())
|
|
|
|
Config->OutputFile = Tok;
|
|
|
|
expect(")");
|
|
|
|
}
|
|
|
|
|
2016-02-12 05:17:59 +08:00
|
|
|
void ScriptParser::readOutputArch() {
|
2015-10-13 05:50:08 +08:00
|
|
|
// Error checking only for now.
|
|
|
|
expect("(");
|
|
|
|
next();
|
|
|
|
expect(")");
|
|
|
|
}
|
|
|
|
|
2016-02-12 05:17:59 +08:00
|
|
|
void ScriptParser::readOutputFormat() {
|
2015-10-01 01:23:26 +08:00
|
|
|
// Error checking only for now.
|
|
|
|
expect("(");
|
|
|
|
next();
|
2015-10-13 05:08:41 +08:00
|
|
|
StringRef Tok = next();
|
|
|
|
if (Tok == ")")
|
|
|
|
return;
|
2016-02-03 04:27:59 +08:00
|
|
|
if (Tok != ",") {
|
2016-03-11 22:43:02 +08:00
|
|
|
setError("unexpected token: " + Tok);
|
2016-02-03 04:27:59 +08:00
|
|
|
return;
|
|
|
|
}
|
2015-10-13 05:08:41 +08:00
|
|
|
next();
|
|
|
|
expect(",");
|
|
|
|
next();
|
2015-10-01 01:23:26 +08:00
|
|
|
expect(")");
|
|
|
|
}
|
|
|
|
|
2016-07-19 17:25:43 +08:00
|
|
|
void ScriptParser::readPhdrs() {
|
|
|
|
expect("{");
|
|
|
|
while (!Error && !skip("}")) {
|
|
|
|
StringRef Tok = next();
|
2016-07-21 18:43:25 +08:00
|
|
|
Opt.PhdrsCommands.push_back({Tok, PT_NULL, false, false, UINT_MAX});
|
2016-07-19 17:25:43 +08:00
|
|
|
PhdrsCommand &PhdrCmd = Opt.PhdrsCommands.back();
|
|
|
|
|
|
|
|
PhdrCmd.Type = readPhdrType();
|
|
|
|
do {
|
|
|
|
Tok = next();
|
|
|
|
if (Tok == ";")
|
|
|
|
break;
|
|
|
|
if (Tok == "FILEHDR")
|
|
|
|
PhdrCmd.HasFilehdr = true;
|
|
|
|
else if (Tok == "PHDRS")
|
|
|
|
PhdrCmd.HasPhdrs = true;
|
2016-07-21 18:43:25 +08:00
|
|
|
else if (Tok == "FLAGS") {
|
|
|
|
expect("(");
|
|
|
|
next().getAsInteger(0, PhdrCmd.Flags);
|
|
|
|
expect(")");
|
|
|
|
} else
|
2016-07-19 17:25:43 +08:00
|
|
|
setError("unexpected header attribute: " + Tok);
|
|
|
|
} while (!Error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-12 05:17:59 +08:00
|
|
|
void ScriptParser::readSearchDir() {
|
2015-10-09 01:51:41 +08:00
|
|
|
expect("(");
|
2016-03-09 01:13:12 +08:00
|
|
|
Config->SearchPaths.push_back(next());
|
2015-10-09 01:51:41 +08:00
|
|
|
expect(")");
|
|
|
|
}
|
|
|
|
|
2016-02-12 05:17:59 +08:00
|
|
|
void ScriptParser::readSections() {
|
2016-04-21 04:13:41 +08:00
|
|
|
Opt.DoLayout = true;
|
2015-11-12 17:52:08 +08:00
|
|
|
expect("{");
|
2016-04-16 18:10:32 +08:00
|
|
|
while (!Error && !skip("}")) {
|
2016-07-25 07:05:57 +08:00
|
|
|
StringRef Tok = next();
|
|
|
|
if (peek() == "=") {
|
|
|
|
readAssignment(Tok);
|
|
|
|
expect(";");
|
|
|
|
} else if (Tok == "PROVIDE") {
|
2016-07-22 15:38:40 +08:00
|
|
|
readProvide(false);
|
Make readExpr return an Expr object instead of a vector of tokens.
Previously, we handled an expression as a vector of tokens. In other
words, an expression was a vector of uncooked raw StringRefs.
When we need a value of an expression, we used ExprParser to run
the expression.
The separation was needed essentially because parse time is too
early to evaluate an expression. In order to evaluate an expression,
we need to finalize section sizes. Because linker script parsing
is done at very early stage of the linking process, we can't
evaluate expressions while parsing.
The above mechanism worked fairly well, but there were a few
drawbacks.
One thing is that we sometimes have to parse the same expression
more than once in order to find the end of the expression.
In some contexts, linker script expressions have no clear end marker.
So, we needed to recognize balanced expressions and ternary operators.
The other is poor error reporting. Since expressions are parsed
basically twice, and some information that is available at the first
stage is lost in the second stage, it was hard to print out
apprpriate error messages.
This patch fixes the issues with a new approach.
Now the expression parsing is integrated into ScriptParser.
ExprParser class is removed. Expressions are represented as lambdas
instead of vectors of tokens. Lambdas captures information they
need to run themselves when they are created.
In this way, ends of expressions are naturally detected, and
errors are handled in the usual way. This patch also reduces
the amount of code.
Differential Revision: https://reviews.llvm.org/D22728
llvm-svn: 276574
2016-07-25 02:19:40 +08:00
|
|
|
} else if (Tok == "PROVIDE_HIDDEN") {
|
2016-07-22 15:38:40 +08:00
|
|
|
readProvide(true);
|
Make readExpr return an Expr object instead of a vector of tokens.
Previously, we handled an expression as a vector of tokens. In other
words, an expression was a vector of uncooked raw StringRefs.
When we need a value of an expression, we used ExprParser to run
the expression.
The separation was needed essentially because parse time is too
early to evaluate an expression. In order to evaluate an expression,
we need to finalize section sizes. Because linker script parsing
is done at very early stage of the linking process, we can't
evaluate expressions while parsing.
The above mechanism worked fairly well, but there were a few
drawbacks.
One thing is that we sometimes have to parse the same expression
more than once in order to find the end of the expression.
In some contexts, linker script expressions have no clear end marker.
So, we needed to recognize balanced expressions and ternary operators.
The other is poor error reporting. Since expressions are parsed
basically twice, and some information that is available at the first
stage is lost in the second stage, it was hard to print out
apprpriate error messages.
This patch fixes the issues with a new approach.
Now the expression parsing is integrated into ScriptParser.
ExprParser class is removed. Expressions are represented as lambdas
instead of vectors of tokens. Lambdas captures information they
need to run themselves when they are created.
In this way, ends of expressions are naturally detected, and
errors are handled in the usual way. This patch also reduces
the amount of code.
Differential Revision: https://reviews.llvm.org/D22728
llvm-svn: 276574
2016-07-25 02:19:40 +08:00
|
|
|
} else {
|
2016-07-12 14:39:48 +08:00
|
|
|
readOutputSectionDescription(Tok);
|
Make readExpr return an Expr object instead of a vector of tokens.
Previously, we handled an expression as a vector of tokens. In other
words, an expression was a vector of uncooked raw StringRefs.
When we need a value of an expression, we used ExprParser to run
the expression.
The separation was needed essentially because parse time is too
early to evaluate an expression. In order to evaluate an expression,
we need to finalize section sizes. Because linker script parsing
is done at very early stage of the linking process, we can't
evaluate expressions while parsing.
The above mechanism worked fairly well, but there were a few
drawbacks.
One thing is that we sometimes have to parse the same expression
more than once in order to find the end of the expression.
In some contexts, linker script expressions have no clear end marker.
So, we needed to recognize balanced expressions and ternary operators.
The other is poor error reporting. Since expressions are parsed
basically twice, and some information that is available at the first
stage is lost in the second stage, it was hard to print out
apprpriate error messages.
This patch fixes the issues with a new approach.
Now the expression parsing is integrated into ScriptParser.
ExprParser class is removed. Expressions are represented as lambdas
instead of vectors of tokens. Lambdas captures information they
need to run themselves when they are created.
In this way, ends of expressions are naturally detected, and
errors are handled in the usual way. This patch also reduces
the amount of code.
Differential Revision: https://reviews.llvm.org/D22728
llvm-svn: 276574
2016-07-25 02:19:40 +08:00
|
|
|
}
|
2016-04-16 18:10:32 +08:00
|
|
|
}
|
2015-11-12 17:52:08 +08:00
|
|
|
}
|
|
|
|
|
Make readExpr return an Expr object instead of a vector of tokens.
Previously, we handled an expression as a vector of tokens. In other
words, an expression was a vector of uncooked raw StringRefs.
When we need a value of an expression, we used ExprParser to run
the expression.
The separation was needed essentially because parse time is too
early to evaluate an expression. In order to evaluate an expression,
we need to finalize section sizes. Because linker script parsing
is done at very early stage of the linking process, we can't
evaluate expressions while parsing.
The above mechanism worked fairly well, but there were a few
drawbacks.
One thing is that we sometimes have to parse the same expression
more than once in order to find the end of the expression.
In some contexts, linker script expressions have no clear end marker.
So, we needed to recognize balanced expressions and ternary operators.
The other is poor error reporting. Since expressions are parsed
basically twice, and some information that is available at the first
stage is lost in the second stage, it was hard to print out
apprpriate error messages.
This patch fixes the issues with a new approach.
Now the expression parsing is integrated into ScriptParser.
ExprParser class is removed. Expressions are represented as lambdas
instead of vectors of tokens. Lambdas captures information they
need to run themselves when they are created.
In this way, ends of expressions are naturally detected, and
errors are handled in the usual way. This patch also reduces
the amount of code.
Differential Revision: https://reviews.llvm.org/D22728
llvm-svn: 276574
2016-07-25 02:19:40 +08:00
|
|
|
static int precedence(StringRef Op) {
|
|
|
|
return StringSwitch<int>(Op)
|
|
|
|
.Case("*", 4)
|
|
|
|
.Case("/", 4)
|
|
|
|
.Case("+", 3)
|
|
|
|
.Case("-", 3)
|
|
|
|
.Case("<", 2)
|
|
|
|
.Case(">", 2)
|
|
|
|
.Case(">=", 2)
|
|
|
|
.Case("<=", 2)
|
|
|
|
.Case("==", 2)
|
|
|
|
.Case("!=", 2)
|
|
|
|
.Case("&", 1)
|
|
|
|
.Default(-1);
|
|
|
|
}
|
|
|
|
|
2016-07-12 14:39:48 +08:00
|
|
|
void ScriptParser::readOutputSectionDescription(StringRef OutSec) {
|
2016-07-21 14:43:01 +08:00
|
|
|
OutputSectionCommand *Cmd = new OutputSectionCommand(OutSec);
|
|
|
|
Opt.Commands.emplace_back(Cmd);
|
2015-11-12 17:52:08 +08:00
|
|
|
expect(":");
|
2016-07-22 11:36:24 +08:00
|
|
|
|
|
|
|
// Parse constraints.
|
|
|
|
if (skip("ONLY_IF_RO"))
|
|
|
|
Cmd->Constraint = ReadOnly;
|
|
|
|
if (skip("ONLY_IF_RW"))
|
|
|
|
Cmd->Constraint = ReadWrite;
|
2015-11-12 17:52:08 +08:00
|
|
|
expect("{");
|
2016-04-22 06:00:51 +08:00
|
|
|
|
2016-02-03 04:27:59 +08:00
|
|
|
while (!Error && !skip("}")) {
|
2016-02-23 15:47:54 +08:00
|
|
|
StringRef Tok = next();
|
|
|
|
if (Tok == "*") {
|
2016-07-21 22:26:59 +08:00
|
|
|
auto *InCmd = new InputSectionDescription();
|
|
|
|
Cmd->Commands.emplace_back(InCmd);
|
2016-04-22 06:00:51 +08:00
|
|
|
expect("(");
|
|
|
|
while (!Error && !skip(")"))
|
2016-07-21 22:26:59 +08:00
|
|
|
InCmd->Patterns.push_back(next());
|
2016-02-23 15:47:54 +08:00
|
|
|
} else if (Tok == "KEEP") {
|
|
|
|
expect("(");
|
2016-04-22 06:00:51 +08:00
|
|
|
expect("*");
|
|
|
|
expect("(");
|
2016-07-21 22:26:59 +08:00
|
|
|
auto *InCmd = new InputSectionDescription();
|
|
|
|
Cmd->Commands.emplace_back(InCmd);
|
2016-04-22 06:00:51 +08:00
|
|
|
while (!Error && !skip(")")) {
|
2016-07-21 22:26:59 +08:00
|
|
|
Opt.KeptSections.push_back(peek());
|
|
|
|
InCmd->Patterns.push_back(next());
|
2016-04-22 06:00:51 +08:00
|
|
|
}
|
2016-02-23 15:47:54 +08:00
|
|
|
expect(")");
|
2016-07-25 07:13:48 +08:00
|
|
|
} else if (Tok == "PROVIDE") {
|
|
|
|
readProvide(false);
|
|
|
|
} else if (Tok == "PROVIDE_HIDDEN") {
|
|
|
|
readProvide(true);
|
2016-02-23 15:47:54 +08:00
|
|
|
} else {
|
2016-03-12 16:31:34 +08:00
|
|
|
setError("unknown command " + Tok);
|
2016-02-23 15:47:54 +08:00
|
|
|
}
|
2015-11-12 17:52:08 +08:00
|
|
|
}
|
2016-07-21 14:43:01 +08:00
|
|
|
Cmd->Phdrs = readOutputSectionPhdrs();
|
2016-04-22 06:00:51 +08:00
|
|
|
|
2016-02-26 22:48:31 +08:00
|
|
|
StringRef Tok = peek();
|
|
|
|
if (Tok.startswith("=")) {
|
|
|
|
if (!Tok.startswith("=0x")) {
|
2016-03-13 11:17:44 +08:00
|
|
|
setError("filler should be a hexadecimal value");
|
2016-02-26 22:48:31 +08:00
|
|
|
return;
|
|
|
|
}
|
2016-02-28 13:09:11 +08:00
|
|
|
Tok = Tok.substr(3);
|
2016-07-21 15:48:54 +08:00
|
|
|
Cmd->Filler = parseHex(Tok);
|
2016-02-26 22:48:31 +08:00
|
|
|
next();
|
|
|
|
}
|
2015-11-12 17:52:08 +08:00
|
|
|
}
|
|
|
|
|
2016-07-22 15:38:40 +08:00
|
|
|
void ScriptParser::readProvide(bool Hidden) {
|
|
|
|
expect("(");
|
2016-07-25 07:05:57 +08:00
|
|
|
if (SymbolAssignment *Assignment = readAssignment(next())) {
|
2016-07-22 15:38:40 +08:00
|
|
|
Assignment->Provide = true;
|
|
|
|
Assignment->Hidden = Hidden;
|
|
|
|
}
|
|
|
|
expect(")");
|
|
|
|
expect(";");
|
|
|
|
}
|
|
|
|
|
2016-07-25 07:05:57 +08:00
|
|
|
SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
|
2016-07-12 14:39:48 +08:00
|
|
|
expect("=");
|
Make readExpr return an Expr object instead of a vector of tokens.
Previously, we handled an expression as a vector of tokens. In other
words, an expression was a vector of uncooked raw StringRefs.
When we need a value of an expression, we used ExprParser to run
the expression.
The separation was needed essentially because parse time is too
early to evaluate an expression. In order to evaluate an expression,
we need to finalize section sizes. Because linker script parsing
is done at very early stage of the linking process, we can't
evaluate expressions while parsing.
The above mechanism worked fairly well, but there were a few
drawbacks.
One thing is that we sometimes have to parse the same expression
more than once in order to find the end of the expression.
In some contexts, linker script expressions have no clear end marker.
So, we needed to recognize balanced expressions and ternary operators.
The other is poor error reporting. Since expressions are parsed
basically twice, and some information that is available at the first
stage is lost in the second stage, it was hard to print out
apprpriate error messages.
This patch fixes the issues with a new approach.
Now the expression parsing is integrated into ScriptParser.
ExprParser class is removed. Expressions are represented as lambdas
instead of vectors of tokens. Lambdas captures information they
need to run themselves when they are created.
In this way, ends of expressions are naturally detected, and
errors are handled in the usual way. This patch also reduces
the amount of code.
Differential Revision: https://reviews.llvm.org/D22728
llvm-svn: 276574
2016-07-25 02:19:40 +08:00
|
|
|
Expr E = readExpr();
|
2016-07-25 07:05:57 +08:00
|
|
|
auto *Cmd = new SymbolAssignment(Name, E);
|
|
|
|
Opt.Commands.emplace_back(Cmd);
|
|
|
|
return Cmd;
|
2016-07-12 14:39:48 +08:00
|
|
|
}
|
|
|
|
|
Make readExpr return an Expr object instead of a vector of tokens.
Previously, we handled an expression as a vector of tokens. In other
words, an expression was a vector of uncooked raw StringRefs.
When we need a value of an expression, we used ExprParser to run
the expression.
The separation was needed essentially because parse time is too
early to evaluate an expression. In order to evaluate an expression,
we need to finalize section sizes. Because linker script parsing
is done at very early stage of the linking process, we can't
evaluate expressions while parsing.
The above mechanism worked fairly well, but there were a few
drawbacks.
One thing is that we sometimes have to parse the same expression
more than once in order to find the end of the expression.
In some contexts, linker script expressions have no clear end marker.
So, we needed to recognize balanced expressions and ternary operators.
The other is poor error reporting. Since expressions are parsed
basically twice, and some information that is available at the first
stage is lost in the second stage, it was hard to print out
apprpriate error messages.
This patch fixes the issues with a new approach.
Now the expression parsing is integrated into ScriptParser.
ExprParser class is removed. Expressions are represented as lambdas
instead of vectors of tokens. Lambdas captures information they
need to run themselves when they are created.
In this way, ends of expressions are naturally detected, and
errors are handled in the usual way. This patch also reduces
the amount of code.
Differential Revision: https://reviews.llvm.org/D22728
llvm-svn: 276574
2016-07-25 02:19:40 +08:00
|
|
|
// This is an operator-precedence parser to parse a linker
|
|
|
|
// script expression.
|
|
|
|
Expr ScriptParser::readExpr() { return readExpr1(readPrimary(), 0); }
|
2016-07-22 15:38:40 +08:00
|
|
|
|
Make readExpr return an Expr object instead of a vector of tokens.
Previously, we handled an expression as a vector of tokens. In other
words, an expression was a vector of uncooked raw StringRefs.
When we need a value of an expression, we used ExprParser to run
the expression.
The separation was needed essentially because parse time is too
early to evaluate an expression. In order to evaluate an expression,
we need to finalize section sizes. Because linker script parsing
is done at very early stage of the linking process, we can't
evaluate expressions while parsing.
The above mechanism worked fairly well, but there were a few
drawbacks.
One thing is that we sometimes have to parse the same expression
more than once in order to find the end of the expression.
In some contexts, linker script expressions have no clear end marker.
So, we needed to recognize balanced expressions and ternary operators.
The other is poor error reporting. Since expressions are parsed
basically twice, and some information that is available at the first
stage is lost in the second stage, it was hard to print out
apprpriate error messages.
This patch fixes the issues with a new approach.
Now the expression parsing is integrated into ScriptParser.
ExprParser class is removed. Expressions are represented as lambdas
instead of vectors of tokens. Lambdas captures information they
need to run themselves when they are created.
In this way, ends of expressions are naturally detected, and
errors are handled in the usual way. This patch also reduces
the amount of code.
Differential Revision: https://reviews.llvm.org/D22728
llvm-svn: 276574
2016-07-25 02:19:40 +08:00
|
|
|
// This is a part of the operator-precedence parser. This function
|
|
|
|
// assumes that the remaining token stream starts with an operator.
|
|
|
|
Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) {
|
|
|
|
while (!atEOF() && !Error) {
|
|
|
|
// Read an operator and an expression.
|
|
|
|
StringRef Op1 = peek();
|
|
|
|
if (Op1 == "?")
|
|
|
|
return readTernary(Lhs);
|
|
|
|
if (precedence(Op1) < MinPrec)
|
|
|
|
break;
|
|
|
|
next();
|
|
|
|
Expr Rhs = readPrimary();
|
|
|
|
|
|
|
|
// Evaluate the remaining part of the expression first if the
|
|
|
|
// next operator has greater precedence than the previous one.
|
|
|
|
// For example, if we have read "+" and "3", and if the next
|
|
|
|
// operator is "*", then we'll evaluate 3 * ... part first.
|
|
|
|
while (!atEOF()) {
|
|
|
|
StringRef Op2 = peek();
|
|
|
|
if (precedence(Op2) <= precedence(Op1))
|
2016-07-22 15:38:40 +08:00
|
|
|
break;
|
Make readExpr return an Expr object instead of a vector of tokens.
Previously, we handled an expression as a vector of tokens. In other
words, an expression was a vector of uncooked raw StringRefs.
When we need a value of an expression, we used ExprParser to run
the expression.
The separation was needed essentially because parse time is too
early to evaluate an expression. In order to evaluate an expression,
we need to finalize section sizes. Because linker script parsing
is done at very early stage of the linking process, we can't
evaluate expressions while parsing.
The above mechanism worked fairly well, but there were a few
drawbacks.
One thing is that we sometimes have to parse the same expression
more than once in order to find the end of the expression.
In some contexts, linker script expressions have no clear end marker.
So, we needed to recognize balanced expressions and ternary operators.
The other is poor error reporting. Since expressions are parsed
basically twice, and some information that is available at the first
stage is lost in the second stage, it was hard to print out
apprpriate error messages.
This patch fixes the issues with a new approach.
Now the expression parsing is integrated into ScriptParser.
ExprParser class is removed. Expressions are represented as lambdas
instead of vectors of tokens. Lambdas captures information they
need to run themselves when they are created.
In this way, ends of expressions are naturally detected, and
errors are handled in the usual way. This patch also reduces
the amount of code.
Differential Revision: https://reviews.llvm.org/D22728
llvm-svn: 276574
2016-07-25 02:19:40 +08:00
|
|
|
Rhs = readExpr1(Rhs, precedence(Op2));
|
|
|
|
}
|
2016-07-22 15:38:40 +08:00
|
|
|
|
Make readExpr return an Expr object instead of a vector of tokens.
Previously, we handled an expression as a vector of tokens. In other
words, an expression was a vector of uncooked raw StringRefs.
When we need a value of an expression, we used ExprParser to run
the expression.
The separation was needed essentially because parse time is too
early to evaluate an expression. In order to evaluate an expression,
we need to finalize section sizes. Because linker script parsing
is done at very early stage of the linking process, we can't
evaluate expressions while parsing.
The above mechanism worked fairly well, but there were a few
drawbacks.
One thing is that we sometimes have to parse the same expression
more than once in order to find the end of the expression.
In some contexts, linker script expressions have no clear end marker.
So, we needed to recognize balanced expressions and ternary operators.
The other is poor error reporting. Since expressions are parsed
basically twice, and some information that is available at the first
stage is lost in the second stage, it was hard to print out
apprpriate error messages.
This patch fixes the issues with a new approach.
Now the expression parsing is integrated into ScriptParser.
ExprParser class is removed. Expressions are represented as lambdas
instead of vectors of tokens. Lambdas captures information they
need to run themselves when they are created.
In this way, ends of expressions are naturally detected, and
errors are handled in the usual way. This patch also reduces
the amount of code.
Differential Revision: https://reviews.llvm.org/D22728
llvm-svn: 276574
2016-07-25 02:19:40 +08:00
|
|
|
Lhs = combine(Op1, Lhs, Rhs);
|
2016-07-12 14:39:48 +08:00
|
|
|
}
|
Make readExpr return an Expr object instead of a vector of tokens.
Previously, we handled an expression as a vector of tokens. In other
words, an expression was a vector of uncooked raw StringRefs.
When we need a value of an expression, we used ExprParser to run
the expression.
The separation was needed essentially because parse time is too
early to evaluate an expression. In order to evaluate an expression,
we need to finalize section sizes. Because linker script parsing
is done at very early stage of the linking process, we can't
evaluate expressions while parsing.
The above mechanism worked fairly well, but there were a few
drawbacks.
One thing is that we sometimes have to parse the same expression
more than once in order to find the end of the expression.
In some contexts, linker script expressions have no clear end marker.
So, we needed to recognize balanced expressions and ternary operators.
The other is poor error reporting. Since expressions are parsed
basically twice, and some information that is available at the first
stage is lost in the second stage, it was hard to print out
apprpriate error messages.
This patch fixes the issues with a new approach.
Now the expression parsing is integrated into ScriptParser.
ExprParser class is removed. Expressions are represented as lambdas
instead of vectors of tokens. Lambdas captures information they
need to run themselves when they are created.
In this way, ends of expressions are naturally detected, and
errors are handled in the usual way. This patch also reduces
the amount of code.
Differential Revision: https://reviews.llvm.org/D22728
llvm-svn: 276574
2016-07-25 02:19:40 +08:00
|
|
|
return Lhs;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t static getConstant(StringRef S) {
|
|
|
|
if (S == "COMMONPAGESIZE" || S == "MAXPAGESIZE")
|
|
|
|
return Target->PageSize;
|
|
|
|
error("unknown constant: " + S);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Expr ScriptParser::readPrimary() {
|
|
|
|
StringRef Tok = next();
|
|
|
|
|
|
|
|
if (Tok == ".")
|
|
|
|
return [](uint64_t Dot) { return Dot; };
|
|
|
|
|
|
|
|
if (Tok == "(") {
|
|
|
|
Expr E = readExpr();
|
|
|
|
expect(")");
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Built-in functions are parsed here.
|
|
|
|
// https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.
|
|
|
|
if (Tok == "ALIGN") {
|
|
|
|
expect("(");
|
|
|
|
Expr E = readExpr();
|
|
|
|
expect(")");
|
|
|
|
return [=](uint64_t Dot) { return alignTo(Dot, E(Dot)); };
|
|
|
|
}
|
|
|
|
if (Tok == "CONSTANT") {
|
|
|
|
expect("(");
|
|
|
|
StringRef Tok = next();
|
|
|
|
expect(")");
|
|
|
|
return [=](uint64_t Dot) { return getConstant(Tok); };
|
|
|
|
}
|
|
|
|
if (Tok == "DATA_SEGMENT_ALIGN") {
|
|
|
|
expect("(");
|
|
|
|
Expr E = readExpr();
|
|
|
|
expect(",");
|
|
|
|
readExpr();
|
|
|
|
expect(")");
|
|
|
|
return [=](uint64_t Dot) -> uint64_t {
|
|
|
|
uint64_t Val = E(Dot);
|
|
|
|
return alignTo(Dot, Val) + (Dot & (Val - 1));
|
|
|
|
};
|
|
|
|
}
|
|
|
|
if (Tok == "DATA_SEGMENT_END") {
|
|
|
|
expect("(");
|
|
|
|
expect(".");
|
|
|
|
expect(")");
|
|
|
|
return [](uint64_t Dot) { return Dot; };
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse a number literal
|
|
|
|
uint64_t V = 0;
|
|
|
|
if (Tok.getAsInteger(0, V))
|
|
|
|
setError("malformed number: " + Tok);
|
|
|
|
return [=](uint64_t Dot) { return V; };
|
|
|
|
}
|
|
|
|
|
|
|
|
Expr ScriptParser::readTernary(Expr Cond) {
|
|
|
|
next();
|
|
|
|
Expr L = readExpr();
|
|
|
|
expect(":");
|
|
|
|
Expr R = readExpr();
|
|
|
|
return [=](uint64_t Dot) { return Cond(Dot) ? L(Dot) : R(Dot); };
|
|
|
|
}
|
|
|
|
|
|
|
|
Expr ScriptParser::combine(StringRef Op, Expr L, Expr R) {
|
|
|
|
if (Op == "*")
|
|
|
|
return [=](uint64_t Dot) { return L(Dot) * R(Dot); };
|
|
|
|
if (Op == "/") {
|
|
|
|
return [=](uint64_t Dot) -> uint64_t {
|
|
|
|
uint64_t RHS = R(Dot);
|
|
|
|
if (RHS == 0) {
|
|
|
|
error("division by zero");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return L(Dot) / RHS;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
if (Op == "+")
|
|
|
|
return [=](uint64_t Dot) { return L(Dot) + R(Dot); };
|
|
|
|
if (Op == "-")
|
|
|
|
return [=](uint64_t Dot) { return L(Dot) - R(Dot); };
|
|
|
|
if (Op == "<")
|
|
|
|
return [=](uint64_t Dot) { return L(Dot) < R(Dot); };
|
|
|
|
if (Op == ">")
|
|
|
|
return [=](uint64_t Dot) { return L(Dot) > R(Dot); };
|
|
|
|
if (Op == ">=")
|
|
|
|
return [=](uint64_t Dot) { return L(Dot) >= R(Dot); };
|
|
|
|
if (Op == "<=")
|
|
|
|
return [=](uint64_t Dot) { return L(Dot) <= R(Dot); };
|
|
|
|
if (Op == "==")
|
|
|
|
return [=](uint64_t Dot) { return L(Dot) == R(Dot); };
|
|
|
|
if (Op == "!=")
|
|
|
|
return [=](uint64_t Dot) { return L(Dot) != R(Dot); };
|
|
|
|
if (Op == "&")
|
|
|
|
return [=](uint64_t Dot) { return L(Dot) & R(Dot); };
|
|
|
|
llvm_unreachable("invalid operator");
|
2016-07-12 14:39:48 +08:00
|
|
|
}
|
|
|
|
|
2016-07-19 17:25:43 +08:00
|
|
|
std::vector<StringRef> ScriptParser::readOutputSectionPhdrs() {
|
|
|
|
std::vector<StringRef> Phdrs;
|
|
|
|
while (!Error && peek().startswith(":")) {
|
|
|
|
StringRef Tok = next();
|
|
|
|
Tok = (Tok.size() == 1) ? next() : Tok.substr(1);
|
|
|
|
if (Tok.empty()) {
|
|
|
|
setError("section header name is empty");
|
|
|
|
break;
|
|
|
|
}
|
2016-07-21 03:36:36 +08:00
|
|
|
Phdrs.push_back(Tok);
|
2016-07-19 17:25:43 +08:00
|
|
|
}
|
|
|
|
return Phdrs;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned ScriptParser::readPhdrType() {
|
|
|
|
StringRef Tok = next();
|
2016-07-21 03:36:38 +08:00
|
|
|
unsigned Ret = StringSwitch<unsigned>(Tok)
|
|
|
|
.Case("PT_NULL", PT_NULL)
|
|
|
|
.Case("PT_LOAD", PT_LOAD)
|
|
|
|
.Case("PT_DYNAMIC", PT_DYNAMIC)
|
|
|
|
.Case("PT_INTERP", PT_INTERP)
|
|
|
|
.Case("PT_NOTE", PT_NOTE)
|
|
|
|
.Case("PT_SHLIB", PT_SHLIB)
|
|
|
|
.Case("PT_PHDR", PT_PHDR)
|
|
|
|
.Case("PT_TLS", PT_TLS)
|
|
|
|
.Case("PT_GNU_EH_FRAME", PT_GNU_EH_FRAME)
|
|
|
|
.Case("PT_GNU_STACK", PT_GNU_STACK)
|
|
|
|
.Case("PT_GNU_RELRO", PT_GNU_RELRO)
|
|
|
|
.Default(-1);
|
2016-07-19 17:25:43 +08:00
|
|
|
|
2016-07-21 03:36:38 +08:00
|
|
|
if (Ret == (unsigned)-1) {
|
|
|
|
setError("invalid program header type: " + Tok);
|
|
|
|
return PT_NULL;
|
|
|
|
}
|
|
|
|
return Ret;
|
2016-07-19 17:25:43 +08:00
|
|
|
}
|
|
|
|
|
2015-11-26 13:53:00 +08:00
|
|
|
static bool isUnderSysroot(StringRef Path) {
|
|
|
|
if (Config->Sysroot == "")
|
|
|
|
return false;
|
|
|
|
for (; !Path.empty(); Path = sys::path::parent_path(Path))
|
|
|
|
if (sys::fs::equivalent(Config->Sysroot, Path))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-04-21 04:13:41 +08:00
|
|
|
// Entry point.
|
|
|
|
void elf::readLinkerScript(MemoryBufferRef MB) {
|
2015-11-26 13:53:00 +08:00
|
|
|
StringRef Path = MB.getBufferIdentifier();
|
2016-04-21 04:13:41 +08:00
|
|
|
ScriptParser(MB.getBuffer(), isUnderSysroot(Path)).run();
|
|
|
|
}
|
|
|
|
|
|
|
|
template class elf::LinkerScript<ELF32LE>;
|
|
|
|
template class elf::LinkerScript<ELF32BE>;
|
|
|
|
template class elf::LinkerScript<ELF64LE>;
|
|
|
|
template class elf::LinkerScript<ELF64BE>;
|