[llvm-commits] CVS: llvm/lib/CodeGen/MachOWriter.cpp
Nate Begeman
natebegeman at mac.com
Fri Sep 8 15:42:26 PDT 2006
Changes in directory llvm/lib/CodeGen:
MachOWriter.cpp updated: 1.4 -> 1.5
---
Log message:
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.
---
Diffs of the changes: (+75 -43)
MachOWriter.cpp | 118 +++++++++++++++++++++++++++++++++++---------------------
1 files changed, 75 insertions(+), 43 deletions(-)
Index: llvm/lib/CodeGen/MachOWriter.cpp
diff -u llvm/lib/CodeGen/MachOWriter.cpp:1.4 llvm/lib/CodeGen/MachOWriter.cpp:1.5
--- llvm/lib/CodeGen/MachOWriter.cpp:1.4 Sat Sep 2 12:37:30 2006
+++ llvm/lib/CodeGen/MachOWriter.cpp Fri Sep 8 17:42:09 2006
@@ -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 @@
// 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 @@
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 @@
//===----------------------------------------------------------------------===//
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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::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 @@
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;
+ }
+}
More information about the llvm-commits
mailing list