diff options
author | Nate Begeman <natebegeman@mac.com> | 2006-09-08 22:42:09 +0000 |
---|---|---|
committer | Nate Begeman <natebegeman@mac.com> | 2006-09-08 22:42:09 +0000 |
commit | 94be248dbb2d2a44e8f4d47f161b93704d33d279 (patch) | |
tree | abcb89fb4085d6e568c5ab258f2b04da3790b62b /lib/Target/PowerPC/PPCMachOWriter.cpp | |
parent | 6f34b43292fe478b28ac4b1c6f7c0162cda71c5f (diff) |
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/Target/PowerPC/PPCMachOWriter.cpp')
-rw-r--r-- | lib/Target/PowerPC/PPCMachOWriter.cpp | 88 |
1 files changed, 86 insertions, 2 deletions
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; + } +} |