Reject moving the location counter backwards.

We were only checking when the assignment was inside a section.

llvm-svn: 295454
This commit is contained in:
Rafael Espindola 2017-02-17 16:01:51 +00:00
parent 0429c0cf8b
commit 4cd7352c4f
3 changed files with 31 additions and 21 deletions

View File

@ -95,7 +95,23 @@ static bool isUnderSysroot(StringRef Path) {
// symbols, whose value is an offset from beginning of section and regular
// symbols whose value is absolute.
template <class ELFT>
static void assignSymbol(SymbolAssignment *Cmd, typename ELFT::uint Dot = 0) {
void LinkerScript<ELFT>::assignSymbol(SymbolAssignment *Cmd, bool InSec) {
if (Cmd->Name == ".") {
uintX_t Val = Cmd->Expression(Dot);
if (Val < Dot) {
if (InSec)
error("unable to move location counter backward for: " +
CurOutSec->Name);
else
error("unable to move location counter backward");
}
Dot = Val;
// Update to location counter means update to section size.
if (InSec)
CurOutSec->Size = Dot - CurOutSec->Addr;
return;
}
if (!Cmd->Sym)
return;
@ -113,7 +129,8 @@ static void assignSymbol(SymbolAssignment *Cmd, typename ELFT::uint Dot = 0) {
cast<DefinedRegular<ELFT>>(Cmd->Sym)->Value = Cmd->Expression(Dot);
}
template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
template <class ELFT>
void LinkerScript<ELFT>::addSymbol(SymbolAssignment *Cmd) {
if (Cmd->Name == ".")
return;
@ -133,7 +150,7 @@ template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
// If there are sections, then let the value be assigned later in
// `assignAddresses`.
if (!ScriptConfig->HasSections)
assignSymbol<ELFT>(Cmd);
assignSymbol(Cmd);
}
bool SymbolAssignment::classof(const BaseCommand *C) {
@ -310,7 +327,7 @@ void LinkerScript<ELFT>::processCommands(OutputSectionFactory<ELFT> &Factory) {
// Handle symbol assignments outside of any output section.
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base1.get())) {
addSymbol<ELFT>(Cmd);
addSymbol(Cmd);
continue;
}
@ -352,7 +369,7 @@ void LinkerScript<ELFT>::processCommands(OutputSectionFactory<ELFT> &Factory) {
// ".foo : { ...; bar = .; }". Handle them.
for (const std::unique_ptr<BaseCommand> &Base : Cmd->Commands)
if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get()))
addSymbol<ELFT>(OutCmd);
addSymbol(OutCmd);
// Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign
// is given, input sections are aligned to that value, whether the
@ -451,17 +468,7 @@ void LinkerScript<ELFT>::switchTo(OutputSectionBase *Sec) {
template <class ELFT> void LinkerScript<ELFT>::process(BaseCommand &Base) {
// This handles the assignments to symbol or to a location counter (.)
if (auto *AssignCmd = dyn_cast<SymbolAssignment>(&Base)) {
if (AssignCmd->Name == ".") {
// Update to location counter means update to section size.
uintX_t Val = AssignCmd->Expression(Dot);
if (Val < Dot)
error("unable to move location counter backward for: " +
CurOutSec->Name);
Dot = Val;
CurOutSec->Size = Dot - CurOutSec->Addr;
return;
}
assignSymbol<ELFT>(AssignCmd, Dot);
assignSymbol(AssignCmd, true);
return;
}
@ -784,11 +791,7 @@ void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry> &Phdrs) {
for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base.get())) {
if (Cmd->Name == ".") {
Dot = Cmd->Expression(Dot);
} else if (Cmd->Sym) {
assignSymbol<ELFT>(Cmd, Dot);
}
assignSymbol(Cmd);
continue;
}

View File

@ -275,6 +275,8 @@ public:
int getSectionIndex(StringRef Name);
private:
void assignSymbol(SymbolAssignment *Cmd, bool InSec = false);
void addSymbol(SymbolAssignment *Cmd);
void computeInputSections(InputSectionDescription *);
void discard(ArrayRef<InputSectionBase<ELFT> *> V);

View File

@ -0,0 +1,5 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
# RUN: echo "SECTIONS { . = 0x20; . = 0x10; }" > %t.script
# RUN: not ld.lld %t.o --script %t.script -o %t -shared 2>&1 | FileCheck %s
# CHECK: unable to move location counter backward