mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
Make use of common-symbol alignment info in ELF loader.
Patch by Amara Emerson. llvm-svn: 166919
This commit is contained in:
parent
86db334e17
commit
fdb1d1af73
@ -17,6 +17,7 @@
|
||||
#include "RuntimeDyldELF.h"
|
||||
#include "RuntimeDyldMachO.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
@ -27,16 +28,6 @@ RuntimeDyldImpl::~RuntimeDyldImpl() {}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace {
|
||||
// Helper for extensive error checking in debug builds.
|
||||
error_code Check(error_code Err) {
|
||||
if (Err) {
|
||||
report_fatal_error(Err.message());
|
||||
}
|
||||
return Err;
|
||||
}
|
||||
} // end anonymous namespace
|
||||
|
||||
// Resolve the relocations for all symbols we currently know about.
|
||||
void RuntimeDyldImpl::resolveRelocations() {
|
||||
// First, resolve relocations associated with external symbols.
|
||||
@ -78,9 +69,9 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) {
|
||||
// Used sections from the object file
|
||||
ObjSectionToIDMap LocalSections;
|
||||
|
||||
// Common symbols requiring allocation, and the total size required to
|
||||
// allocate all common symbols.
|
||||
// Common symbols requiring allocation, with their sizes and alignments
|
||||
CommonSymbolMap CommonSymbols;
|
||||
// Maximum required total memory to allocate all common symbols
|
||||
uint64_t CommonSize = 0;
|
||||
|
||||
error_code err;
|
||||
@ -100,10 +91,11 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) {
|
||||
bool isCommon = flags & SymbolRef::SF_Common;
|
||||
if (isCommon) {
|
||||
// Add the common symbols to a list. We'll allocate them all below.
|
||||
uint64_t Align = getCommonSymbolAlignment(*i);
|
||||
uint64_t Size = 0;
|
||||
Check(i->getSize(Size));
|
||||
CommonSize += Size;
|
||||
CommonSymbols[*i] = Size;
|
||||
CommonSize += Size + Align;
|
||||
CommonSymbols[*i] = CommonSymbolInfo(Size, Align);
|
||||
} else {
|
||||
if (SymType == object::SymbolRef::ST_Function ||
|
||||
SymType == object::SymbolRef::ST_Data ||
|
||||
@ -201,11 +193,20 @@ void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj,
|
||||
// Assign the address of each symbol
|
||||
for (CommonSymbolMap::const_iterator it = CommonSymbols.begin(),
|
||||
itEnd = CommonSymbols.end(); it != itEnd; it++) {
|
||||
uint64_t Size = it->second.first;
|
||||
uint64_t Align = it->second.second;
|
||||
StringRef Name;
|
||||
it->first.getName(Name);
|
||||
if (Align) {
|
||||
// This symbol has an alignment requirement.
|
||||
uint64_t AlignOffset = OffsetToAlignment((uint64_t)Addr, Align);
|
||||
Addr += AlignOffset;
|
||||
Offset += AlignOffset;
|
||||
DEBUG(dbgs() << "Allocating common symbol " << Name << " address " <<
|
||||
format("0x%x\n", Addr));
|
||||
}
|
||||
Obj.updateSymbolAddress(it->first, (uint64_t)Addr);
|
||||
SymbolTable[Name.data()] = SymbolLoc(SectionID, Offset);
|
||||
uint64_t Size = it->second;
|
||||
Offset += Size;
|
||||
Addr += Size;
|
||||
}
|
||||
|
@ -796,6 +796,13 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
}
|
||||
}
|
||||
|
||||
unsigned RuntimeDyldELF::getCommonSymbolAlignment(const SymbolRef &Sym) {
|
||||
// In ELF, the value of an SHN_COMMON symbol is its alignment requirement.
|
||||
uint64_t Align;
|
||||
Check(Sym.getValue(Align));
|
||||
return Align;
|
||||
}
|
||||
|
||||
bool RuntimeDyldELF::isCompatibleFormat(const ObjectBuffer *Buffer) const {
|
||||
if (Buffer->getBufferSize() < strlen(ELF::ElfMagic))
|
||||
return false;
|
||||
|
@ -18,8 +18,18 @@
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace {
|
||||
// Helper for extensive error checking in debug builds.
|
||||
error_code Check(error_code Err) {
|
||||
if (Err) {
|
||||
report_fatal_error(Err.message());
|
||||
}
|
||||
return Err;
|
||||
}
|
||||
} // end anonymous namespace
|
||||
|
||||
class RuntimeDyldELF : public RuntimeDyldImpl {
|
||||
protected:
|
||||
void resolveX86_64Relocation(uint8_t *LocalAddress,
|
||||
@ -64,6 +74,8 @@ protected:
|
||||
const SymbolTableMap &Symbols,
|
||||
StubMap &Stubs);
|
||||
|
||||
unsigned getCommonSymbolAlignment(const SymbolRef &Sym);
|
||||
|
||||
virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer);
|
||||
|
||||
uint64_t findPPC64TOC() const;
|
||||
|
@ -140,8 +140,10 @@ protected:
|
||||
typedef StringMap<SymbolLoc> SymbolTableMap;
|
||||
SymbolTableMap GlobalSymbolTable;
|
||||
|
||||
// Keep a map of common symbols to their sizes
|
||||
typedef std::map<SymbolRef, unsigned> CommonSymbolMap;
|
||||
// Pair representing the size and alignment requirement for a common symbol.
|
||||
typedef std::pair<unsigned, unsigned> CommonSymbolInfo;
|
||||
// Keep a map of common symbols to their info pairs
|
||||
typedef std::map<SymbolRef, CommonSymbolInfo> CommonSymbolMap;
|
||||
|
||||
// For each symbol, keep a list of relocations based on it. Anytime
|
||||
// its address is reassigned (the JIT re-compiled the function, e.g.),
|
||||
@ -192,6 +194,13 @@ protected:
|
||||
return (uint8_t*)Sections[SectionID].Address;
|
||||
}
|
||||
|
||||
// Subclasses can override this method to get the alignment requirement of
|
||||
// a common symbol. Returns no alignment requirement if not implemented.
|
||||
virtual unsigned getCommonSymbolAlignment(const SymbolRef &Sym) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void writeInt16BE(uint8_t *Addr, uint16_t Value) {
|
||||
if (sys::isLittleEndianHost())
|
||||
Value = sys::SwapByteOrder(Value);
|
||||
|
32
test/ExecutionEngine/MCJIT/test-common-symbols-alignment.ll
Normal file
32
test/ExecutionEngine/MCJIT/test-common-symbols-alignment.ll
Normal file
@ -0,0 +1,32 @@
|
||||
; RUN: %lli -mtriple=%mcjit_triple -use-mcjit -O0 %s
|
||||
|
||||
; This test checks that common symbols have been allocated addresses honouring
|
||||
; the alignment requirement.
|
||||
|
||||
@CS1 = common global i32 0, align 16
|
||||
@CS2 = common global i8 0, align 1
|
||||
@CS3 = common global i32 0, align 16
|
||||
|
||||
define i32 @main() nounwind {
|
||||
entry:
|
||||
%retval = alloca i32, align 4
|
||||
%ptr = alloca i32, align 4
|
||||
store i32 0, i32* %retval
|
||||
store i32 ptrtoint (i32* @CS3 to i32), i32* %ptr, align 4
|
||||
%0 = load i32* %ptr, align 4
|
||||
%and = and i32 %0, 15
|
||||
%tobool = icmp ne i32 %and, 0
|
||||
br i1 %tobool, label %if.then, label %if.else
|
||||
|
||||
if.then: ; preds = %entry
|
||||
store i32 1, i32* %retval
|
||||
br label %return
|
||||
|
||||
if.else: ; preds = %entry
|
||||
store i32 0, i32* %retval
|
||||
br label %return
|
||||
|
||||
return: ; preds = %if.else, %if.then
|
||||
%1 = load i32* %retval
|
||||
ret i32 %1
|
||||
}
|
Loading…
Reference in New Issue
Block a user