diff options
Diffstat (limited to 'ELF')
-rw-r--r-- | ELF/Arch/X86.cpp | 18 | ||||
-rw-r--r-- | ELF/Arch/X86_64.cpp | 22 | ||||
-rw-r--r-- | ELF/Relocations.cpp | 43 | ||||
-rw-r--r-- | ELF/ScriptLexer.cpp | 10 | ||||
-rw-r--r-- | ELF/ScriptParser.cpp | 3 |
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(); |