aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/bugpoint/Miscompilation.cpp2
-rw-r--r--tools/bugpoint/ToolRunner.h1
-rw-r--r--tools/lli/RecordingMemoryManager.cpp11
-rw-r--r--tools/lli/RecordingMemoryManager.h7
-rw-r--r--tools/lli/lli.cpp30
-rw-r--r--tools/llvm-config/llvm-config.cpp1
-rw-r--r--tools/llvm-link/llvm-link.cpp4
-rw-r--r--tools/llvm-mc/llvm-mc.cpp9
-rw-r--r--tools/llvm-objdump/CMakeLists.txt1
-rw-r--r--tools/llvm-objdump/COFFDump.cpp2
-rw-r--r--tools/llvm-objdump/ELFDump.cpp14
-rw-r--r--tools/llvm-objdump/MCFunction.cpp138
-rw-r--r--tools/llvm-objdump/MCFunction.h100
-rw-r--r--tools/llvm-objdump/MachODump.cpp440
-rw-r--r--tools/llvm-objdump/llvm-objdump.cpp214
-rw-r--r--tools/llvm-objdump/llvm-objdump.h19
-rw-r--r--tools/llvm-readobj/COFFDumper.cpp8
-rw-r--r--tools/llvm-readobj/ELFDumper.cpp56
-rw-r--r--tools/llvm-readobj/MachODumper.cpp7
-rw-r--r--tools/llvm-rtdyld/llvm-rtdyld.cpp2
-rw-r--r--tools/llvm-shlib/Makefile3
-rw-r--r--tools/llvm-symbolizer/LLVMSymbolize.cpp36
-rw-r--r--tools/llvm-symbolizer/LLVMSymbolize.h6
-rw-r--r--tools/lto/LTOCodeGenerator.cpp24
-rw-r--r--tools/lto/LTOCodeGenerator.h1
-rw-r--r--tools/lto/LTOModule.cpp14
-rw-r--r--tools/lto/Makefile3
-rw-r--r--tools/macho-dump/macho-dump.cpp2
-rw-r--r--tools/obj2yaml/coff2yaml.cpp378
-rw-r--r--tools/obj2yaml/obj2yaml.cpp32
-rw-r--r--tools/obj2yaml/obj2yaml.h12
-rw-r--r--tools/opt/opt.cpp1
-rw-r--r--tools/yaml2obj/CMakeLists.txt4
-rw-r--r--tools/yaml2obj/Makefile2
-rw-r--r--tools/yaml2obj/yaml2coff.cpp288
-rw-r--r--tools/yaml2obj/yaml2elf.cpp78
-rw-r--r--tools/yaml2obj/yaml2obj.cpp671
-rw-r--r--tools/yaml2obj/yaml2obj.h22
38 files changed, 918 insertions, 1725 deletions
diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp
index c676a05..11ac0de 100644
--- a/tools/bugpoint/Miscompilation.cpp
+++ b/tools/bugpoint/Miscompilation.cpp
@@ -130,7 +130,7 @@ ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix,
//
OwningPtr<Module> PrefixOutput(ParseInputFile(BitcodeResult,
BD.getContext()));
- if (PrefixOutput == 0) {
+ if (!PrefixOutput) {
errs() << BD.getToolName() << ": Error reading bitcode file '"
<< BitcodeResult << "'!\n";
exit(1);
diff --git a/tools/bugpoint/ToolRunner.h b/tools/bugpoint/ToolRunner.h
index bb83ce4..28c09f5 100644
--- a/tools/bugpoint/ToolRunner.h
+++ b/tools/bugpoint/ToolRunner.h
@@ -21,6 +21,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/PathV1.h"
#include "llvm/Support/SystemUtils.h"
#include <exception>
#include <vector>
diff --git a/tools/lli/RecordingMemoryManager.cpp b/tools/lli/RecordingMemoryManager.cpp
index e4d992d..1fa8176 100644
--- a/tools/lli/RecordingMemoryManager.cpp
+++ b/tools/lli/RecordingMemoryManager.cpp
@@ -98,17 +98,6 @@ uint8_t *RecordingMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignme
void RecordingMemoryManager::deallocateFunctionBody(void *Body) {
llvm_unreachable("Unexpected!");
}
-uint8_t* RecordingMemoryManager::startExceptionTable(const Function* F, uintptr_t &ActualSize) {
- llvm_unreachable("Unexpected!");
- return 0;
-}
-void RecordingMemoryManager::endExceptionTable(const Function *F, uint8_t *TableStart,
- uint8_t *TableEnd, uint8_t* FrameRegister) {
- llvm_unreachable("Unexpected!");
-}
-void RecordingMemoryManager::deallocateExceptionTable(void *ET) {
- llvm_unreachable("Unexpected!");
-}
static int jit_noop() {
return 0;
diff --git a/tools/lli/RecordingMemoryManager.h b/tools/lli/RecordingMemoryManager.h
index 991f535..b2919c3 100644
--- a/tools/lli/RecordingMemoryManager.h
+++ b/tools/lli/RecordingMemoryManager.h
@@ -58,7 +58,7 @@ public:
void *getPointerToNamedFunction(const std::string &Name,
bool AbortOnFailure = true);
- bool applyPermissions(std::string *ErrMsg) { return false; }
+ bool finalizeMemory(std::string *ErrMsg) { return false; }
// The following obsolete JITMemoryManager calls are stubbed out for
// this model.
@@ -75,11 +75,6 @@ public:
uint8_t *allocateSpace(intptr_t Size, unsigned Alignment);
uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
void deallocateFunctionBody(void *Body);
- uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize);
- void endExceptionTable(const Function *F, uint8_t *TableStart,
- uint8_t *TableEnd, uint8_t* FrameRegister);
- void deallocateExceptionTable(void *ET);
-
};
} // end namespace llvm
diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp
index 297763f..031f945 100644
--- a/tools/lli/lli.cpp
+++ b/tools/lli/lli.cpp
@@ -159,11 +159,6 @@ namespace {
clEnumValEnd));
cl::opt<bool>
- EnableJITExceptionHandling("jit-enable-eh",
- cl::desc("Emit exception handling information"),
- cl::init(false));
-
- cl::opt<bool>
GenerateSoftFloatCalls("soft-float",
cl::desc("Generate software floating point library calls"),
cl::init(false));
@@ -259,7 +254,7 @@ void layoutRemoteTargetMemory(RemoteTarget *T, RecordingMemoryManager *JMM) {
EE->mapSectionAddress(const_cast<void*>(Offsets[i].first), Addr);
DEBUG(dbgs() << " Mapping local: " << Offsets[i].first
- << " to remote: " << format("%p", Addr) << "\n");
+ << " to remote: 0x" << format("%llx", Addr) << "\n");
}
@@ -274,12 +269,12 @@ void layoutRemoteTargetMemory(RemoteTarget *T, RecordingMemoryManager *JMM) {
T->loadCode(Addr, Offsets[i].first, Sizes[i]);
DEBUG(dbgs() << " loading code: " << Offsets[i].first
- << " to remote: " << format("%p", Addr) << "\n");
+ << " to remote: 0x" << format("%llx", Addr) << "\n");
} else {
T->loadData(Addr, Offsets[i].first, Sizes[i]);
DEBUG(dbgs() << " loading data: " << Offsets[i].first
- << " to remote: " << format("%p", Addr) << "\n");
+ << " to remote: 0x" << format("%llx", Addr) << "\n");
}
}
@@ -342,14 +337,14 @@ int main(int argc, char **argv, char * const *envp) {
Mod->setTargetTriple(Triple::normalize(TargetTriple));
// Enable MCJIT if desired.
- JITMemoryManager *JMM = 0;
+ RTDyldMemoryManager *RTDyldMM = 0;
if (UseMCJIT && !ForceInterpreter) {
builder.setUseMCJIT(true);
if (RemoteMCJIT)
- JMM = new RecordingMemoryManager();
+ RTDyldMM = new RecordingMemoryManager();
else
- JMM = new SectionMemoryManager();
- builder.setJITMemoryManager(JMM);
+ RTDyldMM = new SectionMemoryManager();
+ builder.setMCJITMemoryManager(RTDyldMM);
} else {
if (RemoteMCJIT) {
errs() << "error: Remote process execution requires -use-mcjit\n";
@@ -381,7 +376,6 @@ int main(int argc, char **argv, char * const *envp) {
// Remote target execution doesn't handle EH or debug registration.
if (!RemoteMCJIT) {
- Options.JITExceptionHandling = EnableJITExceptionHandling;
Options.JITEmitDebugInfo = EmitJitDebugInfo;
Options.JITEmitDebugInfoToDisk = EmitJitDebugInfoToDisk;
}
@@ -467,7 +461,7 @@ int main(int argc, char **argv, char * const *envp) {
int Result;
if (RemoteMCJIT) {
- RecordingMemoryManager *MM = static_cast<RecordingMemoryManager*>(JMM);
+ RecordingMemoryManager *MM = static_cast<RecordingMemoryManager*>(RTDyldMM);
// Everything is prepared now, so lay out our program for the target
// address space, assign the section addresses to resolve any relocations,
// and send it to the target.
@@ -489,8 +483,8 @@ int main(int argc, char **argv, char * const *envp) {
// FIXME: argv and envp handling.
uint64_t Entry = (uint64_t)EE->getPointerToFunction(EntryFn);
- DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at "
- << format("%p", Entry) << "\n");
+ DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"
+ << format("%llx", Entry) << "\n");
if (Target.executeCode(Entry, Result))
errs() << "ERROR: " << Target.getErrorMsg() << "\n";
@@ -501,8 +495,8 @@ int main(int argc, char **argv, char * const *envp) {
// invalidated will be known.
(void)EE->getPointerToFunction(EntryFn);
// Clear instruction cache before code will be executed.
- if (JMM)
- static_cast<SectionMemoryManager*>(JMM)->invalidateInstructionCache();
+ if (RTDyldMM)
+ static_cast<SectionMemoryManager*>(RTDyldMM)->invalidateInstructionCache();
// Run main.
Result = EE->runFunctionAsMain(EntryFn, InputArgv, envp);
diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp
index 7edf5ec..5151d1a 100644
--- a/tools/llvm-config/llvm-config.cpp
+++ b/tools/llvm-config/llvm-config.cpp
@@ -25,6 +25,7 @@
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/PathV1.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
#include <set>
diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp
index 3a2d84a..01a61c6 100644
--- a/tools/llvm-link/llvm-link.cpp
+++ b/tools/llvm-link/llvm-link.cpp
@@ -93,6 +93,7 @@ int main(int argc, char **argv) {
return 1;
}
+ Linker L(Composite.get());
for (unsigned i = BaseArg+1; i < InputFilenames.size(); ++i) {
OwningPtr<Module> M(LoadFile(argv[0], InputFilenames[i], Context));
if (M.get() == 0) {
@@ -102,8 +103,7 @@ int main(int argc, char **argv) {
if (Verbose) errs() << "Linking in '" << InputFilenames[i] << "'\n";
- if (Linker::LinkModules(Composite.get(), M.get(), Linker::DestroySource,
- &ErrorMessage)) {
+ if (L.linkInModule(M.get(), &ErrorMessage)) {
errs() << argv[0] << ": link error in '" << InputFilenames[i]
<< "': " << ErrorMessage << "\n";
return 1;
diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp
index 243899b..289a445 100644
--- a/tools/llvm-mc/llvm-mc.cpp
+++ b/tools/llvm-mc/llvm-mc.cpp
@@ -16,7 +16,6 @@
#include "llvm/ADT/OwningPtr.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrInfo.h"
@@ -27,7 +26,6 @@
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetAsmParser.h"
-#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/FormattedStream.h"
@@ -40,7 +38,6 @@
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
-#include "llvm/Support/system_error.h"
using namespace llvm;
static cl::opt<std::string>
@@ -382,12 +379,12 @@ int main(int argc, char **argv) {
// it later.
SrcMgr.setIncludeDirs(IncludeDirs);
- llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TripleName));
- assert(MAI && "Unable to create target asm info!");
-
llvm::OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
assert(MRI && "Unable to create target register info!");
+ llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName));
+ assert(MAI && "Unable to create target asm info!");
+
// FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
// MCObjectFileInfo needs a MCContext reference in order to initialize itself.
OwningPtr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
diff --git a/tools/llvm-objdump/CMakeLists.txt b/tools/llvm-objdump/CMakeLists.txt
index 0c49d0b..e983ec9 100644
--- a/tools/llvm-objdump/CMakeLists.txt
+++ b/tools/llvm-objdump/CMakeLists.txt
@@ -12,5 +12,4 @@ add_llvm_tool(llvm-objdump
COFFDump.cpp
ELFDump.cpp
MachODump.cpp
- MCFunction.cpp
)
diff --git a/tools/llvm-objdump/COFFDump.cpp b/tools/llvm-objdump/COFFDump.cpp
index 2ada683..7b55007 100644
--- a/tools/llvm-objdump/COFFDump.cpp
+++ b/tools/llvm-objdump/COFFDump.cpp
@@ -178,7 +178,7 @@ static error_code resolveSymbol(const std::vector<RelocationRef> &Rels,
uint64_t Ofs;
if (error_code ec = I->getOffset(Ofs)) return ec;
if (Ofs == Offset) {
- if (error_code ec = I->getSymbol(Sym)) return ec;
+ Sym = *I->getSymbol();
break;
}
}
diff --git a/tools/llvm-objdump/ELFDump.cpp b/tools/llvm-objdump/ELFDump.cpp
index bd15231..ef1f0e9 100644
--- a/tools/llvm-objdump/ELFDump.cpp
+++ b/tools/llvm-objdump/ELFDump.cpp
@@ -63,7 +63,7 @@ void printProgramHeaders(
<< format(Fmt, (uint64_t)pi->p_vaddr)
<< "paddr "
<< format(Fmt, (uint64_t)pi->p_paddr)
- << format("align 2**%u\n", CountTrailingZeros_64(pi->p_align))
+ << format("align 2**%u\n", countTrailingZeros<uint64_t>(pi->p_align))
<< " filesz "
<< format(Fmt, (uint64_t)pi->p_filesz)
<< "memsz "
@@ -79,22 +79,18 @@ void printProgramHeaders(
void llvm::printELFFileHeader(const object::ObjectFile *Obj) {
// Little-endian 32-bit
- if (const ELFObjectFile<ELFType<support::little, 4, false> > *ELFObj =
- dyn_cast<ELFObjectFile<ELFType<support::little, 4, false> > >(Obj))
+ if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj))
printProgramHeaders(ELFObj);
// Big-endian 32-bit
- if (const ELFObjectFile<ELFType<support::big, 4, false> > *ELFObj =
- dyn_cast<ELFObjectFile<ELFType<support::big, 4, false> > >(Obj))
+ if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj))
printProgramHeaders(ELFObj);
// Little-endian 64-bit
- if (const ELFObjectFile<ELFType<support::little, 8, true> > *ELFObj =
- dyn_cast<ELFObjectFile<ELFType<support::little, 8, true> > >(Obj))
+ if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
printProgramHeaders(ELFObj);
// Big-endian 64-bit
- if (const ELFObjectFile<ELFType<support::big, 8, true> > *ELFObj =
- dyn_cast<ELFObjectFile<ELFType<support::big, 8, true> > >(Obj))
+ if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))
printProgramHeaders(ELFObj);
}
diff --git a/tools/llvm-objdump/MCFunction.cpp b/tools/llvm-objdump/MCFunction.cpp
deleted file mode 100644
index 5c67f1b..0000000
--- a/tools/llvm-objdump/MCFunction.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-//===-- MCFunction.cpp ----------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the algorithm to break down a region of machine code
-// into basic blocks and try to reconstruct a CFG from it.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MCFunction.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/MC/MCDisassembler.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCInstPrinter.h"
-#include "llvm/MC/MCInstrAnalysis.h"
-#include "llvm/MC/MCInstrDesc.h"
-#include "llvm/MC/MCInstrInfo.h"
-#include "llvm/Support/MemoryObject.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/system_error.h"
-#include <set>
-using namespace llvm;
-
-MCFunction
-MCFunction::createFunctionFromMC(StringRef Name, const MCDisassembler *DisAsm,
- const MemoryObject &Region, uint64_t Start,
- uint64_t End, const MCInstrAnalysis *Ana,
- raw_ostream &DebugOut,
- SmallVectorImpl<uint64_t> &Calls) {
- std::vector<MCDecodedInst> Instructions;
- std::set<uint64_t> Splits;
- Splits.insert(Start);
- uint64_t Size;
-
- MCFunction f(Name);
-
- {
- DenseSet<uint64_t> VisitedInsts;
- SmallVector<uint64_t, 16> WorkList;
- WorkList.push_back(Start);
- // Disassemble code and gather basic block split points.
- while (!WorkList.empty()) {
- uint64_t Index = WorkList.pop_back_val();
- if (VisitedInsts.find(Index) != VisitedInsts.end())
- continue; // Already visited this location.
-
- for (;Index < End; Index += Size) {
- VisitedInsts.insert(Index);
-
- MCInst Inst;
- if (DisAsm->getInstruction(Inst, Size, Region, Index, DebugOut, nulls())){
- Instructions.push_back(MCDecodedInst(Index, Size, Inst));
- if (Ana->isBranch(Inst)) {
- uint64_t targ = Ana->evaluateBranch(Inst, Index, Size);
- if (targ != -1ULL && targ == Index+Size)
- continue; // Skip nop jumps.
-
- // If we could determine the branch target, make a note to start a
- // new basic block there and add the target to the worklist.
- if (targ != -1ULL) {
- Splits.insert(targ);
- WorkList.push_back(targ);
- WorkList.push_back(Index+Size);
- }
- Splits.insert(Index+Size);
- break;
- } else if (Ana->isReturn(Inst)) {
- // Return instruction. This basic block ends here.
- Splits.insert(Index+Size);
- break;
- } else if (Ana->isCall(Inst)) {
- uint64_t targ = Ana->evaluateBranch(Inst, Index, Size);
- // Add the call to the call list if the destination is known.
- if (targ != -1ULL && targ != Index+Size)
- Calls.push_back(targ);
- }
- } else {
- errs().write_hex(Index) << ": warning: invalid instruction encoding\n";
- if (Size == 0)
- Size = 1; // skip illegible bytes
- }
- }
- }
- }
-
- // Make sure the instruction list is sorted.
- std::sort(Instructions.begin(), Instructions.end());
-
- // Create basic blocks.
- unsigned ii = 0, ie = Instructions.size();
- for (std::set<uint64_t>::iterator spi = Splits.begin(),
- spe = llvm::prior(Splits.end()); spi != spe; ++spi) {
- MCBasicBlock BB;
- uint64_t BlockEnd = *llvm::next(spi);
- // Add instructions to the BB.
- for (; ii != ie; ++ii) {
- if (Instructions[ii].Address < *spi ||
- Instructions[ii].Address >= BlockEnd)
- break;
- BB.addInst(Instructions[ii]);
- }
- f.addBlock(*spi, BB);
- }
-
- std::sort(f.Blocks.begin(), f.Blocks.end());
-
- // Calculate successors of each block.
- for (MCFunction::iterator i = f.begin(), e = f.end(); i != e; ++i) {
- MCBasicBlock &BB = const_cast<MCBasicBlock&>(i->second);
- if (BB.getInsts().empty()) continue;
- const MCDecodedInst &Inst = BB.getInsts().back();
-
- if (Ana->isBranch(Inst.Inst)) {
- uint64_t targ = Ana->evaluateBranch(Inst.Inst, Inst.Address, Inst.Size);
- if (targ == -1ULL) {
- // Indirect branch. Bail and add all blocks of the function as a
- // successor.
- for (MCFunction::iterator i = f.begin(), e = f.end(); i != e; ++i)
- BB.addSucc(i->first);
- } else if (targ != Inst.Address+Inst.Size)
- BB.addSucc(targ);
- // Conditional branches can also fall through to the next block.
- if (Ana->isConditionalBranch(Inst.Inst) && llvm::next(i) != e)
- BB.addSucc(llvm::next(i)->first);
- } else {
- // No branch. Fall through to the next block.
- if (!Ana->isReturn(Inst.Inst) && llvm::next(i) != e)
- BB.addSucc(llvm::next(i)->first);
- }
- }
-
- return f;
-}
diff --git a/tools/llvm-objdump/MCFunction.h b/tools/llvm-objdump/MCFunction.h
deleted file mode 100644
index 6d3a548..0000000
--- a/tools/llvm-objdump/MCFunction.h
+++ /dev/null
@@ -1,100 +0,0 @@
-//===-- MCFunction.h ------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the data structures to hold a CFG reconstructed from
-// machine code.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_OBJECTDUMP_MCFUNCTION_H
-#define LLVM_OBJECTDUMP_MCFUNCTION_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/MC/MCInst.h"
-#include <map>
-
-namespace llvm {
-
-class MCDisassembler;
-class MCInstrAnalysis;
-class MemoryObject;
-class raw_ostream;
-
-/// MCDecodedInst - Small container to hold an MCInst and associated info like
-/// address and size.
-struct MCDecodedInst {
- uint64_t Address;
- uint64_t Size;
- MCInst Inst;
-
- MCDecodedInst() {}
- MCDecodedInst(uint64_t Address, uint64_t Size, MCInst Inst)
- : Address(Address), Size(Size), Inst(Inst) {}
-
- bool operator<(const MCDecodedInst &RHS) const {
- return Address < RHS.Address;
- }
-};
-
-/// MCBasicBlock - Consists of multiple MCDecodedInsts and a list of successing
-/// MCBasicBlocks.
-class MCBasicBlock {
- std::vector<MCDecodedInst> Insts;
- typedef DenseSet<uint64_t> SetTy;
- SetTy Succs;
-public:
- ArrayRef<MCDecodedInst> getInsts() const { return Insts; }
-
- typedef SetTy::const_iterator succ_iterator;
- succ_iterator succ_begin() const { return Succs.begin(); }
- succ_iterator succ_end() const { return Succs.end(); }
-
- bool contains(uint64_t Addr) const { return Succs.count(Addr); }
-
- void addInst(const MCDecodedInst &Inst) { Insts.push_back(Inst); }
- void addSucc(uint64_t Addr) { Succs.insert(Addr); }
-
- bool operator<(const MCBasicBlock &RHS) const {
- return Insts.size() < RHS.Insts.size();
- }
-};
-
-/// MCFunction - Represents a named function in machine code, containing
-/// multiple MCBasicBlocks.
-class MCFunction {
- const StringRef Name;
- // Keep BBs sorted by address.
- typedef std::vector<std::pair<uint64_t, MCBasicBlock> > MapTy;
- MapTy Blocks;
-public:
- MCFunction(StringRef Name) : Name(Name) {}
-
- // Create an MCFunction from a region of binary machine code.
- static MCFunction
- createFunctionFromMC(StringRef Name, const MCDisassembler *DisAsm,
- const MemoryObject &Region, uint64_t Start, uint64_t End,
- const MCInstrAnalysis *Ana, raw_ostream &DebugOut,
- SmallVectorImpl<uint64_t> &Calls);
-
- typedef MapTy::const_iterator iterator;
- iterator begin() const { return Blocks.begin(); }
- iterator end() const { return Blocks.end(); }
-
- StringRef getName() const { return Name; }
-
- MCBasicBlock &addBlock(uint64_t Address, const MCBasicBlock &BB) {
- Blocks.push_back(std::make_pair(Address, BB));
- return Blocks.back().second;
- }
-};
-
-}
-
-#endif
diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp
index 6797e2d..27e1623 100644
--- a/tools/llvm-objdump/MachODump.cpp
+++ b/tools/llvm-objdump/MachODump.cpp
@@ -12,9 +12,9 @@
//===----------------------------------------------------------------------===//
#include "llvm-objdump.h"
-#include "MCFunction.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -44,10 +44,6 @@ using namespace llvm;
using namespace object;
static cl::opt<bool>
- CFG("cfg", cl::desc("Create a CFG for every symbol in the object file and"
- " write it to a graphviz file (MachO-only)"));
-
-static cl::opt<bool>
UseDbg("g", cl::desc("Print line information from debug info if available"));
static cl::opt<std::string>
@@ -91,97 +87,64 @@ struct SymbolSorter {
}
};
-// Print additional information about an address, if available.
-static void DumpAddress(uint64_t Address, ArrayRef<SectionRef> Sections,
- const MachOObjectFile *MachOObj, raw_ostream &OS) {
- for (unsigned i = 0; i != Sections.size(); ++i) {
- uint64_t SectAddr = 0, SectSize = 0;
- Sections[i].getAddress(SectAddr);
- Sections[i].getSize(SectSize);
- uint64_t addr = SectAddr;
- if (SectAddr <= Address &&
- SectAddr + SectSize > Address) {
- StringRef bytes, name;
- Sections[i].getContents(bytes);
- Sections[i].getName(name);
- // Print constant strings.
- if (!name.compare("__cstring"))
- OS << '"' << bytes.substr(addr, bytes.find('\0', addr)) << '"';
- // Print constant CFStrings.
- if (!name.compare("__cfstring"))
- OS << "@\"" << bytes.substr(addr, bytes.find('\0', addr)) << '"';
- }
- }
-}
+// Types for the storted data in code table that is built before disassembly
+// and the predicate function to sort them.
+typedef std::pair<uint64_t, DiceRef> DiceTableEntry;
+typedef std::vector<DiceTableEntry> DiceTable;
+typedef DiceTable::iterator dice_table_iterator;
-typedef std::map<uint64_t, MCFunction*> FunctionMapTy;
-typedef SmallVector<MCFunction, 16> FunctionListTy;
-static void createMCFunctionAndSaveCalls(StringRef Name,
- const MCDisassembler *DisAsm,
- MemoryObject &Object, uint64_t Start,
- uint64_t End,
- MCInstrAnalysis *InstrAnalysis,
- uint64_t Address,
- raw_ostream &DebugOut,
- FunctionMapTy &FunctionMap,
- FunctionListTy &Functions) {
- SmallVector<uint64_t, 16> Calls;
- MCFunction f =
- MCFunction::createFunctionFromMC(Name, DisAsm, Object, Start, End,
- InstrAnalysis, DebugOut, Calls);
- Functions.push_back(f);
- FunctionMap[Address] = &Functions.back();
-
- // Add the gathered callees to the map.
- for (unsigned i = 0, e = Calls.size(); i != e; ++i)
- FunctionMap.insert(std::make_pair(Calls[i], (MCFunction*)0));
+static bool
+compareDiceTableEntries(const DiceTableEntry i,
+ const DiceTableEntry j) {
+ return i.first == j.first;
}
-// Write a graphviz file for the CFG inside an MCFunction.
-static void emitDOTFile(const char *FileName, const MCFunction &f,
- MCInstPrinter *IP) {
- // Start a new dot file.
- std::string Error;
- raw_fd_ostream Out(FileName, Error);
- if (!Error.empty()) {
- errs() << "llvm-objdump: warning: " << Error << '\n';
- return;
- }
-
- Out << "digraph " << f.getName() << " {\n";
- Out << "graph [ rankdir = \"LR\" ];\n";
- for (MCFunction::iterator i = f.begin(), e = f.end(); i != e; ++i) {
- bool hasPreds = false;
- // Only print blocks that have predecessors.
- // FIXME: Slow.
- for (MCFunction::iterator pi = f.begin(), pe = f.end(); pi != pe;
- ++pi)
- if (pi->second.contains(i->first)) {
- hasPreds = true;
- break;
- }
-
- if (!hasPreds && i != f.begin())
- continue;
-
- Out << '"' << i->first << "\" [ label=\"<a>";
- // Print instructions.
- for (unsigned ii = 0, ie = i->second.getInsts().size(); ii != ie;
- ++ii) {
- // Escape special chars and print the instruction in mnemonic form.
- std::string Str;
- raw_string_ostream OS(Str);
- IP->printInst(&i->second.getInsts()[ii].Inst, OS, "");
- Out << DOT::EscapeString(OS.str()) << '|';
+static void DumpDataInCode(const char *bytes, uint64_t Size,
+ unsigned short Kind) {
+ uint64_t Value;
+
+ switch (Kind) {
+ case macho::Data:
+ switch (Size) {
+ case 4:
+ Value = bytes[3] << 24 |
+ bytes[2] << 16 |
+ bytes[1] << 8 |
+ bytes[0];
+ outs() << "\t.long " << Value;
+ break;
+ case 2:
+ Value = bytes[1] << 8 |
+ bytes[0];
+ outs() << "\t.short " << Value;
+ break;
+ case 1:
+ Value = bytes[0];
+ outs() << "\t.byte " << Value;
+ break;
}
- Out << "<o>\" shape=\"record\" ];\n";
-
- // Add edges.
- for (MCBasicBlock::succ_iterator si = i->second.succ_begin(),
- se = i->second.succ_end(); si != se; ++si)
- Out << i->first << ":o -> " << *si <<":a\n";
+ outs() << "\t@ KIND_DATA\n";
+ break;
+ case macho::JumpTable8:
+ Value = bytes[0];
+ outs() << "\t.byte " << Value << "\t@ KIND_JUMP_TABLE8";
+ break;
+ case macho::JumpTable16:
+ Value = bytes[1] << 8 |
+ bytes[0];
+ outs() << "\t.short " << Value << "\t@ KIND_JUMP_TABLE16";
+ break;
+ case macho::JumpTable32:
+ Value = bytes[3] << 24 |
+ bytes[2] << 16 |
+ bytes[1] << 8 |
+ bytes[0];
+ outs() << "\t.long " << Value << "\t@ KIND_JUMP_TABLE32";
+ break;
+ default:
+ outs() << "\t@ data in code kind = " << Kind << "\n";
+ break;
}
- Out << "}\n";
}
static void
@@ -189,7 +152,8 @@ getSectionsAndSymbols(const macho::Header Header,
MachOObjectFile *MachOObj,
std::vector<SectionRef> &Sections,
std::vector<SymbolRef> &Symbols,
- SmallVectorImpl<uint64_t> &FoundFns) {
+ SmallVectorImpl<uint64_t> &FoundFns,
+ uint64_t &BaseSegmentAddress) {
error_code ec;
for (symbol_iterator SI = MachOObj->begin_symbols(),
SE = MachOObj->end_symbols(); SI != SE; SI.increment(ec))
@@ -205,6 +169,7 @@ getSectionsAndSymbols(const macho::Header Header,
MachOObjectFile::LoadCommandInfo Command =
MachOObj->getFirstLoadCommandInfo();
+ bool BaseSegmentAddressSet = false;
for (unsigned i = 0; ; ++i) {
if (Command.C.Type == macho::LCT_FunctionStarts) {
// We found a function starts segment, parse the addresses for later
@@ -214,6 +179,15 @@ getSectionsAndSymbols(const macho::Header Header,
MachOObj->ReadULEB128s(LLC.DataOffset, FoundFns);
}
+ else if (Command.C.Type == macho::LCT_Segment) {
+ macho::SegmentLoadCommand SLC =
+ MachOObj->getSegmentLoadCommand(Command);
+ StringRef SegName = SLC.Name;
+ if(!BaseSegmentAddressSet && SegName != "__PAGEZERO") {
+ BaseSegmentAddressSet = true;
+ BaseSegmentAddress = SLC.VMAddress;
+ }
+ }
if (i == Header.NumLoadCommands - 1)
break;
@@ -251,11 +225,12 @@ static void DisassembleInputMachO2(StringRef Filename,
InstrAnalysis(TheTarget->createMCInstrAnalysis(InstrInfo.get()));
// Set up disassembler.
- OwningPtr<const MCAsmInfo> AsmInfo(TheTarget->createMCAsmInfo(TripleName));
+ OwningPtr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
+ OwningPtr<const MCAsmInfo> AsmInfo(
+ TheTarget->createMCAsmInfo(*MRI, TripleName));
OwningPtr<const MCSubtargetInfo>
STI(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI));
- OwningPtr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
OwningPtr<MCInstPrinter>
IP(TheTarget->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *InstrInfo,
@@ -271,17 +246,41 @@ static void DisassembleInputMachO2(StringRef Filename,
macho::Header Header = MachOOF->getHeader();
+ // FIXME: FoundFns isn't used anymore. Using symbols/LC_FUNCTION_STARTS to
+ // determine function locations will eventually go in MCObjectDisassembler.
+ // FIXME: Using the -cfg command line option, this code used to be able to
+ // annotate relocations with the referenced symbol's name, and if this was
+ // inside a __[cf]string section, the data it points to. This is now replaced
+ // by the upcoming MCSymbolizer, which needs the appropriate setup done above.
std::vector<SectionRef> Sections;
std::vector<SymbolRef> Symbols;
SmallVector<uint64_t, 8> FoundFns;
+ uint64_t BaseSegmentAddress;
- getSectionsAndSymbols(Header, MachOOF, Sections, Symbols, FoundFns);
+ getSectionsAndSymbols(Header, MachOOF, Sections, Symbols, FoundFns,
+ BaseSegmentAddress);
// Make a copy of the unsorted symbol list. FIXME: duplication
std::vector<SymbolRef> UnsortedSymbols(Symbols);
// Sort the symbols by address, just in case they didn't come in that way.
std::sort(Symbols.begin(), Symbols.end(), SymbolSorter());
+ // Build a data in code table that is sorted on by the address of each entry.
+ uint64_t BaseAddress = 0;
+ if (Header.FileType == macho::HFT_Object)
+ Sections[0].getAddress(BaseAddress);
+ else
+ BaseAddress = BaseSegmentAddress;
+ DiceTable Dices;
+ error_code ec;
+ for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices();
+ DI != DE; DI.increment(ec)){
+ uint32_t Offset;
+ DI->getOffset(Offset);
+ Dices.push_back(std::make_pair(BaseAddress + Offset, *DI));
+ }
+ array_pod_sort(Dices.begin(), Dices.end());
+
#ifndef NDEBUG
raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
#else
@@ -307,31 +306,24 @@ static void DisassembleInputMachO2(StringRef Filename,
diContext.reset(DIContext::getDWARFContext(DbgObj));
}
- FunctionMapTy FunctionMap;
- FunctionListTy Functions;
-
for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
+
+ bool SectIsText = false;
+ Sections[SectIdx].isText(SectIsText);
+ if (SectIsText == false)
+ continue;
+
StringRef SectName;
if (Sections[SectIdx].getName(SectName) ||
SectName != "__text")
continue; // Skip non-text sections
DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl();
+
StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR);
if (SegmentName != "__TEXT")
continue;
- // Insert the functions from the function starts segment into our map.
- uint64_t VMAddr;
- Sections[SectIdx].getAddress(VMAddr);
- for (unsigned i = 0, e = FoundFns.size(); i != e; ++i) {
- StringRef SectBegin;
- Sections[SectIdx].getContents(SectBegin);
- uint64_t Offset = (uint64_t)SectBegin.data();
- FunctionMap.insert(std::make_pair(VMAddr + FoundFns[i]-Offset,
- (MCFunction*)0));
- }
-
StringRef Bytes;
Sections[SectIdx].getContents(Bytes);
StringRefMemoryObject memoryObject(Bytes);
@@ -347,10 +339,9 @@ static void DisassembleInputMachO2(StringRef Filename,
Sections[SectIdx].getAddress(SectionAddress);
RelocOffset -= SectionAddress;
- SymbolRef RelocSym;
- RI->getSymbol(RelocSym);
+ symbol_iterator RelocSym = RI->getSymbol();
- Relocs.push_back(std::make_pair(RelocOffset, RelocSym));
+ Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
}
array_pod_sort(Relocs.begin(), Relocs.end());
@@ -402,52 +393,56 @@ static void DisassembleInputMachO2(StringRef Filename,
symbolTableWorked = true;
- if (!CFG) {
- // Normal disassembly, print addresses, bytes and mnemonic form.
- StringRef SymName;
- Symbols[SymIdx].getName(SymName);
-
- outs() << SymName << ":\n";
- DILineInfo lastLine;
- for (uint64_t Index = Start; Index < End; Index += Size) {
- MCInst Inst;
-
- if (DisAsm->getInstruction(Inst, Size, memoryObject, Index,
- DebugOut, nulls())) {
- uint64_t SectAddress = 0;
- Sections[SectIdx].getAddress(SectAddress);
- outs() << format("%8" PRIx64 ":\t", SectAddress + Index);
-
- DumpBytes(StringRef(Bytes.data() + Index, Size));
- IP->printInst(&Inst, outs(), "");
-
- // Print debug info.
- if (diContext) {
- DILineInfo dli =
- diContext->getLineInfoForAddress(SectAddress + Index);
- // Print valid line info if it changed.
- if (dli != lastLine && dli.getLine() != 0)
- outs() << "\t## " << dli.getFileName() << ':'
- << dli.getLine() << ':' << dli.getColumn();
- lastLine = dli;
- }
- outs() << "\n";
- } else {
- errs() << "llvm-objdump: warning: invalid instruction encoding\n";
- if (Size == 0)
- Size = 1; // skip illegible bytes
+ outs() << SymName << ":\n";
+ DILineInfo lastLine;
+ for (uint64_t Index = Start; Index < End; Index += Size) {
+ MCInst Inst;
+
+ uint64_t SectAddress = 0;
+ Sections[SectIdx].getAddress(SectAddress);
+ outs() << format("%8" PRIx64 ":\t", SectAddress + Index);
+
+ // Check the data in code table here to see if this is data not an
+ // instruction to be disassembled.
+ DiceTable Dice;
+ Dice.push_back(std::make_pair(SectAddress + Index, DiceRef()));
+ dice_table_iterator DTI = std::search(Dices.begin(), Dices.end(),
+ Dice.begin(), Dice.end(),
+ compareDiceTableEntries);
+ if (DTI != Dices.end()){
+ uint16_t Length;
+ DTI->second.getLength(Length);
+ DumpBytes(StringRef(Bytes.data() + Index, Length));
+ uint16_t Kind;
+ DTI->second.getKind(Kind);
+ DumpDataInCode(Bytes.data() + Index, Length, Kind);
+ continue;
+ }
+
+ if (DisAsm->getInstruction(Inst, Size, memoryObject, Index,
+ DebugOut, nulls())) {
+ DumpBytes(StringRef(Bytes.data() + Index, Size));
+ IP->printInst(&Inst, outs(), "");
+
+ // Print debug info.
+ if (diContext) {
+ DILineInfo dli =
+ diContext->getLineInfoForAddress(SectAddress + Index);
+ // Print valid line info if it changed.
+ if (dli != lastLine && dli.getLine() != 0)
+ outs() << "\t## " << dli.getFileName() << ':'
+ << dli.getLine() << ':' << dli.getColumn();
+ lastLine = dli;
}
+ outs() << "\n";
+ } else {
+ errs() << "llvm-objdump: warning: invalid instruction encoding\n";
+ if (Size == 0)
+ Size = 1; // skip illegible bytes
}
- } else {
- // Create CFG and use it for disassembly.
- StringRef SymName;
- Symbols[SymIdx].getName(SymName);
- createMCFunctionAndSaveCalls(
- SymName, DisAsm.get(), memoryObject, Start, End,
- InstrAnalysis.get(), Start, DebugOut, FunctionMap, Functions);
}
}
- if (!CFG && !symbolTableWorked) {
+ if (!symbolTableWorked) {
// Reading the symbol table didn't work, disassemble the whole section.
uint64_t SectAddress;
Sections[SectIdx].getAddress(SectAddress);
@@ -470,142 +465,5 @@ static void DisassembleInputMachO2(StringRef Filename,
}
}
}
-
- if (CFG) {
- if (!symbolTableWorked) {
- // Reading the symbol table didn't work, create a big __TEXT symbol.
- uint64_t SectSize = 0, SectAddress = 0;
- Sections[SectIdx].getSize(SectSize);
- Sections[SectIdx].getAddress(SectAddress);
- createMCFunctionAndSaveCalls("__TEXT", DisAsm.get(), memoryObject,
- 0, SectSize,
- InstrAnalysis.get(),
- SectAddress, DebugOut,
- FunctionMap, Functions);
- }
- for (std::map<uint64_t, MCFunction*>::iterator mi = FunctionMap.begin(),
- me = FunctionMap.end(); mi != me; ++mi)
- if (mi->second == 0) {
- // Create functions for the remaining callees we have gathered,
- // but we didn't find a name for them.
- uint64_t SectSize = 0;
- Sections[SectIdx].getSize(SectSize);
-
- SmallVector<uint64_t, 16> Calls;
- MCFunction f =
- MCFunction::createFunctionFromMC("unknown", DisAsm.get(),
- memoryObject, mi->first,
- SectSize,
- InstrAnalysis.get(), DebugOut,
- Calls);
- Functions.push_back(f);
- mi->second = &Functions.back();
- for (unsigned i = 0, e = Calls.size(); i != e; ++i) {
- std::pair<uint64_t, MCFunction*> p(Calls[i], (MCFunction*)0);
- if (FunctionMap.insert(p).second)
- mi = FunctionMap.begin();
- }
- }
-
- DenseSet<uint64_t> PrintedBlocks;
- for (unsigned ffi = 0, ffe = Functions.size(); ffi != ffe; ++ffi) {
- MCFunction &f = Functions[ffi];
- for (MCFunction::iterator fi = f.begin(), fe = f.end(); fi != fe; ++fi){
- if (!PrintedBlocks.insert(fi->first).second)
- continue; // We already printed this block.
-
- // We assume a block has predecessors when it's the first block after
- // a symbol.
- bool hasPreds = FunctionMap.find(fi->first) != FunctionMap.end();
-
- // See if this block has predecessors.
- // FIXME: Slow.
- for (MCFunction::iterator pi = f.begin(), pe = f.end(); pi != pe;
- ++pi)
- if (pi->second.contains(fi->first)) {
- hasPreds = true;
- break;
- }
-
- uint64_t SectSize = 0, SectAddress;
- Sections[SectIdx].getSize(SectSize);
- Sections[SectIdx].getAddress(SectAddress);
-
- // No predecessors, this is a data block. Print as .byte directives.
- if (!hasPreds) {
- uint64_t End = llvm::next(fi) == fe ? SectSize :
- llvm::next(fi)->first;
- outs() << "# " << End-fi->first << " bytes of data:\n";
- for (unsigned pos = fi->first; pos != End; ++pos) {
- outs() << format("%8x:\t", SectAddress + pos);
- DumpBytes(StringRef(Bytes.data() + pos, 1));
- outs() << format("\t.byte 0x%02x\n", (uint8_t)Bytes[pos]);
- }
- continue;
- }
-
- if (fi->second.contains(fi->first)) // Print a header for simple loops
- outs() << "# Loop begin:\n";
-
- DILineInfo lastLine;
- // Walk over the instructions and print them.
- for (unsigned ii = 0, ie = fi->second.getInsts().size(); ii != ie;
- ++ii) {
- const MCDecodedInst &Inst = fi->second.getInsts()[ii];
-
- // If there's a symbol at this address, print its name.
- if (FunctionMap.find(SectAddress + Inst.Address) !=
- FunctionMap.end())
- outs() << FunctionMap[SectAddress + Inst.Address]-> getName()
- << ":\n";
-
- outs() << format("%8" PRIx64 ":\t", SectAddress + Inst.Address);
- DumpBytes(StringRef(Bytes.data() + Inst.Address, Inst.Size));
-
- if (fi->second.contains(fi->first)) // Indent simple loops.
- outs() << '\t';
-
- IP->printInst(&Inst.Inst, outs(), "");
-
- // Look for relocations inside this instructions, if there is one
- // print its target and additional information if available.
- for (unsigned j = 0; j != Relocs.size(); ++j)
- if (Relocs[j].first >= SectAddress + Inst.Address &&
- Relocs[j].first < SectAddress + Inst.Address + Inst.Size) {
- StringRef SymName;
- uint64_t Addr;
- Relocs[j].second.getAddress(Addr);
- Relocs[j].second.getName(SymName);
-
- outs() << "\t# " << SymName << ' ';
- DumpAddress(Addr, Sections, MachOOF, outs());
- }
-
- // If this instructions contains an address, see if we can evaluate
- // it and print additional information.
- uint64_t targ = InstrAnalysis->evaluateBranch(Inst.Inst,
- Inst.Address,
- Inst.Size);
- if (targ != -1ULL)
- DumpAddress(targ, Sections, MachOOF, outs());
-
- // Print debug info.
- if (diContext) {
- DILineInfo dli =
- diContext->getLineInfoForAddress(SectAddress + Inst.Address);
- // Print valid line info if it changed.
- if (dli != lastLine && dli.getLine() != 0)
- outs() << "\t## " << dli.getFileName() << ':'
- << dli.getLine() << ':' << dli.getColumn();
- lastLine = dli;
- }
-
- outs() << '\n';
- }
- }
-
- emitDOTFile((f.getName().str() + ".dot").c_str(), f, IP.get());
- }
- }
}
}
diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp
index 247b90f..8049dac 100644
--- a/tools/llvm-objdump/llvm-objdump.cpp
+++ b/tools/llvm-objdump/llvm-objdump.cpp
@@ -17,17 +17,25 @@
//===----------------------------------------------------------------------===//
#include "llvm-objdump.h"
-#include "MCFunction.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCAtom.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCFunction.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCModule.h"
+#include "llvm/MC/MCObjectDisassembler.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCObjectSymbolizer.h"
#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCRelocationInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
@@ -123,6 +131,14 @@ static cl::alias
PrivateHeadersShort("p", cl::desc("Alias for --private-headers"),
cl::aliasopt(PrivateHeaders));
+static cl::opt<bool>
+Symbolize("symbolize", cl::desc("When disassembling instructions, "
+ "try to symbolize operands."));
+
+static cl::opt<bool>
+CFG("cfg", cl::desc("Create a CFG for every function found in the object"
+ " and write it to a graphviz file"));
+
static StringRef ToolName;
bool llvm::error(error_code ec) {
@@ -137,8 +153,13 @@ static const Target *getTarget(const ObjectFile *Obj = NULL) {
// Figure out the target triple.
llvm::Triple TheTriple("unknown-unknown-unknown");
if (TripleName.empty()) {
- if (Obj)
+ if (Obj) {
TheTriple.setArch(Triple::ArchType(Obj->getArch()));
+ // TheTriple defaults to ELF, and COFF doesn't have an environment:
+ // the best we can do here is indicate that it is mach-o.
+ if (Obj->isMachO())
+ TheTriple.setEnvironment(Triple::MachO);
+ }
} else
TheTriple.setTriple(Triple::normalize(TripleName));
@@ -156,7 +177,51 @@ static const Target *getTarget(const ObjectFile *Obj = NULL) {
return TheTarget;
}
-void llvm::StringRefMemoryObject::anchor() { }
+// Write a graphviz file for the CFG inside an MCFunction.
+static void emitDOTFile(const char *FileName, const MCFunction &f,
+ MCInstPrinter *IP) {
+ // Start a new dot file.
+ std::string Error;
+ raw_fd_ostream Out(FileName, Error);
+ if (!Error.empty()) {
+ errs() << "llvm-objdump: warning: " << Error << '\n';
+ return;
+ }
+
+ Out << "digraph \"" << f.getName() << "\" {\n";
+ Out << "graph [ rankdir = \"LR\" ];\n";
+ for (MCFunction::const_iterator i = f.begin(), e = f.end(); i != e; ++i) {
+ // Only print blocks that have predecessors.
+ bool hasPreds = (*i)->pred_begin() != (*i)->pred_end();
+
+ if (!hasPreds && i != f.begin())
+ continue;
+
+ Out << '"' << (*i)->getInsts()->getBeginAddr() << "\" [ label=\"<a>";
+ // Print instructions.
+ for (unsigned ii = 0, ie = (*i)->getInsts()->size(); ii != ie;
+ ++ii) {
+ if (ii != 0) // Not the first line, start a new row.
+ Out << '|';
+ if (ii + 1 == ie) // Last line, add an end id.
+ Out << "<o>";
+
+ // Escape special chars and print the instruction in mnemonic form.
+ std::string Str;
+ raw_string_ostream OS(Str);
+ IP->printInst(&(*i)->getInsts()->at(ii).Inst, OS, "");
+ Out << DOT::EscapeString(OS.str());
+ }
+ Out << "\" shape=\"record\" ];\n";
+
+ // Add edges.
+ for (MCBasicBlock::succ_const_iterator si = (*i)->succ_begin(),
+ se = (*i)->succ_end(); si != se; ++si)
+ Out << (*i)->getInsts()->getBeginAddr() << ":o -> "
+ << (*si)->getInsts()->getBeginAddr() << ":a\n";
+ }
+ Out << "}\n";
+}
void llvm::DumpBytes(StringRef bytes) {
static const char hex_rep[] = "0123456789abcdef";
@@ -207,6 +272,96 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
FeaturesStr = Features.getString();
}
+ OwningPtr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
+ if (!MRI) {
+ errs() << "error: no register info for target " << TripleName << "\n";
+ return;
+ }
+
+ // Set up disassembler.
+ OwningPtr<const MCAsmInfo> AsmInfo(
+ TheTarget->createMCAsmInfo(*MRI, TripleName));
+ if (!AsmInfo) {
+ errs() << "error: no assembly info for target " << TripleName << "\n";
+ return;
+ }
+
+ OwningPtr<const MCSubtargetInfo> STI(
+ TheTarget->createMCSubtargetInfo(TripleName, "", FeaturesStr));
+ if (!STI) {
+ errs() << "error: no subtarget info for target " << TripleName << "\n";
+ return;
+ }
+
+ OwningPtr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
+ if (!MII) {
+ errs() << "error: no instruction info for target " << TripleName << "\n";
+ return;
+ }
+
+ OwningPtr<MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI));
+ if (!DisAsm) {
+ errs() << "error: no disassembler for target " << TripleName << "\n";
+ return;
+ }
+
+ OwningPtr<const MCObjectFileInfo> MOFI;
+ OwningPtr<MCContext> Ctx;
+
+ if (Symbolize) {
+ MOFI.reset(new MCObjectFileInfo);
+ Ctx.reset(new MCContext(*AsmInfo.get(), *MRI.get(), MOFI.get()));
+ OwningPtr<MCRelocationInfo> RelInfo(
+ TheTarget->createMCRelocationInfo(TripleName, *Ctx.get()));
+ if (RelInfo) {
+ OwningPtr<MCSymbolizer> Symzer(
+ MCObjectSymbolizer::createObjectSymbolizer(*Ctx.get(), RelInfo, Obj));
+ if (Symzer)
+ DisAsm->setSymbolizer(Symzer);
+ }
+ }
+
+ OwningPtr<const MCInstrAnalysis>
+ MIA(TheTarget->createMCInstrAnalysis(MII.get()));
+
+ int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
+ OwningPtr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
+ AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI));
+ if (!IP) {
+ errs() << "error: no instruction printer for target " << TripleName
+ << '\n';
+ return;
+ }
+
+ if (CFG) {
+ OwningPtr<MCObjectDisassembler> OD(
+ new MCObjectDisassembler(*Obj, *DisAsm, *MIA));
+ OwningPtr<MCModule> Mod(OD->buildModule(/* withCFG */ true));
+ for (MCModule::const_atom_iterator AI = Mod->atom_begin(),
+ AE = Mod->atom_end();
+ AI != AE; ++AI) {
+ outs() << "Atom " << (*AI)->getName() << ": \n";
+ if (const MCTextAtom *TA = dyn_cast<MCTextAtom>(*AI)) {
+ for (MCTextAtom::const_iterator II = TA->begin(), IE = TA->end();
+ II != IE;
+ ++II) {
+ IP->printInst(&II->Inst, outs(), "");
+ outs() << "\n";
+ }
+ }
+ }
+ for (MCModule::const_func_iterator FI = Mod->func_begin(),
+ FE = Mod->func_end();
+ FI != FE; ++FI) {
+ static int filenum = 0;
+ emitDOTFile((Twine((*FI)->getName()) + "_" +
+ utostr(filenum) + ".dot").str().c_str(),
+ **FI, IP.get());
+ ++filenum;
+ }
+ }
+
+
error_code ec;
for (section_iterator i = Obj->begin_sections(),
e = Obj->end_sections();
@@ -272,53 +427,13 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
if (Symbols.empty())
Symbols.push_back(std::make_pair(0, name));
- // Set up disassembler.
- OwningPtr<const MCAsmInfo> AsmInfo(TheTarget->createMCAsmInfo(TripleName));
-
- if (!AsmInfo) {
- errs() << "error: no assembly info for target " << TripleName << "\n";
- return;
- }
-
- OwningPtr<const MCSubtargetInfo> STI(
- TheTarget->createMCSubtargetInfo(TripleName, "", FeaturesStr));
-
- if (!STI) {
- errs() << "error: no subtarget info for target " << TripleName << "\n";
- return;
- }
-
- OwningPtr<const MCDisassembler> DisAsm(
- TheTarget->createMCDisassembler(*STI));
- if (!DisAsm) {
- errs() << "error: no disassembler for target " << TripleName << "\n";
- return;
- }
-
- OwningPtr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
- if (!MRI) {
- errs() << "error: no register info for target " << TripleName << "\n";
- return;
- }
- OwningPtr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
- if (!MII) {
- errs() << "error: no instruction info for target " << TripleName << "\n";
- return;
- }
-
- int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
- OwningPtr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
- AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI));
- if (!IP) {
- errs() << "error: no instruction printer for target " << TripleName
- << '\n';
- return;
- }
+ SmallString<40> Comments;
+ raw_svector_ostream CommentStream(Comments);
StringRef Bytes;
if (error(i->getContents(Bytes))) break;
- StringRefMemoryObject memoryObject(Bytes);
+ StringRefMemoryObject memoryObject(Bytes, SectionAddr);
uint64_t Size;
uint64_t Index;
uint64_t SectSize;
@@ -352,14 +467,17 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
for (Index = Start; Index < End; Index += Size) {
MCInst Inst;
- if (DisAsm->getInstruction(Inst, Size, memoryObject, Index,
- DebugOut, nulls())) {
+ if (DisAsm->getInstruction(Inst, Size, memoryObject,
+ SectionAddr + Index,
+ DebugOut, CommentStream)) {
outs() << format("%8" PRIx64 ":", SectionAddr + Index);
if (!NoShowRawInsn) {
outs() << "\t";
DumpBytes(StringRef(Bytes.data() + Index, Size));
}
IP->printInst(&Inst, outs(), "");
+ outs() << CommentStream.str();
+ Comments.clear();
outs() << "\n";
} else {
errs() << ToolName << ": warning: invalid instruction encoding\n";
diff --git a/tools/llvm-objdump/llvm-objdump.h b/tools/llvm-objdump/llvm-objdump.h
index ca7bced..87f19ba 100644
--- a/tools/llvm-objdump/llvm-objdump.h
+++ b/tools/llvm-objdump/llvm-objdump.h
@@ -13,7 +13,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/StringRefMemoryObject.h"
namespace llvm {
@@ -35,23 +35,6 @@ void DisassembleInputMachO(StringRef Filename);
void printCOFFUnwindInfo(const object::COFFObjectFile* o);
void printELFFileHeader(const object::ObjectFile *o);
-class StringRefMemoryObject : public MemoryObject {
- virtual void anchor();
- StringRef Bytes;
-public:
- StringRefMemoryObject(StringRef bytes) : Bytes(bytes) {}
-
- uint64_t getBase() const { return 0; }
- uint64_t getExtent() const { return Bytes.size(); }
-
- int readByte(uint64_t Addr, uint8_t *Byte) const {
- if (Addr >= getExtent())
- return -1;
- *Byte = Bytes[Addr];
- return 0;
- }
-};
-
}
#endif
diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp
index 94aafa7..3cbb9b3 100644
--- a/tools/llvm-readobj/COFFDumper.cpp
+++ b/tools/llvm-readobj/COFFDumper.cpp
@@ -201,8 +201,7 @@ static error_code resolveSymbol(const std::vector<RelocationRef> &Rels,
return EC;
if (Ofs == Offset) {
- if (error_code EC = RelI->getSymbol(Sym))
- return EC;
+ Sym = *RelI->getSymbol();
return readobj_error::success;
}
}
@@ -670,14 +669,13 @@ void COFFDumper::printRelocation(section_iterator SecI,
uint64_t Offset;
uint64_t RelocType;
SmallString<32> RelocName;
- SymbolRef Symbol;
StringRef SymbolName;
StringRef Contents;
if (error(RelI->getOffset(Offset))) return;
if (error(RelI->getType(RelocType))) return;
if (error(RelI->getTypeName(RelocName))) return;
- if (error(RelI->getSymbol(Symbol))) return;
- if (error(Symbol.getName(SymbolName))) return;
+ symbol_iterator Symbol = RelI->getSymbol();
+ if (error(Symbol->getName(SymbolName))) return;
if (error(SecI->getContents(Contents))) return;
if (opts::ExpandRelocs) {
diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp
index ea1b83f..67bbafa 100644
--- a/tools/llvm-readobj/ELFDumper.cpp
+++ b/tools/llvm-readobj/ELFDumper.cpp
@@ -69,42 +69,32 @@ private:
namespace llvm {
+template <class ELFT>
+static error_code createELFDumper(const ELFObjectFile<ELFT> *Obj,
+ StreamWriter &Writer,
+ OwningPtr<ObjDumper> &Result) {
+ Result.reset(new ELFDumper<ELFT>(Obj, Writer));
+ return readobj_error::success;
+}
+
error_code createELFDumper(const object::ObjectFile *Obj,
StreamWriter& Writer,
OwningPtr<ObjDumper> &Result) {
- typedef ELFType<support::little, 4, false> Little32ELF;
- typedef ELFType<support::big, 4, false> Big32ELF;
- typedef ELFType<support::little, 4, true > Little64ELF;
- typedef ELFType<support::big, 8, true > Big64ELF;
-
- typedef ELFObjectFile<Little32ELF> LittleELF32Obj;
- typedef ELFObjectFile<Big32ELF > BigELF32Obj;
- typedef ELFObjectFile<Little64ELF> LittleELF64Obj;
- typedef ELFObjectFile<Big64ELF > BigELF64Obj;
-
// Little-endian 32-bit
- if (const LittleELF32Obj *ELFObj = dyn_cast<LittleELF32Obj>(Obj)) {
- Result.reset(new ELFDumper<Little32ELF>(ELFObj, Writer));
- return readobj_error::success;
- }
+ if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj))
+ return createELFDumper(ELFObj, Writer, Result);
// Big-endian 32-bit
- if (const BigELF32Obj *ELFObj = dyn_cast<BigELF32Obj>(Obj)) {
- Result.reset(new ELFDumper<Big32ELF>(ELFObj, Writer));
- return readobj_error::success;
- }
+ if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj))
+ return createELFDumper(ELFObj, Writer, Result);
// Little-endian 64-bit
- if (const LittleELF64Obj *ELFObj = dyn_cast<LittleELF64Obj>(Obj)) {
- Result.reset(new ELFDumper<Little64ELF>(ELFObj, Writer));
- return readobj_error::success;
- }
+ if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
+ return createELFDumper(ELFObj, Writer, Result);
// Big-endian 64-bit
- if (const BigELF64Obj *ELFObj = dyn_cast<BigELF64Obj>(Obj)) {
- Result.reset(new ELFDumper<Big64ELF>(ELFObj, Writer));
- return readobj_error::success;
- }
+ if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))
+ return createELFDumper(ELFObj, Writer, Result);
return readobj_error::unsupported_obj_file_format;
}
@@ -579,9 +569,8 @@ void ELFDumper<ELFT>::printRelocation(section_iterator Sec,
uint64_t Offset;
uint64_t RelocType;
SmallString<32> RelocName;
- int64_t Info;
+ int64_t Addend;
StringRef SymbolName;
- SymbolRef Symbol;
if (Obj->getElfHeader()->e_type == ELF::ET_REL){
if (error(RelI->getOffset(Offset))) return;
} else {
@@ -589,22 +578,23 @@ void ELFDumper<ELFT>::printRelocation(section_iterator Sec,
}
if (error(RelI->getType(RelocType))) return;
if (error(RelI->getTypeName(RelocName))) return;
- if (error(RelI->getAdditionalInfo(Info))) return;
- if (error(RelI->getSymbol(Symbol))) return;
- if (error(Symbol.getName(SymbolName))) return;
+ if (error(getELFRelocationAddend(*RelI, Addend))) return;
+ symbol_iterator Symbol = RelI->getSymbol();
+ if (Symbol != Obj->end_symbols() && error(Symbol->getName(SymbolName)))
+ return;
if (opts::ExpandRelocs) {
DictScope Group(W, "Relocation");
W.printHex("Offset", Offset);
W.printNumber("Type", RelocName, RelocType);
W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-");
- W.printHex("Info", Info);
+ W.printHex("Addend", Addend);
} else {
raw_ostream& OS = W.startLine();
OS << W.hex(Offset)
<< " " << RelocName
<< " " << (SymbolName.size() > 0 ? SymbolName : "-")
- << " " << W.hex(Info)
+ << " " << W.hex(Addend)
<< "\n";
}
}
diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp
index 31dc5ce..8df6fd6 100644
--- a/tools/llvm-readobj/MachODumper.cpp
+++ b/tools/llvm-readobj/MachODumper.cpp
@@ -341,12 +341,11 @@ void MachODumper::printRelocation(const MachOObjectFile *Obj,
uint64_t Offset;
SmallString<32> RelocName;
StringRef SymbolName;
- SymbolRef Symbol;
if (error(RelI->getOffset(Offset))) return;
if (error(RelI->getTypeName(RelocName))) return;
- if (error(RelI->getSymbol(Symbol))) return;
- if (symbol_iterator(Symbol) != Obj->end_symbols() &&
- error(Symbol.getName(SymbolName)))
+ symbol_iterator Symbol = RelI->getSymbol();
+ if (Symbol != Obj->end_symbols() &&
+ error(Symbol->getName(SymbolName)))
return;
DataRefImpl DR = RelI->getRawDataRefImpl();
diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp
index ead541a..b68f2a0 100644
--- a/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -69,7 +69,7 @@ public:
return 0;
}
- bool applyPermissions(std::string *ErrMsg) { return false; }
+ bool finalizeMemory(std::string *ErrMsg) { return false; }
// Invalidate instruction cache for sections with execute permissions.
// Some platforms with separate data cache and instruction cache require
diff --git a/tools/llvm-shlib/Makefile b/tools/llvm-shlib/Makefile
index 6d6c6e9..8697bbf 100644
--- a/tools/llvm-shlib/Makefile
+++ b/tools/llvm-shlib/Makefile
@@ -51,8 +51,7 @@ ifeq ($(HOST_OS),Darwin)
LLVMLibsOptions := $(LLVMLibsOptions) -all_load
# extra options to override libtool defaults
LLVMLibsOptions := $(LLVMLibsOptions) \
- -Wl,-dead_strip \
- -Wl,-seg1addr -Wl,0xE0000000
+ -Wl,-dead_strip
# Mac OS X 10.4 and earlier tools do not allow a second -install_name on command line
DARWIN_VERS := $(shell echo $(TARGET_TRIPLE) | sed 's/.*darwin\([0-9]*\).*/\1/')
diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp
index 29d91a0..7fccedf 100644
--- a/tools/llvm-symbolizer/LLVMSymbolize.cpp
+++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp
@@ -15,6 +15,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include <sstream>
@@ -63,7 +64,12 @@ ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
SymbolAddress == UnknownAddressOrSize)
continue;
uint64_t SymbolSize;
- if (error(si->getSize(SymbolSize)) || SymbolSize == UnknownAddressOrSize)
+ // Getting symbol size is linear for Mach-O files, so assume that symbol
+ // occupies the memory range up to the following symbol.
+ if (isa<MachOObjectFile>(Obj))
+ SymbolSize = 0;
+ else if (error(si->getSize(SymbolSize)) ||
+ SymbolSize == UnknownAddressOrSize)
continue;
StringRef SymbolName;
if (error(si->getName(SymbolName)))
@@ -71,7 +77,7 @@ ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
// FIXME: If a function has alias, there are two entries in symbol table
// with same address size. Make sure we choose the correct one.
SymbolMapTy &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects;
- SymbolDesc SD = { SymbolAddress, SymbolAddress + SymbolSize };
+ SymbolDesc SD = { SymbolAddress, SymbolSize };
M.insert(std::make_pair(SD, SymbolName));
}
}
@@ -80,15 +86,18 @@ bool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
std::string &Name, uint64_t &Addr,
uint64_t &Size) const {
const SymbolMapTy &M = Type == SymbolRef::ST_Function ? Functions : Objects;
- SymbolDesc SD = { Address, Address + 1 };
- SymbolMapTy::const_iterator it = M.find(SD);
- if (it == M.end())
+ if (M.empty())
return false;
- if (Address < it->first.Addr || Address >= it->first.AddrEnd)
+ SymbolDesc SD = { Address, Address };
+ SymbolMapTy::const_iterator it = M.upper_bound(SD);
+ if (it == M.begin())
+ return false;
+ --it;
+ if (it->first.Size != 0 && it->first.Addr + it->first.Size <= Address)
return false;
Name = it->second.str();
Addr = it->first.Addr;
- Size = it->first.AddrEnd - it->first.Addr;
+ Size = it->first.Size;
return true;
}
@@ -200,8 +209,8 @@ static bool getObjectEndianness(const ObjectFile *Obj, bool &IsLittleEndian) {
static ObjectFile *getObjectFile(const std::string &Path) {
OwningPtr<MemoryBuffer> Buff;
- if (error_code ec = MemoryBuffer::getFile(Path, Buff))
- error(ec);
+ if (error(MemoryBuffer::getFile(Path, Buff)))
+ return 0;
return ObjectFile::createObjectFile(Buff.take());
}
@@ -236,9 +245,12 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
if (isa<MachOObjectFile>(Obj)) {
const std::string &ResourceName =
getDarwinDWARFResourceForModule(ModuleName);
- ObjectFile *ResourceObj = getObjectFile(ResourceName);
- if (ResourceObj != 0)
- DbgObj = ResourceObj;
+ bool ResourceFileExists = false;
+ if (!sys::fs::exists(ResourceName, ResourceFileExists) &&
+ ResourceFileExists) {
+ if (ObjectFile *ResourceObj = getObjectFile(ResourceName))
+ DbgObj = ResourceObj;
+ }
}
Context = DIContext::getDWARFContext(DbgObj);
assert(Context);
diff --git a/tools/llvm-symbolizer/LLVMSymbolize.h b/tools/llvm-symbolizer/LLVMSymbolize.h
index 0733dfb..188331b 100644
--- a/tools/llvm-symbolizer/LLVMSymbolize.h
+++ b/tools/llvm-symbolizer/LLVMSymbolize.h
@@ -82,9 +82,11 @@ private:
struct SymbolDesc {
uint64_t Addr;
- uint64_t AddrEnd;
+ // If size is 0, assume that symbol occupies the whole memory range up to
+ // the following symbol.
+ uint64_t Size;
friend bool operator<(const SymbolDesc &s1, const SymbolDesc &s2) {
- return s1.AddrEnd <= s2.Addr;
+ return s1.Addr < s2.Addr;
}
};
typedef std::map<SymbolDesc, StringRef> SymbolMapTy;
diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp
index 5f5f76f..465ccb4 100644
--- a/tools/lto/LTOCodeGenerator.cpp
+++ b/tools/lto/LTOCodeGenerator.cpp
@@ -69,7 +69,7 @@ const char* LTOCodeGenerator::getVersionString() {
LTOCodeGenerator::LTOCodeGenerator()
: _context(getGlobalContext()),
- _linker("LinkTimeOptimizer", "ld-temp.o", _context), _target(NULL),
+ _linker(new Module("ld-temp.o", _context)), _target(NULL),
_emitDwarfDebugInfo(false), _scopeRestrictionsDone(false),
_codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC),
_nativeObjectFile(NULL) {
@@ -81,6 +81,7 @@ LTOCodeGenerator::LTOCodeGenerator()
LTOCodeGenerator::~LTOCodeGenerator() {
delete _target;
delete _nativeObjectFile;
+ delete _linker.getModule();
for (std::vector<char*>::iterator I = _codegenOptions.begin(),
E = _codegenOptions.end(); I != E; ++I)
@@ -88,7 +89,7 @@ LTOCodeGenerator::~LTOCodeGenerator() {
}
bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) {
- bool ret = _linker.LinkInModule(mod->getLLVVMModule(), &errMsg);
+ bool ret = _linker.linkInModule(mod->getLLVVMModule(), &errMsg);
const std::vector<const char*> &undefs = mod->getAsmUndefinedRefs();
for (int i = 0, e = undefs.size(); i != e; ++i)
@@ -219,10 +220,15 @@ const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) {
return _nativeObjectFile->getBufferStart();
}
-bool LTOCodeGenerator::determineTarget(std::string& errMsg) {
+bool LTOCodeGenerator::determineTarget(std::string &errMsg) {
if (_target != NULL)
return false;
+ // if options were requested, set them
+ if (!_codegenOptions.empty())
+ cl::ParseCommandLineOptions(_codegenOptions.size(),
+ const_cast<char **>(&_codegenOptions[0]));
+
std::string TripleStr = _linker.getModule()->getTargetTriple();
if (TripleStr.empty())
TripleStr = sys::getDefaultTargetTriple();
@@ -304,7 +310,7 @@ void LTOCodeGenerator::applyScopeRestrictions() {
// mark which symbols can not be internalized
MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(),NULL);
- Mangler mangler(Context, *_target->getDataLayout());
+ Mangler mangler(Context, _target);
std::vector<const char*> mustPreserveList;
SmallPtrSet<GlobalValue*, 8> asmUsed;
@@ -360,12 +366,7 @@ bool LTOCodeGenerator::generateObjectFile(raw_ostream &out,
Module* mergedModule = _linker.getModule();
- // if options were requested, set them
- if (!_codegenOptions.empty())
- cl::ParseCommandLineOptions(_codegenOptions.size(),
- const_cast<char **>(&_codegenOptions[0]));
-
- // mark which symbols can not be internalized
+ // Mark which symbols can not be internalized
this->applyScopeRestrictions();
// Instantiate the pass manager to organize the passes.
@@ -381,12 +382,11 @@ bool LTOCodeGenerator::generateObjectFile(raw_ostream &out,
// Enabling internalize here would use its AllButMain variant. It
// keeps only main if it exists and does nothing for libraries. Instead
// we create the pass ourselves with the symbol list provided by the linker.
- if (!DisableOpt) {
+ if (!DisableOpt)
PassManagerBuilder().populateLTOPassManager(passes,
/*Internalize=*/false,
!DisableInline,
DisableGVNLoadPRE);
- }
// Make sure everything is still good.
passes.add(createVerifierPass());
diff --git a/tools/lto/LTOCodeGenerator.h b/tools/lto/LTOCodeGenerator.h
index 601dbfa..a4ade9f 100644
--- a/tools/lto/LTOCodeGenerator.h
+++ b/tools/lto/LTOCodeGenerator.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/Linker.h"
#include <string>
+#include <vector>
namespace llvm {
class LLVMContext;
diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp
index d805f49..263e8b3 100644
--- a/tools/lto/LTOModule.cpp
+++ b/tools/lto/LTOModule.cpp
@@ -29,6 +29,7 @@
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SourceMgr.h"
@@ -158,17 +159,20 @@ SSPBufferSize("stack-protector-buffer-size", cl::init(8),
LTOModule::LTOModule(llvm::Module *m, llvm::TargetMachine *t)
: _module(m), _target(t),
_context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(), NULL),
- _mangler(_context, *_target->getDataLayout()) {}
+ _mangler(_context, t) {}
/// isBitcodeFile - Returns 'true' if the file (or memory contents) is LLVM
/// bitcode.
bool LTOModule::isBitcodeFile(const void *mem, size_t length) {
- return llvm::sys::IdentifyFileType((const char*)mem, length)
- == llvm::sys::Bitcode_FileType;
+ return sys::fs::identify_magic(StringRef((const char *)mem, length)) ==
+ sys::fs::file_magic::bitcode;
}
bool LTOModule::isBitcodeFile(const char *path) {
- return llvm::sys::Path(path).isBitcodeFile();
+ sys::fs::file_magic type;
+ if (sys::fs::identify_magic(path, type))
+ return false;
+ return type == sys::fs::file_magic::bitcode;
}
/// isBitcodeFileForTarget - Returns 'true' if the file (or memory contents) is
@@ -487,7 +491,7 @@ void LTOModule::addDefinedSymbol(const GlobalValue *def, bool isFunction) {
// set alignment part log2() can have rounding errors
uint32_t align = def->getAlignment();
- uint32_t attr = align ? CountTrailingZeros_32(def->getAlignment()) : 0;
+ uint32_t attr = align ? countTrailingZeros(def->getAlignment()) : 0;
// set permissions part
if (isFunction) {
diff --git a/tools/lto/Makefile b/tools/lto/Makefile
index ab2e16e..30719f4 100644
--- a/tools/lto/Makefile
+++ b/tools/lto/Makefile
@@ -39,8 +39,7 @@ ifeq ($(HOST_OS),Darwin)
endif
# extra options to override libtool defaults
LLVMLibsOptions := $(LLVMLibsOptions) \
- -Wl,-dead_strip \
- -Wl,-seg1addr -Wl,0xE0000000
+ -Wl,-dead_strip
# Mac OS X 10.4 and earlier tools do not allow a second -install_name on command line
DARWIN_VERS := $(shell echo $(TARGET_TRIPLE) | sed 's/.*darwin\([0-9]*\).*/\1/')
diff --git a/tools/macho-dump/macho-dump.cpp b/tools/macho-dump/macho-dump.cpp
index 88fd452..897a785 100644
--- a/tools/macho-dump/macho-dump.cpp
+++ b/tools/macho-dump/macho-dump.cpp
@@ -292,7 +292,7 @@ DumpDataInCodeDataCommand(const MachOObjectFile &Obj,
<< " ('datasize', " << LLC.DataSize << ")\n"
<< " ('_data_regions', [\n";
- unsigned NumRegions = LLC.DataSize / 8;
+ unsigned NumRegions = LLC.DataSize / sizeof(macho::DataInCodeTableEntry);
for (unsigned i = 0; i < NumRegions; ++i) {
macho::DataInCodeTableEntry DICE =
Obj.getDataInCodeTableEntry(LLC.DataOffset, i);
diff --git a/tools/obj2yaml/coff2yaml.cpp b/tools/obj2yaml/coff2yaml.cpp
index 5106a4a..0ec35bf 100644
--- a/tools/obj2yaml/coff2yaml.cpp
+++ b/tools/obj2yaml/coff2yaml.cpp
@@ -9,346 +9,112 @@
#include "obj2yaml.h"
#include "llvm/Object/COFF.h"
+#include "llvm/Object/COFFYAML.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/YAMLTraits.h"
using namespace llvm;
-template <typename One, typename Two>
-struct pod_pair { // I'd much rather use std::pair, but it's not a POD
- One first;
- Two second;
-};
-
-#define STRING_PAIR(x) {COFF::x, #x}
-static const pod_pair<COFF::MachineTypes, const char *>
-MachineTypePairs [] = {
- STRING_PAIR(IMAGE_FILE_MACHINE_UNKNOWN),
- STRING_PAIR(IMAGE_FILE_MACHINE_AM33),
- STRING_PAIR(IMAGE_FILE_MACHINE_AMD64),
- STRING_PAIR(IMAGE_FILE_MACHINE_ARM),
- STRING_PAIR(IMAGE_FILE_MACHINE_ARMV7),
- STRING_PAIR(IMAGE_FILE_MACHINE_EBC),
- STRING_PAIR(IMAGE_FILE_MACHINE_I386),
- STRING_PAIR(IMAGE_FILE_MACHINE_IA64),
- STRING_PAIR(IMAGE_FILE_MACHINE_M32R),
- STRING_PAIR(IMAGE_FILE_MACHINE_MIPS16),
- STRING_PAIR(IMAGE_FILE_MACHINE_MIPSFPU),
- STRING_PAIR(IMAGE_FILE_MACHINE_MIPSFPU16),
- STRING_PAIR(IMAGE_FILE_MACHINE_POWERPC),
- STRING_PAIR(IMAGE_FILE_MACHINE_POWERPCFP),
- STRING_PAIR(IMAGE_FILE_MACHINE_R4000),
- STRING_PAIR(IMAGE_FILE_MACHINE_SH3),
- STRING_PAIR(IMAGE_FILE_MACHINE_SH3DSP),
- STRING_PAIR(IMAGE_FILE_MACHINE_SH4),
- STRING_PAIR(IMAGE_FILE_MACHINE_SH5),
- STRING_PAIR(IMAGE_FILE_MACHINE_THUMB),
- STRING_PAIR(IMAGE_FILE_MACHINE_WCEMIPSV2)
-};
-
-static const pod_pair<COFF::SectionCharacteristics, const char *>
-SectionCharacteristicsPairs1 [] = {
- STRING_PAIR(IMAGE_SCN_TYPE_NO_PAD),
- STRING_PAIR(IMAGE_SCN_CNT_CODE),
- STRING_PAIR(IMAGE_SCN_CNT_INITIALIZED_DATA),
- STRING_PAIR(IMAGE_SCN_CNT_UNINITIALIZED_DATA),
- STRING_PAIR(IMAGE_SCN_LNK_OTHER),
- STRING_PAIR(IMAGE_SCN_LNK_INFO),
- STRING_PAIR(IMAGE_SCN_LNK_REMOVE),
- STRING_PAIR(IMAGE_SCN_LNK_COMDAT),
- STRING_PAIR(IMAGE_SCN_GPREL),
- STRING_PAIR(IMAGE_SCN_MEM_PURGEABLE),
- STRING_PAIR(IMAGE_SCN_MEM_16BIT),
- STRING_PAIR(IMAGE_SCN_MEM_LOCKED),
- STRING_PAIR(IMAGE_SCN_MEM_PRELOAD)
-};
+namespace {
-static const pod_pair<COFF::SectionCharacteristics, const char *>
-SectionCharacteristicsPairsAlignment [] = {
- STRING_PAIR(IMAGE_SCN_ALIGN_1BYTES),
- STRING_PAIR(IMAGE_SCN_ALIGN_2BYTES),
- STRING_PAIR(IMAGE_SCN_ALIGN_4BYTES),
- STRING_PAIR(IMAGE_SCN_ALIGN_8BYTES),
- STRING_PAIR(IMAGE_SCN_ALIGN_16BYTES),
- STRING_PAIR(IMAGE_SCN_ALIGN_32BYTES),
- STRING_PAIR(IMAGE_SCN_ALIGN_64BYTES),
- STRING_PAIR(IMAGE_SCN_ALIGN_128BYTES),
- STRING_PAIR(IMAGE_SCN_ALIGN_256BYTES),
- STRING_PAIR(IMAGE_SCN_ALIGN_512BYTES),
- STRING_PAIR(IMAGE_SCN_ALIGN_1024BYTES),
- STRING_PAIR(IMAGE_SCN_ALIGN_2048BYTES),
- STRING_PAIR(IMAGE_SCN_ALIGN_4096BYTES),
- STRING_PAIR(IMAGE_SCN_ALIGN_8192BYTES)
-};
-
-static const pod_pair<COFF::SectionCharacteristics, const char *>
-SectionCharacteristicsPairs2 [] = {
- STRING_PAIR(IMAGE_SCN_LNK_NRELOC_OVFL),
- STRING_PAIR(IMAGE_SCN_MEM_DISCARDABLE),
- STRING_PAIR(IMAGE_SCN_MEM_NOT_CACHED),
- STRING_PAIR(IMAGE_SCN_MEM_NOT_PAGED),
- STRING_PAIR(IMAGE_SCN_MEM_SHARED),
- STRING_PAIR(IMAGE_SCN_MEM_EXECUTE),
- STRING_PAIR(IMAGE_SCN_MEM_READ),
- STRING_PAIR(IMAGE_SCN_MEM_WRITE)
-};
-
-static const pod_pair<COFF::SymbolBaseType, const char *>
-SymbolBaseTypePairs [] = {
- STRING_PAIR(IMAGE_SYM_TYPE_NULL),
- STRING_PAIR(IMAGE_SYM_TYPE_VOID),
- STRING_PAIR(IMAGE_SYM_TYPE_CHAR),
- STRING_PAIR(IMAGE_SYM_TYPE_SHORT),
- STRING_PAIR(IMAGE_SYM_TYPE_INT),
- STRING_PAIR(IMAGE_SYM_TYPE_LONG),
- STRING_PAIR(IMAGE_SYM_TYPE_FLOAT),
- STRING_PAIR(IMAGE_SYM_TYPE_DOUBLE),
- STRING_PAIR(IMAGE_SYM_TYPE_STRUCT),
- STRING_PAIR(IMAGE_SYM_TYPE_UNION),
- STRING_PAIR(IMAGE_SYM_TYPE_ENUM),
- STRING_PAIR(IMAGE_SYM_TYPE_MOE),
- STRING_PAIR(IMAGE_SYM_TYPE_BYTE),
- STRING_PAIR(IMAGE_SYM_TYPE_WORD),
- STRING_PAIR(IMAGE_SYM_TYPE_UINT),
- STRING_PAIR(IMAGE_SYM_TYPE_DWORD)
-};
+class COFFDumper {
+ const object::COFFObjectFile &Obj;
+ COFFYAML::Object YAMLObj;
+ void dumpHeader(const object::coff_file_header *Header);
+ void dumpSections(unsigned numSections);
+ void dumpSymbols(unsigned numSymbols);
-static const pod_pair<COFF::SymbolComplexType, const char *>
-SymbolComplexTypePairs [] = {
- STRING_PAIR(IMAGE_SYM_DTYPE_NULL),
- STRING_PAIR(IMAGE_SYM_DTYPE_POINTER),
- STRING_PAIR(IMAGE_SYM_DTYPE_FUNCTION),
- STRING_PAIR(IMAGE_SYM_DTYPE_ARRAY),
+public:
+ COFFDumper(const object::COFFObjectFile &Obj);
+ COFFYAML::Object &getYAMLObj();
};
-static const pod_pair<COFF::SymbolStorageClass, const char *>
-SymbolStorageClassPairs [] = {
- STRING_PAIR(IMAGE_SYM_CLASS_END_OF_FUNCTION),
- STRING_PAIR(IMAGE_SYM_CLASS_NULL),
- STRING_PAIR(IMAGE_SYM_CLASS_AUTOMATIC),
- STRING_PAIR(IMAGE_SYM_CLASS_EXTERNAL),
- STRING_PAIR(IMAGE_SYM_CLASS_STATIC),
- STRING_PAIR(IMAGE_SYM_CLASS_REGISTER),
- STRING_PAIR(IMAGE_SYM_CLASS_EXTERNAL_DEF),
- STRING_PAIR(IMAGE_SYM_CLASS_LABEL),
- STRING_PAIR(IMAGE_SYM_CLASS_UNDEFINED_LABEL),
- STRING_PAIR(IMAGE_SYM_CLASS_MEMBER_OF_STRUCT),
- STRING_PAIR(IMAGE_SYM_CLASS_ARGUMENT),
- STRING_PAIR(IMAGE_SYM_CLASS_STRUCT_TAG),
- STRING_PAIR(IMAGE_SYM_CLASS_MEMBER_OF_UNION),
- STRING_PAIR(IMAGE_SYM_CLASS_UNION_TAG),
- STRING_PAIR(IMAGE_SYM_CLASS_TYPE_DEFINITION),
- STRING_PAIR(IMAGE_SYM_CLASS_UNDEFINED_STATIC),
- STRING_PAIR(IMAGE_SYM_CLASS_ENUM_TAG),
- STRING_PAIR(IMAGE_SYM_CLASS_MEMBER_OF_ENUM),
- STRING_PAIR(IMAGE_SYM_CLASS_REGISTER_PARAM),
- STRING_PAIR(IMAGE_SYM_CLASS_BIT_FIELD),
- STRING_PAIR(IMAGE_SYM_CLASS_BLOCK),
- STRING_PAIR(IMAGE_SYM_CLASS_FUNCTION),
- STRING_PAIR(IMAGE_SYM_CLASS_END_OF_STRUCT),
- STRING_PAIR(IMAGE_SYM_CLASS_FILE),
- STRING_PAIR(IMAGE_SYM_CLASS_SECTION),
- STRING_PAIR(IMAGE_SYM_CLASS_WEAK_EXTERNAL),
- STRING_PAIR(IMAGE_SYM_CLASS_CLR_TOKEN),
-};
-
-static const pod_pair<COFF::RelocationTypeX86, const char *>
-RelocationTypeX86Pairs [] = {
- STRING_PAIR(IMAGE_REL_I386_ABSOLUTE),
- STRING_PAIR(IMAGE_REL_I386_DIR16),
- STRING_PAIR(IMAGE_REL_I386_REL16),
- STRING_PAIR(IMAGE_REL_I386_DIR32),
- STRING_PAIR(IMAGE_REL_I386_DIR32NB),
- STRING_PAIR(IMAGE_REL_I386_SEG12),
- STRING_PAIR(IMAGE_REL_I386_SECTION),
- STRING_PAIR(IMAGE_REL_I386_SECREL),
- STRING_PAIR(IMAGE_REL_I386_TOKEN),
- STRING_PAIR(IMAGE_REL_I386_SECREL7),
- STRING_PAIR(IMAGE_REL_I386_REL32),
- STRING_PAIR(IMAGE_REL_AMD64_ABSOLUTE),
- STRING_PAIR(IMAGE_REL_AMD64_ADDR64),
- STRING_PAIR(IMAGE_REL_AMD64_ADDR32),
- STRING_PAIR(IMAGE_REL_AMD64_ADDR32NB),
- STRING_PAIR(IMAGE_REL_AMD64_REL32),
- STRING_PAIR(IMAGE_REL_AMD64_REL32_1),
- STRING_PAIR(IMAGE_REL_AMD64_REL32_2),
- STRING_PAIR(IMAGE_REL_AMD64_REL32_3),
- STRING_PAIR(IMAGE_REL_AMD64_REL32_4),
- STRING_PAIR(IMAGE_REL_AMD64_REL32_5),
- STRING_PAIR(IMAGE_REL_AMD64_SECTION),
- STRING_PAIR(IMAGE_REL_AMD64_SECREL),
- STRING_PAIR(IMAGE_REL_AMD64_SECREL7),
- STRING_PAIR(IMAGE_REL_AMD64_TOKEN),
- STRING_PAIR(IMAGE_REL_AMD64_SREL32),
- STRING_PAIR(IMAGE_REL_AMD64_PAIR),
- STRING_PAIR(IMAGE_REL_AMD64_SSPAN32)
-};
-
-static const pod_pair<COFF::RelocationTypesARM, const char *>
-RelocationTypesARMPairs [] = {
- STRING_PAIR(IMAGE_REL_ARM_ABSOLUTE),
- STRING_PAIR(IMAGE_REL_ARM_ADDR32),
- STRING_PAIR(IMAGE_REL_ARM_ADDR32NB),
- STRING_PAIR(IMAGE_REL_ARM_BRANCH24),
- STRING_PAIR(IMAGE_REL_ARM_BRANCH11),
- STRING_PAIR(IMAGE_REL_ARM_TOKEN),
- STRING_PAIR(IMAGE_REL_ARM_BLX24),
- STRING_PAIR(IMAGE_REL_ARM_BLX11),
- STRING_PAIR(IMAGE_REL_ARM_SECTION),
- STRING_PAIR(IMAGE_REL_ARM_SECREL),
- STRING_PAIR(IMAGE_REL_ARM_MOV32A),
- STRING_PAIR(IMAGE_REL_ARM_MOV32T),
- STRING_PAIR(IMAGE_REL_ARM_BRANCH20T),
- STRING_PAIR(IMAGE_REL_ARM_BRANCH24T),
- STRING_PAIR(IMAGE_REL_ARM_BLX23T)
-};
-#undef STRING_PAIR
-
-static raw_ostream &writeName(raw_ostream &Out,
- const char *Name, std::size_t NameSize) {
- for (std::size_t i = 0; i < NameSize; ++i) {
- if (!Name[i]) break;
- Out << Name[i];
- }
- return Out;
}
-// Given an array of pod_pair<enum, const char *>, write all enums that match
-template <typename T, std::size_t N>
-static raw_ostream &writeBitMask(raw_ostream &Out,
- const pod_pair<T, const char *> (&Arr)[N],
- unsigned long Val) {
- for (std::size_t i = 0; i < N; ++i)
- if (Val & Arr[i].first)
- Out << Arr[i].second << ", ";
- return Out;
+static void check(error_code ec) {
+ if (ec)
+ report_fatal_error(ec.message());
}
-// Given an array of pod_pair<enum, const char *>, look up a value
-template <typename T, std::size_t N>
-const char *nameLookup(const pod_pair<T, const char *> (&Arr)[N],
- unsigned long Val, const char *NotFound = NULL) {
- T n = static_cast<T>(Val);
- for (std::size_t i = 0; i < N; ++i)
- if (n == Arr[i].first)
- return Arr[i].second;
- return NotFound;
+COFFDumper::COFFDumper(const object::COFFObjectFile &Obj) : Obj(Obj) {
+ const object::coff_file_header *Header;
+ check(Obj.getHeader(Header));
+ dumpHeader(Header);
+ dumpSections(Header->NumberOfSections);
+ dumpSymbols(Header->NumberOfSymbols);
}
-static void yamlCOFFHeader(const object::coff_file_header *Header,
- raw_ostream &Out) {
- Out << "header: !Header\n";
- Out << " Machine: ";
- Out << nameLookup(MachineTypePairs, Header->Machine, "# Unknown_MachineTypes")
- << " # (";
- objyaml::writeHexNumber(Out, Header->Machine) << ")\n\n";
+void COFFDumper::dumpHeader(const object::coff_file_header *Header) {
+ YAMLObj.Header.Machine = Header->Machine;
+ YAMLObj.Header.Characteristics = Header->Characteristics;
}
-
-static void yamlCOFFSections(object::COFFObjectFile &Obj,
- std::size_t NumSections, raw_ostream &Out) {
+void COFFDumper::dumpSections(unsigned NumSections) {
+ std::vector<COFFYAML::Section> &Sections = YAMLObj.Sections;
error_code ec;
- Out << "sections:\n";
for (object::section_iterator iter = Obj.begin_sections();
iter != Obj.end_sections(); iter.increment(ec)) {
- const object::coff_section *sect = Obj.getCOFFSection(iter);
-
- Out << " - !Section\n";
- Out << " Name: ";
- writeName(Out, sect->Name, sizeof(sect->Name)) << '\n';
-
- Out << " Characteristics: [";
- writeBitMask(Out, SectionCharacteristicsPairs1, sect->Characteristics);
- Out << nameLookup(SectionCharacteristicsPairsAlignment,
- sect->Characteristics & 0x00F00000, "# Unrecognized_IMAGE_SCN_ALIGN")
- << ", ";
- writeBitMask(Out, SectionCharacteristicsPairs2, sect->Characteristics);
- Out << "] # ";
- objyaml::writeHexNumber(Out, sect->Characteristics) << '\n';
+ check(ec);
+ const object::coff_section *Sect = Obj.getCOFFSection(iter);
+ COFFYAML::Section Sec;
+ Sec.Name = Sect->Name; // FIXME: check the null termination!
+ uint32_t Characteristics = Sect->Characteristics;
+ Sec.Header.Characteristics = Characteristics;
+ Sec.Alignment = 1 << (((Characteristics >> 20) & 0xf) - 1);
ArrayRef<uint8_t> sectionData;
- Obj.getSectionContents(sect, sectionData);
- Out << " SectionData: ";
- objyaml::writeHexStream(Out, sectionData) << '\n';
- if (iter->begin_relocations() != iter->end_relocations())
- Out << " Relocations:\n";
+ Obj.getSectionContents(Sect, sectionData);
+ Sec.SectionData = object::yaml::BinaryRef(sectionData);
+
+ std::vector<COFFYAML::Relocation> Relocations;
for (object::relocation_iterator rIter = iter->begin_relocations();
rIter != iter->end_relocations(); rIter.increment(ec)) {
const object::coff_relocation *reloc = Obj.getCOFFRelocation(rIter);
-
- Out << " - !Relocation\n";
- Out << " VirtualAddress: " ;
- objyaml::writeHexNumber(Out, reloc->VirtualAddress) << '\n';
- Out << " SymbolTableIndex: " << reloc->SymbolTableIndex << '\n';
- Out << " Type: "
- << nameLookup(RelocationTypeX86Pairs, reloc->Type) << '\n';
- // TODO: Use the correct reloc type for the machine.
- Out << '\n';
- }
-
+ COFFYAML::Relocation Rel;
+ object::symbol_iterator Sym = rIter->getSymbol();
+ StringRef Name;
+ Sym->getName(Rel.SymbolName);
+ Rel.VirtualAddress = reloc->VirtualAddress;
+ Rel.Type = reloc->Type;
+ Relocations.push_back(Rel);
+ }
+ Sec.Relocations = Relocations;
+ Sections.push_back(Sec);
}
}
-static void yamlCOFFSymbols(object::COFFObjectFile &Obj, std::size_t NumSymbols,
- raw_ostream &Out) {
+void COFFDumper::dumpSymbols(unsigned NumSymbols) {
error_code ec;
- Out << "symbols:\n";
+ std::vector<COFFYAML::Symbol> &Symbols = YAMLObj.Symbols;
for (object::symbol_iterator iter = Obj.begin_symbols();
iter != Obj.end_symbols(); iter.increment(ec)) {
- // Gather all the info that we need
- StringRef str;
- const object::coff_symbol *symbol = Obj.getCOFFSymbol(iter);
- Obj.getSymbolName(symbol, str);
- std::size_t simpleType = symbol->getBaseType();
- std::size_t complexType = symbol->getComplexType();
- std::size_t storageClass = symbol->StorageClass;
-
- Out << " - !Symbol\n";
- Out << " Name: " << str << '\n';
-
- Out << " Value: " << symbol->Value << '\n';
- Out << " SectionNumber: " << symbol->SectionNumber << '\n';
-
- Out << " SimpleType: "
- << nameLookup(SymbolBaseTypePairs, simpleType,
- "# Unknown_SymbolBaseType")
- << " # (" << simpleType << ")\n";
-
- Out << " ComplexType: "
- << nameLookup(SymbolComplexTypePairs, complexType,
- "# Unknown_SymbolComplexType")
- << " # (" << complexType << ")\n";
-
- Out << " StorageClass: "
- << nameLookup(SymbolStorageClassPairs, storageClass,
- "# Unknown_StorageClass")
- << " # (" << (int) storageClass << ")\n";
-
- if (symbol->NumberOfAuxSymbols > 0) {
- ArrayRef<uint8_t> aux = Obj.getSymbolAuxData(symbol);
- Out << " NumberOfAuxSymbols: "
- << (int) symbol->NumberOfAuxSymbols << '\n';
- Out << " AuxillaryData: ";
- objyaml::writeHexStream(Out, aux);
- }
-
- Out << '\n';
+ check(ec);
+ const object::coff_symbol *Symbol = Obj.getCOFFSymbol(iter);
+ COFFYAML::Symbol Sym;
+ Obj.getSymbolName(Symbol, Sym.Name);
+ Sym.SimpleType = COFF::SymbolBaseType(Symbol->getBaseType());
+ Sym.ComplexType = COFF::SymbolComplexType(Symbol->getComplexType());
+ Sym.Header.StorageClass = Symbol->StorageClass;
+ Sym.Header.Value = Symbol->Value;
+ Sym.Header.SectionNumber = Symbol->SectionNumber;
+ Sym.Header.NumberOfAuxSymbols = Symbol->NumberOfAuxSymbols;
+ Sym.AuxiliaryData = object::yaml::BinaryRef(Obj.getSymbolAuxData(Symbol));
+ Symbols.push_back(Sym);
}
}
+COFFYAML::Object &COFFDumper::getYAMLObj() {
+ return YAMLObj;
+}
-error_code coff2yaml(raw_ostream &Out, MemoryBuffer *TheObj) {
+error_code coff2yaml(raw_ostream &Out, MemoryBuffer *Buff) {
error_code ec;
- object::COFFObjectFile obj(TheObj, ec);
- if (ec)
- return ec;
-
- const object::coff_file_header *hd;
- ec = obj.getHeader(hd);
- if (ec)
- return ec;
+ object::COFFObjectFile Obj(Buff, ec);
+ check(ec);
+ COFFDumper Dumper(Obj);
- yamlCOFFHeader(hd, Out);
- yamlCOFFSections(obj, hd->NumberOfSections, Out);
- yamlCOFFSymbols(obj, hd->NumberOfSymbols, Out);
+ yaml::Output Yout(Out);
+ Yout << Dumper.getYAMLObj();
- return ec;
+ return object::object_error::success;
}
diff --git a/tools/obj2yaml/obj2yaml.cpp b/tools/obj2yaml/obj2yaml.cpp
index 821c9ac..8d128b3 100644
--- a/tools/obj2yaml/obj2yaml.cpp
+++ b/tools/obj2yaml/obj2yaml.cpp
@@ -18,38 +18,6 @@
using namespace llvm;
-namespace objyaml { // generic yaml-writing specific routines
-
-unsigned char printable(unsigned char Ch) {
- return Ch >= ' ' && Ch <= '~' ? Ch : '.';
-}
-
-raw_ostream &writeHexStream(raw_ostream &Out, const ArrayRef<uint8_t> arr) {
- const char *hex = "0123456789ABCDEF";
- Out << " !hex \"";
-
- typedef ArrayRef<uint8_t>::const_iterator iter_t;
- const iter_t end = arr.end();
- for (iter_t iter = arr.begin(); iter != end; ++iter)
- Out << hex[(*iter >> 4) & 0x0F] << hex[(*iter & 0x0F)];
-
- Out << "\" # |";
- for (iter_t iter = arr.begin(); iter != end; ++iter)
- Out << printable(*iter);
- Out << "|\n";
-
- return Out;
-}
-
-raw_ostream &writeHexNumber(raw_ostream &Out, unsigned long long N) {
- if (N >= 10)
- Out << "0x";
- Out.write_hex(N);
- return Out;
-}
-
-} // end namespace yaml
-
namespace {
enum ObjectFileType {
coff
diff --git a/tools/obj2yaml/obj2yaml.h b/tools/obj2yaml/obj2yaml.h
index 7d52a2d..bde82e6 100644
--- a/tools/obj2yaml/obj2yaml.h
+++ b/tools/obj2yaml/obj2yaml.h
@@ -13,22 +13,10 @@
#ifndef LLVM_TOOLS_OBJ2YAML_H
#define LLVM_TOOLS_OBJ2YAML_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
-namespace objyaml { // routines for writing YAML
-// Write a hex stream:
-// <Prefix> !hex: "<hex digits>" #|<ASCII chars>\n
- llvm::raw_ostream &writeHexStream
- (llvm::raw_ostream &Out, const llvm::ArrayRef<uint8_t> arr);
-
-// Writes a number in hex; prefix it by 0x if it is >= 10
- llvm::raw_ostream &writeHexNumber
- (llvm::raw_ostream &Out, unsigned long long N);
-}
-
llvm::error_code coff2yaml(llvm::raw_ostream &Out, llvm::MemoryBuffer *TheObj);
#endif
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index e385d7f..57b03b4 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -567,6 +567,7 @@ int main(int argc, char **argv) {
// Initialize passes
PassRegistry &Registry = *PassRegistry::getPassRegistry();
initializeCore(Registry);
+ initializeDebugIRPass(Registry);
initializeScalarOpts(Registry);
initializeObjCARCOpts(Registry);
initializeVectorization(Registry);
diff --git a/tools/yaml2obj/CMakeLists.txt b/tools/yaml2obj/CMakeLists.txt
index f8b1197..8d9d652 100644
--- a/tools/yaml2obj/CMakeLists.txt
+++ b/tools/yaml2obj/CMakeLists.txt
@@ -1,5 +1,9 @@
+set(LLVM_LINK_COMPONENTS object)
+
add_llvm_utility(yaml2obj
yaml2obj.cpp
+ yaml2coff.cpp
+ yaml2elf.cpp
)
target_link_libraries(yaml2obj LLVMSupport)
diff --git a/tools/yaml2obj/Makefile b/tools/yaml2obj/Makefile
index cb6f477..8801795 100644
--- a/tools/yaml2obj/Makefile
+++ b/tools/yaml2obj/Makefile
@@ -9,7 +9,7 @@
LEVEL = ../..
TOOLNAME = yaml2obj
-LINK_COMPONENTS := support
+LINK_COMPONENTS := object
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
diff --git a/tools/yaml2obj/yaml2coff.cpp b/tools/yaml2obj/yaml2coff.cpp
new file mode 100644
index 0000000..11aae0e
--- /dev/null
+++ b/tools/yaml2obj/yaml2coff.cpp
@@ -0,0 +1,288 @@
+//===- yaml2coff - Convert YAML to a COFF object file ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief The COFF component of yaml2obj.
+///
+//===----------------------------------------------------------------------===//
+
+#include "yaml2obj.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Object/COFFYAML.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/raw_ostream.h"
+#include <vector>
+
+using namespace llvm;
+
+/// This parses a yaml stream that represents a COFF object file.
+/// See docs/yaml2obj for the yaml scheema.
+struct COFFParser {
+ COFFParser(COFFYAML::Object &Obj) : Obj(Obj) {
+ // A COFF string table always starts with a 4 byte size field. Offsets into
+ // it include this size, so allocate it now.
+ StringTable.append(4, 0);
+ }
+
+ bool parseSections() {
+ for (std::vector<COFFYAML::Section>::iterator i = Obj.Sections.begin(),
+ e = Obj.Sections.end(); i != e; ++i) {
+ COFFYAML::Section &Sec = *i;
+
+ // If the name is less than 8 bytes, store it in place, otherwise
+ // store it in the string table.
+ StringRef Name = Sec.Name;
+
+ if (Name.size() <= COFF::NameSize) {
+ std::copy(Name.begin(), Name.end(), Sec.Header.Name);
+ } else {
+ // Add string to the string table and format the index for output.
+ unsigned Index = getStringIndex(Name);
+ std::string str = utostr(Index);
+ if (str.size() > 7) {
+ errs() << "String table got too large";
+ return false;
+ }
+ Sec.Header.Name[0] = '/';
+ std::copy(str.begin(), str.end(), Sec.Header.Name + 1);
+ }
+
+ Sec.Header.Characteristics |= (Log2_32(Sec.Alignment) + 1) << 20;
+ }
+ return true;
+ }
+
+ bool parseSymbols() {
+ for (std::vector<COFFYAML::Symbol>::iterator i = Obj.Symbols.begin(),
+ e = Obj.Symbols.end(); i != e; ++i) {
+ COFFYAML::Symbol &Sym = *i;
+
+ // If the name is less than 8 bytes, store it in place, otherwise
+ // store it in the string table.
+ StringRef Name = Sym.Name;
+ if (Name.size() <= COFF::NameSize) {
+ std::copy(Name.begin(), Name.end(), Sym.Header.Name);
+ } else {
+ // Add string to the string table and format the index for output.
+ unsigned Index = getStringIndex(Name);
+ *reinterpret_cast<support::aligned_ulittle32_t*>(
+ Sym.Header.Name + 4) = Index;
+ }
+
+ Sym.Header.Type = Sym.SimpleType;
+ Sym.Header.Type |= Sym.ComplexType << COFF::SCT_COMPLEX_TYPE_SHIFT;
+ }
+ return true;
+ }
+
+ bool parse() {
+ if (!parseSections())
+ return false;
+ if (!parseSymbols())
+ return false;
+ return true;
+ }
+
+ unsigned getStringIndex(StringRef Str) {
+ StringMap<unsigned>::iterator i = StringTableMap.find(Str);
+ if (i == StringTableMap.end()) {
+ unsigned Index = StringTable.size();
+ StringTable.append(Str.begin(), Str.end());
+ StringTable.push_back(0);
+ StringTableMap[Str] = Index;
+ return Index;
+ }
+ return i->second;
+ }
+
+ COFFYAML::Object &Obj;
+
+ StringMap<unsigned> StringTableMap;
+ std::string StringTable;
+};
+
+// Take a CP and assign addresses and sizes to everything. Returns false if the
+// layout is not valid to do.
+static bool layoutCOFF(COFFParser &CP) {
+ uint32_t SectionTableStart = 0;
+ uint32_t SectionTableSize = 0;
+
+ // The section table starts immediately after the header, including the
+ // optional header.
+ SectionTableStart = sizeof(COFF::header) + CP.Obj.Header.SizeOfOptionalHeader;
+ SectionTableSize = sizeof(COFF::section) * CP.Obj.Sections.size();
+
+ uint32_t CurrentSectionDataOffset = SectionTableStart + SectionTableSize;
+
+ // Assign each section data address consecutively.
+ for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(),
+ e = CP.Obj.Sections.end();
+ i != e; ++i) {
+ if (i->SectionData.binary_size() > 0) {
+ i->Header.SizeOfRawData = i->SectionData.binary_size();
+ i->Header.PointerToRawData = CurrentSectionDataOffset;
+ CurrentSectionDataOffset += i->Header.SizeOfRawData;
+ if (!i->Relocations.empty()) {
+ i->Header.PointerToRelocations = CurrentSectionDataOffset;
+ i->Header.NumberOfRelocations = i->Relocations.size();
+ CurrentSectionDataOffset += i->Header.NumberOfRelocations *
+ COFF::RelocationSize;
+ }
+ // TODO: Handle alignment.
+ } else {
+ i->Header.SizeOfRawData = 0;
+ i->Header.PointerToRawData = 0;
+ }
+ }
+
+ uint32_t SymbolTableStart = CurrentSectionDataOffset;
+
+ // Calculate number of symbols.
+ uint32_t NumberOfSymbols = 0;
+ for (std::vector<COFFYAML::Symbol>::iterator i = CP.Obj.Symbols.begin(),
+ e = CP.Obj.Symbols.end();
+ i != e; ++i) {
+ unsigned AuxBytes = i->AuxiliaryData.binary_size();
+ if (AuxBytes % COFF::SymbolSize != 0) {
+ errs() << "AuxiliaryData size not a multiple of symbol size!\n";
+ return false;
+ }
+ i->Header.NumberOfAuxSymbols = AuxBytes / COFF::SymbolSize;
+ NumberOfSymbols += 1 + i->Header.NumberOfAuxSymbols;
+ }
+
+ // Store all the allocated start addresses in the header.
+ CP.Obj.Header.NumberOfSections = CP.Obj.Sections.size();
+ CP.Obj.Header.NumberOfSymbols = NumberOfSymbols;
+ CP.Obj.Header.PointerToSymbolTable = SymbolTableStart;
+
+ *reinterpret_cast<support::ulittle32_t *>(&CP.StringTable[0])
+ = CP.StringTable.size();
+
+ return true;
+}
+
+template <typename value_type>
+struct binary_le_impl {
+ value_type Value;
+ binary_le_impl(value_type V) : Value(V) {}
+};
+
+template <typename value_type>
+raw_ostream &operator <<( raw_ostream &OS
+ , const binary_le_impl<value_type> &BLE) {
+ char Buffer[sizeof(BLE.Value)];
+ support::endian::write<value_type, support::little, support::unaligned>(
+ Buffer, BLE.Value);
+ OS.write(Buffer, sizeof(BLE.Value));
+ return OS;
+}
+
+template <typename value_type>
+binary_le_impl<value_type> binary_le(value_type V) {
+ return binary_le_impl<value_type>(V);
+}
+
+bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
+ OS << binary_le(CP.Obj.Header.Machine)
+ << binary_le(CP.Obj.Header.NumberOfSections)
+ << binary_le(CP.Obj.Header.TimeDateStamp)
+ << binary_le(CP.Obj.Header.PointerToSymbolTable)
+ << binary_le(CP.Obj.Header.NumberOfSymbols)
+ << binary_le(CP.Obj.Header.SizeOfOptionalHeader)
+ << binary_le(CP.Obj.Header.Characteristics);
+
+ // Output section table.
+ for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(),
+ e = CP.Obj.Sections.end();
+ i != e; ++i) {
+ OS.write(i->Header.Name, COFF::NameSize);
+ OS << binary_le(i->Header.VirtualSize)
+ << binary_le(i->Header.VirtualAddress)
+ << binary_le(i->Header.SizeOfRawData)
+ << binary_le(i->Header.PointerToRawData)
+ << binary_le(i->Header.PointerToRelocations)
+ << binary_le(i->Header.PointerToLineNumbers)
+ << binary_le(i->Header.NumberOfRelocations)
+ << binary_le(i->Header.NumberOfLineNumbers)
+ << binary_le(i->Header.Characteristics);
+ }
+
+ unsigned CurSymbol = 0;
+ StringMap<unsigned> SymbolTableIndexMap;
+ for (std::vector<COFFYAML::Symbol>::iterator I = CP.Obj.Symbols.begin(),
+ E = CP.Obj.Symbols.end();
+ I != E; ++I) {
+ SymbolTableIndexMap[I->Name] = CurSymbol;
+ CurSymbol += 1 + I->Header.NumberOfAuxSymbols;
+ }
+
+ // Output section data.
+ for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(),
+ e = CP.Obj.Sections.end();
+ i != e; ++i) {
+ i->SectionData.writeAsBinary(OS);
+ for (unsigned I2 = 0, E2 = i->Relocations.size(); I2 != E2; ++I2) {
+ const COFFYAML::Relocation &R = i->Relocations[I2];
+ uint32_t SymbolTableIndex = SymbolTableIndexMap[R.SymbolName];
+ OS << binary_le(R.VirtualAddress)
+ << binary_le(SymbolTableIndex)
+ << binary_le(R.Type);
+ }
+ }
+
+ // Output symbol table.
+
+ for (std::vector<COFFYAML::Symbol>::const_iterator i = CP.Obj.Symbols.begin(),
+ e = CP.Obj.Symbols.end();
+ i != e; ++i) {
+ OS.write(i->Header.Name, COFF::NameSize);
+ OS << binary_le(i->Header.Value)
+ << binary_le(i->Header.SectionNumber)
+ << binary_le(i->Header.Type)
+ << binary_le(i->Header.StorageClass)
+ << binary_le(i->Header.NumberOfAuxSymbols);
+ i->AuxiliaryData.writeAsBinary(OS);
+ }
+
+ // Output string table.
+ OS.write(&CP.StringTable[0], CP.StringTable.size());
+ return true;
+}
+
+int yaml2coff(llvm::raw_ostream &Out, llvm::MemoryBuffer *Buf) {
+ yaml::Input YIn(Buf->getBuffer());
+ COFFYAML::Object Doc;
+ YIn >> Doc;
+ if (YIn.error()) {
+ errs() << "yaml2obj: Failed to parse YAML file!\n";
+ return 1;
+ }
+
+ COFFParser CP(Doc);
+ if (!CP.parse()) {
+ errs() << "yaml2obj: Failed to parse YAML file!\n";
+ return 1;
+ }
+
+ if (!layoutCOFF(CP)) {
+ errs() << "yaml2obj: Failed to layout COFF file!\n";
+ return 1;
+ }
+ if (!writeCOFF(CP, Out)) {
+ errs() << "yaml2obj: Failed to write COFF file!\n";
+ return 1;
+ }
+ return 0;
+}
diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp
new file mode 100644
index 0000000..45ccb62
--- /dev/null
+++ b/tools/yaml2obj/yaml2elf.cpp
@@ -0,0 +1,78 @@
+//===- yaml2elf - Convert YAML to a ELF object file -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief The ELF component of yaml2obj.
+///
+//===----------------------------------------------------------------------===//
+
+#include "yaml2obj.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/Object/ELFYAML.h"
+#include "llvm/Support/ELF.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+template <class ELFT>
+static void writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
+ const ELFYAML::FileHeader &Hdr = Doc.Header;
+ using namespace llvm::ELF;
+ using namespace llvm::object;
+ typename ELFObjectFile<ELFT>::Elf_Ehdr Header;
+ memset(&Header, 0, sizeof(Header));
+ Header.e_ident[EI_MAG0] = 0x7f;
+ Header.e_ident[EI_MAG1] = 'E';
+ Header.e_ident[EI_MAG2] = 'L';
+ Header.e_ident[EI_MAG3] = 'F';
+ Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
+ bool IsLittleEndian = ELFT::TargetEndianness == support::little;
+ Header.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
+
+ Header.e_ident[EI_VERSION] = EV_CURRENT;
+
+ // TODO: Implement ELF_ELFOSABI enum.
+ Header.e_ident[EI_OSABI] = ELFOSABI_NONE;
+ // TODO: Implement ELF_ABIVERSION enum.
+ Header.e_ident[EI_ABIVERSION] = 0;
+ Header.e_type = Hdr.Type;
+ Header.e_machine = Hdr.Machine;
+ Header.e_version = EV_CURRENT;
+ Header.e_entry = Hdr.Entry;
+ Header.e_ehsize = sizeof(Header);
+
+ // TODO: Section headers and program headers.
+
+ OS.write((const char *)&Header, sizeof(Header));
+}
+
+int yaml2elf(llvm::raw_ostream &Out, llvm::MemoryBuffer *Buf) {
+ yaml::Input YIn(Buf->getBuffer());
+ ELFYAML::Object Doc;
+ YIn >> Doc;
+ if (YIn.error()) {
+ errs() << "yaml2obj: Failed to parse YAML file!\n";
+ return 1;
+ }
+ if (Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64)) {
+ if (Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB))
+ writeELF<object::ELFType<support::little, 8, true> >(outs(), Doc);
+ else
+ writeELF<object::ELFType<support::big, 8, true> >(outs(), Doc);
+ } else {
+ if (Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB))
+ writeELF<object::ELFType<support::little, 4, false> >(outs(), Doc);
+ else
+ writeELF<object::ELFType<support::big, 4, false> >(outs(), Doc);
+ }
+
+ return 0;
+}
diff --git a/tools/yaml2obj/yaml2obj.cpp b/tools/yaml2obj/yaml2obj.cpp
index 32dee54..6d1107c 100644
--- a/tools/yaml2obj/yaml2obj.cpp
+++ b/tools/yaml2obj/yaml2obj.cpp
@@ -14,646 +14,42 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/COFF.h"
-#include "llvm/Support/Casting.h"
+#include "yaml2obj.h"
+#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Endian.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
-#include <vector>
using namespace llvm;
static cl::opt<std::string>
Input(cl::Positional, cl::desc("<input>"), cl::init("-"));
-// The structure of the yaml files is not an exact 1:1 match to COFF. In order
-// to use yaml::IO, we use these structures which are closer to the source.
-namespace COFFYAML {
- struct Section {
- COFF::section Header;
- StringRef SectionData;
- std::vector<COFF::relocation> Relocations;
- StringRef Name;
- Section() {
- memset(&Header, 0, sizeof(COFF::section));
- }
- };
-
- struct Symbol {
- COFF::symbol Header;
- COFF::SymbolBaseType SimpleType;
- COFF::SymbolComplexType ComplexType;
- StringRef AuxiliaryData;
- StringRef Name;
- Symbol() {
- memset(&Header, 0, sizeof(COFF::symbol));
- }
- };
-
- struct Object {
- COFF::header Header;
- std::vector<Section> Sections;
- std::vector<Symbol> Symbols;
- Object() {
- memset(&Header, 0, sizeof(COFF::header));
- }
- };
-}
-
-/// This parses a yaml stream that represents a COFF object file.
-/// See docs/yaml2obj for the yaml scheema.
-struct COFFParser {
- COFFParser(COFFYAML::Object &Obj) : Obj(Obj) {
- // A COFF string table always starts with a 4 byte size field. Offsets into
- // it include this size, so allocate it now.
- StringTable.append(4, 0);
- }
-
- bool parseSections() {
- for (std::vector<COFFYAML::Section>::iterator i = Obj.Sections.begin(),
- e = Obj.Sections.end(); i != e; ++i) {
- COFFYAML::Section &Sec = *i;
-
- // If the name is less than 8 bytes, store it in place, otherwise
- // store it in the string table.
- StringRef Name = Sec.Name;
-
- if (Name.size() <= COFF::NameSize) {
- std::copy(Name.begin(), Name.end(), Sec.Header.Name);
- } else {
- // Add string to the string table and format the index for output.
- unsigned Index = getStringIndex(Name);
- std::string str = utostr(Index);
- if (str.size() > 7) {
- errs() << "String table got too large";
- return false;
- }
- Sec.Header.Name[0] = '/';
- std::copy(str.begin(), str.end(), Sec.Header.Name + 1);
- }
- }
- return true;
- }
-
- bool parseSymbols() {
- for (std::vector<COFFYAML::Symbol>::iterator i = Obj.Symbols.begin(),
- e = Obj.Symbols.end(); i != e; ++i) {
- COFFYAML::Symbol &Sym = *i;
-
- // If the name is less than 8 bytes, store it in place, otherwise
- // store it in the string table.
- StringRef Name = Sym.Name;
- if (Name.size() <= COFF::NameSize) {
- std::copy(Name.begin(), Name.end(), Sym.Header.Name);
- } else {
- // Add string to the string table and format the index for output.
- unsigned Index = getStringIndex(Name);
- *reinterpret_cast<support::aligned_ulittle32_t*>(
- Sym.Header.Name + 4) = Index;
- }
-
- Sym.Header.Type = Sym.SimpleType;
- Sym.Header.Type |= Sym.ComplexType << COFF::SCT_COMPLEX_TYPE_SHIFT;
- }
- return true;
- }
-
- bool parse() {
- if (!parseSections())
- return false;
- if (!parseSymbols())
- return false;
- return true;
- }
-
- unsigned getStringIndex(StringRef Str) {
- StringMap<unsigned>::iterator i = StringTableMap.find(Str);
- if (i == StringTableMap.end()) {
- unsigned Index = StringTable.size();
- StringTable.append(Str.begin(), Str.end());
- StringTable.push_back(0);
- StringTableMap[Str] = Index;
- return Index;
- }
- return i->second;
- }
-
- COFFYAML::Object &Obj;
-
- StringMap<unsigned> StringTableMap;
- std::string StringTable;
-};
-
-// Take a CP and assign addresses and sizes to everything. Returns false if the
-// layout is not valid to do.
-static bool layoutCOFF(COFFParser &CP) {
- uint32_t SectionTableStart = 0;
- uint32_t SectionTableSize = 0;
-
- // The section table starts immediately after the header, including the
- // optional header.
- SectionTableStart = sizeof(COFF::header) + CP.Obj.Header.SizeOfOptionalHeader;
- SectionTableSize = sizeof(COFF::section) * CP.Obj.Sections.size();
-
- uint32_t CurrentSectionDataOffset = SectionTableStart + SectionTableSize;
-
- // Assign each section data address consecutively.
- for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(),
- e = CP.Obj.Sections.end();
- i != e; ++i) {
- if (!i->SectionData.empty()) {
- i->Header.SizeOfRawData = i->SectionData.size()/2;
- i->Header.PointerToRawData = CurrentSectionDataOffset;
- CurrentSectionDataOffset += i->Header.SizeOfRawData;
- if (!i->Relocations.empty()) {
- i->Header.PointerToRelocations = CurrentSectionDataOffset;
- i->Header.NumberOfRelocations = i->Relocations.size();
- CurrentSectionDataOffset += i->Header.NumberOfRelocations *
- COFF::RelocationSize;
- }
- // TODO: Handle alignment.
- } else {
- i->Header.SizeOfRawData = 0;
- i->Header.PointerToRawData = 0;
- }
- }
-
- uint32_t SymbolTableStart = CurrentSectionDataOffset;
-
- // Calculate number of symbols.
- uint32_t NumberOfSymbols = 0;
- for (std::vector<COFFYAML::Symbol>::iterator i = CP.Obj.Symbols.begin(),
- e = CP.Obj.Symbols.end();
- i != e; ++i) {
- unsigned AuxBytes = i->AuxiliaryData.size() / 2;
- if (AuxBytes % COFF::SymbolSize != 0) {
- errs() << "AuxiliaryData size not a multiple of symbol size!\n";
- return false;
- }
- i->Header.NumberOfAuxSymbols = AuxBytes / COFF::SymbolSize;
- NumberOfSymbols += 1 + i->Header.NumberOfAuxSymbols;
- }
-
- // Store all the allocated start addresses in the header.
- CP.Obj.Header.NumberOfSections = CP.Obj.Sections.size();
- CP.Obj.Header.NumberOfSymbols = NumberOfSymbols;
- CP.Obj.Header.PointerToSymbolTable = SymbolTableStart;
-
- *reinterpret_cast<support::ulittle32_t *>(&CP.StringTable[0])
- = CP.StringTable.size();
-
- return true;
-}
-
-template <typename value_type>
-struct binary_le_impl {
- value_type Value;
- binary_le_impl(value_type V) : Value(V) {}
-};
-
-template <typename value_type>
-raw_ostream &operator <<( raw_ostream &OS
- , const binary_le_impl<value_type> &BLE) {
- char Buffer[sizeof(BLE.Value)];
- support::endian::write<value_type, support::little, support::unaligned>(
- Buffer, BLE.Value);
- OS.write(Buffer, sizeof(BLE.Value));
- return OS;
-}
-
-template <typename value_type>
-binary_le_impl<value_type> binary_le(value_type V) {
- return binary_le_impl<value_type>(V);
-}
-
-static bool writeHexData(StringRef Data, raw_ostream &OS) {
- unsigned Size = Data.size();
- if (Size % 2)
- return false;
-
- for (unsigned I = 0; I != Size; I += 2) {
- uint8_t Byte;
- if (Data.substr(I, 2).getAsInteger(16, Byte))
- return false;
- OS.write(Byte);
- }
-
- return true;
-}
-
-bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
- OS << binary_le(CP.Obj.Header.Machine)
- << binary_le(CP.Obj.Header.NumberOfSections)
- << binary_le(CP.Obj.Header.TimeDateStamp)
- << binary_le(CP.Obj.Header.PointerToSymbolTable)
- << binary_le(CP.Obj.Header.NumberOfSymbols)
- << binary_le(CP.Obj.Header.SizeOfOptionalHeader)
- << binary_le(CP.Obj.Header.Characteristics);
-
- // Output section table.
- for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(),
- e = CP.Obj.Sections.end();
- i != e; ++i) {
- OS.write(i->Header.Name, COFF::NameSize);
- OS << binary_le(i->Header.VirtualSize)
- << binary_le(i->Header.VirtualAddress)
- << binary_le(i->Header.SizeOfRawData)
- << binary_le(i->Header.PointerToRawData)
- << binary_le(i->Header.PointerToRelocations)
- << binary_le(i->Header.PointerToLineNumbers)
- << binary_le(i->Header.NumberOfRelocations)
- << binary_le(i->Header.NumberOfLineNumbers)
- << binary_le(i->Header.Characteristics);
- }
-
- // Output section data.
- for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(),
- e = CP.Obj.Sections.end();
- i != e; ++i) {
- if (!i->SectionData.empty()) {
- if (!writeHexData(i->SectionData, OS)) {
- errs() << "SectionData must be a collection of pairs of hex bytes";
- return false;
- }
- }
- for (unsigned I2 = 0, E2 = i->Relocations.size(); I2 != E2; ++I2) {
- const COFF::relocation &R = i->Relocations[I2];
- OS << binary_le(R.VirtualAddress)
- << binary_le(R.SymbolTableIndex)
- << binary_le(R.Type);
- }
- }
-
- // Output symbol table.
-
- for (std::vector<COFFYAML::Symbol>::const_iterator i = CP.Obj.Symbols.begin(),
- e = CP.Obj.Symbols.end();
- i != e; ++i) {
- OS.write(i->Header.Name, COFF::NameSize);
- OS << binary_le(i->Header.Value)
- << binary_le(i->Header.SectionNumber)
- << binary_le(i->Header.Type)
- << binary_le(i->Header.StorageClass)
- << binary_le(i->Header.NumberOfAuxSymbols);
- if (!i->AuxiliaryData.empty()) {
- if (!writeHexData(i->AuxiliaryData, OS)) {
- errs() << "AuxiliaryData must be a collection of pairs of hex bytes";
- return false;
- }
- }
- }
-
- // Output string table.
- OS.write(&CP.StringTable[0], CP.StringTable.size());
- return true;
-}
-
-LLVM_YAML_IS_SEQUENCE_VECTOR(COFF::relocation)
-LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Section)
-LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Symbol)
-
-namespace llvm {
-
-namespace COFF {
- Characteristics operator|(Characteristics a, Characteristics b) {
- uint32_t Ret = static_cast<uint32_t>(a) | static_cast<uint32_t>(b);
- return static_cast<Characteristics>(Ret);
- }
-
- SectionCharacteristics
- operator|(SectionCharacteristics a, SectionCharacteristics b) {
- uint32_t Ret = static_cast<uint32_t>(a) | static_cast<uint32_t>(b);
- return static_cast<SectionCharacteristics>(Ret);
- }
-}
-
-namespace yaml {
-
-#define BCase(X) IO.bitSetCase(Value, #X, COFF::X);
-
-template <>
-struct ScalarBitSetTraits<COFF::SectionCharacteristics> {
- static void bitset(IO &IO, COFF::SectionCharacteristics &Value) {
- BCase(IMAGE_SCN_TYPE_NO_PAD);
- BCase(IMAGE_SCN_CNT_CODE);
- BCase(IMAGE_SCN_CNT_INITIALIZED_DATA);
- BCase(IMAGE_SCN_CNT_UNINITIALIZED_DATA);
- BCase(IMAGE_SCN_LNK_OTHER);
- BCase(IMAGE_SCN_LNK_INFO);
- BCase(IMAGE_SCN_LNK_REMOVE);
- BCase(IMAGE_SCN_LNK_COMDAT);
- BCase(IMAGE_SCN_GPREL);
- BCase(IMAGE_SCN_MEM_PURGEABLE);
- BCase(IMAGE_SCN_MEM_16BIT);
- BCase(IMAGE_SCN_MEM_LOCKED);
- BCase(IMAGE_SCN_MEM_PRELOAD);
- BCase(IMAGE_SCN_ALIGN_1BYTES);
- BCase(IMAGE_SCN_ALIGN_2BYTES);
- BCase(IMAGE_SCN_ALIGN_4BYTES);
- BCase(IMAGE_SCN_ALIGN_8BYTES);
- BCase(IMAGE_SCN_ALIGN_16BYTES);
- BCase(IMAGE_SCN_ALIGN_32BYTES);
- BCase(IMAGE_SCN_ALIGN_64BYTES);
- BCase(IMAGE_SCN_ALIGN_128BYTES);
- BCase(IMAGE_SCN_ALIGN_256BYTES);
- BCase(IMAGE_SCN_ALIGN_512BYTES);
- BCase(IMAGE_SCN_ALIGN_1024BYTES);
- BCase(IMAGE_SCN_ALIGN_2048BYTES);
- BCase(IMAGE_SCN_ALIGN_4096BYTES);
- BCase(IMAGE_SCN_ALIGN_8192BYTES);
- BCase(IMAGE_SCN_LNK_NRELOC_OVFL);
- BCase(IMAGE_SCN_MEM_DISCARDABLE);
- BCase(IMAGE_SCN_MEM_NOT_CACHED);
- BCase(IMAGE_SCN_MEM_NOT_PAGED);
- BCase(IMAGE_SCN_MEM_SHARED);
- BCase(IMAGE_SCN_MEM_EXECUTE);
- BCase(IMAGE_SCN_MEM_READ);
- BCase(IMAGE_SCN_MEM_WRITE);
- }
-};
-
-template <>
-struct ScalarBitSetTraits<COFF::Characteristics> {
- static void bitset(IO &IO, COFF::Characteristics &Value) {
- BCase(IMAGE_FILE_RELOCS_STRIPPED);
- BCase(IMAGE_FILE_EXECUTABLE_IMAGE);
- BCase(IMAGE_FILE_LINE_NUMS_STRIPPED);
- BCase(IMAGE_FILE_LOCAL_SYMS_STRIPPED);
- BCase(IMAGE_FILE_AGGRESSIVE_WS_TRIM);
- BCase(IMAGE_FILE_LARGE_ADDRESS_AWARE);
- BCase(IMAGE_FILE_BYTES_REVERSED_LO);
- BCase(IMAGE_FILE_32BIT_MACHINE);
- BCase(IMAGE_FILE_DEBUG_STRIPPED);
- BCase(IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP);
- BCase(IMAGE_FILE_NET_RUN_FROM_SWAP);
- BCase(IMAGE_FILE_SYSTEM);
- BCase(IMAGE_FILE_DLL);
- BCase(IMAGE_FILE_UP_SYSTEM_ONLY);
- BCase(IMAGE_FILE_BYTES_REVERSED_HI);
- }
-};
-#undef BCase
-
-#define ECase(X) IO.enumCase(Value, #X, COFF::X);
-
-template <>
-struct ScalarEnumerationTraits<COFF::SymbolComplexType> {
- static void enumeration(IO &IO, COFF::SymbolComplexType &Value) {
- ECase(IMAGE_SYM_DTYPE_NULL);
- ECase(IMAGE_SYM_DTYPE_POINTER);
- ECase(IMAGE_SYM_DTYPE_FUNCTION);
- ECase(IMAGE_SYM_DTYPE_ARRAY);
- }
-};
-
-template <>
-struct ScalarEnumerationTraits<COFF::SymbolStorageClass> {
- static void enumeration(IO &IO, COFF::SymbolStorageClass &Value) {
- ECase(IMAGE_SYM_CLASS_END_OF_FUNCTION);
- ECase(IMAGE_SYM_CLASS_NULL);
- ECase(IMAGE_SYM_CLASS_AUTOMATIC);
- ECase(IMAGE_SYM_CLASS_EXTERNAL);
- ECase(IMAGE_SYM_CLASS_STATIC);
- ECase(IMAGE_SYM_CLASS_REGISTER);
- ECase(IMAGE_SYM_CLASS_EXTERNAL_DEF);
- ECase(IMAGE_SYM_CLASS_LABEL);
- ECase(IMAGE_SYM_CLASS_UNDEFINED_LABEL);
- ECase(IMAGE_SYM_CLASS_MEMBER_OF_STRUCT);
- ECase(IMAGE_SYM_CLASS_ARGUMENT);
- ECase(IMAGE_SYM_CLASS_STRUCT_TAG);
- ECase(IMAGE_SYM_CLASS_MEMBER_OF_UNION);
- ECase(IMAGE_SYM_CLASS_UNION_TAG);
- ECase(IMAGE_SYM_CLASS_TYPE_DEFINITION);
- ECase(IMAGE_SYM_CLASS_UNDEFINED_STATIC);
- ECase(IMAGE_SYM_CLASS_ENUM_TAG);
- ECase(IMAGE_SYM_CLASS_MEMBER_OF_ENUM);
- ECase(IMAGE_SYM_CLASS_REGISTER_PARAM);
- ECase(IMAGE_SYM_CLASS_BIT_FIELD);
- ECase(IMAGE_SYM_CLASS_BLOCK);
- ECase(IMAGE_SYM_CLASS_FUNCTION);
- ECase(IMAGE_SYM_CLASS_END_OF_STRUCT);
- ECase(IMAGE_SYM_CLASS_FILE);
- ECase(IMAGE_SYM_CLASS_SECTION);
- ECase(IMAGE_SYM_CLASS_WEAK_EXTERNAL);
- ECase(IMAGE_SYM_CLASS_CLR_TOKEN);
- }
-};
-
-template <>
-struct ScalarEnumerationTraits<COFF::SymbolBaseType> {
- static void enumeration(IO &IO, COFF::SymbolBaseType &Value) {
- ECase(IMAGE_SYM_TYPE_NULL);
- ECase(IMAGE_SYM_TYPE_VOID);
- ECase(IMAGE_SYM_TYPE_CHAR);
- ECase(IMAGE_SYM_TYPE_SHORT);
- ECase(IMAGE_SYM_TYPE_INT);
- ECase(IMAGE_SYM_TYPE_LONG);
- ECase(IMAGE_SYM_TYPE_FLOAT);
- ECase(IMAGE_SYM_TYPE_DOUBLE);
- ECase(IMAGE_SYM_TYPE_STRUCT);
- ECase(IMAGE_SYM_TYPE_UNION);
- ECase(IMAGE_SYM_TYPE_ENUM);
- ECase(IMAGE_SYM_TYPE_MOE);
- ECase(IMAGE_SYM_TYPE_BYTE);
- ECase(IMAGE_SYM_TYPE_WORD);
- ECase(IMAGE_SYM_TYPE_UINT);
- ECase(IMAGE_SYM_TYPE_DWORD);
- }
-};
-
-template <>
-struct ScalarEnumerationTraits<COFF::MachineTypes> {
- static void enumeration(IO &IO, COFF::MachineTypes &Value) {
- ECase(IMAGE_FILE_MACHINE_UNKNOWN);
- ECase(IMAGE_FILE_MACHINE_AM33);
- ECase(IMAGE_FILE_MACHINE_AMD64);
- ECase(IMAGE_FILE_MACHINE_ARM);
- ECase(IMAGE_FILE_MACHINE_ARMV7);
- ECase(IMAGE_FILE_MACHINE_EBC);
- ECase(IMAGE_FILE_MACHINE_I386);
- ECase(IMAGE_FILE_MACHINE_IA64);
- ECase(IMAGE_FILE_MACHINE_M32R);
- ECase(IMAGE_FILE_MACHINE_MIPS16);
- ECase(IMAGE_FILE_MACHINE_MIPSFPU);
- ECase(IMAGE_FILE_MACHINE_MIPSFPU16);
- ECase(IMAGE_FILE_MACHINE_POWERPC);
- ECase(IMAGE_FILE_MACHINE_POWERPCFP);
- ECase(IMAGE_FILE_MACHINE_R4000);
- ECase(IMAGE_FILE_MACHINE_SH3);
- ECase(IMAGE_FILE_MACHINE_SH3DSP);
- ECase(IMAGE_FILE_MACHINE_SH4);
- ECase(IMAGE_FILE_MACHINE_SH5);
- ECase(IMAGE_FILE_MACHINE_THUMB);
- ECase(IMAGE_FILE_MACHINE_WCEMIPSV2);
- }
-};
-
-template <>
-struct ScalarEnumerationTraits<COFF::RelocationTypeX86> {
- static void enumeration(IO &IO, COFF::RelocationTypeX86 &Value) {
- ECase(IMAGE_REL_I386_ABSOLUTE);
- ECase(IMAGE_REL_I386_DIR16);
- ECase(IMAGE_REL_I386_REL16);
- ECase(IMAGE_REL_I386_DIR32);
- ECase(IMAGE_REL_I386_DIR32NB);
- ECase(IMAGE_REL_I386_SEG12);
- ECase(IMAGE_REL_I386_SECTION);
- ECase(IMAGE_REL_I386_SECREL);
- ECase(IMAGE_REL_I386_TOKEN);
- ECase(IMAGE_REL_I386_SECREL7);
- ECase(IMAGE_REL_I386_REL32);
- ECase(IMAGE_REL_AMD64_ABSOLUTE);
- ECase(IMAGE_REL_AMD64_ADDR64);
- ECase(IMAGE_REL_AMD64_ADDR32);
- ECase(IMAGE_REL_AMD64_ADDR32NB);
- ECase(IMAGE_REL_AMD64_REL32);
- ECase(IMAGE_REL_AMD64_REL32_1);
- ECase(IMAGE_REL_AMD64_REL32_2);
- ECase(IMAGE_REL_AMD64_REL32_3);
- ECase(IMAGE_REL_AMD64_REL32_4);
- ECase(IMAGE_REL_AMD64_REL32_5);
- ECase(IMAGE_REL_AMD64_SECTION);
- ECase(IMAGE_REL_AMD64_SECREL);
- ECase(IMAGE_REL_AMD64_SECREL7);
- ECase(IMAGE_REL_AMD64_TOKEN);
- ECase(IMAGE_REL_AMD64_SREL32);
- ECase(IMAGE_REL_AMD64_PAIR);
- ECase(IMAGE_REL_AMD64_SSPAN32);
- }
-};
-
-#undef ECase
-
-template <>
-struct MappingTraits<COFFYAML::Symbol> {
- struct NStorageClass {
- NStorageClass(IO&) : StorageClass(COFF::SymbolStorageClass(0)) {
- }
- NStorageClass(IO&, uint8_t S) : StorageClass(COFF::SymbolStorageClass(S)) {
- }
- uint8_t denormalize(IO &) {
- return StorageClass;
- }
-
- COFF::SymbolStorageClass StorageClass;
- };
-
- static void mapping(IO &IO, COFFYAML::Symbol &S) {
- MappingNormalization<NStorageClass, uint8_t> NS(IO, S.Header.StorageClass);
-
- IO.mapRequired("SimpleType", S.SimpleType);
- IO.mapOptional("NumberOfAuxSymbols", S.Header.NumberOfAuxSymbols);
- IO.mapRequired("Name", S.Name);
- IO.mapRequired("StorageClass", NS->StorageClass);
- IO.mapOptional("AuxiliaryData", S.AuxiliaryData);
- IO.mapRequired("ComplexType", S.ComplexType);
- IO.mapRequired("Value", S.Header.Value);
- IO.mapRequired("SectionNumber", S.Header.SectionNumber);
- }
+// TODO: The "right" way to tell what kind of object file a given YAML file
+// corresponds to is to look at YAML "tags" (e.g. `!Foo`). Then, different
+// tags (`!ELF`, `!COFF`, etc.) would be used to discriminate between them.
+// Interpreting the tags is needed eventually for when writing test cases,
+// so that we can e.g. have `!Archive` contain a sequence of `!ELF`, and
+// just Do The Right Thing. However, interpreting these tags and acting on
+// them appropriately requires some work in the YAML parser and the YAMLIO
+// library.
+enum YAMLObjectFormat {
+ YOF_COFF,
+ YOF_ELF
};
-template <>
-struct MappingTraits<COFF::header> {
- struct NMachine {
- NMachine(IO&) : Machine(COFF::MachineTypes(0)) {
- }
- NMachine(IO&, uint16_t M) : Machine(COFF::MachineTypes(M)) {
- }
- uint16_t denormalize(IO &) {
- return Machine;
- }
- COFF::MachineTypes Machine;
- };
-
- struct NCharacteristics {
- NCharacteristics(IO&) : Characteristics(COFF::Characteristics(0)) {
- }
- NCharacteristics(IO&, uint16_t C) :
- Characteristics(COFF::Characteristics(C)) {
- }
- uint16_t denormalize(IO &) {
- return Characteristics;
- }
+cl::opt<YAMLObjectFormat> Format(
+ "format",
+ cl::desc("Interpret input as this type of object file"),
+ cl::values(
+ clEnumValN(YOF_COFF, "coff", "COFF object file format"),
+ clEnumValN(YOF_ELF, "elf", "ELF object file format"),
+ clEnumValEnd));
- COFF::Characteristics Characteristics;
- };
-
- static void mapping(IO &IO, COFF::header &H) {
- MappingNormalization<NMachine, uint16_t> NM(IO, H.Machine);
- MappingNormalization<NCharacteristics, uint16_t> NC(IO, H.Characteristics);
-
- IO.mapRequired("Machine", NM->Machine);
- IO.mapOptional("Characteristics", NC->Characteristics);
- }
-};
-
-template <>
-struct MappingTraits<COFF::relocation> {
- struct NType {
- NType(IO &) : Type(COFF::RelocationTypeX86(0)) {
- }
- NType(IO &, uint16_t T) : Type(COFF::RelocationTypeX86(T)) {
- }
- uint16_t denormalize(IO &) {
- return Type;
- }
- COFF::RelocationTypeX86 Type;
- };
-
- static void mapping(IO &IO, COFF::relocation &Rel) {
- MappingNormalization<NType, uint16_t> NT(IO, Rel.Type);
-
- IO.mapRequired("Type", NT->Type);
- IO.mapRequired("VirtualAddress", Rel.VirtualAddress);
- IO.mapRequired("SymbolTableIndex", Rel.SymbolTableIndex);
- }
-};
-
-template <>
-struct MappingTraits<COFFYAML::Section> {
- struct NCharacteristics {
- NCharacteristics(IO &) : Characteristics(COFF::SectionCharacteristics(0)) {
- }
- NCharacteristics(IO &, uint32_t C) :
- Characteristics(COFF::SectionCharacteristics(C)) {
- }
- uint32_t denormalize(IO &) {
- return Characteristics;
- }
- COFF::SectionCharacteristics Characteristics;
- };
-
- static void mapping(IO &IO, COFFYAML::Section &Sec) {
- MappingNormalization<NCharacteristics, uint32_t> NC(IO,
- Sec.Header.Characteristics);
- IO.mapOptional("Relocations", Sec.Relocations);
- IO.mapRequired("SectionData", Sec.SectionData);
- IO.mapRequired("Characteristics", NC->Characteristics);
- IO.mapRequired("Name", Sec.Name);
- }
-};
-
-template <>
-struct MappingTraits<COFFYAML::Object> {
- static void mapping(IO &IO, COFFYAML::Object &Obj) {
- IO.mapRequired("sections", Obj.Sections);
- IO.mapRequired("header", Obj.Header);
- IO.mapRequired("symbols", Obj.Symbols);
- }
-};
-} // end namespace yaml
-} // end namespace llvm
int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv);
@@ -664,27 +60,12 @@ int main(int argc, char **argv) {
OwningPtr<MemoryBuffer> Buf;
if (MemoryBuffer::getFileOrSTDIN(Input, Buf))
return 1;
-
- yaml::Input YIn(Buf->getBuffer());
- COFFYAML::Object Doc;
- YIn >> Doc;
- if (YIn.error()) {
- errs() << "yaml2obj: Failed to parse YAML file!\n";
- return 1;
- }
-
- COFFParser CP(Doc);
- if (!CP.parse()) {
- errs() << "yaml2obj: Failed to parse YAML file!\n";
- return 1;
- }
-
- if (!layoutCOFF(CP)) {
- errs() << "yaml2obj: Failed to layout COFF file!\n";
- return 1;
- }
- if (!writeCOFF(CP, outs())) {
- errs() << "yaml2obj: Failed to write COFF file!\n";
+ if (Format == YOF_COFF) {
+ return yaml2coff(outs(), Buf.get());
+ } else if (Format == YOF_ELF) {
+ return yaml2elf(outs(), Buf.get());
+ } else {
+ errs() << "Not yet implemented\n";
return 1;
}
}
diff --git a/tools/yaml2obj/yaml2obj.h b/tools/yaml2obj/yaml2obj.h
new file mode 100644
index 0000000..095435c
--- /dev/null
+++ b/tools/yaml2obj/yaml2obj.h
@@ -0,0 +1,22 @@
+//===--- yaml2obj.h - -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief Common declarations for yaml2obj
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_YAML2OBJ_H
+#define LLVM_TOOLS_YAML2OBJ_H
+
+namespace llvm {
+ class raw_ostream;
+ class MemoryBuffer;
+}
+int yaml2coff(llvm::raw_ostream &Out, llvm::MemoryBuffer *Buf);
+int yaml2elf(llvm::raw_ostream &Out, llvm::MemoryBuffer *Buf);
+
+#endif