]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/tools/llvm-mc/Disassembler.cpp
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / tools / llvm-mc / Disassembler.cpp
1 //===- Disassembler.cpp - Disassembler for hex strings --------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This class implements the disassembler of strings of bytes written in
11 // hexadecimal, from standard input or from a file.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "Disassembler.h"
16 #include "llvm/ADT/OwningPtr.h"
17 #include "llvm/ADT/Triple.h"
18 #include "llvm/MC/MCDisassembler.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCStreamer.h"
21 #include "llvm/MC/MCSubtargetInfo.h"
22 #include "llvm/Support/MemoryBuffer.h"
23 #include "llvm/Support/MemoryObject.h"
24 #include "llvm/Support/SourceMgr.h"
25 #include "llvm/Support/TargetRegistry.h"
26 #include "llvm/Support/raw_ostream.h"
27
28 using namespace llvm;
29
30 typedef std::vector<std::pair<unsigned char, const char*> > ByteArrayTy;
31
32 namespace {
33 class VectorMemoryObject : public MemoryObject {
34 private:
35   const ByteArrayTy &Bytes;
36 public:
37   VectorMemoryObject(const ByteArrayTy &bytes) : Bytes(bytes) {}
38
39   uint64_t getBase() const { return 0; }
40   uint64_t getExtent() const { return Bytes.size(); }
41
42   int readByte(uint64_t Addr, uint8_t *Byte) const {
43     if (Addr >= getExtent())
44       return -1;
45     *Byte = Bytes[Addr].first;
46     return 0;
47   }
48 };
49 }
50
51 static bool PrintInsts(const MCDisassembler &DisAsm,
52                        const ByteArrayTy &Bytes,
53                        SourceMgr &SM, raw_ostream &Out,
54                        MCStreamer &Streamer) {
55   // Wrap the vector in a MemoryObject.
56   VectorMemoryObject memoryObject(Bytes);
57
58   // Disassemble it to strings.
59   uint64_t Size;
60   uint64_t Index;
61
62   for (Index = 0; Index < Bytes.size(); Index += Size) {
63     MCInst Inst;
64
65     MCDisassembler::DecodeStatus S;
66     S = DisAsm.getInstruction(Inst, Size, memoryObject, Index,
67                               /*REMOVE*/ nulls(), nulls());
68     switch (S) {
69     case MCDisassembler::Fail:
70       SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
71                       SourceMgr::DK_Warning,
72                       "invalid instruction encoding");
73       if (Size == 0)
74         Size = 1; // skip illegible bytes
75       break;
76
77     case MCDisassembler::SoftFail:
78       SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
79                       SourceMgr::DK_Warning,
80                       "potentially undefined instruction encoding");
81       // Fall through
82
83     case MCDisassembler::Success:
84       Streamer.EmitInstruction(Inst);
85       break;
86     }
87   }
88
89   return false;
90 }
91
92 static bool ByteArrayFromString(ByteArrayTy &ByteArray,
93                                 StringRef &Str,
94                                 SourceMgr &SM) {
95   while (!Str.empty()) {
96     // Strip horizontal whitespace.
97     if (size_t Pos = Str.find_first_not_of(" \t\r")) {
98       Str = Str.substr(Pos);
99       continue;
100     }
101
102     // If this is the end of a line or start of a comment, remove the rest of
103     // the line.
104     if (Str[0] == '\n' || Str[0] == '#') {
105       // Strip to the end of line if we already processed any bytes on this
106       // line.  This strips the comment and/or the \n.
107       if (Str[0] == '\n') {
108         Str = Str.substr(1);
109       } else {
110         Str = Str.substr(Str.find_first_of('\n'));
111         if (!Str.empty())
112           Str = Str.substr(1);
113       }
114       continue;
115     }
116
117     // Get the current token.
118     size_t Next = Str.find_first_of(" \t\n\r#");
119     StringRef Value = Str.substr(0, Next);
120
121     // Convert to a byte and add to the byte vector.
122     unsigned ByteVal;
123     if (Value.getAsInteger(0, ByteVal) || ByteVal > 255) {
124       // If we have an error, print it and skip to the end of line.
125       SM.PrintMessage(SMLoc::getFromPointer(Value.data()), SourceMgr::DK_Error,
126                       "invalid input token");
127       Str = Str.substr(Str.find('\n'));
128       ByteArray.clear();
129       continue;
130     }
131
132     ByteArray.push_back(std::make_pair((unsigned char)ByteVal, Value.data()));
133     Str = Str.substr(Next);
134   }
135
136   return false;
137 }
138
139 int Disassembler::disassemble(const Target &T,
140                               const std::string &Triple,
141                               MCSubtargetInfo &STI,
142                               MCStreamer &Streamer,
143                               MemoryBuffer &Buffer,
144                               SourceMgr &SM,
145                               raw_ostream &Out) {
146   OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler(STI));
147   if (!DisAsm) {
148     errs() << "error: no disassembler for target " << Triple << "\n";
149     return -1;
150   }
151
152   // Set up initial section manually here
153   Streamer.InitSections();
154
155   bool ErrorOccurred = false;
156
157   // Convert the input to a vector for disassembly.
158   ByteArrayTy ByteArray;
159   StringRef Str = Buffer.getBuffer();
160
161   ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM);
162
163   if (!ByteArray.empty())
164     ErrorOccurred |= PrintInsts(*DisAsm, ByteArray, SM, Out, Streamer);
165
166   return ErrorOccurred;
167 }