summaryrefslogtreecommitdiff
path: root/ELF
diff options
context:
space:
mode:
Diffstat (limited to 'ELF')
-rw-r--r--ELF/Arch/X86.cpp18
-rw-r--r--ELF/Arch/X86_64.cpp22
-rw-r--r--ELF/Relocations.cpp43
-rw-r--r--ELF/ScriptLexer.cpp10
-rw-r--r--ELF/ScriptParser.cpp3
5 files changed, 51 insertions, 45 deletions
diff --git a/ELF/Arch/X86.cpp b/ELF/Arch/X86.cpp
index fc848917d4e95..10517bef14f38 100644
--- a/ELF/Arch/X86.cpp
+++ b/ELF/Arch/X86.cpp
@@ -192,9 +192,9 @@ void X86::writePltHeader(uint8_t *Buf) const {
}
const uint8_t PltData[] = {
- 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushl (GOTPLT+4)
- 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *(GOTPLT+8)
- 0x90, 0x90, 0x90, 0x90 // nop
+ 0xff, 0x35, 0, 0, 0, 0, // pushl (GOTPLT+4)
+ 0xff, 0x25, 0, 0, 0, 0, // jmp *(GOTPLT+8)
+ 0x90, 0x90, 0x90, 0x90, // nop
};
memcpy(Buf, PltData, sizeof(PltData));
uint32_t GotPlt = InX::GotPlt->getVA();
@@ -206,9 +206,9 @@ void X86::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
uint64_t PltEntryAddr, int32_t Index,
unsigned RelOff) const {
const uint8_t Inst[] = {
- 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, // jmp *foo_in_GOT|*foo@GOT(%ebx)
- 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $reloc_offset
- 0xe9, 0x00, 0x00, 0x00, 0x00 // jmp .PLT0@PC
+ 0xff, 0x00, 0, 0, 0, 0, // jmp *foo_in_GOT or jmp *foo@GOT(%ebx)
+ 0x68, 0, 0, 0, 0, // pushl $reloc_offset
+ 0xe9, 0, 0, 0, 0, // jmp .PLT0@PC
};
memcpy(Buf, Inst, sizeof(Inst));
@@ -318,7 +318,7 @@ void X86::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
// subl $x@ntpoff,%eax
const uint8_t Inst[] = {
0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax
- 0x81, 0xe8, 0x00, 0x00, 0x00, 0x00 // subl 0(%ebx), %eax
+ 0x81, 0xe8, 0, 0, 0, 0, // subl Val(%ebx), %eax
};
memcpy(Loc - 3, Inst, sizeof(Inst));
write32le(Loc + 5, Val);
@@ -333,7 +333,7 @@ void X86::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const {
// addl x@gotntpoff(%ebx), %eax
const uint8_t Inst[] = {
0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax
- 0x03, 0x83, 0x00, 0x00, 0x00, 0x00 // addl 0(%ebx), %eax
+ 0x03, 0x83, 0, 0, 0, 0, // addl Val(%ebx), %eax
};
memcpy(Loc - 3, Inst, sizeof(Inst));
write32le(Loc + 5, Val);
@@ -394,7 +394,7 @@ void X86::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
const uint8_t Inst[] = {
0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0,%eax
0x90, // nop
- 0x8d, 0x74, 0x26, 0x00 // leal 0(%esi,1),%esi
+ 0x8d, 0x74, 0x26, 0x00, // leal 0(%esi,1),%esi
};
memcpy(Loc - 2, Inst, sizeof(Inst));
}
diff --git a/ELF/Arch/X86_64.cpp b/ELF/Arch/X86_64.cpp
index 14e354b9f4fb9..c977d9247d928 100644
--- a/ELF/Arch/X86_64.cpp
+++ b/ELF/Arch/X86_64.cpp
@@ -129,9 +129,9 @@ void X86_64<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &S) const {
template <class ELFT> void X86_64<ELFT>::writePltHeader(uint8_t *Buf) const {
const uint8_t PltData[] = {
- 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushq GOTPLT+8(%rip)
- 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *GOTPLT+16(%rip)
- 0x0f, 0x1f, 0x40, 0x00 // nop
+ 0xff, 0x35, 0, 0, 0, 0, // pushq GOTPLT+8(%rip)
+ 0xff, 0x25, 0, 0, 0, 0, // jmp *GOTPLT+16(%rip)
+ 0x0f, 0x1f, 0x40, 0x00, // nop
};
memcpy(Buf, PltData, sizeof(PltData));
uint64_t GotPlt = InX::GotPlt->getVA();
@@ -145,9 +145,9 @@ void X86_64<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
uint64_t PltEntryAddr, int32_t Index,
unsigned RelOff) const {
const uint8_t Inst[] = {
- 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *got(%rip)
- 0x68, 0x00, 0x00, 0x00, 0x00, // pushq <relocation index>
- 0xe9, 0x00, 0x00, 0x00, 0x00 // jmpq plt[0]
+ 0xff, 0x25, 0, 0, 0, 0, // jmpq *got(%rip)
+ 0x68, 0, 0, 0, 0, // pushq <relocation index>
+ 0xe9, 0, 0, 0, 0, // jmpq plt[0]
};
memcpy(Buf, Inst, sizeof(Inst));
@@ -175,7 +175,7 @@ void X86_64<ELFT>::relaxTlsGdToLe(uint8_t *Loc, RelType Type,
// lea x@tpoff,%rax
const uint8_t Inst[] = {
0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
- 0x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00 // lea x@tpoff,%rax
+ 0x48, 0x8d, 0x80, 0, 0, 0, 0, // lea x@tpoff,%rax
};
memcpy(Loc - 4, Inst, sizeof(Inst));
@@ -198,7 +198,7 @@ void X86_64<ELFT>::relaxTlsGdToIe(uint8_t *Loc, RelType Type,
// addq x@tpoff,%rax
const uint8_t Inst[] = {
0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
- 0x48, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00 // addq x@tpoff,%rax
+ 0x48, 0x03, 0x05, 0, 0, 0, 0, // addq x@tpoff,%rax
};
memcpy(Loc - 4, Inst, sizeof(Inst));
@@ -274,9 +274,9 @@ void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, RelType Type,
}
const uint8_t Inst[] = {
- 0x66, 0x66, // .word 0x6666
- 0x66, // .byte 0x66
- 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00 // mov %fs:0,%rax
+ 0x66, 0x66, // .word 0x6666
+ 0x66, // .byte 0x66
+ 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax
};
memcpy(Loc - 3, Inst, sizeof(Inst));
}
diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp
index 94ea3e1557c48..1aa0957b1d01e 100644
--- a/ELF/Relocations.cpp
+++ b/ELF/Relocations.cpp
@@ -581,44 +581,38 @@ static RelExpr getPltExpr(Symbol &Sym, RelExpr Expr, bool &IsConstant) {
return toPlt(Expr);
}
+// This modifies the expression if we can use a copy relocation or point the
+// symbol to the PLT.
template <class ELFT>
static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type,
InputSectionBase &S, uint64_t RelOff,
bool &IsConstant) {
- // We can create any dynamic relocation if a section is simply writable.
- if (S.Flags & SHF_WRITE)
- return Expr;
-
- // Or, if we are allowed to create dynamic relocations against
- // read-only sections (i.e. when "-z notext" is given),
- // we can create a dynamic relocation as we want, too.
- if (!Config->ZText) {
- // We use PLT for relocations that may overflow in runtime,
- // see comment for getPltExpr().
- if (Sym.isFunc() && !Target->isPicRel(Type))
- return getPltExpr(Sym, Expr, IsConstant);
- return Expr;
- }
-
// If a relocation can be applied at link-time, we don't need to
// create a dynamic relocation in the first place.
if (IsConstant)
return Expr;
- // If we got here we know that this relocation would require the dynamic
- // linker to write a value to read only memory.
-
- // If the relocation is to a weak undef, give up on it and produce a
- // non preemptible 0.
- if (Sym.isUndefWeak()) {
+ // If the relocation is to a weak undef, and we are producing
+ // executable, give up on it and produce a non preemptible 0.
+ if (!Config->Shared && Sym.isUndefWeak()) {
Sym.IsPreemptible = false;
IsConstant = true;
return Expr;
}
+ // We can create any dynamic relocation supported by the dynamic linker if a
+ // section is writable or we are passed -z notext.
+ bool CanWrite = (S.Flags & SHF_WRITE) || !Config->ZText;
+ if (CanWrite && Target->isPicRel(Type))
+ return Expr;
+
+ // If we got here we know that this relocation would require the dynamic
+ // linker to write a value to read only memory or use an unsupported
+ // relocation.
+
// We can hack around it if we are producing an executable and
// the refered symbol can be preemepted to refer to the executable.
- if (Config->Shared || (Config->Pic && !isRelExpr(Expr))) {
+ if (!CanWrite && (Config->Shared || (Config->Pic && !isRelExpr(Expr)))) {
error(
"can't create dynamic relocation " + toString(Type) + " against " +
(Sym.getName().empty() ? "local symbol" : "symbol: " + toString(Sym)) +
@@ -627,6 +621,11 @@ static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type,
return Expr;
}
+ // Copy relocations are only possible if we are creating an executable and the
+ // symbol is shared.
+ if (!Sym.isShared() || Config->Shared)
+ return Expr;
+
if (Sym.getVisibility() != STV_DEFAULT) {
error("cannot preempt symbol: " + toString(Sym) +
getLocation(S, Sym, RelOff));
diff --git a/ELF/ScriptLexer.cpp b/ELF/ScriptLexer.cpp
index 9f33c16f36b0e..ef5a1cff7590d 100644
--- a/ELF/ScriptLexer.cpp
+++ b/ELF/ScriptLexer.cpp
@@ -115,11 +115,19 @@ void ScriptLexer::tokenize(MemoryBufferRef MB) {
continue;
}
+ // ">foo" is parsed to ">" and "foo", but ">>" is parsed to ">>".
+ if (S.startswith("<<") || S.startswith("<=") || S.startswith(">>") ||
+ S.startswith(">=")) {
+ Vec.push_back(S.substr(0, 2));
+ S = S.substr(2);
+ continue;
+ }
+
// Unquoted token. This is more relaxed than tokens in C-like language,
// so that you can write "file-name.cpp" as one bare token, for example.
size_t Pos = S.find_first_not_of(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
- "0123456789_.$/\\~=+[]*?-!<>^:");
+ "0123456789_.$/\\~=+[]*?-!^:");
// A character that cannot start a word (which is usually a
// punctuation) forms a single character token.
diff --git a/ELF/ScriptParser.cpp b/ELF/ScriptParser.cpp
index c1176ccfa8d56..4263944981f2d 100644
--- a/ELF/ScriptParser.cpp
+++ b/ELF/ScriptParser.cpp
@@ -151,6 +151,7 @@ static ExprValue add(ExprValue A, ExprValue B) {
}
static ExprValue sub(ExprValue A, ExprValue B) {
+ // The distance between two symbols in sections is absolute.
if (!A.isAbsolute() && !B.isAbsolute())
return A.getValue() - B.getValue();
return {A.Sec, false, A.getSectionOffset() - B.getValue(), A.Loc};
@@ -707,8 +708,6 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) {
if (consume(">"))
Cmd->MemoryRegionName = next();
- else if (peek().startswith(">"))
- Cmd->MemoryRegionName = next().drop_front();
Cmd->Phdrs = readOutputSectionPhdrs();