summaryrefslogtreecommitdiff
path: root/tools/llvm-objdump
diff options
context:
space:
mode:
authorAhmed Bougacha <ahmed.bougacha@gmail.com>2013-08-21 07:29:02 +0000
committerAhmed Bougacha <ahmed.bougacha@gmail.com>2013-08-21 07:29:02 +0000
commit171ac8ca175bec5bc0bff8b3006850f70e0569c9 (patch)
tree629e8af629e547fae5ee5d1fca6d1a8837d6826b /tools/llvm-objdump
parentf176482752fbea3139394e280adfb10270dd3aac (diff)
downloadllvm-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.cpp38
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);
}
}