forked from OSchip/llvm-project
PowerPC: Initial support for PowerPC64 MCJIT
This patch adds initial support for MCJIT for PPC64-elf-abi. The TOC relocation and ODP handling is implemented. It fixes the following ExecutionEngine testcases: ExecutionEngine/2003-01-04-ArgumentBug.ll ExecutionEngine/2003-01-04-LoopTest.ll ExecutionEngine/2003-01-04-PhiTest.ll ExecutionEngine/2003-01-09-SARTest.ll ExecutionEngine/2003-01-10-FUCOM.ll ExecutionEngine/2003-01-15-AlignmentTest.ll ExecutionEngine/2003-05-11-PHIRegAllocBug.ll ExecutionEngine/2003-06-04-bzip2-bug.ll ExecutionEngine/2003-06-05-PHIBug.ll ExecutionEngine/2003-08-15-AllocaAssertion.ll ExecutionEngine/2003-08-21-EnvironmentTest.ll ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll ExecutionEngine/simplesttest.ll ExecutionEngine/simpletest.ll ExecutionEngine/stubs.ll ExecutionEngine/test-arith.ll ExecutionEngine/test-branch.ll ExecutionEngine/test-call-no-external-funcs.ll ExecutionEngine/test-cast.ll ExecutionEngine/test-common-symbols.ll ExecutionEngine/test-constantexpr.ll ExecutionEngine/test-fp-no-external-funcs.ll ExecutionEngine/test-fp.ll ExecutionEngine/test-global-init-nonzero.ll ExecutionEngine/test-global.ll ExecutionEngine/test-loadstore.ll ExecutionEngine/test-local.ll ExecutionEngine/test-logical.ll ExecutionEngine/test-loop.ll ExecutionEngine/test-phi.ll ExecutionEngine/test-ret.ll ExecutionEngine/test-return.ll ExecutionEngine/test-setcond-fp.ll ExecutionEngine/test-setcond-int.ll ExecutionEngine/test-shift.ll llvm-svn: 166678
This commit is contained in:
parent
f2aceda854
commit
5fc11b3554
|
@ -190,7 +190,7 @@ void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj,
|
|||
if (!Addr)
|
||||
report_fatal_error("Unable to allocate memory for common symbols!");
|
||||
uint64_t Offset = 0;
|
||||
Sections.push_back(SectionEntry(Addr, TotalSize, TotalSize, 0));
|
||||
Sections.push_back(SectionEntry(StringRef(), Addr, TotalSize, TotalSize, 0));
|
||||
memset(Addr, 0, TotalSize);
|
||||
|
||||
DEBUG(dbgs() << "emitCommonSection SectionID: " << SectionID
|
||||
|
@ -233,10 +233,12 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
|
|||
bool IsVirtual;
|
||||
bool IsZeroInit;
|
||||
uint64_t DataSize;
|
||||
StringRef Name;
|
||||
Check(Section.isRequiredForExecution(IsRequired));
|
||||
Check(Section.isVirtual(IsVirtual));
|
||||
Check(Section.isZeroInit(IsZeroInit));
|
||||
Check(Section.getSize(DataSize));
|
||||
Check(Section.getName(Name));
|
||||
|
||||
unsigned Allocate;
|
||||
unsigned SectionID = Sections.size();
|
||||
|
@ -264,6 +266,7 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
|
|||
memcpy(Addr, pData, DataSize);
|
||||
|
||||
DEBUG(dbgs() << "emitSection SectionID: " << SectionID
|
||||
<< " Name: " << Name
|
||||
<< " obj addr: " << format("%p", pData)
|
||||
<< " new addr: " << format("%p", Addr)
|
||||
<< " DataSize: " << DataSize
|
||||
|
@ -279,6 +282,7 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
|
|||
Allocate = 0;
|
||||
Addr = 0;
|
||||
DEBUG(dbgs() << "emitSection SectionID: " << SectionID
|
||||
<< " Name: " << Name
|
||||
<< " obj addr: " << format("%p", data.data())
|
||||
<< " new addr: 0"
|
||||
<< " DataSize: " << DataSize
|
||||
|
@ -287,7 +291,8 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
|
|||
<< "\n");
|
||||
}
|
||||
|
||||
Sections.push_back(SectionEntry(Addr, Allocate, DataSize,(uintptr_t)pData));
|
||||
Sections.push_back(SectionEntry(Name, Addr, Allocate, DataSize,
|
||||
(uintptr_t)pData));
|
||||
return SectionID;
|
||||
}
|
||||
|
||||
|
@ -352,6 +357,24 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) {
|
|||
*StubAddr = JrT9Instr;
|
||||
StubAddr++;
|
||||
*StubAddr = NopInstr;
|
||||
return Addr;
|
||||
} else if (Arch == Triple::ppc64) {
|
||||
// PowerPC64 stub: the address points to a function descriptor
|
||||
// instead of the function itself. Load the function address
|
||||
// on r11 and sets it to control register. Also loads the function
|
||||
// TOC in r2 and environment pointer to r11.
|
||||
writeInt32BE(Addr, 0x3D800000); // lis r12, highest(addr)
|
||||
writeInt32BE(Addr+4, 0x618C0000); // ori r12, higher(addr)
|
||||
writeInt32BE(Addr+8, 0x798C07C6); // sldi r12, r12, 32
|
||||
writeInt32BE(Addr+12, 0x658C0000); // oris r12, r12, h(addr)
|
||||
writeInt32BE(Addr+16, 0x618C0000); // ori r12, r12, l(addr)
|
||||
writeInt32BE(Addr+20, 0xF8410028); // std r2, 40(r1)
|
||||
writeInt32BE(Addr+24, 0xE96C0000); // ld r11, 0(r12)
|
||||
writeInt32BE(Addr+28, 0xE84C0008); // ld r2, 0(r12)
|
||||
writeInt32BE(Addr+32, 0x7D6903A6); // mtctr r11
|
||||
writeInt32BE(Addr+36, 0xE96C0010); // ld r11, 16(r2)
|
||||
writeInt32BE(Addr+40, 0x4E800420); // bctr
|
||||
|
||||
return Addr;
|
||||
}
|
||||
return Addr;
|
||||
|
|
|
@ -30,6 +30,14 @@ using namespace llvm::object;
|
|||
|
||||
namespace {
|
||||
|
||||
static inline
|
||||
error_code check(error_code Err) {
|
||||
if (Err) {
|
||||
report_fatal_error(Err.message());
|
||||
}
|
||||
return Err;
|
||||
}
|
||||
|
||||
template<support::endianness target_endianness, bool is64Bits>
|
||||
class DyldELFObject : public ELFObjectFile<target_endianness, is64Bits> {
|
||||
LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
|
||||
|
@ -340,6 +348,179 @@ void RuntimeDyldELF::resolveMIPSRelocation(uint8_t *LocalAddress,
|
|||
}
|
||||
}
|
||||
|
||||
// Return the .TOC. section address to R_PPC64_TOC relocations.
|
||||
uint64_t RuntimeDyldELF::findPPC64TOC() const {
|
||||
// The TOC consists of sections .got, .toc, .tocbss, .plt in that
|
||||
// order. The TOC starts where the first of these sections starts.
|
||||
SectionList::const_iterator it = Sections.begin();
|
||||
SectionList::const_iterator ite = Sections.end();
|
||||
for (; it != ite; ++it) {
|
||||
if (it->Name == ".got" ||
|
||||
it->Name == ".toc" ||
|
||||
it->Name == ".tocbss" ||
|
||||
it->Name == ".plt")
|
||||
break;
|
||||
}
|
||||
if (it == ite) {
|
||||
// This may happen for
|
||||
// * references to TOC base base (sym@toc, .odp relocation) without
|
||||
// a .toc directive.
|
||||
// In this case just use the first section (which is usually
|
||||
// the .odp) since the code won't reference the .toc base
|
||||
// directly.
|
||||
it = Sections.begin();
|
||||
}
|
||||
assert (it != ite);
|
||||
// Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000
|
||||
// thus permitting a full 64 Kbytes segment.
|
||||
return it->LoadAddress + 0x8000;
|
||||
}
|
||||
|
||||
// Returns the sections and offset associated with the ODP entry referenced
|
||||
// by Symbol.
|
||||
void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj,
|
||||
ObjSectionToIDMap &LocalSections,
|
||||
RelocationValueRef &Rel) {
|
||||
// Get the ELF symbol value (st_value) to compare with Relocation offset in
|
||||
// .opd entries
|
||||
|
||||
error_code err;
|
||||
for (section_iterator si = Obj.begin_sections(),
|
||||
se = Obj.end_sections(); si != se; si.increment(err)) {
|
||||
StringRef SectionName;
|
||||
check(si->getName(SectionName));
|
||||
if (SectionName != ".opd")
|
||||
continue;
|
||||
|
||||
for (relocation_iterator i = si->begin_relocations(),
|
||||
e = si->end_relocations(); i != e;) {
|
||||
check(err);
|
||||
|
||||
// The R_PPC64_ADDR64 relocation indicates the first field
|
||||
// of a .opd entry
|
||||
uint64_t TypeFunc;
|
||||
check(i->getType(TypeFunc));
|
||||
if (TypeFunc != ELF::R_PPC64_ADDR64) {
|
||||
i.increment(err);
|
||||
continue;
|
||||
}
|
||||
|
||||
SymbolRef TargetSymbol;
|
||||
uint64_t TargetSymbolOffset;
|
||||
int64_t TargetAdditionalInfo;
|
||||
check(i->getSymbol(TargetSymbol));
|
||||
check(i->getOffset(TargetSymbolOffset));
|
||||
check(i->getAdditionalInfo(TargetAdditionalInfo));
|
||||
|
||||
i = i.increment(err);
|
||||
if (i == e)
|
||||
break;
|
||||
check(err);
|
||||
|
||||
// Just check if following relocation is a R_PPC64_TOC
|
||||
uint64_t TypeTOC;
|
||||
check(i->getType(TypeTOC));
|
||||
if (TypeTOC != ELF::R_PPC64_TOC)
|
||||
continue;
|
||||
|
||||
// Finally compares the Symbol value and the target symbol offset
|
||||
// to check if this .opd entry refers to the symbol the relocation
|
||||
// points to.
|
||||
if (Rel.Addend != (intptr_t)TargetSymbolOffset)
|
||||
continue;
|
||||
|
||||
section_iterator tsi(Obj.end_sections());
|
||||
check(TargetSymbol.getSection(tsi));
|
||||
Rel.SectionID = findOrEmitSection(Obj, (*tsi), true, LocalSections);
|
||||
Rel.Addend = (intptr_t)TargetAdditionalInfo;
|
||||
return;
|
||||
}
|
||||
}
|
||||
llvm_unreachable("Attempting to get address of ODP entry!");
|
||||
}
|
||||
|
||||
// Relocation masks following the #lo(value), #hi(value), #higher(value),
|
||||
// and #highest(value) macros defined in section 4.5.1. Relocation Types
|
||||
// in PPC-elf64abi document.
|
||||
//
|
||||
static inline
|
||||
uint16_t applyPPClo (uint64_t value)
|
||||
{
|
||||
return value & 0xffff;
|
||||
}
|
||||
|
||||
static inline
|
||||
uint16_t applyPPChi (uint64_t value)
|
||||
{
|
||||
return (value >> 16) & 0xffff;
|
||||
}
|
||||
|
||||
static inline
|
||||
uint16_t applyPPChigher (uint64_t value)
|
||||
{
|
||||
return (value >> 32) & 0xffff;
|
||||
}
|
||||
|
||||
static inline
|
||||
uint16_t applyPPChighest (uint64_t value)
|
||||
{
|
||||
return (value >> 48) & 0xffff;
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::resolvePPC64Relocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
uint64_t Value,
|
||||
uint32_t Type,
|
||||
int64_t Addend) {
|
||||
switch (Type) {
|
||||
default:
|
||||
llvm_unreachable("Relocation type not implemented yet!");
|
||||
break;
|
||||
case ELF::R_PPC64_ADDR16_LO :
|
||||
writeInt16BE(LocalAddress, applyPPClo (Value + Addend));
|
||||
break;
|
||||
case ELF::R_PPC64_ADDR16_HI :
|
||||
writeInt16BE(LocalAddress, applyPPChi (Value + Addend));
|
||||
break;
|
||||
case ELF::R_PPC64_ADDR16_HIGHER :
|
||||
writeInt16BE(LocalAddress, applyPPChigher (Value + Addend));
|
||||
break;
|
||||
case ELF::R_PPC64_ADDR16_HIGHEST :
|
||||
writeInt16BE(LocalAddress, applyPPChighest (Value + Addend));
|
||||
break;
|
||||
case ELF::R_PPC64_ADDR14 : {
|
||||
assert(((Value + Addend) & 3) == 0);
|
||||
// Preserve the AA/LK bits in the branch instruction
|
||||
uint8_t aalk = *(LocalAddress+3);
|
||||
writeInt16BE(LocalAddress + 2, (aalk & 3) | ((Value + Addend) & 0xfffc));
|
||||
} break;
|
||||
case ELF::R_PPC64_REL24 : {
|
||||
int32_t delta = static_cast<int32_t>(Value - FinalAddress + Addend);
|
||||
if (SignExtend32<24>(delta) != delta)
|
||||
llvm_unreachable("Relocation R_PPC64_REL24 overflow");
|
||||
// Generates a 'bl <address>' instruction
|
||||
writeInt32BE(LocalAddress, 0x48000001 | (delta & 0x03FFFFFC));
|
||||
} break;
|
||||
case ELF::R_PPC64_ADDR64 :
|
||||
writeInt64BE(LocalAddress, Value + Addend);
|
||||
break;
|
||||
case ELF::R_PPC64_TOC :
|
||||
writeInt64BE(LocalAddress, findPPC64TOC());
|
||||
break;
|
||||
case ELF::R_PPC64_TOC16 : {
|
||||
uint64_t TOCStart = findPPC64TOC();
|
||||
Value = applyPPClo((Value + Addend) - TOCStart);
|
||||
writeInt16BE(LocalAddress, applyPPClo(Value));
|
||||
} break;
|
||||
case ELF::R_PPC64_TOC16_DS : {
|
||||
uint64_t TOCStart = findPPC64TOC();
|
||||
Value = ((Value + Addend) - TOCStart);
|
||||
writeInt16BE(LocalAddress, applyPPClo(Value));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RuntimeDyldELF::resolveRelocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
uint64_t Value,
|
||||
|
@ -366,6 +547,9 @@ void RuntimeDyldELF::resolveRelocation(uint8_t *LocalAddress,
|
|||
(uint32_t)(Value & 0xffffffffL), Type,
|
||||
(uint32_t)(Addend & 0xffffffffL));
|
||||
break;
|
||||
case Triple::ppc64:
|
||||
resolvePPC64Relocation(LocalAddress, FinalAddress, Value, Type, Addend);
|
||||
break;
|
||||
default: llvm_unreachable("Unsupported CPU type!");
|
||||
}
|
||||
}
|
||||
|
@ -390,6 +574,8 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
|
|||
RelocationValueRef Value;
|
||||
// First search for the symbol in the local symbol table
|
||||
SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data());
|
||||
SymbolRef::Type SymType;
|
||||
Symbol.getType(SymType);
|
||||
if (lsi != Symbols.end()) {
|
||||
Value.SectionID = lsi->second.first;
|
||||
Value.Addend = lsi->second.second;
|
||||
|
@ -401,8 +587,6 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
|
|||
Value.SectionID = gsi->second.first;
|
||||
Value.Addend = gsi->second.second;
|
||||
} else {
|
||||
SymbolRef::Type SymType;
|
||||
Symbol.getType(SymType);
|
||||
switch (SymType) {
|
||||
case SymbolRef::ST_Debug: {
|
||||
// TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously
|
||||
|
@ -516,6 +700,93 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
|
|||
Section.StubOffset, RelType, 0);
|
||||
Section.StubOffset += getMaxStubSize();
|
||||
}
|
||||
} else if (Arch == Triple::ppc64) {
|
||||
if (RelType == ELF::R_PPC64_REL24) {
|
||||
// A PPC branch relocation will need a stub function if the target is
|
||||
// an external symbol (Symbol::ST_Unknown) or if the target address
|
||||
// is not within the signed 24-bits branch address.
|
||||
SectionEntry &Section = Sections[Rel.SectionID];
|
||||
uint8_t *Target = Section.Address + Rel.Offset;
|
||||
bool RangeOverflow = false;
|
||||
if (SymType != SymbolRef::ST_Unknown) {
|
||||
// A function call may points to the .opd entry, so the final symbol value
|
||||
// in calculated based in the relocation values in .opd section.
|
||||
findOPDEntrySection(Obj, ObjSectionToID, Value);
|
||||
uint8_t *RelocTarget = Sections[Value.SectionID].Address + Value.Addend;
|
||||
int32_t delta = static_cast<int32_t>(Target - RelocTarget);
|
||||
// If it is within 24-bits branch range, just set the branch target
|
||||
if (SignExtend32<24>(delta) == delta) {
|
||||
RelocationEntry RE(Rel.SectionID, Rel.Offset, RelType, Value.Addend);
|
||||
if (Value.SymbolName)
|
||||
addRelocationForSymbol(RE, Value.SymbolName);
|
||||
else
|
||||
addRelocationForSection(RE, Value.SectionID);
|
||||
} else {
|
||||
RangeOverflow = true;
|
||||
}
|
||||
}
|
||||
if (SymType == SymbolRef::ST_Unknown || RangeOverflow == true) {
|
||||
// It is an external symbol (SymbolRef::ST_Unknown) or within a range
|
||||
// larger than 24-bits.
|
||||
StubMap::const_iterator i = Stubs.find(Value);
|
||||
if (i != Stubs.end()) {
|
||||
// Symbol function stub already created, just relocate to it
|
||||
resolveRelocation(Target, (uint64_t)Target, (uint64_t)Section.Address
|
||||
+ i->second, RelType, 0);
|
||||
DEBUG(dbgs() << " Stub function found\n");
|
||||
} else {
|
||||
// Create a new stub function.
|
||||
DEBUG(dbgs() << " Create a new stub function\n");
|
||||
Stubs[Value] = Section.StubOffset;
|
||||
uint8_t *StubTargetAddr = createStubFunction(Section.Address +
|
||||
Section.StubOffset);
|
||||
RelocationEntry RE(Rel.SectionID, StubTargetAddr - Section.Address,
|
||||
ELF::R_PPC64_ADDR64, Value.Addend);
|
||||
|
||||
// Generates the 64-bits address loads as exemplified in section
|
||||
// 4.5.1 in PPC64 ELF ABI.
|
||||
RelocationEntry REhst(Rel.SectionID,
|
||||
StubTargetAddr - Section.Address + 2,
|
||||
ELF::R_PPC64_ADDR16_HIGHEST, Value.Addend);
|
||||
RelocationEntry REhr(Rel.SectionID,
|
||||
StubTargetAddr - Section.Address + 6,
|
||||
ELF::R_PPC64_ADDR16_HIGHER, Value.Addend);
|
||||
RelocationEntry REh(Rel.SectionID,
|
||||
StubTargetAddr - Section.Address + 14,
|
||||
ELF::R_PPC64_ADDR16_HI, Value.Addend);
|
||||
RelocationEntry REl(Rel.SectionID,
|
||||
StubTargetAddr - Section.Address + 18,
|
||||
ELF::R_PPC64_ADDR16_LO, Value.Addend);
|
||||
|
||||
if (Value.SymbolName) {
|
||||
addRelocationForSymbol(REhst, Value.SymbolName);
|
||||
addRelocationForSymbol(REhr, Value.SymbolName);
|
||||
addRelocationForSymbol(REh, Value.SymbolName);
|
||||
addRelocationForSymbol(REl, Value.SymbolName);
|
||||
} else {
|
||||
addRelocationForSection(REhst, Value.SectionID);
|
||||
addRelocationForSection(REhr, Value.SectionID);
|
||||
addRelocationForSection(REh, Value.SectionID);
|
||||
addRelocationForSection(REl, Value.SectionID);
|
||||
}
|
||||
|
||||
resolveRelocation(Target, (uint64_t)Target, (uint64_t)Section.Address
|
||||
+ Section.StubOffset, RelType, 0);
|
||||
if (SymType == SymbolRef::ST_Unknown)
|
||||
// Restore the TOC for external calls
|
||||
writeInt32BE(Target+4, 0xE8410028); // ld r2,40(r1)
|
||||
Section.StubOffset += getMaxStubSize();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RelocationEntry RE(Rel.SectionID, Rel.Offset, RelType, Value.Addend);
|
||||
// Extra check to avoid relocation againt empty symbols (usually
|
||||
// the R_PPC64_TOC).
|
||||
if (Value.SymbolName && !TargetName.empty())
|
||||
addRelocationForSymbol(RE, Value.SymbolName);
|
||||
else
|
||||
addRelocationForSection(RE, Value.SectionID);
|
||||
}
|
||||
} else {
|
||||
RelocationEntry RE(Rel.SectionID, Rel.Offset, RelType, Value.Addend);
|
||||
if (Value.SymbolName)
|
||||
|
|
|
@ -46,6 +46,12 @@ protected:
|
|||
uint32_t Type,
|
||||
int32_t Addend);
|
||||
|
||||
void resolvePPC64Relocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
uint64_t Value,
|
||||
uint32_t Type,
|
||||
int64_t Addend);
|
||||
|
||||
virtual void resolveRelocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
uint64_t Value,
|
||||
|
@ -60,6 +66,11 @@ protected:
|
|||
|
||||
virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer);
|
||||
|
||||
uint64_t findPPC64TOC() const;
|
||||
void findOPDEntrySection(ObjectImage &Obj,
|
||||
ObjSectionToIDMap &LocalSections,
|
||||
RelocationValueRef &Rel);
|
||||
|
||||
public:
|
||||
RuntimeDyldELF(RTDyldMemoryManager *mm)
|
||||
: RuntimeDyldImpl(mm) {}
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/Support/SwapByteOrder.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/system_error.h"
|
||||
#include <map>
|
||||
|
@ -41,6 +43,9 @@ class Twine;
|
|||
/// linker.
|
||||
class SectionEntry {
|
||||
public:
|
||||
/// Name - section name.
|
||||
StringRef Name;
|
||||
|
||||
/// Address - address in the linker's memory where the section resides.
|
||||
uint8_t *Address;
|
||||
|
||||
|
@ -61,9 +66,9 @@ public:
|
|||
/// for calculating relocations in some object formats (like MachO).
|
||||
uintptr_t ObjAddress;
|
||||
|
||||
SectionEntry(uint8_t *address, size_t size, uintptr_t stubOffset,
|
||||
uintptr_t objAddress)
|
||||
: Address(address), Size(size), LoadAddress((uintptr_t)address),
|
||||
SectionEntry(StringRef name, uint8_t *address, size_t size,
|
||||
uintptr_t stubOffset, uintptr_t objAddress)
|
||||
: Name(name), Address(address), Size(size), LoadAddress((uintptr_t)address),
|
||||
StubOffset(stubOffset), ObjAddress(objAddress) {}
|
||||
};
|
||||
|
||||
|
@ -163,6 +168,8 @@ protected:
|
|||
return 8; // 32-bit instruction and 32-bit address
|
||||
else if (Arch == Triple::mipsel)
|
||||
return 16;
|
||||
else if (Arch == Triple::ppc64)
|
||||
return 44;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
@ -185,6 +192,35 @@ protected:
|
|||
return (uint8_t*)Sections[SectionID].Address;
|
||||
}
|
||||
|
||||
void writeInt16BE(uint8_t *Addr, uint16_t Value) {
|
||||
if (sys::isLittleEndianHost())
|
||||
Value = sys::SwapByteOrder(Value);
|
||||
*Addr = (Value >> 8) & 0xFF;
|
||||
*(Addr+1) = Value & 0xFF;
|
||||
}
|
||||
|
||||
void writeInt32BE(uint8_t *Addr, uint32_t Value) {
|
||||
if (sys::isLittleEndianHost())
|
||||
Value = sys::SwapByteOrder(Value);
|
||||
*Addr = (Value >> 24) & 0xFF;
|
||||
*(Addr+1) = (Value >> 16) & 0xFF;
|
||||
*(Addr+2) = (Value >> 8) & 0xFF;
|
||||
*(Addr+3) = Value & 0xFF;
|
||||
}
|
||||
|
||||
void writeInt64BE(uint8_t *Addr, uint64_t Value) {
|
||||
if (sys::isLittleEndianHost())
|
||||
Value = sys::SwapByteOrder(Value);
|
||||
*Addr = (Value >> 56) & 0xFF;
|
||||
*(Addr+1) = (Value >> 48) & 0xFF;
|
||||
*(Addr+2) = (Value >> 40) & 0xFF;
|
||||
*(Addr+3) = (Value >> 32) & 0xFF;
|
||||
*(Addr+4) = (Value >> 24) & 0xFF;
|
||||
*(Addr+5) = (Value >> 16) & 0xFF;
|
||||
*(Addr+6) = (Value >> 8) & 0xFF;
|
||||
*(Addr+7) = Value & 0xFF;
|
||||
}
|
||||
|
||||
/// \brief Given the common symbols discovered in the object file, emit a
|
||||
/// new section for them and update the symbol mappings in the object and
|
||||
/// symbol table.
|
||||
|
|
Loading…
Reference in New Issue