diff options
author | dim <dim@FreeBSD.org> | 2012-02-05 23:56:22 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-02-05 23:56:22 +0000 |
commit | eb8951e7f7015d193e6640deb0ebde32f01b72d8 (patch) | |
tree | 8052b8010f619e8d40e5e3b37482591f537e0ca0 /contrib/llvm/tools/llvm-objdump/MCFunction.cpp | |
parent | 4de4d315e465f872a81f448b1788cc017f2d2033 (diff) | |
parent | 07637c87f826cdf411f0673595e9bc92ebd793f2 (diff) | |
download | FreeBSD-src-eb8951e7f7015d193e6640deb0ebde32f01b72d8.zip FreeBSD-src-eb8951e7f7015d193e6640deb0ebde32f01b72d8.tar.gz |
Add a WITH_CLANG_EXTRAS option for src.conf(5), disabled by default,
that builds the following additional llvm/clang tools:
- bugpoint
- llc
- lli
- llvm-ar
- llvm-as
- llvm-bcanalyzer
- llvm-diff
- llvm-dis
- llvm-extract
- llvm-ld
- llvm-link
- llvm-mc
- llvm-nm
- llvm-objdump
- llvm-prof
- llvm-ranlib
- llvm-rtdyld
- llvm-stub
- macho-dump
- opt
These tools are mainly useful for people that want to manipulate llvm
bitcode (.bc) and llvm assembly language (.ll) files, or want to tinker
with llvm and clang themselves.
MFC after: 2 weeks
Diffstat (limited to 'contrib/llvm/tools/llvm-objdump/MCFunction.cpp')
-rw-r--r-- | contrib/llvm/tools/llvm-objdump/MCFunction.cpp | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/contrib/llvm/tools/llvm-objdump/MCFunction.cpp b/contrib/llvm/tools/llvm-objdump/MCFunction.cpp new file mode 100644 index 0000000..5c67f1b --- /dev/null +++ b/contrib/llvm/tools/llvm-objdump/MCFunction.cpp @@ -0,0 +1,138 @@ +//===-- 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; +} |