[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:
Michael J. Spencer 2013-01-04 20:36:28 +00:00
parent 4588a1a205
commit bae14cef80
5 changed files with 465 additions and 385 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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!");