forked from OSchip/llvm-project
[Object][ELF] Add a maximum alignment. This is used by createELFObjectFile to create a properly aligned reader.
llvm-svn: 171520
This commit is contained in:
parent
4588a1a205
commit
bae14cef80
File diff suppressed because it is too large
Load Diff
|
@ -28,6 +28,8 @@
|
|||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
|
||||
using support::endianness;
|
||||
|
||||
namespace {
|
||||
|
||||
static inline
|
||||
|
@ -38,19 +40,22 @@ error_code check(error_code Err) {
|
|||
return Err;
|
||||
}
|
||||
|
||||
template<support::endianness target_endianness, bool is64Bits>
|
||||
class DyldELFObject : public ELFObjectFile<target_endianness, is64Bits> {
|
||||
LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
|
||||
template<endianness target_endianness, std::size_t max_alignment, bool is64Bits>
|
||||
class DyldELFObject
|
||||
: public ELFObjectFile<target_endianness, max_alignment, is64Bits> {
|
||||
LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits)
|
||||
|
||||
typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
|
||||
typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
|
||||
typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel;
|
||||
typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela;
|
||||
typedef Elf_Shdr_Impl<target_endianness, max_alignment, is64Bits> Elf_Shdr;
|
||||
typedef Elf_Sym_Impl<target_endianness, max_alignment, is64Bits> Elf_Sym;
|
||||
typedef
|
||||
Elf_Rel_Impl<target_endianness, max_alignment, is64Bits, false> Elf_Rel;
|
||||
typedef
|
||||
Elf_Rel_Impl<target_endianness, max_alignment, is64Bits, true> Elf_Rela;
|
||||
|
||||
typedef Elf_Ehdr_Impl<target_endianness, is64Bits> Elf_Ehdr;
|
||||
typedef Elf_Ehdr_Impl<target_endianness, max_alignment, is64Bits> Elf_Ehdr;
|
||||
|
||||
typedef typename ELFDataTypeTypedefHelper<
|
||||
target_endianness, is64Bits>::value_type addr_type;
|
||||
target_endianness, max_alignment, is64Bits>::value_type addr_type;
|
||||
|
||||
public:
|
||||
DyldELFObject(MemoryBuffer *Wrapper, error_code &ec);
|
||||
|
@ -60,24 +65,25 @@ public:
|
|||
|
||||
// Methods for type inquiry through isa, cast and dyn_cast
|
||||
static inline bool classof(const Binary *v) {
|
||||
return (isa<ELFObjectFile<target_endianness, is64Bits> >(v)
|
||||
&& classof(cast<ELFObjectFile<target_endianness, is64Bits> >(v)));
|
||||
return (isa<ELFObjectFile<target_endianness, max_alignment, is64Bits> >(v)
|
||||
&& classof(cast<ELFObjectFile
|
||||
<target_endianness, max_alignment, is64Bits> >(v)));
|
||||
}
|
||||
static inline bool classof(
|
||||
const ELFObjectFile<target_endianness, is64Bits> *v) {
|
||||
const ELFObjectFile<target_endianness, max_alignment, is64Bits> *v) {
|
||||
return v->isDyldType();
|
||||
}
|
||||
};
|
||||
|
||||
template<support::endianness target_endianness, bool is64Bits>
|
||||
template<endianness target_endianness, std::size_t max_alignment, bool is64Bits>
|
||||
class ELFObjectImage : public ObjectImageCommon {
|
||||
protected:
|
||||
DyldELFObject<target_endianness, is64Bits> *DyldObj;
|
||||
DyldELFObject<target_endianness, max_alignment, is64Bits> *DyldObj;
|
||||
bool Registered;
|
||||
|
||||
public:
|
||||
ELFObjectImage(ObjectBuffer *Input,
|
||||
DyldELFObject<target_endianness, is64Bits> *Obj)
|
||||
DyldELFObject<target_endianness, max_alignment, is64Bits> *Obj)
|
||||
: ObjectImageCommon(Input, Obj),
|
||||
DyldObj(Obj),
|
||||
Registered(false) {}
|
||||
|
@ -113,17 +119,16 @@ class ELFObjectImage : public ObjectImageCommon {
|
|||
// The MemoryBuffer passed into this constructor is just a wrapper around the
|
||||
// actual memory. Ultimately, the Binary parent class will take ownership of
|
||||
// this MemoryBuffer object but not the underlying memory.
|
||||
template<support::endianness target_endianness, bool is64Bits>
|
||||
DyldELFObject<target_endianness, is64Bits>::DyldELFObject(MemoryBuffer *Wrapper,
|
||||
error_code &ec)
|
||||
: ELFObjectFile<target_endianness, is64Bits>(Wrapper, ec) {
|
||||
template<endianness target_endianness, std::size_t max_alignment, bool is64Bits>
|
||||
DyldELFObject<target_endianness, max_alignment, is64Bits>
|
||||
::DyldELFObject(MemoryBuffer *Wrapper, error_code &ec)
|
||||
: ELFObjectFile<target_endianness, max_alignment, is64Bits>(Wrapper, ec) {
|
||||
this->isDyldELFObject = true;
|
||||
}
|
||||
|
||||
template<support::endianness target_endianness, bool is64Bits>
|
||||
void DyldELFObject<target_endianness, is64Bits>::updateSectionAddress(
|
||||
const SectionRef &Sec,
|
||||
uint64_t Addr) {
|
||||
template<endianness target_endianness, std::size_t max_alignment, bool is64Bits>
|
||||
void DyldELFObject<target_endianness, max_alignment, is64Bits>
|
||||
::updateSectionAddress(const SectionRef &Sec, uint64_t Addr) {
|
||||
DataRefImpl ShdrRef = Sec.getRawDataRefImpl();
|
||||
Elf_Shdr *shdr = const_cast<Elf_Shdr*>(
|
||||
reinterpret_cast<const Elf_Shdr *>(ShdrRef.p));
|
||||
|
@ -133,14 +138,13 @@ void DyldELFObject<target_endianness, is64Bits>::updateSectionAddress(
|
|||
shdr->sh_addr = static_cast<addr_type>(Addr);
|
||||
}
|
||||
|
||||
template<support::endianness target_endianness, bool is64Bits>
|
||||
void DyldELFObject<target_endianness, is64Bits>::updateSymbolAddress(
|
||||
const SymbolRef &SymRef,
|
||||
uint64_t Addr) {
|
||||
template<endianness target_endianness, std::size_t max_align, bool is64Bits>
|
||||
void DyldELFObject<target_endianness, max_align, is64Bits>
|
||||
::updateSymbolAddress(const SymbolRef &SymRef, uint64_t Addr){
|
||||
|
||||
Elf_Sym *sym = const_cast<Elf_Sym*>(
|
||||
ELFObjectFile<target_endianness, is64Bits>::
|
||||
getSymbol(SymRef.getRawDataRefImpl()));
|
||||
ELFObjectFile<target_endianness, max_align, is64Bits>
|
||||
::getSymbol(SymRef.getRawDataRefImpl()));
|
||||
|
||||
// This assumes the address passed in matches the target address bitness
|
||||
// The template-based type cast handles everything else.
|
||||
|
@ -149,7 +153,6 @@ void DyldELFObject<target_endianness, is64Bits>::updateSymbolAddress(
|
|||
|
||||
} // namespace
|
||||
|
||||
|
||||
namespace llvm {
|
||||
|
||||
ObjectImage *RuntimeDyldELF::createObjectImage(ObjectBuffer *Buffer) {
|
||||
|
@ -161,24 +164,24 @@ ObjectImage *RuntimeDyldELF::createObjectImage(ObjectBuffer *Buffer) {
|
|||
error_code ec;
|
||||
|
||||
if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) {
|
||||
DyldELFObject<support::little, false> *Obj =
|
||||
new DyldELFObject<support::little, false>(Buffer->getMemBuffer(), ec);
|
||||
return new ELFObjectImage<support::little, false>(Buffer, Obj);
|
||||
DyldELFObject<support::little, 4, false> *Obj =
|
||||
new DyldELFObject<support::little, 4, false>(Buffer->getMemBuffer(), ec);
|
||||
return new ELFObjectImage<support::little, 4, false>(Buffer, Obj);
|
||||
}
|
||||
else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) {
|
||||
DyldELFObject<support::big, false> *Obj =
|
||||
new DyldELFObject<support::big, false>(Buffer->getMemBuffer(), ec);
|
||||
return new ELFObjectImage<support::big, false>(Buffer, Obj);
|
||||
DyldELFObject<support::big, 4, false> *Obj =
|
||||
new DyldELFObject<support::big, 4, false>(Buffer->getMemBuffer(), ec);
|
||||
return new ELFObjectImage<support::big, 4, false>(Buffer, Obj);
|
||||
}
|
||||
else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) {
|
||||
DyldELFObject<support::big, true> *Obj =
|
||||
new DyldELFObject<support::big, true>(Buffer->getMemBuffer(), ec);
|
||||
return new ELFObjectImage<support::big, true>(Buffer, Obj);
|
||||
DyldELFObject<support::big, 8, true> *Obj =
|
||||
new DyldELFObject<support::big, 8, true>(Buffer->getMemBuffer(), ec);
|
||||
return new ELFObjectImage<support::big, 8, true>(Buffer, Obj);
|
||||
}
|
||||
else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) {
|
||||
DyldELFObject<support::little, true> *Obj =
|
||||
new DyldELFObject<support::little, true>(Buffer->getMemBuffer(), ec);
|
||||
return new ELFObjectImage<support::little, true>(Buffer, Obj);
|
||||
DyldELFObject<support::little, 8, true> *Obj =
|
||||
new DyldELFObject<support::little, 8, true>(Buffer->getMemBuffer(), ec);
|
||||
return new ELFObjectImage<support::little, 8, true>(Buffer, Obj);
|
||||
}
|
||||
else
|
||||
llvm_unreachable("Unexpected ELF format");
|
||||
|
@ -207,7 +210,7 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section,
|
|||
case ELF::R_X86_64_32S: {
|
||||
Value += Addend;
|
||||
assert((Type == ELF::R_X86_64_32 && (Value <= UINT32_MAX)) ||
|
||||
(Type == ELF::R_X86_64_32S &&
|
||||
(Type == ELF::R_X86_64_32S &&
|
||||
((int64_t)Value <= INT32_MAX && (int64_t)Value >= INT32_MIN)));
|
||||
uint32_t TruncatedAddr = (Value & 0xFFFFFFFF);
|
||||
uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset);
|
||||
|
@ -288,7 +291,7 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section,
|
|||
default:
|
||||
llvm_unreachable("Not implemented relocation type!");
|
||||
|
||||
// Write a 32bit value to relocation address, taking into account the
|
||||
// Write a 32bit value to relocation address, taking into account the
|
||||
// implicit addend encoded in the target.
|
||||
case ELF::R_ARM_TARGET1 :
|
||||
case ELF::R_ARM_ABS32 :
|
||||
|
@ -299,7 +302,7 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section,
|
|||
// Last 4 bit should be shifted.
|
||||
case ELF::R_ARM_MOVW_ABS_NC :
|
||||
// We are not expecting any other addend in the relocation address.
|
||||
// Using 0x000F0FFF because MOVW has its 16 bit immediate split into 2
|
||||
// Using 0x000F0FFF because MOVW has its 16 bit immediate split into 2
|
||||
// non-contiguous fields.
|
||||
assert((*TargetPtr & 0x000F0FFF) == 0);
|
||||
Value = Value & 0xFFFF;
|
||||
|
@ -550,7 +553,6 @@ void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint64_t Value,
|
||||
|
@ -630,9 +632,9 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
|
|||
// Default to 'true' in case isText fails (though it never does).
|
||||
bool isCode = true;
|
||||
si->isText(isCode);
|
||||
Value.SectionID = findOrEmitSection(Obj,
|
||||
(*si),
|
||||
isCode,
|
||||
Value.SectionID = findOrEmitSection(Obj,
|
||||
(*si),
|
||||
isCode,
|
||||
ObjSectionToID);
|
||||
Value.Addend = Addend;
|
||||
break;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
|
@ -22,16 +23,37 @@ ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) {
|
|||
std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object);
|
||||
error_code ec;
|
||||
|
||||
std::size_t MaxAlignment =
|
||||
1ULL << CountTrailingZeros_64(uintptr_t(Object->getBufferStart()));
|
||||
|
||||
if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB)
|
||||
return new ELFObjectFile<support::little, false>(Object, ec);
|
||||
if (MaxAlignment >= 4)
|
||||
return new ELFObjectFile<support::little, 4, false>(Object, ec);
|
||||
else if (MaxAlignment >= 2)
|
||||
return new ELFObjectFile<support::little, 2, false>(Object, ec);
|
||||
else
|
||||
llvm_unreachable("Invalid alignment for ELF file!");
|
||||
else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB)
|
||||
return new ELFObjectFile<support::big, false>(Object, ec);
|
||||
if (MaxAlignment >= 4)
|
||||
return new ELFObjectFile<support::big, 4, false>(Object, ec);
|
||||
else if (MaxAlignment >= 2)
|
||||
return new ELFObjectFile<support::big, 2, false>(Object, ec);
|
||||
else
|
||||
llvm_unreachable("Invalid alignment for ELF file!");
|
||||
else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB)
|
||||
return new ELFObjectFile<support::big, true>(Object, ec);
|
||||
if (MaxAlignment >= 8)
|
||||
return new ELFObjectFile<support::big, 8, true>(Object, ec);
|
||||
else if (MaxAlignment >= 2)
|
||||
return new ELFObjectFile<support::big, 2, true>(Object, ec);
|
||||
else
|
||||
llvm_unreachable("Invalid alignment for ELF file!");
|
||||
else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) {
|
||||
ELFObjectFile<support::little, true> *result =
|
||||
new ELFObjectFile<support::little, true>(Object, ec);
|
||||
return result;
|
||||
if (MaxAlignment >= 8)
|
||||
return new ELFObjectFile<support::little, 8, true>(Object, ec);
|
||||
else if (MaxAlignment >= 2)
|
||||
return new ELFObjectFile<support::little, 2, true>(Object, ec);
|
||||
else
|
||||
llvm_unreachable("Invalid alignment for ELF file!");
|
||||
}
|
||||
|
||||
report_fatal_error("Buffer is not an ELF object file!");
|
||||
|
|
Loading…
Reference in New Issue