[lld] r293283 - [ELF][ARM] Use SyntheticSections for Thunks
Peter Smith via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 27 05:10:17 PST 2017
Author: psmith
Date: Fri Jan 27 07:10:16 2017
New Revision: 293283
URL: http://llvm.org/viewvc/llvm-project?rev=293283&view=rev
Log:
[ELF][ARM] Use SyntheticSections for Thunks
Thunks are now implemented by redirecting the relocation to the
symbol S, to a symbol TS in a Thunk. The Thunk will transfer control
to S. This has the following implications:
- All the side-effects of Thunks happen within createThunks()
- Thunks are no longer stored in InputSections and Symbols no longer
need to hold a pointer to a Thunk
- The synthetic Thunk sections need to be merged into OutputSections
This implementation is almost a direct conversion of the existing
Thunks with the following exceptions:
- Mips LA25 Thunks are placed before the InputSection that defines
the symbol that needs a Thunk.
- All ARM Thunks are placed at the end of the OutputSection of the
first caller to the Thunk.
Range extension Thunks are not supported yet so it is optimistically
assumed that all Thunks can be reused.
Differential Revision: https://reviews.llvm.org/D29129
Modified:
lld/trunk/ELF/InputFiles.cpp
lld/trunk/ELF/InputSection.cpp
lld/trunk/ELF/InputSection.h
lld/trunk/ELF/LTO.cpp
lld/trunk/ELF/LTO.h
lld/trunk/ELF/Relocations.cpp
lld/trunk/ELF/Relocations.h
lld/trunk/ELF/SymbolTable.cpp
lld/trunk/ELF/Symbols.cpp
lld/trunk/ELF/Symbols.h
lld/trunk/ELF/SyntheticSections.cpp
lld/trunk/ELF/SyntheticSections.h
lld/trunk/ELF/Target.cpp
lld/trunk/ELF/Target.h
lld/trunk/ELF/Thunks.cpp
lld/trunk/ELF/Thunks.h
lld/trunk/ELF/Writer.cpp
lld/trunk/test/ELF/arm-thumb-interwork-shared.s
lld/trunk/test/ELF/arm-thumb-interwork-thunk.s
lld/trunk/test/ELF/mips-npic-call-pic.s
Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Fri Jan 27 07:10:16 2017
@@ -488,7 +488,7 @@ SymbolBody *elf::ObjectFile<ELFT>::creat
StringRefZ Name = this->StringTable.data() + Sym->st_name;
if (Sym->st_shndx == SHN_UNDEF)
return new (BAlloc)
- Undefined<ELFT>(Name, /*IsLocal=*/true, StOther, Type, this);
+ Undefined(Name, /*IsLocal=*/true, StOther, Type, this);
return new (BAlloc) DefinedRegular<ELFT>(Name, /*IsLocal=*/true, StOther,
Type, Value, Size, Sec, this);
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Fri Jan 27 07:10:16 2017
@@ -99,10 +99,6 @@ template <class ELFT> size_t InputSectio
if (auto *S = dyn_cast<SyntheticSection<ELFT>>(this))
return S->getSize();
- if (auto *D = dyn_cast<InputSection<ELFT>>(this))
- if (D->getThunksSize() > 0)
- return D->getThunkOff() + D->getThunksSize();
-
return Data.size();
}
@@ -214,21 +210,6 @@ InputSectionBase<ELFT> *InputSection<ELF
return Sections[this->Info];
}
-template <class ELFT> void InputSection<ELFT>::addThunk(const Thunk<ELFT> *T) {
- Thunks.push_back(T);
-}
-
-template <class ELFT> uint64_t InputSection<ELFT>::getThunkOff() const {
- return this->Data.size();
-}
-
-template <class ELFT> uint64_t InputSection<ELFT>::getThunksSize() const {
- uint64_t Total = 0;
- for (const Thunk<ELFT> *T : Thunks)
- Total += T->size();
- return Total;
-}
-
// This is used for -r. We can't use memcpy to copy relocations because we need
// to update symbol table offset and section index for each relocation. So we
// copy relocations one by one.
@@ -302,11 +283,6 @@ getRelocTargetVA(uint32_t Type, typename
return In<ELFT>::Got->getTlsIndexOff() + A - In<ELFT>::Got->getSize();
case R_TLSLD_PC:
return In<ELFT>::Got->getTlsIndexVA() + A - P;
- case R_THUNK_ABS:
- return Body.getThunkVA<ELFT>() + A;
- case R_THUNK_PC:
- case R_THUNK_PLT_PC:
- return Body.getThunkVA<ELFT>() + A - P;
case R_PPC_TOC:
return getPPC64TocBase() + A;
case R_TLSGD:
@@ -551,19 +527,6 @@ template <class ELFT> void InputSection<
// Iterate over all relocation sections that apply to this section.
uint8_t *BufEnd = Buf + OutSecOff + Data.size();
this->relocate(Buf, BufEnd);
-
- // The section might have a data/code generated by the linker and need
- // to be written after the section. Usually these are thunks - small piece
- // of code used to jump between "incompatible" functions like PIC and non-PIC
- // or if the jump target too far and its address does not fit to the short
- // jump istruction.
- if (!Thunks.empty()) {
- Buf += OutSecOff + getThunkOff();
- for (const Thunk<ELFT> *T : Thunks) {
- T->writeTo(Buf);
- Buf += T->size();
- }
- }
}
template <class ELFT>
Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Fri Jan 27 07:10:16 2017
@@ -280,17 +280,6 @@ public:
InputSectionBase<ELFT> *getRelocatedSection();
- // Register thunk related to the symbol. When the section is written
- // to a mmap'ed file, target is requested to write an actual thunk code.
- // Now thunks is supported for MIPS and ARM target only.
- void addThunk(const Thunk<ELFT> *T);
-
- // The offset of synthetic thunk code from beginning of this section.
- uint64_t getThunkOff() const;
-
- // Size of chunk with thunks code.
- uint64_t getThunksSize() const;
-
template <class RelTy>
void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
@@ -303,8 +292,6 @@ public:
private:
template <class RelTy>
void copyRelocations(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
-
- llvm::TinyPtrVector<const Thunk<ELFT> *> Thunks;
};
template <class ELFT> InputSection<ELFT> InputSection<ELFT>::Discarded;
Modified: lld/trunk/ELF/LTO.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LTO.cpp?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/LTO.cpp (original)
+++ lld/trunk/ELF/LTO.cpp Fri Jan 27 07:10:16 2017
@@ -96,12 +96,12 @@ BitcodeCompiler::BitcodeCompiler() : LTO
BitcodeCompiler::~BitcodeCompiler() = default;
-template <class ELFT> static void undefine(Symbol *S) {
- replaceBody<Undefined<ELFT>>(S, S->body()->getName(), /*IsLocal=*/false,
- STV_DEFAULT, S->body()->Type, nullptr);
+static void undefine(Symbol *S) {
+ replaceBody<Undefined>(S, S->body()->getName(), /*IsLocal=*/false,
+ STV_DEFAULT, S->body()->Type, nullptr);
}
-template <class ELFT> void BitcodeCompiler::add(BitcodeFile &F) {
+void BitcodeCompiler::add(BitcodeFile &F) {
lto::InputFile &Obj = *F.Obj;
unsigned SymNum = 0;
std::vector<Symbol *> Syms = F.getSymbols();
@@ -126,7 +126,7 @@ template <class ELFT> void BitcodeCompil
R.VisibleToRegularObj =
Sym->IsUsedInRegularObj || (R.Prevailing && Sym->includeInDynsym());
if (R.Prevailing)
- undefine<ELFT>(Sym);
+ undefine(Sym);
}
checkError(LTOObj->add(std::move(F.Obj), Resols));
}
@@ -157,8 +157,3 @@ std::vector<InputFile *> BitcodeCompiler
}
return Ret;
}
-
-template void BitcodeCompiler::template add<ELF32LE>(BitcodeFile &);
-template void BitcodeCompiler::template add<ELF32BE>(BitcodeFile &);
-template void BitcodeCompiler::template add<ELF64LE>(BitcodeFile &);
-template void BitcodeCompiler::template add<ELF64BE>(BitcodeFile &);
Modified: lld/trunk/ELF/LTO.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LTO.h?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/LTO.h (original)
+++ lld/trunk/ELF/LTO.h Fri Jan 27 07:10:16 2017
@@ -43,7 +43,7 @@ public:
BitcodeCompiler();
~BitcodeCompiler();
- template <class ELFT> void add(BitcodeFile &F);
+ void add(BitcodeFile &F);
std::vector<InputFile *> compile();
private:
Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Fri Jan 27 07:10:16 2017
@@ -43,6 +43,7 @@
#include "Relocations.h"
#include "Config.h"
+#include "Memory.h"
#include "OutputSections.h"
#include "Strings.h"
#include "SymbolTable.h"
@@ -52,6 +53,7 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
using namespace llvm;
using namespace llvm::ELF;
@@ -300,16 +302,14 @@ template <class ELFT> static bool isAbso
}
static bool needsPlt(RelExpr Expr) {
- return isRelExprOneOf<R_PLT_PC, R_PPC_PLT_OPD, R_PLT, R_PLT_PAGE_PC,
- R_THUNK_PLT_PC>(Expr);
+ return isRelExprOneOf<R_PLT_PC, R_PPC_PLT_OPD, R_PLT, R_PLT_PAGE_PC>(Expr);
}
// True if this expression is of the form Sym - X, where X is a position in the
// file (PC, or GOT for example).
static bool isRelExpr(RelExpr Expr) {
return isRelExprOneOf<R_PC, R_GOTREL, R_GOTREL_FROM_END, R_MIPS_GOTREL,
- R_PAGE_PC, R_RELAX_GOT_PC, R_THUNK_PC, R_THUNK_PLT_PC>(
- Expr);
+ R_PAGE_PC, R_RELAX_GOT_PC>(Expr);
}
template <class ELFT>
@@ -321,8 +321,7 @@ static bool isStaticLinkTimeConstant(Rel
if (isRelExprOneOf<R_SIZE, R_GOT_FROM_END, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE,
R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_TLSGD,
R_GOT_PAGE_PC, R_GOT_PC, R_PLT_PC, R_TLSGD_PC, R_TLSGD,
- R_PPC_PLT_OPD, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT,
- R_THUNK_PC, R_THUNK_PLT_PC>(E))
+ R_PPC_PLT_OPD, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT>(E))
return true;
// These never do, except if the entire file is position dependent or if
@@ -467,7 +466,6 @@ static RelExpr adjustExpr(const elf::Obj
if (Expr == R_GOT_PC && !isAbsoluteValue<ELFT>(Body))
Expr = Target->adjustRelaxExpr(Type, Data, Expr);
}
- Expr = Target->getThunkExpr(Expr, Type, &File, Body);
if (IsWrite || isStaticLinkTimeConstant<ELFT>(Expr, Type, Body, S, RelOff))
return Expr;
@@ -685,7 +683,6 @@ static void scanRelocs(InputSectionBase<
continue;
if (needsPlt(Expr) ||
- isRelExprOneOf<R_THUNK_ABS, R_THUNK_PC, R_THUNK_PLT_PC>(Expr) ||
refersToGotEntry(Expr) || !isPreemptible(Body, Type)) {
// If the relocation points to something in the file, we can process it.
bool Constant =
@@ -805,33 +802,126 @@ template <class ELFT> void scanRelocatio
scanRelocs(S, S.rels());
}
+// Insert the Thunks for OutputSection OS into their designated place
+// in the Sections vector, and recalculate the InputSection output section
+// offsets.
+// This may invalidate any output section offsets stored outside of InputSection
+template <class ELFT>
+static void mergeThunks(OutputSection<ELFT> *OS,
+ std::vector<ThunkSection<ELFT> *> &Thunks) {
+ // Order Thunks in ascending OutSecOff
+ auto ThunkCmp = [](const ThunkSection<ELFT> *A, const ThunkSection<ELFT> *B) {
+ return A->OutSecOff < B->OutSecOff;
+ };
+ std::stable_sort(Thunks.begin(), Thunks.end(), ThunkCmp);
+
+ // Merge sorted vectors of Thunks and InputSections by OutSecOff
+ std::vector<InputSection<ELFT> *> Tmp;
+ Tmp.reserve(OS->Sections.size() + Thunks.size());
+ auto MergeCmp = [](const ThunkSection<ELFT> *Thunk,
+ const InputSection<ELFT> *IS) {
+ // All thunks go before any non-executable InputSections
+ if ((IS->Flags & SHF_EXECINSTR) == 0)
+ return true;
+ // Some Thunk Sections such as the Mips LA25 thunk must be placed before
+ // the InputSections that they target. We represent this by assigning the
+ // ThunkSection the same OutSecOff and always placing the Thunk first if
+ // the OutSecOff values are the same.
+ return Thunk->OutSecOff <= IS->OutSecOff;
+ };
+ std::merge(OS->Sections.begin(), OS->Sections.end(), Thunks.begin(),
+ Thunks.end(), std::back_inserter(Tmp), MergeCmp);
+ OS->Sections = std::move(Tmp);
+ OS->Size = 0;
+ OS->assignOffsets();
+}
+
+// Process all relocations from the InputSections that have been assigned
+// to OutputSections and redirect through Thunks if needed.
+//
+// createThunks must be called after scanRelocs has created the Relocations for
+// each InputSection. It must be called before the static symbol table is
+// finalized. If any Thunks are added to an OutputSection the output section
+// offsets of the InputSections will change.
+//
+// FIXME: All Thunks are assumed to be in range of the relocation. Range
+// extension Thunks are not yet supported.
template <class ELFT>
void createThunks(ArrayRef<OutputSectionBase *> OutputSections) {
+ // Track Symbols that already have a Thunk
+ DenseMap<SymbolBody *, Thunk<ELFT> *> ThunkedSymbols;
+ // Track InputSections that have a ThunkSection placed in front
+ DenseMap<InputSection<ELFT> *, ThunkSection<ELFT> *> ThunkedSections;
+ // Track the ThunksSections that need to be inserted into an OutputSection
+ std::map<OutputSection<ELFT> *, std::vector<ThunkSection<ELFT> *>>
+ ThunkSections;
+
+ // Find or create a Thunk for Body for relocation Type
+ auto GetThunk = [&](SymbolBody &Body, uint32_t Type) {
+ auto res = ThunkedSymbols.insert({&Body, nullptr});
+ if (res.second == true)
+ res.first->second = addThunk<ELFT>(Type, Body);
+ return std::make_pair(res.first->second, res.second);
+ };
+
+ // Find or create a ThunkSection to be placed immediately before IS
+ auto GetISThunkSec = [&](InputSection<ELFT> *IS, OutputSection<ELFT> *OS) {
+ ThunkSection<ELFT> *TS = ThunkedSections.lookup(IS);
+ if (TS)
+ return TS;
+ auto *TOS = cast<OutputSection<ELFT>>(IS->OutSec);
+ TS = make<ThunkSection<ELFT>>(TOS, IS->OutSecOff);
+ ThunkSections[OS].push_back(TS);
+ ThunkedSections[IS] = TS;
+ return TS;
+ };
+ // Find or create a ThunkSection to be placed at the end of OS
+ auto GetOSThunkSec = [&](ThunkSection<ELFT> *&TS, OutputSection<ELFT> *OS) {
+ if (TS == nullptr) {
+ TS = make<ThunkSection<ELFT>>(OS, OS->Size);
+ ThunkSections[OS].push_back(TS);
+ }
+ return TS;
+ };
+ // Create all the Thunks and insert them into synthetic ThunkSections. The
+ // ThunkSections are later inserted back into the OutputSection.
+
+ // We separate the creation of ThunkSections from the insertion of the
+ // ThunkSections back into the OutputSection as ThunkSections are not always
+ // inserted into the same OutputSection as the caller.
for (OutputSectionBase *Base : OutputSections) {
auto *OS = dyn_cast<OutputSection<ELFT>>(Base);
if (OS == nullptr)
continue;
+
+ ThunkSection<ELFT> *OSTS = nullptr;
for (InputSection<ELFT> *IS : OS->Sections) {
- for (const Relocation &Rel : IS->Relocations) {
- if (Rel.Sym == nullptr)
- continue;
- RelExpr Expr = Rel.Expr;
- // Some targets might require creation of thunks for relocations.
- // Now we support only MIPS which requires LA25 thunk to call PIC
- // code from non-PIC one, and ARM which requires interworking.
- if (Expr == R_THUNK_ABS || Expr == R_THUNK_PC ||
- Expr == R_THUNK_PLT_PC)
- addThunk<ELFT>(Rel.Type, *Rel.Sym, *IS);
+ for (Relocation &Rel : IS->Relocations) {
+ SymbolBody &Body = *Rel.Sym;
+ if (Target->needsThunk(Rel.Expr, Rel.Type, IS->getFile(), Body)) {
+ Thunk<ELFT> *T;
+ bool IsNew;
+ std::tie(T, IsNew) = GetThunk(Body, Rel.Type);
+ if (IsNew) {
+ // Find or create a ThunkSection for the new Thunk
+ ThunkSection<ELFT> *TS;
+ if (auto *TIS = T->getTargetInputSection())
+ TS = GetISThunkSec(TIS, OS);
+ else
+ TS = GetOSThunkSec(OSTS, OS);
+ TS->addThunk(T);
+ }
+ // Redirect relocation to Thunk, we never go via the PLT to a Thunk
+ Rel.Sym = T->ThunkSym;
+ Rel.Expr = fromPlt(Rel.Expr);
+ }
}
}
}
- // Added thunks may affect the output section offset
- for (OutputSectionBase *Base : OutputSections)
- if (auto *OS = dyn_cast<OutputSection<ELFT>>(Base))
- if (OS->Type == SHT_PROGBITS) {
- OS->Size = 0;
- OS->assignOffsets();
- }
+
+ // Merge all created synthetic ThunkSections back into OutputSection
+ for (auto &KV : ThunkSections)
+ mergeThunks<ELFT>(KV.first, KV.second);
}
template void scanRelocations<ELF32LE>(InputSectionBase<ELF32LE> &);
Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Fri Jan 27 07:10:16 2017
@@ -61,9 +61,6 @@ enum RelExpr {
R_RELAX_TLS_IE_TO_LE,
R_RELAX_TLS_LD_TO_LE,
R_SIZE,
- R_THUNK_ABS,
- R_THUNK_PC,
- R_THUNK_PLT_PC,
R_TLS,
R_TLSDESC,
R_TLSDESC_PAGE,
Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Fri Jan 27 07:10:16 2017
@@ -115,7 +115,7 @@ template <class ELFT> void SymbolTable<E
// Compile bitcode files and replace bitcode symbols.
LTO.reset(new BitcodeCompiler);
for (BitcodeFile *F : BitcodeFiles)
- LTO->add<ELFT>(*F);
+ LTO->add(*F);
for (InputFile *File : LTO->compile()) {
ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(File);
@@ -256,7 +256,7 @@ Symbol *SymbolTable<ELFT>::addUndefined(
insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, File);
if (WasInserted) {
S->Binding = Binding;
- replaceBody<Undefined<ELFT>>(S, Name, IsLocal, StOther, Type, File);
+ replaceBody<Undefined>(S, Name, IsLocal, StOther, Type, File);
return S;
}
if (Binding != STB_WEAK) {
@@ -428,7 +428,7 @@ void SymbolTable<ELFT>::addShared(Shared
// Make sure we preempt DSO symbols with default visibility.
if (Sym.getVisibility() == STV_DEFAULT)
S->ExportDynamic = true;
- if (WasInserted || isa<Undefined<ELFT>>(S->body())) {
+ if (WasInserted || isa<Undefined>(S->body())) {
replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef);
if (!S->isWeak())
F->IsUsed = true;
Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Fri Jan 27 07:10:16 2017
@@ -132,14 +132,6 @@ bool SymbolBody::isPreemptible() const {
return true;
}
-template <class ELFT> bool SymbolBody::hasThunk() const {
- if (auto *DR = dyn_cast<DefinedRegular<ELFT>>(this))
- return DR->ThunkData != nullptr;
- if (auto *S = dyn_cast<SharedSymbol<ELFT>>(this))
- return S->ThunkData != nullptr;
- return false;
-}
-
template <class ELFT>
typename ELFT::uint SymbolBody::getVA(typename ELFT::uint Addend) const {
typename ELFT::uint OutVA = getSymVA<ELFT>(*this, Addend);
@@ -171,16 +163,6 @@ template <class ELFT> typename ELFT::uin
PltIndex * Target->PltEntrySize;
}
-template <class ELFT> typename ELFT::uint SymbolBody::getThunkVA() const {
- if (const auto *DR = dyn_cast<DefinedRegular<ELFT>>(this))
- return DR->ThunkData->getVA();
- if (const auto *S = dyn_cast<SharedSymbol<ELFT>>(this))
- return S->ThunkData->getVA();
- if (const auto *S = dyn_cast<Undefined<ELFT>>(this))
- return S->ThunkData->getVA();
- fatal("getThunkVA() not supported for Symbol class\n");
-}
-
template <class ELFT> typename ELFT::uint SymbolBody::getSize() const {
if (const auto *C = dyn_cast<DefinedCommon>(this))
return C->Size;
@@ -241,9 +223,8 @@ template <class ELFT> bool DefinedRegula
(Section->getFile()->getObj().getHeader()->e_flags & EF_MIPS_PIC);
}
-template <typename ELFT>
-Undefined<ELFT>::Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther,
- uint8_t Type, InputFile *File)
+Undefined::Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther,
+ uint8_t Type, InputFile *File)
: SymbolBody(SymbolBody::UndefinedKind, Name, IsLocal, StOther, Type) {
this->File = File;
}
@@ -338,11 +319,6 @@ std::string lld::toString(const SymbolBo
return B.getName();
}
-template bool SymbolBody::hasThunk<ELF32LE>() const;
-template bool SymbolBody::hasThunk<ELF32BE>() const;
-template bool SymbolBody::hasThunk<ELF64LE>() const;
-template bool SymbolBody::hasThunk<ELF64BE>() const;
-
template uint32_t SymbolBody::template getVA<ELF32LE>(uint32_t) const;
template uint32_t SymbolBody::template getVA<ELF32BE>(uint32_t) const;
template uint64_t SymbolBody::template getVA<ELF64LE>(uint64_t) const;
@@ -363,11 +339,6 @@ template uint32_t SymbolBody::template g
template uint64_t SymbolBody::template getGotPltVA<ELF64LE>() const;
template uint64_t SymbolBody::template getGotPltVA<ELF64BE>() const;
-template uint32_t SymbolBody::template getThunkVA<ELF32LE>() const;
-template uint32_t SymbolBody::template getThunkVA<ELF32BE>() const;
-template uint64_t SymbolBody::template getThunkVA<ELF64LE>() const;
-template uint64_t SymbolBody::template getThunkVA<ELF64BE>() const;
-
template uint32_t SymbolBody::template getGotPltOffset<ELF32LE>() const;
template uint32_t SymbolBody::template getGotPltOffset<ELF32BE>() const;
template uint64_t SymbolBody::template getGotPltOffset<ELF64LE>() const;
@@ -383,11 +354,6 @@ template uint32_t SymbolBody::template g
template uint64_t SymbolBody::template getSize<ELF64LE>() const;
template uint64_t SymbolBody::template getSize<ELF64BE>() const;
-template class elf::Undefined<ELF32LE>;
-template class elf::Undefined<ELF32BE>;
-template class elf::Undefined<ELF64LE>;
-template class elf::Undefined<ELF64BE>;
-
template class elf::SharedSymbol<ELF32LE>;
template class elf::SharedSymbol<ELF32BE>;
template class elf::SharedSymbol<ELF64LE>;
Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Fri Jan 27 07:10:16 2017
@@ -76,7 +76,6 @@ public:
bool isInGot() const { return GotIndex != -1U; }
bool isInPlt() const { return PltIndex != -1U; }
- template <class ELFT> bool hasThunk() const;
template <class ELFT>
typename ELFT::uint getVA(typename ELFT::uint Addend = 0) const;
@@ -86,7 +85,6 @@ public:
template <class ELFT> typename ELFT::uint getGotPltOffset() const;
template <class ELFT> typename ELFT::uint getGotPltVA() const;
template <class ELFT> typename ELFT::uint getPltVA() const;
- template <class ELFT> typename ELFT::uint getThunkVA() const;
template <class ELFT> typename ELFT::uint getSize() const;
// The file from which this symbol was created.
@@ -210,10 +208,6 @@ public:
// If this is null, the symbol is an absolute symbol.
InputSectionBase<ELFT> *&Section;
- // If non-null the symbol has a Thunk that may be used as an alternative
- // destination for callers of this Symbol.
- Thunk<ELFT> *ThunkData = nullptr;
-
private:
static InputSectionBase<ELFT> *NullInputSection;
};
@@ -242,7 +236,7 @@ public:
const OutputSectionBase *Section;
};
-template <class ELFT> class Undefined : public SymbolBody {
+class Undefined : public SymbolBody {
public:
Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t Type,
InputFile *F);
@@ -251,12 +245,6 @@ public:
return S->kind() == UndefinedKind;
}
- // If non-null the symbol has a Thunk that may be used as an alternative
- // destination for callers of this Symbol. When linking a DSO undefined
- // symbols are implicitly imported, the symbol lookup will be performed by
- // the dynamic loader. A call to an undefined symbol will be given a PLT
- // entry and on ARM this may need a Thunk if the caller is in Thumb state.
- Thunk<ELFT> *ThunkData = nullptr;
InputFile *file() { return this->File; }
};
@@ -291,9 +279,6 @@ public:
// CopyOffset is significant only when needsCopy() is true.
uintX_t CopyOffset = 0;
- // If non-null the symbol has a Thunk that may be used as an alternative
- // destination for callers of this Symbol.
- Thunk<ELFT> *ThunkData = nullptr;
bool needsCopy() const { return this->NeedsCopyOrPltAddr && !this->isFunc(); }
OutputSection<ELFT> *getBssSectionForCopy() const;
@@ -431,8 +416,7 @@ struct Symbol {
// ELFT, and we verify this with the static_asserts in replaceBody.
llvm::AlignedCharArrayUnion<
DefinedCommon, DefinedRegular<llvm::object::ELF64LE>, DefinedSynthetic,
- Undefined<llvm::object::ELF64LE>, SharedSymbol<llvm::object::ELF64LE>,
- LazyArchive, LazyObject>
+ Undefined, SharedSymbol<llvm::object::ELF64LE>, LazyArchive, LazyObject>
Body;
SymbolBody *body() { return reinterpret_cast<SymbolBody *>(Body.buffer); }
Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Fri Jan 27 07:10:16 2017
@@ -1904,6 +1904,27 @@ void ARMExidxSentinelSection<ELFT>::writ
write32le(Buf + 4, 0x1);
}
+template <class ELFT>
+ThunkSection<ELFT>::ThunkSection(OutputSectionBase *OS, uint64_t Off)
+ : SyntheticSection<ELFT>(SHF_ALLOC, SHT_PROGBITS,
+ sizeof(typename ELFT::uint), ".text.thunk") {
+ this->OutSec = OS;
+ this->OutSecOff = Off;
+}
+
+template <class ELFT> void ThunkSection<ELFT>::addThunk(Thunk<ELFT> *T) {
+ uint64_t Off = alignTo(Size, T->alignment);
+ T->Offset = Off;
+ Thunks.push_back(T);
+ T->addSymbols(*this);
+ Size = Off + T->size();
+}
+
+template <class ELFT> void ThunkSection<ELFT>::writeTo(uint8_t *Buf) {
+ for (const Thunk<ELFT> *T : Thunks)
+ T->writeTo(Buf + T->Offset, *this);
+}
+
template InputSection<ELF32LE> *elf::createCommonSection();
template InputSection<ELF32BE> *elf::createCommonSection();
template InputSection<ELF64LE> *elf::createCommonSection();
@@ -2046,3 +2067,8 @@ template class elf::ARMExidxSentinelSect
template class elf::ARMExidxSentinelSection<ELF32BE>;
template class elf::ARMExidxSentinelSection<ELF64LE>;
template class elf::ARMExidxSentinelSection<ELF64BE>;
+
+template class elf::ThunkSection<ELF32LE>;
+template class elf::ThunkSection<ELF32BE>;
+template class elf::ThunkSection<ELF64LE>;
+template class elf::ThunkSection<ELF64BE>;
Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Fri Jan 27 07:10:16 2017
@@ -699,6 +699,26 @@ public:
void writeTo(uint8_t *Buf) override;
};
+// A container for one or more linker generated thunks. Instances of these
+// thunks including ARM interworking and Mips LA25 PI to non-PI thunks.
+template <class ELFT> class ThunkSection : public SyntheticSection<ELFT> {
+public:
+ // ThunkSection in OS, with desired OutSecOff of Off
+ ThunkSection(OutputSectionBase *OS, uint64_t Off);
+
+ // Add a newly created Thunk to this container:
+ // Thunk is given offset from start of this InputSection
+ // Thunk defines a symbol in this InputSection that can be used as target
+ // of a relocation
+ void addThunk(Thunk<ELFT> *T);
+ size_t getSize() const override { return Size; }
+ void writeTo(uint8_t *Buf) override;
+
+private:
+ std::vector<const Thunk<ELFT> *> Thunks;
+ size_t Size = 0;
+};
+
template <class ELFT> InputSection<ELFT> *createCommonSection();
template <class ELFT> InputSection<ELFT> *createInterpSection();
template <class ELFT> MergeInputSection<ELFT> *createCommentSection();
Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Fri Jan 27 07:10:16 2017
@@ -228,8 +228,8 @@ public:
int32_t Index, unsigned RelOff) const override;
void addPltSymbols(InputSectionData *IS, uint64_t Off) const override;
void addPltHeaderSymbols(InputSectionData *ISD) const override;
- RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType, const InputFile *File,
- const SymbolBody &S) const override;
+ bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File,
+ const SymbolBody &S) const override;
void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
};
@@ -246,8 +246,8 @@ public:
void writePltHeader(uint8_t *Buf) const override;
void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
int32_t Index, unsigned RelOff) const override;
- RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType, const InputFile *File,
- const SymbolBody &S) const override;
+ bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File,
+ const SymbolBody &S) const override;
void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
bool usesOnlyLowPageBits(uint32_t Type) const override;
};
@@ -298,10 +298,9 @@ uint64_t TargetInfo::getImplicitAddend(c
bool TargetInfo::usesOnlyLowPageBits(uint32_t Type) const { return false; }
-RelExpr TargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType,
- const InputFile *File,
- const SymbolBody &S) const {
- return Expr;
+bool TargetInfo::needsThunk(RelExpr Expr, uint32_t RelocType,
+ const InputFile *File, const SymbolBody &S) const {
+ return false;
}
bool TargetInfo::isTlsInitialExecRel(uint32_t Type) const { return false; }
@@ -1771,15 +1770,15 @@ void ARMTargetInfo::addPltSymbols(InputS
addSyntheticLocal("$d", STT_NOTYPE, Off + 12, 0, IS);
}
-RelExpr ARMTargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType,
- const InputFile *File,
- const SymbolBody &S) const {
+bool ARMTargetInfo::needsThunk(RelExpr Expr, uint32_t RelocType,
+ const InputFile *File,
+ const SymbolBody &S) const {
// If S is an undefined weak symbol in an executable we don't need a Thunk.
// In a DSO calls to undefined symbols, including weak ones get PLT entries
// which may need a thunk.
if (S.isUndefined() && !S.isLocal() && S.symbol()->isWeak() &&
!Config->Shared)
- return Expr;
+ return false;
// A state change from ARM to Thumb and vice versa must go through an
// interworking thunk if the relocation type is not R_ARM_CALL or
// R_ARM_THM_CALL.
@@ -1790,19 +1789,17 @@ RelExpr ARMTargetInfo::getThunkExpr(RelE
// Source is ARM, all PLT entries are ARM so no interworking required.
// Otherwise we need to interwork if Symbol has bit 0 set (Thumb).
if (Expr == R_PC && ((S.getVA<ELF32LE>() & 1) == 1))
- return R_THUNK_PC;
+ return true;
break;
case R_ARM_THM_JUMP19:
case R_ARM_THM_JUMP24:
// Source is Thumb, all PLT entries are ARM so interworking is required.
// Otherwise we need to interwork if Symbol has bit 0 clear (ARM).
- if (Expr == R_PLT_PC)
- return R_THUNK_PLT_PC;
- if ((S.getVA<ELF32LE>() & 1) == 0)
- return R_THUNK_PC;
+ if (Expr == R_PLT_PC || ((S.getVA<ELF32LE>() & 1) == 0))
+ return true;
break;
}
- return Expr;
+ return false;
}
void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
@@ -2215,26 +2212,26 @@ void MipsTargetInfo<ELFT>::writePlt(uint
}
template <class ELFT>
-RelExpr MipsTargetInfo<ELFT>::getThunkExpr(RelExpr Expr, uint32_t Type,
- const InputFile *File,
- const SymbolBody &S) const {
+bool MipsTargetInfo<ELFT>::needsThunk(RelExpr Expr, uint32_t Type,
+ const InputFile *File,
+ const SymbolBody &S) const {
// Any MIPS PIC code function is invoked with its address in register $t9.
// So if we have a branch instruction from non-PIC code to the PIC one
// we cannot make the jump directly and need to create a small stubs
// to save the target function address.
// See page 3-38 ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
if (Type != R_MIPS_26)
- return Expr;
+ return false;
auto *F = dyn_cast_or_null<ELFFileBase<ELFT>>(File);
if (!F)
- return Expr;
+ return false;
// If current file has PIC code, LA25 stub is not required.
if (F->getObj().getHeader()->e_flags & EF_MIPS_PIC)
- return Expr;
+ return false;
auto *D = dyn_cast<DefinedRegular<ELFT>>(&S);
// LA25 is required if target file has PIC code
// or target symbol is a PIC symbol.
- return D && D->isMipsPIC() ? R_THUNK_ABS : Expr;
+ return D && D->isMipsPIC();
}
template <class ELFT>
Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Fri Jan 27 07:10:16 2017
@@ -41,8 +41,8 @@ public:
virtual void writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr, int32_t Index,
unsigned RelOff) const {}
- virtual void addPltHeaderSymbols(InputSectionData* IS) const {}
- virtual void addPltSymbols(InputSectionData* IS, uint64_t Off) const {}
+ virtual void addPltHeaderSymbols(InputSectionData *IS) const {}
+ virtual void addPltSymbols(InputSectionData *IS, uint64_t Off) const {}
// Returns true if a relocation only uses the low bits of a value such that
// all those bits are in in the same page. For example, if the relocation
// only uses the low 12 bits in a system with 4k pages. If this is true, the
@@ -51,14 +51,9 @@ public:
virtual bool usesOnlyLowPageBits(uint32_t Type) const;
// Decide whether a Thunk is needed for the relocation from File
- // targeting S. Returns one of:
- // Expr if there is no Thunk required
- // R_THUNK_ABS if thunk is required and expression is absolute
- // R_THUNK_PC if thunk is required and expression is pc rel
- // R_THUNK_PLT_PC if thunk is required to PLT entry and expression is pc rel
- virtual RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType,
- const InputFile *File,
- const SymbolBody &S) const;
+ // targeting S.
+ virtual bool needsThunk(RelExpr Expr, uint32_t RelocType,
+ const InputFile *File, const SymbolBody &S) const;
virtual RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const = 0;
virtual void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const = 0;
virtual ~TargetInfo();
Modified: lld/trunk/ELF/Thunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.cpp?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/Thunks.cpp (original)
+++ lld/trunk/ELF/Thunks.cpp Fri Jan 27 07:10:16 2017
@@ -28,6 +28,7 @@
#include "Memory.h"
#include "OutputSections.h"
#include "Symbols.h"
+#include "SyntheticSections.h"
#include "Target.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ELF.h"
@@ -52,53 +53,54 @@ namespace {
template <class ELFT>
class ARMToThumbV7ABSLongThunk final : public Thunk<ELFT> {
public:
- ARMToThumbV7ABSLongThunk(const SymbolBody &Dest,
- const InputSection<ELFT> &Owner)
- : Thunk<ELFT>(Dest, Owner) {}
+ ARMToThumbV7ABSLongThunk(const SymbolBody &Dest) : Thunk<ELFT>(Dest) {}
uint32_t size() const override { return 12; }
- void writeTo(uint8_t *Buf) const override;
+ void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const override;
+ void addSymbols(ThunkSection<ELFT> &IS) override;
};
template <class ELFT> class ARMToThumbV7PILongThunk final : public Thunk<ELFT> {
public:
- ARMToThumbV7PILongThunk(const SymbolBody &Dest,
- const InputSection<ELFT> &Owner)
- : Thunk<ELFT>(Dest, Owner) {}
+ ARMToThumbV7PILongThunk(const SymbolBody &Dest) : Thunk<ELFT>(Dest) {}
uint32_t size() const override { return 16; }
- void writeTo(uint8_t *Buf) const override;
+ void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const override;
+ void addSymbols(ThunkSection<ELFT> &IS) override;
};
template <class ELFT>
class ThumbToARMV7ABSLongThunk final : public Thunk<ELFT> {
public:
- ThumbToARMV7ABSLongThunk(const SymbolBody &Dest,
- const InputSection<ELFT> &Owner)
- : Thunk<ELFT>(Dest, Owner) {}
+ ThumbToARMV7ABSLongThunk(const SymbolBody &Dest) : Thunk<ELFT>(Dest) {
+ this->alignment = 2;
+ }
uint32_t size() const override { return 10; }
- void writeTo(uint8_t *Buf) const override;
+ void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const override;
+ void addSymbols(ThunkSection<ELFT> &IS) override;
};
template <class ELFT> class ThumbToARMV7PILongThunk final : public Thunk<ELFT> {
public:
- ThumbToARMV7PILongThunk(const SymbolBody &Dest,
- const InputSection<ELFT> &Owner)
- : Thunk<ELFT>(Dest, Owner) {}
+ ThumbToARMV7PILongThunk(const SymbolBody &Dest) : Thunk<ELFT>(Dest) {
+ this->alignment = 2;
+ }
uint32_t size() const override { return 12; }
- void writeTo(uint8_t *Buf) const override;
+ void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const override;
+ void addSymbols(ThunkSection<ELFT> &IS) override;
};
// MIPS LA25 thunk
template <class ELFT> class MipsThunk final : public Thunk<ELFT> {
public:
- MipsThunk(const SymbolBody &Dest, const InputSection<ELFT> &Owner)
- : Thunk<ELFT>(Dest, Owner) {}
+ MipsThunk(const SymbolBody &Dest) : Thunk<ELFT>(Dest) {}
uint32_t size() const override { return 16; }
- void writeTo(uint8_t *Buf) const override;
+ void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const override;
+ void addSymbols(ThunkSection<ELFT> &IS) override;
+ InputSection<ELFT> *getTargetInputSection() const override;
};
} // end anonymous namespace
@@ -110,7 +112,8 @@ template <class ELFT> static uint64_t ge
}
template <class ELFT>
-void ARMToThumbV7ABSLongThunk<ELFT>::writeTo(uint8_t *Buf) const {
+void ARMToThumbV7ABSLongThunk<ELFT>::writeTo(uint8_t *Buf,
+ ThunkSection<ELFT> &IS) const {
const uint8_t Data[] = {
0x00, 0xc0, 0x00, 0xe3, // movw ip,:lower16:S
0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S
@@ -123,7 +126,16 @@ void ARMToThumbV7ABSLongThunk<ELFT>::wri
}
template <class ELFT>
-void ThumbToARMV7ABSLongThunk<ELFT>::writeTo(uint8_t *Buf) const {
+void ARMToThumbV7ABSLongThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS) {
+ this->ThunkSym = addSyntheticLocal(
+ Saver.save("__ARMToThumbv7ABSLongThunk_" + this->Destination.getName()),
+ STT_FUNC, this->Offset, size(), &IS);
+ addSyntheticLocal("$a", STT_NOTYPE, this->Offset, 0, &IS);
+}
+
+template <class ELFT>
+void ThumbToARMV7ABSLongThunk<ELFT>::writeTo(uint8_t *Buf,
+ ThunkSection<ELFT> &IS) const {
const uint8_t Data[] = {
0x40, 0xf2, 0x00, 0x0c, // movw ip, :lower16:S
0xc0, 0xf2, 0x00, 0x0c, // movt ip, :upper16:S
@@ -136,7 +148,16 @@ void ThumbToARMV7ABSLongThunk<ELFT>::wri
}
template <class ELFT>
-void ARMToThumbV7PILongThunk<ELFT>::writeTo(uint8_t *Buf) const {
+void ThumbToARMV7ABSLongThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS) {
+ this->ThunkSym = addSyntheticLocal(
+ Saver.save("__ThumbToARMv7ABSLongThunk_" + this->Destination.getName()),
+ STT_FUNC, this->Offset, size(), &IS);
+ addSyntheticLocal("$t", STT_NOTYPE, this->Offset, 0, &IS);
+}
+
+template <class ELFT>
+void ARMToThumbV7PILongThunk<ELFT>::writeTo(uint8_t *Buf,
+ ThunkSection<ELFT> &IS) const {
const uint8_t Data[] = {
0xf0, 0xcf, 0x0f, 0xe3, // P: movw ip,:lower16:S - (P + (L1-P) +8)
0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S - (P + (L1-P+4) +8)
@@ -144,14 +165,23 @@ void ARMToThumbV7PILongThunk<ELFT>::writ
0x1c, 0xff, 0x2f, 0xe1, // bx r12
};
uint64_t S = getARMThunkDestVA<ELFT>(this->Destination);
- uint64_t P = this->getVA();
+ uint64_t P = this->ThunkSym->template getVA<ELFT>();
memcpy(Buf, Data, sizeof(Data));
Target->relocateOne(Buf, R_ARM_MOVW_PREL_NC, S - P - 16);
Target->relocateOne(Buf + 4, R_ARM_MOVT_PREL, S - P - 12);
}
template <class ELFT>
-void ThumbToARMV7PILongThunk<ELFT>::writeTo(uint8_t *Buf) const {
+void ARMToThumbV7PILongThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS) {
+ this->ThunkSym = addSyntheticLocal(
+ Saver.save("__ARMToThumbV7PILongThunk_" + this->Destination.getName()),
+ STT_FUNC, this->Offset, size(), &IS);
+ addSyntheticLocal("$a", STT_NOTYPE, this->Offset, 0, &IS);
+}
+
+template <class ELFT>
+void ThumbToARMV7PILongThunk<ELFT>::writeTo(uint8_t *Buf,
+ ThunkSection<ELFT> &IS) const {
const uint8_t Data[] = {
0x4f, 0xf6, 0xf4, 0x7c, // P: movw ip,:lower16:S - (P + (L1-P) + 4)
0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P+4) + 4)
@@ -159,14 +189,23 @@ void ThumbToARMV7PILongThunk<ELFT>::writ
0x60, 0x47, // bx r12
};
uint64_t S = getARMThunkDestVA<ELFT>(this->Destination);
- uint64_t P = this->getVA();
+ uint64_t P = this->ThunkSym->template getVA<ELFT>();
memcpy(Buf, Data, sizeof(Data));
Target->relocateOne(Buf, R_ARM_THM_MOVW_PREL_NC, S - P - 12);
Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_PREL, S - P - 8);
}
+template <class ELFT>
+void ThumbToARMV7PILongThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS) {
+ this->ThunkSym = addSyntheticLocal(
+ Saver.save("__ThumbToARMV7PILongThunk_" + this->Destination.getName()),
+ STT_FUNC, this->Offset, size(), &IS);
+ addSyntheticLocal("$t", STT_NOTYPE, this->Offset, 0, &IS);
+}
+
// Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
-template <class ELFT> void MipsThunk<ELFT>::writeTo(uint8_t *Buf) const {
+template <class ELFT>
+void MipsThunk<ELFT>::writeTo(uint8_t *Buf, ThunkSection<ELFT> &) const {
const endianness E = ELFT::TargetEndianness;
uint64_t S = this->Destination.template getVA<ELFT>();
@@ -178,20 +217,26 @@ template <class ELFT> void MipsThunk<ELF
Target->relocateOne(Buf + 8, R_MIPS_LO16, S);
}
-template <class ELFT>
-Thunk<ELFT>::Thunk(const SymbolBody &D, const InputSection<ELFT> &O)
- : Destination(D), Owner(O), Offset(O.getThunkOff() + O.getThunksSize()) {}
+template <class ELFT> void MipsThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS) {
+ this->ThunkSym = addSyntheticLocal(
+ Saver.save("__LA25Thunk_" + this->Destination.getName()), STT_FUNC,
+ this->Offset, size(), &IS);
+}
-template <class ELFT> typename ELFT::uint Thunk<ELFT>::getVA() const {
- return Owner.OutSec->Addr + Owner.OutSecOff + Offset;
+template <class ELFT>
+InputSection<ELFT> *MipsThunk<ELFT>::getTargetInputSection() const {
+ auto *DR = dyn_cast<DefinedRegular<ELFT>>(&this->Destination);
+ return dyn_cast<InputSection<ELFT>>(DR->Section);
}
+template <class ELFT>
+Thunk<ELFT>::Thunk(const SymbolBody &D) : Destination(D), Offset(0) {}
+
template <class ELFT> Thunk<ELFT>::~Thunk() = default;
// Creates a thunk for Thumb-ARM interworking.
template <class ELFT>
-static Thunk<ELFT> *createThunkArm(uint32_t Reloc, SymbolBody &S,
- InputSection<ELFT> &IS) {
+static Thunk<ELFT> *addThunkArm(uint32_t Reloc, SymbolBody &S) {
// ARM relocations need ARM to Thumb interworking Thunks.
// Thumb relocations need Thumb to ARM relocations.
// Use position independent Thunks if we require position independent code.
@@ -200,71 +245,34 @@ static Thunk<ELFT> *createThunkArm(uint3
case R_ARM_PLT32:
case R_ARM_JUMP24:
if (Config->Pic)
- return new (BAlloc) ARMToThumbV7PILongThunk<ELFT>(S, IS);
- return new (BAlloc) ARMToThumbV7ABSLongThunk<ELFT>(S, IS);
+ return make<ARMToThumbV7PILongThunk<ELFT>>(S);
+ return make<ARMToThumbV7ABSLongThunk<ELFT>>(S);
case R_ARM_THM_JUMP19:
case R_ARM_THM_JUMP24:
if (Config->Pic)
- return new (BAlloc) ThumbToARMV7PILongThunk<ELFT>(S, IS);
- return new (BAlloc) ThumbToARMV7ABSLongThunk<ELFT>(S, IS);
+ return make<ThumbToARMV7PILongThunk<ELFT>>(S);
+ return make<ThumbToARMV7ABSLongThunk<ELFT>>(S);
}
fatal("unrecognized relocation type");
}
-template <class ELFT>
-static void addThunkARM(uint32_t Reloc, SymbolBody &S, InputSection<ELFT> &IS) {
- // Only one Thunk supported per symbol.
- if (S.hasThunk<ELFT>())
- return;
-
- // ARM Thunks are added to the same InputSection as the relocation. This
- // isn't strictly necessary but it makes it more likely that a limited range
- // branch can reach the Thunk, and it makes Thunks to the PLT section easier
- Thunk<ELFT> *T = createThunkArm(Reloc, S, IS);
- IS.addThunk(T);
- if (auto *Sym = dyn_cast<DefinedRegular<ELFT>>(&S))
- Sym->ThunkData = T;
- else if (auto *Sym = dyn_cast<SharedSymbol<ELFT>>(&S))
- Sym->ThunkData = T;
- else if (auto *Sym = dyn_cast<Undefined<ELFT>>(&S))
- Sym->ThunkData = T;
- else
- fatal("symbol not DefinedRegular or Shared");
-}
-
-template <class ELFT>
-static void addThunkMips(uint32_t RelocType, SymbolBody &S,
- InputSection<ELFT> &IS) {
- // Only one Thunk supported per symbol.
- if (S.hasThunk<ELFT>())
- return;
-
- // Mips Thunks are added to the InputSection defining S.
- auto *R = cast<DefinedRegular<ELFT>>(&S);
- auto *Sec = cast<InputSection<ELFT>>(R->Section);
- auto *T = new (BAlloc) MipsThunk<ELFT>(S, *Sec);
- Sec->addThunk(T);
- R->ThunkData = T;
+template <class ELFT> static Thunk<ELFT> *addThunkMips(SymbolBody &S) {
+ return make<MipsThunk<ELFT>>(S);
}
-template <class ELFT>
-void addThunk(uint32_t RelocType, SymbolBody &S, InputSection<ELFT> &IS) {
+template <class ELFT> Thunk<ELFT> *addThunk(uint32_t RelocType, SymbolBody &S) {
if (Config->EMachine == EM_ARM)
- addThunkARM<ELFT>(RelocType, S, IS);
+ return addThunkArm<ELFT>(RelocType, S);
else if (Config->EMachine == EM_MIPS)
- addThunkMips<ELFT>(RelocType, S, IS);
- else
- llvm_unreachable("add Thunk only supported for ARM and Mips");
+ return addThunkMips<ELFT>(S);
+ llvm_unreachable("add Thunk only supported for ARM and Mips");
+ return nullptr;
}
-template void addThunk<ELF32LE>(uint32_t, SymbolBody &,
- InputSection<ELF32LE> &);
-template void addThunk<ELF32BE>(uint32_t, SymbolBody &,
- InputSection<ELF32BE> &);
-template void addThunk<ELF64LE>(uint32_t, SymbolBody &,
- InputSection<ELF64LE> &);
-template void addThunk<ELF64BE>(uint32_t, SymbolBody &,
- InputSection<ELF64BE> &);
+template Thunk<ELF32LE> *addThunk<ELF32LE>(uint32_t, SymbolBody &);
+template Thunk<ELF32BE> *addThunk<ELF32BE>(uint32_t, SymbolBody &);
+template Thunk<ELF64LE> *addThunk<ELF64LE>(uint32_t, SymbolBody &);
+template Thunk<ELF64BE> *addThunk<ELF64BE>(uint32_t, SymbolBody &);
template class Thunk<ELF32LE>;
template class Thunk<ELF32BE>;
Modified: lld/trunk/ELF/Thunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.h?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/Thunks.h (original)
+++ lld/trunk/ELF/Thunks.h Fri Jan 27 07:10:16 2017
@@ -15,8 +15,8 @@
namespace lld {
namespace elf {
class SymbolBody;
-template <class ELFT> class InputSection;
-
+template <class ELFT> class ThunkSection;
+class OutputSectionBase;
// Class to describe an instance of a Thunk.
// A Thunk is a code-sequence inserted by the linker in between a caller and
// the callee. The relocation to the callee is redirected to the Thunk, which
@@ -24,31 +24,35 @@ template <class ELFT> class InputSection
// include transferring control from non-pi to pi and changing state on
// targets like ARM.
//
-// Thunks can be created for DefinedRegular and Shared Symbols. The Thunk
-// is stored in a field of the Symbol Destination.
-// Thunks to be written to an InputSection are recorded by the InputSection.
+// Thunks can be created for DefinedRegular, Shared and Undefined Symbols.
+// Thunks are assigned to synthetic ThunkSections
template <class ELFT> class Thunk {
- typedef typename ELFT::uint uintX_t;
-
public:
- Thunk(const SymbolBody &Destination, const InputSection<ELFT> &Owner);
+ Thunk(const SymbolBody &Destination);
virtual ~Thunk();
virtual uint32_t size() const { return 0; }
- virtual void writeTo(uint8_t *Buf) const {}
- uintX_t getVA() const;
+ virtual void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const {}
+
+ // All Thunks must define at least one symbol ThunkSym so that we can
+ // redirect relocations to it.
+ virtual void addSymbols(ThunkSection<ELFT> &IS) {}
+
+ // Some Thunks must be placed immediately before their Target as they elide
+ // a branch and fall through to the first Symbol in the Target.
+ virtual InputSection<ELFT> *getTargetInputSection() const { return nullptr; }
-protected:
+ // The alignment requirement for this Thunk, defaults to the size of the
+ // typical code section alignment.
const SymbolBody &Destination;
- const InputSection<ELFT> &Owner;
+ SymbolBody *ThunkSym;
uint64_t Offset;
+ uint32_t alignment = 4;
};
-// For a Relocation to symbol S from InputSection Src, create a Thunk and
-// update the fields of S and the InputSection that the Thunk body will be
-// written to. At present there are implementations for ARM and Mips Thunks.
-template <class ELFT>
-void addThunk(uint32_t RelocType, SymbolBody &S, InputSection<ELFT> &Src);
+// For a Relocation to symbol S create a Thunk to be added to a synthetic
+// ThunkSection. At present there are implementations for ARM and Mips Thunks.
+template <class ELFT> Thunk<ELFT> *addThunk(uint32_t RelocType, SymbolBody &S);
} // namespace elf
} // namespace lld
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Fri Jan 27 07:10:16 2017
@@ -1027,6 +1027,12 @@ template <class ELFT> void Writer<ELFT>:
if (In<ELFT>::Iplt && !In<ELFT>::Iplt->empty())
In<ELFT>::Iplt->addSymbols();
+ // Some architectures use small displacements for jump instructions.
+ // It is linker's responsibility to create thunks containing long
+ // jump instructions if jump targets are too far. Create thunks.
+ if (Target->NeedsThunks)
+ createThunks<ELFT>(OutputSections);
+
// Now that we have defined all possible symbols including linker-
// synthesized ones. Visit all symbols to give the finishing touches.
for (Symbol *S : Symtab<ELFT>::X->getSymbols()) {
@@ -1072,12 +1078,6 @@ template <class ELFT> void Writer<ELFT>:
fixHeaders();
}
- // Some architectures use small displacements for jump instructions.
- // It is linker's responsibility to create thunks containing long
- // jump instructions if jump targets are too far. Create thunks.
- if (Target->NeedsThunks)
- createThunks<ELFT>(OutputSections);
-
// Fill other section headers. The dynamic table is finalized
// at the end because some tags like RELSZ depend on result
// of finalizing other sections.
Modified: lld/trunk/test/ELF/arm-thumb-interwork-shared.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thumb-interwork-shared.s?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-thumb-interwork-shared.s (original)
+++ lld/trunk/test/ELF/arm-thumb-interwork-shared.s Fri Jan 27 07:10:16 2017
@@ -16,12 +16,15 @@ sym1:
// CHECK: Disassembly of section .text:
// CHECK-NEXT: sym1:
-// CHECK: 1000: 00 f0 02 b8 b.w #4
-// CHECK-NEXT: 1004: 00 f0 06 b8 b.w #12
+// CHECK-NEXT: 1000: 00 f0 02 b8 b.w #4 <__ThumbToARMV7PILongThunk_elsewhere+0x4>
+// CHECK-NEXT: 1004: 00 f0 06 b8 b.w #12 <__ThumbToARMV7PILongThunk_weakref+0x4>
+// CHECK: __ThumbToARMV7PILongThunk_elsewhere:
// CHECK-NEXT: 1008: 40 f2 20 0c movw r12, #32
// CHECK-NEXT: 100c: c0 f2 00 0c movt r12, #0
// CHECK-NEXT: 1010: fc 44 add r12, pc
// CHECK-NEXT: 1012: 60 47 bx r12
+
+// CHECK: __ThumbToARMV7PILongThunk_weakref:
// CHECK-NEXT: 1014: 40 f2 24 0c movw r12, #36
// CHECK-NEXT: 1018: c0 f2 00 0c movt r12, #0
// CHECK-NEXT: 101c: fc 44 add r12, pc
Modified: lld/trunk/test/ELF/arm-thumb-interwork-thunk.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thumb-interwork-thunk.s?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-thumb-interwork-thunk.s (original)
+++ lld/trunk/test/ELF/arm-thumb-interwork-thunk.s Fri Jan 27 07:10:16 2017
@@ -78,62 +78,65 @@ arm_caller:
beq arm_callee2
bne arm_callee3
bx lr
-// CHECK-ABS-ARM: Disassembly of section .arm_caller:
-// CHECK-ABS-ARM-NEXT: arm_caller:
-// CHECK-ABS-ARM-NEXT: 1300: 3e ff ff fa blx #-776 <thumb_callee1>
-// CHECK-ABS-ARM-NEXT: 1304: 3d ff ff fa blx #-780 <thumb_callee1>
-// CHECK-ABS-ARM-NEXT: 1308: 06 00 00 ea b #24 <arm_caller+0x28>
-// CHECK-ABS-ARM-NEXT: 130c: 05 00 00 ea b #20 <arm_caller+0x28>
-// CHECK-ABS-ARM-NEXT: 1310: 07 00 00 ea b #28 <arm_caller+0x34>
-// CHECK-ABS-ARM-NEXT: 1314: 09 00 00 ea b #36 <arm_caller+0x40>
-// CHECK-ABS-ARM-NEXT: 1318: 78 ff ff ea b #-544 <arm_callee1>
-// CHECK-ABS-ARM-NEXT: 131c: b7 00 00 0a beq #732 <arm_callee2>
-// CHECK-ABS-ARM-NEXT: 1320: b7 00 00 1a bne #732 <arm_callee3>
-// CHECK-ABS-ARM-NEXT: 1324: 1e ff 2f e1 bx lr
+// CHECK-ARM-ABS-ARM: Disassembly of section .arm_caller:
+// CHECK-ARM-ABS-ARM-NEXT: arm_caller:
+// CHECK-ARM-ABS-ARM-NEXT: 1300: 3e ff ff fa blx #-776 <thumb_callee1>
+// CHECK-ARM-ABS-ARM-NEXT: 1304: 3d ff ff fa blx #-780 <thumb_callee1>
+// CHECK-ARM-ABS-ARM-NEXT: 1308: 06 00 00 ea b #24 <__ARMToThumbv7ABSLongThunk_thumb_callee1>
+// CHECK-ARM-ABS-ARM-NEXT: 130c: 05 00 00 ea b #20 <__ARMToThumbv7ABSLongThunk_thumb_callee1>
+// CHECK-ARM-ABS-ARM-NEXT: 1310: 07 00 00 ea b #28 <__ARMToThumbv7ABSLongThunk_thumb_callee2>
+// CHECK-ARM-ABS-ARM-NEXT: 1314: 09 00 00 ea b #36 <__ARMToThumbv7ABSLongThunk_thumb_callee3>
+// CHECK-ARM-ABS-ARM-NEXT: 1318: 78 ff ff ea b #-544 <arm_callee1>
+// CHECK-ARM-ABS-ARM-NEXT: 131c: b7 00 00 0a beq #732 <arm_callee2>
+// CHECK-ARM-ABS-ARM-NEXT: 1320: b7 00 00 1a bne #732 <arm_callee3>
+// CHECK-ARM-ABS-ARM-NEXT: 1324: 1e ff 2f e1 bx lr
+// CHECK-ARM-ABS-ARM: __ARMToThumbv7ABSLongThunk_thumb_callee1:
// 0x1001 = thumb_callee1
-// CHECK-ABS-ARM-NEXT: 1328: 01 c0 01 e3 movw r12, #4097
-// CHECK-ABS-ARM-NEXT: 132c: 00 c0 40 e3 movt r12, #0
-// CHECK-ABS-ARM-NEXT: 1330: 1c ff 2f e1 bx r12
+// CHECK-ARM-ABS-ARM-NEXT: 1328: 01 c0 01 e3 movw r12, #4097
+// CHECK-ARM-ABS-ARM-NEXT: 132c: 00 c0 40 e3 movt r12, #0
+// CHECK-ARM-ABS-ARM-NEXT: 1330: 1c ff 2f e1 bx r12
// 0x1501 = thumb_callee2
-// CHECK-ABS-ARM-NEXT: 1334: 01 c5 01 e3 movw r12, #5377
-// CHECK-ABS-ARM-NEXT: 1338: 00 c0 40 e3 movt r12, #0
-// CHECK-ABS-ARM-NEXT: 133c: 1c ff 2f e1 bx r12
+// CHECK-ARM-ABS-ARM: __ARMToThumbv7ABSLongThunk_thumb_callee2:
+// CHECK-ARM-ABS-ARM-NEXT: 1334: 01 c5 01 e3 movw r12, #5377
+// CHECK-ARM-ABS-ARM-NEXT: 1338: 00 c0 40 e3 movt r12, #0
+// CHECK-ARM-ABS-ARM-NEXT: 133c: 1c ff 2f e1 bx r12
// 0x1503 = thumb_callee3
-// CHECK-ABS-ARM-NEXT: 1340: 03 c5 01 e3 movw r12, #5379
-// CHECK-ABS-ARM-NEXT: 1344: 00 c0 40 e3 movt r12, #0
-// CHECK-ABS-ARM-NEXT: 1348: 1c ff 2f e1 bx r12
+// CHECK-ARM-ABS-ARM: __ARMToThumbv7ABSLongThunk_thumb_callee3:
+// CHECK-ARM-ABS-ARM-NEXT: 1340: 03 c5 01 e3 movw r12, #5379
+// CHECK-ARM-ABS-ARM-NEXT: 1344: 00 c0 40 e3 movt r12, #0
+// CHECK-ARM-ABS-ARM-NEXT: 1348: 1c ff 2f e1 bx r12
// CHECK-PI-ARM: Disassembly of section .arm_caller:
// CHECK-PI-ARM-NEXT: arm_caller:
-// CHECK-PI-ARM-NEXT: 1300: 3e ff ff fa blx #-776 <thumb_callee1>
-// CHECK-PI-ARM-NEXT: 1304: 3d ff ff fa blx #-780 <thumb_callee1>
-// 0x1308 + 8 + 0x18 = 0x1328
-// CHECK-PI-ARM-NEXT: 1308: 06 00 00 ea b #24 <arm_caller+0x28>
-// 0x130c + 8 + 0x14 = 0x1328
-// CHECK-PI-ARM-NEXT: 130c: 05 00 00 ea b #20 <arm_caller+0x28>
-// 0x1310 + 8 + 0x20 = 0x1338
-// CHECK-PI-ARM-NEXT: 1310: 08 00 00 ea b #32 <arm_caller+0x38>
-// 0x1314 + 8 + 0x2c = 0x1348
-// CHECK-PI-ARM-NEXT: 1314: 0b 00 00 ea b #44 <arm_caller+0x48>
-// CHECK-PI-ARM-NEXT: 1318: 78 ff ff ea b #-544 <arm_callee1>
-// CHECK-PI-ARM-NEXT: 131c: b7 00 00 0a beq #732 <arm_callee2>
-// CHECK-PI-ARM-NEXT: 1320: b7 00 00 1a bne #732 <arm_callee3>
-// CHECK-PI-ARM-NEXT: 1324: 1e ff 2f e1 bx lr
+// CHECK-PI-ARM-NEXT: 1300: 3e ff ff fa blx #-776 <thumb_callee1>
+// CHECK-PI-ARM-NEXT: 1304: 3d ff ff fa blx #-780 <thumb_callee1>
+// CHECK-PI-ARM-NEXT: 1308: 06 00 00 ea b #24 <__ARMToThumbV7PILongThunk_thumb_callee1>
+// CHECK-PI-ARM-NEXT: 130c: 05 00 00 ea b #20 <__ARMToThumbV7PILongThunk_thumb_callee1>
+// CHECK-PI-ARM-NEXT: 1310: 08 00 00 ea b #32 <__ARMToThumbV7PILongThunk_thumb_callee2>
+// CHECK-PI-ARM-NEXT: 1314: 0b 00 00 ea b #44 <__ARMToThumbV7PILongThunk_thumb_callee3>
+// CHECK-PI-ARM-NEXT: 1318: 78 ff ff ea b #-544 <arm_callee1>
+// CHECK-PI-ARM-NEXT: 131c: b7 00 00 0a beq #732 <arm_callee2>
+// CHECK-PI-ARM-NEXT: 1320: b7 00 00 1a bne #732 <arm_callee3>
+// CHECK-PI-ARM-NEXT: 1324: 1e ff 2f e1 bx lr
+// CHECK-PI-ARM: __ARMToThumbV7PILongThunk_thumb_callee1:
// 0x1330 + 8 - 0x337 = 0x1001 = thumb_callee1
-// CHECK-PI-ARM-NEXT: 1328: c9 cc 0f e3 movw r12, #64713
-// CHECK-PI-ARM-NEXT: 132c: ff cf 4f e3 movt r12, #65535
-// CHECK-PI-ARM-NEXT: 1330: 0f c0 8c e0 add r12, r12, pc
-// CHECK-PI-ARM-NEXT: 1334: 1c ff 2f e1 bx r12
+// CHECK-PI-ARM-NEXT: 1328: c9 cc 0f e3 movw r12, #64713
+// CHECK-PI-ARM-NEXT: 132c: ff cf 4f e3 movt r12, #65535
+// CHECK-PI-ARM-NEXT: 1330: 0f c0 8c e0 add r12, r12, pc
+// CHECK-PI-ARM-NEXT: 1334: 1c ff 2f e1 bx r12
+// CHECK-PI-ARM: __ARMToThumbV7PILongThunk_thumb_callee2:
+
+// CHECK-PI-ARM-NEXT: 1338: b9 c1 00 e3 movw r12, #441
+// CHECK-PI-ARM-NEXT: 133c: 00 c0 40 e3 movt r12, #0
+// CHECK-PI-ARM-NEXT: 1340: 0f c0 8c e0 add r12, r12, pc
+// CHECK-PI-ARM-NEXT: 1344: 1c ff 2f e1 bx r12
+// CHECK-PI-ARM: __ARMToThumbV7PILongThunk_thumb_callee3:
// 0x1340 + 8 + 0x1b9 = 0x1501
-// CHECK-PI-ARM-NEXT: 1338: b9 c1 00 e3 movw r12, #441
-// CHECK-PI-ARM-NEXT: 133c: 00 c0 40 e3 movt r12, #0
-// CHECK-PI-ARM-NEXT: 1340: 0f c0 8c e0 add r12, r12, pc
-// CHECK-PI-ARM-NEXT: 1344: 1c ff 2f e1 bx r12
+// CHECK-PI-ARM-NEXT: 1348: ab c1 00 e3 movw r12, #427
+// CHECK-PI-ARM-NEXT: 134c: 00 c0 40 e3 movt r12, #0
+// CHECK-PI-ARM-NEXT: 1350: 0f c0 8c e0 add r12, r12, pc
+// CHECK-PI-ARM-NEXT: 1354: 1c ff 2f e1 bx r12
// 1350 + 8 + 0x1ab = 0x1503
-// CHECK-PI-ARM-NEXT: 1348: ab c1 00 e3 movw r12, #427
-// CHECK-PI-ARM-NEXT: 134c: 00 c0 40 e3 movt r12, #0
-// CHECK-PI-ARM-NEXT: 1350: 0f c0 8c e0 add r12, r12, pc
-// CHECK-PI-ARM-NEXT: 1354: 1c ff 2f e1 bx r12
// All PLT entries are ARM, no need for interworking thunks
// CHECK-PI-ARM-PLT: Disassembly of section .arm_caller:
@@ -182,60 +185,58 @@ thumb_caller:
bne.w arm_callee3
// CHECK-ABS-THUMB: Disassembly of section .thumb_caller:
// CHECK-ABS-THUMB-NEXT: thumb_caller:
-// 0x1400 + 4 - 0x304 = 0x1100 = arm_callee1
-// CHECK-ABS-THUMB-NEXT: 1400: ff f7 7e ee blx #-772
-// 0x1404 + 4 - 0x308 = 0x1100 = arm_callee1
-// CHECK-ABS-THUMB-NEXT: 1404: ff f7 7c ee blx #-776
-// 0x1408 + 4 + 0x14 = 0x520
-// CHECK-ABS-THUMB-NEXT: 1408: 00 f0 0a b8 b.w #20
-// 0x140c + 4 + 0x1a = 0x52a
-// CHECK-ABS-THUMB-NEXT: 140c: 00 f0 0d b8 b.w #26
-// 0x1410 + 4 + 0x20 = 0x534
-// CHECK-ABS-THUMB-NEXT: 1410: 00 f0 10 b8 b.w #32
-// 0x1414 + 4 + 8 = 0x520
-// CHECK-ABS-THUMB-NEXT: 1414: 00 f0 04 80 beq.w #8
-// 0x1418 + 4 + 0xe = 0x52a
-// CHECK-ABS-THUMB-NEXT: 1418: 00 f0 07 80 beq.w #14
-// 0x141c + 4 + 0x14 = 0x534
-// CHECK-ABS-THUMB-NEXT: 141c: 40 f0 0a 80 bne.w #20
+// CHECK-ABS-THUMB-NEXT: 1400: ff f7 7e ee blx #-772
+// CHECK-ABS-THUMB-NEXT: 1404: ff f7 7c ee blx #-776
+// CHECK-ABS-THUMB-NEXT: 1408: 00 f0 0a b8 b.w #20 <__ThumbToARMv7ABSLongThunk_arm_callee1+0x4>
+// CHECK-ABS-THUMB-NEXT: 140c: 00 f0 0d b8 b.w #26 <__ThumbToARMv7ABSLongThunk_arm_callee2+0x4>
+// CHECK-ABS-THUMB-NEXT: 1410: 00 f0 10 b8 b.w #32 <__ThumbToARMv7ABSLongThunk_arm_callee3+0x4>
+// CHECK-ABS-THUMB-NEXT: 1414: 00 f0 04 80 beq.w #8 <__ThumbToARMv7ABSLongThunk_arm_callee1+0x4>
+// CHECK-ABS-THUMB-NEXT: 1418: 00 f0 07 80 beq.w #14 <__ThumbToARMv7ABSLongThunk_arm_callee2+0x4>
+// CHECK-ABS-THUMB-NEXT: 141c: 40 f0 0a 80 bne.w #20 <__ThumbToARMv7ABSLongThunk_arm_callee3+0x4>
+// CHECK-ABS-THUMB: __ThumbToARMv7ABSLongThunk_arm_callee1:
// 0x1100 = arm_callee1
-// CHECK-ABS-THUMB-NEXT: 1420: 41 f2 00 1c movw r12, #4352
-// CHECK-ABS-THUMB-NEXT: 1424: c0 f2 00 0c movt r12, #0
-// CHECK-ABS-THUMB-NEXT: 1428: 60 47 bx r12
+// CHECK-ABS-THUMB-NEXT: 1420: 41 f2 00 1c movw r12, #4352
+// CHECK-ABS-THUMB-NEXT: 1424: c0 f2 00 0c movt r12, #0
+// CHECK-ABS-THUMB-NEXT: 1428: 60 47 bx r12
+// CHECK-ABS-THUMB: __ThumbToARMv7ABSLongThunk_arm_callee2:
// 0x1600 = arm_callee2
-// CHECK-ABS-THUMB-NEXT: 142a: 41 f2 00 6c movw r12, #5632
-// CHECK-ABS-THUMB-NEXT: 142e: c0 f2 00 0c movt r12, #0
-// CHECK-ABS-THUMB-NEXT: 1432: 60 47 bx r12
+// CHECK-ABS-THUMB-NEXT: 142a: 41 f2 00 6c movw r12, #5632
+// CHECK-ABS-THUMB-NEXT: 142e: c0 f2 00 0c movt r12, #0
+// CHECK-ABS-THUMB-NEXT: 1432: 60 47 bx r12
// 0x1604 = arm_callee3
-// CHECK-ABS-THUMB-NEXT: 1434: 41 f2 04 6c movw r12, #5636
-// CHECK-ABS-THUMB-NEXT: 1438: c0 f2 00 0c movt r12, #0
-// CHECK-ABS-THUMB-NEXT: 143c: 60 47 bx r12
+// CHECK-ABS-THUMB: __ThumbToARMv7ABSLongThunk_arm_callee3:
+// CHECK-ABS-THUMB-NEXT: 1434: 41 f2 04 6c movw r12, #5636
+// CHECK-ABS-THUMB-NEXT: 1438: c0 f2 00 0c movt r12, #0
+// CHECK-ABS-THUMB-NEXT: 143c: 60 47 bx r12
// CHECK-PI-THUMB: Disassembly of section .thumb_caller:
// CHECK-PI-THUMB-NEXT: thumb_caller:
-// CHECK-PI-THUMB-NEXT: 1400: ff f7 7e ee blx #-772
-// CHECK-PI-THUMB-NEXT: 1404: ff f7 7c ee blx #-776
-// CHECK-PI-THUMB-NEXT: 1408: 00 f0 0a b8 b.w #20
-// CHECK-PI-THUMB-NEXT: 140c: 00 f0 0e b8 b.w #28
-// CHECK-PI-THUMB-NEXT: 1410: 00 f0 12 b8 b.w #36
-// CHECK-PI-THUMB-NEXT: 1414: 00 f0 04 80 beq.w #8
-// CHECK-PI-THUMB-NEXT: 1418: 00 f0 08 80 beq.w #16
-// CHECK-PI-THUMB-NEXT: 141c: 40 f0 0c 80 bne.w #24
+// CHECK-PI-THUMB-NEXT: 1400: ff f7 7e ee blx #-772
+// CHECK-PI-THUMB-NEXT: 1404: ff f7 7c ee blx #-776
+// CHECK-PI-THUMB-NEXT: 1408: 00 f0 0a b8 b.w #20 <__ThumbToARMV7PILongThunk_arm_callee1+0x4>
+// CHECK-PI-THUMB-NEXT: 140c: 00 f0 0e b8 b.w #28 <__ThumbToARMV7PILongThunk_arm_callee2+0x4>
+// CHECK-PI-THUMB-NEXT: 1410: 00 f0 12 b8 b.w #36 <__ThumbToARMV7PILongThunk_arm_callee3+0x4>
+// CHECK-PI-THUMB-NEXT: 1414: 00 f0 04 80 beq.w #8 <__ThumbToARMV7PILongThunk_arm_callee1+0x4>
+// CHECK-PI-THUMB-NEXT: 1418: 00 f0 08 80 beq.w #16 <__ThumbToARMV7PILongThunk_arm_callee2+0x4>
+// CHECK-PI-THUMB-NEXT: 141c: 40 f0 0c 80 bne.w #24 <__ThumbToARMV7PILongThunk_arm_callee3+0x4>
+// CHECK-PI-THUMB: __ThumbToARMV7PILongThunk_arm_callee1:
// 0x1428 + 4 - 0x32c = 0x1100 = arm_callee1
-// CHECK-PI-THUMB-NEXT: 1420: 4f f6 d4 4c movw r12, #64724
-// CHECK-PI-THUMB-NEXT: 1424: cf f6 ff 7c movt r12, #65535
-// CHECK-PI-THUMB-NEXT: 1428: fc 44 add r12, pc
-// CHECK-PI-THUMB-NEXT: 142a: 60 47 bx r12
+// CHECK-PI-THUMB-NEXT: 1420: 4f f6 d4 4c movw r12, #64724
+// CHECK-PI-THUMB-NEXT: 1424: cf f6 ff 7c movt r12, #65535
+// CHECK-PI-THUMB-NEXT: 1428: fc 44 add r12, pc
+// CHECK-PI-THUMB-NEXT: 142a: 60 47 bx r12
+// CHECK-PI-THUMB: __ThumbToARMV7PILongThunk_arm_callee2:
// 0x1434 + 4 + 0x1c8 = 0x1600 = arm_callee2
-// CHECK-PI-THUMB-NEXT: 142c: 40 f2 c8 1c movw r12, #456
-// CHECK-PI-THUMB-NEXT: 1430: c0 f2 00 0c movt r12, #0
-// CHECK-PI-THUMB-NEXT: 1434: fc 44 add r12, pc
-// CHECK-PI-THUMB-NEXT: 1436: 60 47 bx r12
+// CHECK-PI-THUMB-NEXT: 142c: 40 f2 c8 1c movw r12, #456
+// CHECK-PI-THUMB-NEXT: 1430: c0 f2 00 0c movt r12, #0
+// CHECK-PI-THUMB-NEXT: 1434: fc 44 add r12, pc
+// CHECK-PI-THUMB-NEXT: 1436: 60 47 bx r12
+// CHECK-PI-THUMB: __ThumbToARMV7PILongThunk_arm_callee3:
// 0x1440 + 4 + 0x1c0 = 0x1604 = arm_callee3
-// CHECK-PI-THUMB-NEXT: 1438: 40 f2 c0 1c movw r12, #448
-// CHECK-PI-THUMB-NEXT: 143c: c0 f2 00 0c movt r12, #0
-// CHECK-PI-THUMB-NEXT: 1440: fc 44 add r12, pc
-// CHECK-PI-THUMB-NEXT: 1442: 60 47 bx r12
+// CHECK-PI-THUMB-NEXT: 1438: 40 f2 c0 1c movw r12, #448
+// CHECK-PI-THUMB-NEXT: 143c: c0 f2 00 0c movt r12, #0
+// CHECK-PI-THUMB-NEXT: 1440: fc 44 add r12, pc
+// CHECK-PI-THUMB-NEXT: 1442: 60 47 bx r12
// CHECK-PI-THUMB-PLT: Disassembly of section .arm_caller:
// CHECK-PI-THUMB-PLT-NEXT: thumb_caller:
Modified: lld/trunk/test/ELF/mips-npic-call-pic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-npic-call-pic.s?rev=293283&r1=293282&r2=293283&view=diff
==============================================================================
--- lld/trunk/test/ELF/mips-npic-call-pic.s (original)
+++ lld/trunk/test/ELF/mips-npic-call-pic.s Fri Jan 27 07:10:16 2017
@@ -15,60 +15,65 @@
# CHECK: Disassembly of section .text:
# CHECK-NEXT: __start:
-# CHECK-NEXT: 20000: 0c 00 80 0e jal 131128 <foo1b+0x4>
-# ^-- .pic.foo1a
+# CHECK-NEXT: 20000: 0c 00 80 0c jal 131120 <__LA25Thunk_foo1a>
# CHECK-NEXT: 20004: 00 00 00 00 nop
-# CHECK-NEXT: 20008: 0c 00 80 19 jal 131172 <foo2+0x4>
-# ^-- .pic.foo2
+# CHECK-NEXT: 20008: 0c 00 80 16 jal 131160 <__LA25Thunk_foo2>
# CHECK-NEXT: 2000c: 00 00 00 00 nop
-# CHECK-NEXT: 20010: 0c 00 80 12 jal 131144 <foo1b+0x14>
-# ^-- .pic.foo1b
+# CHECK-NEXT: 20010: 0c 00 80 10 jal 131136 <__LA25Thunk_foo1b>
# CHECK-NEXT: 20014: 00 00 00 00 nop
-# CHECK-NEXT: 20018: 0c 00 80 19 jal 131172 <foo2+0x4>
-# ^-- .pic.foo2
+# CHECK-NEXT: 20018: 0c 00 80 16 jal 131160 <__LA25Thunk_foo2>
# CHECK-NEXT: 2001c: 00 00 00 00 nop
-# CHECK-NEXT: 20020: 0c 00 80 25 jal 131220 <fnpic+0x4>
-# ^-- .pic.fpic
+# CHECK-NEXT: 20020: 0c 00 80 1d jal 131188 <__LA25Thunk_fpic>
# CHECK-NEXT: 20024: 00 00 00 00 nop
-# CHECK-NEXT: 20028: 0c 00 80 24 jal 131216 <fnpic>
+# CHECK-NEXT: 20028: 0c 00 80 28 jal 131232 <fnpic>
# CHECK-NEXT: 2002c: 00 00 00 00 nop
#
-# CHECK: foo1a:
-# CHECK-NEXT: 20030: 00 00 00 00 nop
-#
-# CHECK: foo1b:
-# CHECK-NEXT: 20034: 00 00 00 00 nop
-#
-# CHECK-NEXT: 20038: 3c 19 00 02 lui $25, 2
-# CHECK-NEXT: 2003c: 08 00 80 0c j 131120 <foo1a>
-# CHECK-NEXT: 20040: 27 39 00 30 addiu $25, $25, 48
-# CHECK-NEXT: 20044: 00 00 00 00 nop
-# CHECK-NEXT: 20048: 3c 19 00 02 lui $25, 2
-# CHECK-NEXT: 2004c: 08 00 80 0d j 131124 <foo1b>
-# CHECK-NEXT: 20050: 27 39 00 34 addiu $25, $25, 52
+# CHECK: __LA25Thunk_foo1a:
+# CHECK-NEXT: 20030: 3c 19 00 02 lui $25, 2
+# CHECK-NEXT: 20034: 08 00 80 14 j 131152 <foo1a>
+# CHECK-NEXT: 20038: 27 39 00 50 addiu $25, $25, 80
+# CHECK-NEXT: 2003c: 00 00 00 00 nop
+
+# CHECK: __LA25Thunk_foo1b:
+# CHECK-NEXT: 20040: 3c 19 00 02 lui $25, 2
+# CHECK-NEXT: 20044: 08 00 80 15 j 131156 <foo1b>
+# CHECK-NEXT: 20048: 27 39 00 54 addiu $25, $25, 84
+# CHECK-NEXT: 2004c: 00 00 00 00 nop
+
+# CHECK: foo1a:
+# CHECK-NEXT: 20050: 00 00 00 00 nop
+
+# CHECK: foo1b:
# CHECK-NEXT: 20054: 00 00 00 00 nop
-# CHECK-NEXT: 20058: 00 00 00 00 nop
-# CHECK-NEXT: 2005c: 00 00 00 00 nop
-#
-# CHECK: foo2:
-# CHECK-NEXT: 20060: 00 00 00 00 nop
-#
-# CHECK-NEXT: 20064: 3c 19 00 02 lui $25, 2
-# CHECK-NEXT: 20068: 08 00 80 18 j 131168 <foo2>
-# CHECK-NEXT: 2006c: 27 39 00 60 addiu $25, $25, 96
+
+# CHECK: __LA25Thunk_foo2:
+# CHECK-NEXT: 20058: 3c 19 00 02 lui $25, 2
+# CHECK-NEXT: 2005c: 08 00 80 1c j 131184 <foo2>
+# CHECK-NEXT: 20060: 27 39 00 70 addiu $25, $25, 112
+# CHECK-NEXT: 20064: 00 00 00 00 nop
+# CHECK-NEXT: 20068: 00 00 00 00 nop
+# CHECK-NEXT: 2006c: 00 00 00 00 nop
+
+# CHECK: foo2:
# CHECK-NEXT: 20070: 00 00 00 00 nop
-# CHECK-NEXT: 20074: 00 00 00 00 nop
-# CHECK-NEXT: 20078: 00 00 00 00 nop
-# CHECK-NEXT: 2007c: 00 00 00 00 nop
-#
-# CHECK: fpic:
-# CHECK-NEXT: 20080: 00 00 00 00 nop
-#
-# CHECK: fnpic:
+
+# CHECK: __LA25Thunk_fpic:
+# CHECK-NEXT: 20074: 3c 19 00 02 lui $25, 2
+# CHECK-NEXT: 20078: 08 00 80 24 j 131216 <fpic>
+# CHECK-NEXT: 2007c: 27 39 00 90 addiu $25, $25, 144
+# CHECK-NEXT: 20080: 00 00 00 00 nop
+# CHECK-NEXT: 20084: 00 00 00 00 nop
+# CHECK-NEXT: 20088: 00 00 00 00 nop
+# CHECK-NEXT: 2008c: 00 00 00 00 nop
+
+# CHECK: fpic:
# CHECK-NEXT: 20090: 00 00 00 00 nop
-# CHECK-NEXT: 20094: 3c 19 00 02 lui $25, 2
-# CHECK-NEXT: 20098: 08 00 80 20 j 131200 <fpic>
-# CHECK-NEXT: 2009c: 27 39 00 80 addiu $25, $25, 128
+# CHECK-NEXT: 20094: 00 00 00 00 nop
+# CHECK-NEXT: 20098: 00 00 00 00 nop
+# CHECK-NEXT: 2009c: 00 00 00 00 nop
+
+# CHECK: fnpic:
+# CHECK-NEXT: 200a0: 00 00 00 00 nop
# Make sure the thunks are created properly no matter how
# objects are laid out.
@@ -76,54 +81,58 @@
# RUN: ld.lld %t-pic.o %t-npic.o %t-sto-pic.o -o %t.exe
# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=REVERSE %s
-# REVERSE: foo1a:
-# REVERSE-NEXT: 20000: 00 00 00 00 nop
-#
-# REVERSE: foo1b:
-# REVERSE-NEXT: 20004: 00 00 00 00 nop
-# REVERSE-NEXT: 20008: 3c 19 00 02 lui $25, 2
-# REVERSE-NEXT: 2000c: 08 00 80 00 j 131072 <foo1a>
-# REVERSE-NEXT: 20010: 27 39 00 00 addiu $25, $25, 0
-# REVERSE-NEXT: 20014: 00 00 00 00 nop
-# REVERSE-NEXT: 20018: 3c 19 00 02 lui $25, 2
-# REVERSE-NEXT: 2001c: 08 00 80 01 j 131076 <foo1b>
-# REVERSE-NEXT: 20020: 27 39 00 04 addiu $25, $25, 4
+# REVERSE: Disassembly of section .text:
+# REVERSE-NEXT: __LA25Thunk_foo1a:
+# REVERSE-NEXT: 20000: 3c 19 00 02 lui $25, 2
+# REVERSE-NEXT: 20004: 08 00 80 08 j 131104 <foo1a>
+# REVERSE-NEXT: 20008: 27 39 00 20 addiu $25, $25, 32
+# REVERSE-NEXT: 2000c: 00 00 00 00 nop
+# REVERSE: __LA25Thunk_foo1b:
+# REVERSE-NEXT: 20010: 3c 19 00 02 lui $25, 2
+# REVERSE-NEXT: 20014: 08 00 80 09 j 131108 <foo1b>
+# REVERSE-NEXT: 20018: 27 39 00 24 addiu $25, $25, 36
+# REVERSE-NEXT: 2001c: 00 00 00 00 nop
+# REVERSE: foo1a:
+# REVERSE-NEXT: 20020: 00 00 00 00 nop
+# REVERSE: foo1b:
# REVERSE-NEXT: 20024: 00 00 00 00 nop
-# REVERSE-NEXT: 20028: 00 00 00 00 nop
-# REVERSE-NEXT: 2002c: 00 00 00 00 nop
-#
-# REVERSE: foo2:
-# REVERSE-NEXT: 20030: 00 00 00 00 nop
-# REVERSE-NEXT: 20034: 3c 19 00 02 lui $25, 2
-# REVERSE-NEXT: 20038: 08 00 80 0c j 131120 <foo2>
-# REVERSE-NEXT: 2003c: 27 39 00 30 addiu $25, $25, 48
+# REVERSE: __LA25Thunk_foo2:
+# REVERSE-NEXT: 20028: 3c 19 00 02 lui $25, 2
+# REVERSE-NEXT: 2002c: 08 00 80 10 j 131136 <foo2>
+# REVERSE-NEXT: 20030: 27 39 00 40 addiu $25, $25, 64
+# REVERSE-NEXT: 20034: 00 00 00 00 nop
+# REVERSE-NEXT: 20038: 00 00 00 00 nop
+# REVERSE-NEXT: 2003c: 00 00 00 00 nop
+# REVERSE: foo2:
# REVERSE-NEXT: 20040: 00 00 00 00 nop
# REVERSE-NEXT: 20044: 00 00 00 00 nop
# REVERSE-NEXT: 20048: 00 00 00 00 nop
# REVERSE-NEXT: 2004c: 00 00 00 00 nop
-#
-# REVERSE: __start:
-# REVERSE-NEXT: 20050: 0c 00 80 02 jal 131080 <foo1b+0x4>
+# REVERSE: __start:
+# REVERSE-NEXT: 20050: 0c 00 80 00 jal 131072 <__LA25Thunk_foo1a>
# REVERSE-NEXT: 20054: 00 00 00 00 nop
-# REVERSE-NEXT: 20058: 0c 00 80 0d jal 131124 <foo2+0x4>
+# REVERSE-NEXT: 20058: 0c 00 80 0a jal 131112 <__LA25Thunk_foo2>
# REVERSE-NEXT: 2005c: 00 00 00 00 nop
-# REVERSE-NEXT: 20060: 0c 00 80 06 jal 131096 <foo1b+0x14>
+# REVERSE-NEXT: 20060: 0c 00 80 04 jal 131088 <__LA25Thunk_foo1b>
# REVERSE-NEXT: 20064: 00 00 00 00 nop
-# REVERSE-NEXT: 20068: 0c 00 80 0d jal 131124 <foo2+0x4>
+# REVERSE-NEXT: 20068: 0c 00 80 0a jal 131112 <__LA25Thunk_foo2>
# REVERSE-NEXT: 2006c: 00 00 00 00 nop
-# REVERSE-NEXT: 20070: 0c 00 80 25 jal 131220 <fnpic+0x4>
+# REVERSE-NEXT: 20070: 0c 00 80 20 jal 131200 <__LA25Thunk_fpic>
# REVERSE-NEXT: 20074: 00 00 00 00 nop
-# REVERSE-NEXT: 20078: 0c 00 80 24 jal 131216 <fnpic>
+# REVERSE-NEXT: 20078: 0c 00 80 28 jal 131232 <fnpic>
# REVERSE-NEXT: 2007c: 00 00 00 00 nop
-#
-# REVERSE: fpic:
-# REVERSE-NEXT: 20080: 00 00 00 00 nop
-#
-# REVERSE: fnpic:
+# REVERSE: __LA25Thunk_fpic:
+# REVERSE-NEXT: 20080: 3c 19 00 02 lui $25, 2
+# REVERSE-NEXT: 20084: 08 00 80 24 j 131216 <fpic>
+# REVERSE-NEXT: 20088: 27 39 00 90 addiu $25, $25, 144
+# REVERSE-NEXT: 2008c: 00 00 00 00 nop
+# REVERSE: fpic:
# REVERSE-NEXT: 20090: 00 00 00 00 nop
-# REVERSE-NEXT: 20094: 3c 19 00 02 lui $25, 2
-# REVERSE-NEXT: 20098: 08 00 80 20 j 131200 <fpic>
-# REVERSE-NEXT: 2009c: 27 39 00 80 addiu $25, $25, 128
+# REVERSE-NEXT: 20094: 00 00 00 00 nop
+# REVERSE-NEXT: 20098: 00 00 00 00 nop
+# REVERSE-NEXT: 2009c: 00 00 00 00 nop
+# REVERSE: fnpic:
+# REVERSE-NEXT: 200a0: 00 00 00 00 nop
.text
.globl __start
More information about the llvm-commits
mailing list