]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-mc/Disassembler.cpp
Upgrade our copy of llvm/clang to trunk r154661, in preparation of the
[FreeBSD/FreeBSD.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 "../../lib/MC/MCDisassembler/EDDisassembler.h"
17 #include "../../lib/MC/MCDisassembler/EDInst.h"
18 #include "../../lib/MC/MCDisassembler/EDOperand.h"
19 #include "../../lib/MC/MCDisassembler/EDToken.h"
20 #include "llvm/MC/MCAsmInfo.h"
21 #include "llvm/MC/MCDisassembler.h"
22 #include "llvm/MC/MCInst.h"
23 #include "llvm/MC/MCInstPrinter.h"
24 #include "llvm/MC/MCInstrInfo.h"
25 #include "llvm/MC/MCRegisterInfo.h"
26 #include "llvm/MC/MCSubtargetInfo.h"
27 #include "llvm/ADT/OwningPtr.h"
28 #include "llvm/ADT/Triple.h"
29 #include "llvm/ADT/Twine.h"
30 #include "llvm/Support/MemoryBuffer.h"
31 #include "llvm/Support/MemoryObject.h"
32 #include "llvm/Support/SourceMgr.h"
33 #include "llvm/Support/TargetRegistry.h"
34 #include "llvm/Support/raw_ostream.h"
35 using namespace llvm;
36
37 typedef std::vector<std::pair<unsigned char, const char*> > ByteArrayTy;
38
39 namespace {
40 class VectorMemoryObject : public MemoryObject {
41 private:
42   const ByteArrayTy &Bytes;
43 public:
44   VectorMemoryObject(const ByteArrayTy &bytes) : Bytes(bytes) {}
45
46   uint64_t getBase() const { return 0; }
47   uint64_t getExtent() const { return Bytes.size(); }
48
49   int readByte(uint64_t Addr, uint8_t *Byte) const {
50     if (Addr >= getExtent())
51       return -1;
52     *Byte = Bytes[Addr].first;
53     return 0;
54   }
55 };
56 }
57
58 static bool PrintInsts(const MCDisassembler &DisAsm,
59                        MCInstPrinter &Printer, const ByteArrayTy &Bytes,
60                        SourceMgr &SM, raw_ostream &Out) {
61   // Wrap the vector in a MemoryObject.
62   VectorMemoryObject memoryObject(Bytes);
63
64   // Disassemble it to strings.
65   uint64_t Size;
66   uint64_t Index;
67
68   for (Index = 0; Index < Bytes.size(); Index += Size) {
69     MCInst Inst;
70
71     MCDisassembler::DecodeStatus S;
72     S = DisAsm.getInstruction(Inst, Size, memoryObject, Index,
73                               /*REMOVE*/ nulls(), nulls());
74     switch (S) {
75     case MCDisassembler::Fail:
76       SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
77                       SourceMgr::DK_Warning,
78                       "invalid instruction encoding");
79       if (Size == 0)
80         Size = 1; // skip illegible bytes
81       break;
82
83     case MCDisassembler::SoftFail:
84       SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
85                       SourceMgr::DK_Warning,
86                       "potentially undefined instruction encoding");
87       // Fall through
88
89     case MCDisassembler::Success:
90       Printer.printInst(&Inst, Out, "");
91       Out << "\n";
92       break;
93     }
94   }
95
96   return false;
97 }
98
99 static bool ByteArrayFromString(ByteArrayTy &ByteArray,
100                                 StringRef &Str,
101                                 SourceMgr &SM) {
102   while (!Str.empty()) {
103     // Strip horizontal whitespace.
104     if (size_t Pos = Str.find_first_not_of(" \t\r")) {
105       Str = Str.substr(Pos);
106       continue;
107     }
108
109     // If this is the end of a line or start of a comment, remove the rest of
110     // the line.
111     if (Str[0] == '\n' || Str[0] == '#') {
112       // Strip to the end of line if we already processed any bytes on this
113       // line.  This strips the comment and/or the \n.
114       if (Str[0] == '\n') {
115         Str = Str.substr(1);
116       } else {
117         Str = Str.substr(Str.find_first_of('\n'));
118         if (!Str.empty())
119           Str = Str.substr(1);
120       }
121       continue;
122     }
123
124     // Get the current token.
125     size_t Next = Str.find_first_of(" \t\n\r#");
126     StringRef Value = Str.substr(0, Next);
127
128     // Convert to a byte and add to the byte vector.
129     unsigned ByteVal;
130     if (Value.getAsInteger(0, ByteVal) || ByteVal > 255) {
131       // If we have an error, print it and skip to the end of line.
132       SM.PrintMessage(SMLoc::getFromPointer(Value.data()), SourceMgr::DK_Error,
133                       "invalid input token");
134       Str = Str.substr(Str.find('\n'));
135       ByteArray.clear();
136       continue;
137     }
138
139     ByteArray.push_back(std::make_pair((unsigned char)ByteVal, Value.data()));
140     Str = Str.substr(Next);
141   }
142
143   return false;
144 }
145
146 int Disassembler::disassemble(const Target &T,
147                               const std::string &Triple,
148                               const std::string &Cpu,
149                               const std::string &FeaturesStr,
150                               MemoryBuffer &Buffer,
151                               raw_ostream &Out) {
152   // Set up disassembler.
153   OwningPtr<const MCAsmInfo> AsmInfo(T.createMCAsmInfo(Triple));
154
155   if (!AsmInfo) {
156     errs() << "error: no assembly info for target " << Triple << "\n";
157     return -1;
158   }
159
160   OwningPtr<const MCSubtargetInfo> STI(T.createMCSubtargetInfo(Triple, Cpu,
161                                                                FeaturesStr));
162   if (!STI) {
163     errs() << "error: no subtarget info for target " << Triple << "\n";
164     return -1;
165   }
166
167   OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler(*STI));
168   if (!DisAsm) {
169     errs() << "error: no disassembler for target " << Triple << "\n";
170     return -1;
171   }
172
173   OwningPtr<const MCRegisterInfo> MRI(T.createMCRegInfo(Triple));
174   if (!MRI) {
175     errs() << "error: no register info for target " << Triple << "\n";
176     return -1;
177   }
178
179   OwningPtr<const MCInstrInfo> MII(T.createMCInstrInfo());
180   if (!MII) {
181     errs() << "error: no instruction info for target " << Triple << "\n";
182     return -1;
183   }
184
185   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
186   OwningPtr<MCInstPrinter> IP(T.createMCInstPrinter(AsmPrinterVariant, *AsmInfo,
187                                                     *MII, *MRI, *STI));
188   if (!IP) {
189     errs() << "error: no instruction printer for target " << Triple << '\n';
190     return -1;
191   }
192
193   bool ErrorOccurred = false;
194
195   SourceMgr SM;
196   SM.AddNewSourceBuffer(&Buffer, SMLoc());
197
198   // Convert the input to a vector for disassembly.
199   ByteArrayTy ByteArray;
200   StringRef Str = Buffer.getBuffer();
201
202   ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM);
203
204   if (!ByteArray.empty())
205     ErrorOccurred |= PrintInsts(*DisAsm, *IP, ByteArray, SM, Out);
206
207   return ErrorOccurred;
208 }
209
210 static int byteArrayReader(uint8_t *B, uint64_t A, void *Arg) {
211   ByteArrayTy &ByteArray = *((ByteArrayTy*)Arg);
212
213   if (A >= ByteArray.size())
214     return -1;
215
216   *B = ByteArray[A].first;
217
218   return 0;
219 }
220
221 static int verboseEvaluator(uint64_t *V, unsigned R, void *Arg) {
222   EDDisassembler &disassembler = *(EDDisassembler *)((void **)Arg)[0];
223   raw_ostream &Out = *(raw_ostream *)((void **)Arg)[1];
224
225   if (const char *regName = disassembler.nameWithRegisterID(R))
226     Out << "[" << regName << "/" << R << "]";
227
228   if (disassembler.registerIsStackPointer(R))
229     Out << "(sp)";
230   if (disassembler.registerIsProgramCounter(R))
231     Out << "(pc)";
232
233   *V = 0;
234   return 0;
235 }
236
237 int Disassembler::disassembleEnhanced(const std::string &TS,
238                                       MemoryBuffer &Buffer,
239                                       raw_ostream &Out) {
240   ByteArrayTy ByteArray;
241   StringRef Str = Buffer.getBuffer();
242   SourceMgr SM;
243
244   SM.AddNewSourceBuffer(&Buffer, SMLoc());
245
246   if (ByteArrayFromString(ByteArray, Str, SM)) {
247     return -1;
248   }
249
250   Triple T(TS);
251   EDDisassembler::AssemblySyntax AS;
252
253   switch (T.getArch()) {
254   default:
255     errs() << "error: no default assembly syntax for " << TS.c_str() << "\n";
256     return -1;
257   case Triple::arm:
258   case Triple::thumb:
259     AS = EDDisassembler::kEDAssemblySyntaxARMUAL;
260     break;
261   case Triple::x86:
262   case Triple::x86_64:
263     AS = EDDisassembler::kEDAssemblySyntaxX86ATT;
264     break;
265   }
266
267   OwningPtr<EDDisassembler>
268     disassembler(EDDisassembler::getDisassembler(TS.c_str(), AS));
269
270   if (disassembler == 0) {
271     errs() << "error: couldn't get disassembler for " << TS << '\n';
272     return -1;
273   }
274
275   while (ByteArray.size()) {
276     OwningPtr<EDInst>
277       inst(disassembler->createInst(byteArrayReader, 0, &ByteArray));
278
279     if (inst == 0) {
280       errs() << "error: Didn't get an instruction\n";
281       return -1;
282     }
283
284     ByteArray.erase (ByteArray.begin(), ByteArray.begin() + inst->byteSize());
285
286     unsigned numTokens = inst->numTokens();
287     if ((int)numTokens < 0) {
288       errs() << "error: couldn't count the instruction's tokens\n";
289       return -1;
290     }
291
292     for (unsigned tokenIndex = 0; tokenIndex != numTokens; ++tokenIndex) {
293       EDToken *token;
294
295       if (inst->getToken(token, tokenIndex)) {
296         errs() << "error: Couldn't get token\n";
297         return -1;
298       }
299
300       const char *buf;
301       if (token->getString(buf)) {
302         errs() << "error: Couldn't get string for token\n";
303         return -1;
304       }
305
306       Out << '[';
307       int operandIndex = token->operandID();
308
309       if (operandIndex >= 0)
310         Out << operandIndex << "-";
311
312       switch (token->type()) {
313       case EDToken::kTokenWhitespace: Out << "w"; break;
314       case EDToken::kTokenPunctuation: Out << "p"; break;
315       case EDToken::kTokenOpcode: Out << "o"; break;
316       case EDToken::kTokenLiteral: Out << "l"; break;
317       case EDToken::kTokenRegister: Out << "r"; break;
318       }
319
320       Out << ":" << buf;
321
322       if (token->type() == EDToken::kTokenLiteral) {
323         Out << "=";
324         if (token->literalSign())
325           Out << "-";
326         uint64_t absoluteValue;
327         if (token->literalAbsoluteValue(absoluteValue)) {
328           errs() << "error: Couldn't get the value of a literal token\n";
329           return -1;
330         }
331         Out << absoluteValue;
332       } else if (token->type() == EDToken::kTokenRegister) {
333         Out << "=";
334         unsigned regID;
335         if (token->registerID(regID)) {
336           errs() << "error: Couldn't get the ID of a register token\n";
337           return -1;
338         }
339         Out << "r" << regID;
340       }
341
342       Out << "]";
343     }
344
345     Out << " ";
346
347     if (inst->isBranch())
348       Out << "<br> ";
349     if (inst->isMove())
350       Out << "<mov> ";
351
352     unsigned numOperands = inst->numOperands();
353
354     if ((int)numOperands < 0) {
355       errs() << "error: Couldn't count operands\n";
356       return -1;
357     }
358
359     for (unsigned operandIndex = 0; operandIndex != numOperands;
360          ++operandIndex) {
361       Out << operandIndex << ":";
362
363       EDOperand *operand;
364       if (inst->getOperand(operand, operandIndex)) {
365         errs() << "error: couldn't get operand\n";
366         return -1;
367       }
368
369       uint64_t evaluatedResult;
370       void *Arg[] = { disassembler.get(), &Out };
371       if (operand->evaluate(evaluatedResult, verboseEvaluator, Arg)) {
372         errs() << "error: Couldn't evaluate an operand\n";
373         return -1;
374       }
375       Out << "=" << evaluatedResult << " ";
376     }
377
378     Out << '\n';
379   }
380
381   return 0;
382 }