diff options
author | Ahmed Bougacha <ahmed.bougacha@gmail.com> | 2013-08-21 07:29:02 +0000 |
---|---|---|
committer | Ahmed Bougacha <ahmed.bougacha@gmail.com> | 2013-08-21 07:29:02 +0000 |
commit | 171ac8ca175bec5bc0bff8b3006850f70e0569c9 (patch) | |
tree | 629e8af629e547fae5ee5d1fca6d1a8837d6826b /tools/llvm-objdump | |
parent | f176482752fbea3139394e280adfb10270dd3aac (diff) | |
download | llvm-171ac8ca175bec5bc0bff8b3006850f70e0569c9.tar.gz llvm-171ac8ca175bec5bc0bff8b3006850f70e0569c9.tar.bz2 llvm-171ac8ca175bec5bc0bff8b3006850f70e0569c9.tar.xz |
MC CFG: Add YAML MCModule representation to enable MC CFG testing.
Like yaml ObjectFiles, this will be very useful for testing the MC CFG
implementation (mostly MCObjectDisassembler), by matching the output
with YAML, and for potential users of the MC CFG, by using it as an input.
There isn't much to the actual format, it is just a serialization of the
MCModule class. Of note:
- Basic block references (pred/succ, ..) are represented by the BB's
start address.
- Just as in the MC CFG, instructions are MCInsts with a size.
- Operands have a prefix representing the type (only register and
immediate supported here).
- Instruction opcodes are represented by their names; enum values aren't
stable, enum names mostly are: usually, a change to a name would need
lots of changes in the backend anyway.
Same with registers.
All in all, an example is better than 1000 words, here goes:
A simple binary:
Disassembly of section __TEXT,__text:
_main:
100000f9c: 48 8b 46 08 movq 8(%rsi), %rax
100000fa0: 0f be 00 movsbl (%rax), %eax
100000fa3: 3b 04 25 48 00 00 00 cmpl 72, %eax
100000faa: 0f 8c 07 00 00 00 jl 7 <.Lend>
100000fb0: 2b 04 25 48 00 00 00 subl 72, %eax
.Lend:
100000fb7: c3 ret
And the (pretty verbose) generated YAML:
---
Atoms:
- StartAddress: 0x0000000100000F9C
Size: 20
Type: Text
Content:
- Inst: MOV64rm
Size: 4
Ops: [ RRAX, RRSI, I1, R, I8, R ]
- Inst: MOVSX32rm8
Size: 3
Ops: [ REAX, RRAX, I1, R, I0, R ]
- Inst: CMP32rm
Size: 7
Ops: [ REAX, R, I1, R, I72, R ]
- Inst: JL_4
Size: 6
Ops: [ I7 ]
- StartAddress: 0x0000000100000FB0
Size: 7
Type: Text
Content:
- Inst: SUB32rm
Size: 7
Ops: [ REAX, REAX, R, I1, R, I72, R ]
- StartAddress: 0x0000000100000FB7
Size: 1
Type: Text
Content:
- Inst: RET
Size: 1
Ops: [ ]
Functions:
- Name: __text
BasicBlocks:
- Address: 0x0000000100000F9C
Preds: [ ]
Succs: [ 0x0000000100000FB7, 0x0000000100000FB0 ]
<snip>
...
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@188890 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvm-objdump')
-rw-r--r-- | tools/llvm-objdump/llvm-objdump.cpp | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 122ac83398..a4cd6a2f73 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -31,6 +31,7 @@ #include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCModule.h" +#include "llvm/MC/MCModuleYAML.h" #include "llvm/MC/MCObjectDisassembler.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectSymbolizer.h" @@ -61,6 +62,7 @@ #include <algorithm> #include <cctype> #include <cstring> + using namespace llvm; using namespace object; @@ -139,6 +141,12 @@ 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")); +// FIXME: Does it make sense to have a dedicated tool for yaml cfg output? +static cl::opt<std::string> +YAMLCFG("yaml-cfg", + cl::desc("Create a CFG and write it as a YAML MCModule."), + cl::value_desc("yaml output file")); + static StringRef ToolName; bool llvm::error(error_code ec) { @@ -178,6 +186,7 @@ static const Target *getTarget(const ObjectFile *Obj = NULL) { } // Write a graphviz file for the CFG inside an MCFunction. +// FIXME: Use GraphWriter static void emitDOTFile(const char *FileName, const MCFunction &f, MCInstPrinter *IP) { // Start a new dot file. @@ -333,7 +342,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { return; } - if (CFG) { + if (CFG || !YAMLCFG.empty()) { OwningPtr<MCObjectDisassembler> OD( new MCObjectDisassembler(*Obj, *DisAsm, *MIA)); OwningPtr<MCModule> Mod(OD->buildModule(/* withCFG */ true)); @@ -350,14 +359,25 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { } } } - 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; + if (CFG) { + 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; + } + } + if (!YAMLCFG.empty()) { + std::string Error; + raw_fd_ostream YAMLOut(YAMLCFG.c_str(), Error); + if (!Error.empty()) { + errs() << "llvm-objdump: warning: " << Error << '\n'; + return; + } + mcmodule2yaml(YAMLOut, *Mod, *MII, *MRI); } } |