summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorNate Begeman <natebegeman@mac.com>2006-09-08 22:42:09 +0000
committerNate Begeman <natebegeman@mac.com>2006-09-08 22:42:09 +0000
commit94be248dbb2d2a44e8f4d47f161b93704d33d279 (patch)
treeabcb89fb4085d6e568c5ab258f2b04da3790b62b /lib
parent6f34b43292fe478b28ac4b1c6f7c0162cda71c5f (diff)
downloadllvm-94be248dbb2d2a44e8f4d47f161b93704d33d279.tar.gz
llvm-94be248dbb2d2a44e8f4d47f161b93704d33d279.tar.bz2
llvm-94be248dbb2d2a44e8f4d47f161b93704d33d279.tar.xz
First pass at supporting relocations. Relocations are written correctly to
the file now, however the relocated address is currently wrong. Fixing that will require some deep pondering. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30207 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/MachOWriter.cpp118
-rw-r--r--lib/Target/PowerPC/PPCJITInfo.cpp5
-rw-r--r--lib/Target/PowerPC/PPCMachOWriter.cpp88
-rw-r--r--lib/Target/PowerPC/PPCRelocations.h16
4 files changed, 163 insertions, 64 deletions
diff --git a/lib/CodeGen/MachOWriter.cpp b/lib/CodeGen/MachOWriter.cpp
index 0f6820eddf..5ffd978f34 100644
--- a/lib/CodeGen/MachOWriter.cpp
+++ b/lib/CodeGen/MachOWriter.cpp
@@ -25,8 +25,8 @@
#include "llvm/Module.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/CodeGen/MachineRelocation.h"
#include "llvm/CodeGen/MachOWriter.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/Target/TargetJITInfo.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
@@ -130,19 +130,10 @@ bool MachOCodeEmitter::finishFunction(MachineFunction &F) {
// Get a symbol for the function to add to the symbol table
const GlobalValue *FuncV = F.getFunction();
- MachOWriter::MachOSym FnSym(FuncV, MOW.Mang->getValueName(FuncV), MOS->Index);
-
- // Figure out the binding (linkage) of the symbol.
- switch (FuncV->getLinkage()) {
- default:
- // appending linkage is illegal for functions.
- assert(0 && "Unknown linkage type!");
- case GlobalValue::ExternalLinkage:
- FnSym.n_type |= MachOWriter::MachOSym::N_EXT;
- break;
- case GlobalValue::InternalLinkage:
- break;
- }
+ MachOSym FnSym(FuncV, MOW.Mang->getValueName(FuncV), MOS->Index);
+
+ // FIXME: emit constant pool to appropriate section(s)
+ // FIXME: emit jump table to appropriate section
// Resolve the function's relocations either to concrete pointers in the case
// of branches from one block to another, or to target relocation entries.
@@ -152,15 +143,14 @@ bool MachOCodeEmitter::finishFunction(MachineFunction &F) {
void *MBBAddr = (void *)getMachineBasicBlockAddress(MR.getBasicBlock());
MR.setResultPointer(MBBAddr);
MOW.TM.getJITInfo()->relocate(BufferBegin, &MR, 1, 0);
- // FIXME: we basically want the JITInfo relocate() function to rewrite
- // this guy right now, so we just write the correct displacement
- // to the file.
+ } else if (MR.isConstantPoolIndex() || MR.isJumpTableIndex()) {
+ // Get the address of the index.
+ uint64_t Addr = 0;
+ // Generate the relocation(s) for the index.
+ MOW.GetTargetRelocation(*MOS, MR, Addr);
} else {
- // isString | isGV | isCPI | isJTI
- // FIXME: do something smart here. We won't be able to relocate these
- // until the sections are all layed out, but we still need to
- // record them. Maybe emit TargetRelocations and then resolve
- // those at file writing time?
+ // Handle other types later once we've finalized the sections in the file.
+ MOS->Relocations.push_back(MR);
}
}
Relocations.clear();
@@ -175,7 +165,6 @@ bool MachOCodeEmitter::finishFunction(MachineFunction &F) {
//===----------------------------------------------------------------------===//
MachOWriter::MachOWriter(std::ostream &o, TargetMachine &tm) : O(o), TM(tm) {
- // FIXME: set cpu type and cpu subtype somehow from TM
is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64;
isLittleEndian = TM.getTargetData()->isLittleEndian();
@@ -228,9 +217,7 @@ void MachOWriter::EmitGlobal(GlobalVariable *GV) {
// part of the common block if they are zero initialized and allowed to be
// merged with other symbols.
if (NoInit || GV->hasLinkOnceLinkage() || GV->hasWeakLinkage()) {
- MachOWriter::MachOSym ExtOrCommonSym(GV, Mang->getValueName(GV),
- MachOSym::NO_SECT);
- ExtOrCommonSym.n_type |= MachOSym::N_EXT;
+ MachOSym ExtOrCommonSym(GV, Mang->getValueName(GV), MachOSym::NO_SECT);
// For undefined (N_UNDF) external (N_EXT) types, n_value is the size in
// bytes of the symbol.
ExtOrCommonSym.n_value = Size;
@@ -254,9 +241,20 @@ void MachOWriter::EmitGlobal(GlobalVariable *GV) {
MachOSection &Sec = GV->isConstant() ? getConstSection(Ty) : getDataSection();
AddSymbolToSection(Sec, GV);
- // FIXME: actually write out the initializer to the section. This will
- // require ExecutionEngine's InitializeMemory() function, which will need to
- // be enhanced to support relocations.
+ // FIXME: A couple significant changes are required for this to work, even for
+ // trivial cases such as a constant integer:
+ // 0. InitializeMemory needs to be split out of ExecutionEngine. We don't
+ // want to have to create an ExecutionEngine such as JIT just to write
+ // some bytes into a buffer. The only thing necessary for
+ // InitializeMemory to function properly should be TargetData.
+ //
+ // 1. InitializeMemory needs to be enhanced to return MachineRelocations
+ // rather than accessing the address of objects such basic blocks,
+ // constant pools, and jump tables. The client of InitializeMemory such
+ // as an object writer or jit emitter should then handle these relocs
+ // appropriately.
+ //
+ // FIXME: need to allocate memory for the global initializer.
}
@@ -292,7 +290,7 @@ bool MachOWriter::doFinalization(Module &M) {
// Emit the symbol table to temporary buffers, so that we know the size of
// the string table when we write the load commands in the next phase.
BufferSymbolAndStringTable();
-
+
// Emit the header and load commands.
EmitHeaderAndLoadCommands();
@@ -300,9 +298,7 @@ bool MachOWriter::doFinalization(Module &M) {
EmitSections();
// Emit the relocation entry data for each section.
- // FIXME: presumably this should be a virtual method, since different targets
- // have different relocation types.
- EmitRelocations();
+ O.write((char*)&RelocBuffer[0], RelocBuffer.size());
// Write the symbol table and the string table to the end of the file.
O.write((char*)&SymT[0], SymT.size());
@@ -368,10 +364,32 @@ void MachOWriter::EmitHeaderAndLoadCommands() {
outword(FH, SEG.nsects);
outword(FH, SEG.flags);
- // Step #5: Write out the section commands for each section
+ // Step #5: Finish filling in the fields of the MachOSections
+ uint64_t currentAddr = 0;
for (std::list<MachOSection>::iterator I = SectionList.begin(),
E = SectionList.end(); I != E; ++I) {
- I->offset = SEG.fileoff; // FIXME: separate offset
+ I->addr = currentAddr;
+ I->offset = currentAddr + SEG.fileoff;
+ // FIXME: do we need to do something with alignment here?
+ currentAddr += I->size;
+ }
+
+ // Step #6: Calculate the number of relocations for each section and write out
+ // the section commands for each section
+ currentAddr += SEG.fileoff;
+ for (std::list<MachOSection>::iterator I = SectionList.begin(),
+ E = SectionList.end(); I != E; ++I) {
+ // calculate the relocation info for this section command
+ // FIXME: this could get complicated calculating the address argument, we
+ // should probably split this out into its own function.
+ for (unsigned i = 0, e = I->Relocations.size(); i != e; ++i)
+ GetTargetRelocation(*I, I->Relocations[i], 0);
+ if (I->nreloc != 0) {
+ I->reloff = currentAddr;
+ currentAddr += I->nreloc * 8;
+ }
+
+ // write the finalized section command to the output buffer
outstring(FH, I->sectname, 16);
outstring(FH, I->segname, 16);
outaddr(FH, I->addr);
@@ -387,9 +405,9 @@ void MachOWriter::EmitHeaderAndLoadCommands() {
outword(FH, I->reserved3);
}
- // Step #6: Emit LC_SYMTAB/LC_DYSYMTAB load commands
+ // Step #7: Emit LC_SYMTAB/LC_DYSYMTAB load commands
// FIXME: add size of relocs
- SymTab.symoff = SEG.fileoff + SEG.filesize;
+ SymTab.symoff = currentAddr;
SymTab.nsyms = SymbolTable.size();
SymTab.stroff = SymTab.symoff + SymT.size();
SymTab.strsize = StrT.size();
@@ -436,12 +454,6 @@ void MachOWriter::EmitSections() {
}
}
-void MachOWriter::EmitRelocations() {
- // FIXME: this should probably be a pure virtual function, since the
- // relocation types and layout of the relocations themselves are target
- // specific.
-}
-
/// PartitionByLocal - Simple boolean predicate that returns true if Sym is
/// a local symbol rather than an external symbol.
bool MachOWriter::PartitionByLocal(const MachOSym &Sym) {
@@ -513,3 +525,23 @@ void MachOWriter::BufferSymbolAndStringTable() {
outaddr(SymT, I->n_value);
}
}
+
+MachOSym::MachOSym(const GlobalValue *gv, std::string name, uint8_t sect) :
+ GV(gv), GVName(name), n_strx(0), n_type(sect == NO_SECT ? N_UNDF : N_SECT),
+ n_sect(sect), n_desc(0), n_value(0) {
+ // FIXME: take a target machine, and then add the appropriate prefix for
+ // the linkage type based on the TargetAsmInfo
+ switch (GV->getLinkage()) {
+ default:
+ assert(0 && "Unexpected linkage type!");
+ break;
+ case GlobalValue::WeakLinkage:
+ case GlobalValue::LinkOnceLinkage:
+ assert(!isa<Function>(gv) && "Unexpected linkage type for Function!");
+ case GlobalValue::ExternalLinkage:
+ n_type |= N_EXT;
+ break;
+ case GlobalValue::InternalLinkage:
+ break;
+ }
+}
diff --git a/lib/Target/PowerPC/PPCJITInfo.cpp b/lib/Target/PowerPC/PPCJITInfo.cpp
index a3ca3c52f8..7c1d2a4f49 100644
--- a/lib/Target/PowerPC/PPCJITInfo.cpp
+++ b/lib/Target/PowerPC/PPCJITInfo.cpp
@@ -312,15 +312,12 @@ void PPCJITInfo::relocate(void *Function, MachineRelocation *MR,
"Relocation out of range!");
*RelocPos |= (ResultPtr & ((1 << 14)-1)) << 2;
break;
- case PPC::reloc_absolute_ptr_high: // Pointer relocations.
- case PPC::reloc_absolute_ptr_low:
case PPC::reloc_absolute_high: // high bits of ref -> low 16 of instr
case PPC::reloc_absolute_low: { // low bits of ref -> low 16 of instr
ResultPtr += MR->getConstantVal();
// If this is a high-part access, get the high-part.
- if (MR->getRelocationType() == PPC::reloc_absolute_high ||
- MR->getRelocationType() == PPC::reloc_absolute_ptr_high) {
+ if (MR->getRelocationType() == PPC::reloc_absolute_high) {
// If the low part will have a carry (really a borrow) from the low
// 16-bits into the high 16, add a bit to borrow from.
if (((int)ResultPtr << 16) < 0)
diff --git a/lib/Target/PowerPC/PPCMachOWriter.cpp b/lib/Target/PowerPC/PPCMachOWriter.cpp
index a7da37127d..f82ee340e1 100644
--- a/lib/Target/PowerPC/PPCMachOWriter.cpp
+++ b/lib/Target/PowerPC/PPCMachOWriter.cpp
@@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//
+#include "PPCRelocations.h"
#include "PPCTargetMachine.h"
#include "llvm/PassManager.h"
#include "llvm/CodeGen/MachOWriter.h"
@@ -22,11 +23,28 @@ namespace {
class VISIBILITY_HIDDEN PPCMachOWriter : public MachOWriter {
public:
PPCMachOWriter(std::ostream &O, PPCTargetMachine &TM) : MachOWriter(O, TM) {
- // FIMXE: choose ppc64 when appropriate
- Header.cputype = MachOHeader::CPU_TYPE_POWERPC;
+ if (TM.getTargetData()->getPointerSizeInBits() == 64) {
+ Header.cputype = MachOHeader::CPU_TYPE_POWERPC64;
+ } else {
+ Header.cputype = MachOHeader::CPU_TYPE_POWERPC;
+ }
Header.cpusubtype = MachOHeader::CPU_SUBTYPE_POWERPC_ALL;
}
+ virtual void GetTargetRelocation(MachOSection &MOS, MachineRelocation &MR,
+ uint64_t Addr);
+
+ // Constants for the relocation r_type field.
+ // see <mach-o/ppc/reloc.h>
+ enum { PPC_RELOC_VANILLA, // generic relocation
+ PPC_RELOC_PAIR, // the second relocation entry of a pair
+ PPC_RELOC_BR14, // 14 bit branch displacement to word address
+ PPC_RELOC_BR24, // 24 bit branch displacement to word address
+ PPC_RELOC_HI16, // a PAIR follows with the low 16 bits
+ PPC_RELOC_LO16, // a PAIR follows with the high 16 bits
+ PPC_RELOC_HA16, // a PAIR follows, which is sign extended to 32b
+ PPC_RELOC_LO14 // LO16 with low 2 bits implicitly zero
+ };
};
}
@@ -39,3 +57,69 @@ void llvm::addPPCMachOObjectWriterPass(FunctionPassManager &FPM,
FPM.add(EW);
FPM.add(createPPCCodeEmitterPass(TM, EW->getMachineCodeEmitter()));
}
+
+/// GetTargetRelocation - For the MachineRelocation MR, convert it to one or
+/// more PowerPC MachORelocation(s), add the new relocations to the
+/// MachOSection, and rewrite the instruction at the section offset if required
+/// by that relocation type.
+void PPCMachOWriter::GetTargetRelocation(MachOSection &MOS,
+ MachineRelocation &MR,
+ uint64_t Addr) {
+ // Keep track of whether or not this is an externally defined relocation.
+ uint32_t index = MOS.Index;
+ bool isExtern = false;
+
+ // Get the address of the instruction to rewrite
+ unsigned char *RelocPos = &MOS.SectionData[0] + MR.getMachineCodeOffset();
+
+ // Get the address of whatever it is we're relocating, if possible.
+ if (MR.isGlobalValue()) {
+ // determine whether or not its external and then figure out what section
+ // we put it in if it's a locally defined symbol.
+ } else if (MR.isString()) {
+ // lookup in global values?
+ } else {
+ assert((MR.isConstantPoolIndex() || MR.isJumpTableIndex()) &&
+ "Unhandled MachineRelocation type!");
+ }
+
+ switch ((PPC::RelocationType)MR.getRelocationType()) {
+ default: assert(0 && "Unknown PPC relocation type!");
+ case PPC::reloc_pcrel_bx:
+ case PPC::reloc_pcrel_bcx:
+ case PPC::reloc_absolute_low_ix:
+ assert(0 && "Unhandled PPC relocation type!");
+ break;
+ case PPC::reloc_absolute_high:
+ {
+ MachORelocation HA16(MR.getMachineCodeOffset(), index, false, 2, isExtern,
+ PPC_RELOC_HA16);
+ MachORelocation PAIR(Addr & 0xFFFF, 0xFFFFFF, false, 2, isExtern,
+ PPC_RELOC_PAIR);
+ outword(RelocBuffer, HA16.r_address);
+ outword(RelocBuffer, HA16.getPackedFields());
+ outword(RelocBuffer, PAIR.r_address);
+ outword(RelocBuffer, PAIR.getPackedFields());
+ }
+ MOS.nreloc += 2;
+ Addr += 0x8000;
+ *(unsigned *)RelocPos &= 0xFFFF0000;
+ *(unsigned *)RelocPos |= ((Addr >> 16) & 0xFFFF);
+ break;
+ case PPC::reloc_absolute_low:
+ {
+ MachORelocation LO16(MR.getMachineCodeOffset(), index, false, 2, isExtern,
+ PPC_RELOC_LO16);
+ MachORelocation PAIR(Addr >> 16, 0xFFFFFF, false, 2, isExtern,
+ PPC_RELOC_PAIR);
+ outword(RelocBuffer, LO16.r_address);
+ outword(RelocBuffer, LO16.getPackedFields());
+ outword(RelocBuffer, PAIR.r_address);
+ outword(RelocBuffer, PAIR.getPackedFields());
+ }
+ MOS.nreloc += 2;
+ *(unsigned *)RelocPos &= 0xFFFF0000;
+ *(unsigned *)RelocPos |= (Addr & 0xFFFF);
+ break;
+ }
+}
diff --git a/lib/Target/PowerPC/PPCRelocations.h b/lib/Target/PowerPC/PPCRelocations.h
index 8cb2859d1f..21c688de2c 100644
--- a/lib/Target/PowerPC/PPCRelocations.h
+++ b/lib/Target/PowerPC/PPCRelocations.h
@@ -44,21 +44,7 @@ namespace llvm {
// reloc_absolute_low_ix - Absolute relocation for the 64-bit load/store
// instruction which have two implicit zero bits.
- reloc_absolute_low_ix,
-
- // reloc_absolute_ptr_high - Absolute relocation for references to lazy
- // pointer stubs. In this case, the relocated instruction should be
- // relocated to point to a POINTER to the indicated global. The low-16
- // bits of the instruction are rewritten with the high 16-bits of the
- // address of the pointer.
- reloc_absolute_ptr_high,
-
- // reloc_absolute_ptr_low - Absolute relocation for references to lazy
- // pointer stubs. In this case, the relocated instruction should be
- // relocated to point to a POINTER to the indicated global. The low-16
- // bits of the instruction are rewritten with the low 16-bits of the
- // address of the pointer.
- reloc_absolute_ptr_low
+ reloc_absolute_low_ix
};
}
}