blob: dc2ed3e2c2af9decbf7b3fccba4399f010502e70 [file] [log] [blame]
Sean Callananee5dfd42010-02-01 08:49:35 +00001//===-EDDisassembler.cpp - LLVM Enhanced Disassembler ---------------------===//
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 file implements the Enhanced Disassembly library's disassembler class.
11// The disassembler is responsible for vending individual instructions according
12// to a given architecture and disassembly syntax.
13//
14//===----------------------------------------------------------------------===//
15
Sean Callanan8f993b82010-04-08 00:48:21 +000016#include "EDDisassembler.h"
17#include "EDInst.h"
18
Sean Callananee5dfd42010-02-01 08:49:35 +000019#include "llvm/ADT/OwningPtr.h"
20#include "llvm/ADT/SmallVector.h"
Sean Callanan9899f702010-04-13 21:21:57 +000021#include "llvm/MC/EDInstInfo.h"
Sean Callananee5dfd42010-02-01 08:49:35 +000022#include "llvm/MC/MCAsmInfo.h"
23#include "llvm/MC/MCContext.h"
24#include "llvm/MC/MCDisassembler.h"
25#include "llvm/MC/MCExpr.h"
26#include "llvm/MC/MCInst.h"
27#include "llvm/MC/MCInstPrinter.h"
28#include "llvm/MC/MCStreamer.h"
29#include "llvm/MC/MCParser/AsmLexer.h"
Sean Callananee5dfd42010-02-01 08:49:35 +000030#include "llvm/MC/MCParser/MCAsmParser.h"
31#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
32#include "llvm/Support/MemoryBuffer.h"
33#include "llvm/Support/MemoryObject.h"
34#include "llvm/Support/SourceMgr.h"
35#include "llvm/Target/TargetAsmLexer.h"
36#include "llvm/Target/TargetAsmParser.h"
37#include "llvm/Target/TargetRegistry.h"
38#include "llvm/Target/TargetMachine.h"
39#include "llvm/Target/TargetRegisterInfo.h"
40#include "llvm/Target/TargetSelect.h"
41
Sean Callananee5dfd42010-02-01 08:49:35 +000042using namespace llvm;
43
44bool EDDisassembler::sInitialized = false;
45EDDisassembler::DisassemblerMap_t EDDisassembler::sDisassemblers;
46
Sean Callanan9899f702010-04-13 21:21:57 +000047struct TripleMap {
Sean Callananee5dfd42010-02-01 08:49:35 +000048 Triple::ArchType Arch;
49 const char *String;
Sean Callananee5dfd42010-02-01 08:49:35 +000050};
51
Sean Callanan9899f702010-04-13 21:21:57 +000052static struct TripleMap triplemap[] = {
53 { Triple::x86, "i386-unknown-unknown" },
54 { Triple::x86_64, "x86_64-unknown-unknown" },
55 { Triple::arm, "arm-unknown-unknown" },
56 { Triple::thumb, "thumb-unknown-unknown" },
57 { Triple::InvalidArch, NULL, }
Sean Callananee5dfd42010-02-01 08:49:35 +000058};
59
Sean Callanan9899f702010-04-13 21:21:57 +000060/// infoFromArch - Returns the TripleMap corresponding to a given architecture,
Sean Callananee5dfd42010-02-01 08:49:35 +000061/// or NULL if there is an error
62///
63/// @arg arch - The Triple::ArchType for the desired architecture
Sean Callanan9899f702010-04-13 21:21:57 +000064static const char *tripleFromArch(Triple::ArchType arch) {
Sean Callananee5dfd42010-02-01 08:49:35 +000065 unsigned int infoIndex;
66
Sean Callanan9899f702010-04-13 21:21:57 +000067 for (infoIndex = 0; triplemap[infoIndex].String != NULL; ++infoIndex) {
68 if (arch == triplemap[infoIndex].Arch)
69 return triplemap[infoIndex].String;
Sean Callananee5dfd42010-02-01 08:49:35 +000070 }
71
72 return NULL;
73}
74
75/// getLLVMSyntaxVariant - gets the constant to use to get an assembly printer
76/// for the desired assembly syntax, suitable for passing to
77/// Target::createMCInstPrinter()
78///
79/// @arg arch - The target architecture
80/// @arg syntax - The assembly syntax in sd form
81static int getLLVMSyntaxVariant(Triple::ArchType arch,
82 EDAssemblySyntax_t syntax) {
83 switch (syntax) {
84 default:
85 return -1;
86 // Mappings below from X86AsmPrinter.cpp
87 case kEDAssemblySyntaxX86ATT:
88 if (arch == Triple::x86 || arch == Triple::x86_64)
89 return 0;
90 else
91 return -1;
92 case kEDAssemblySyntaxX86Intel:
93 if (arch == Triple::x86 || arch == Triple::x86_64)
94 return 1;
95 else
96 return -1;
Sean Callanan8f993b82010-04-08 00:48:21 +000097 case kEDAssemblySyntaxARMUAL:
98 if (arch == Triple::arm || arch == Triple::thumb)
99 return 0;
100 else
101 return -1;
Sean Callananee5dfd42010-02-01 08:49:35 +0000102 }
103}
104
Sean Callananee5dfd42010-02-01 08:49:35 +0000105void EDDisassembler::initialize() {
106 if (sInitialized)
107 return;
108
109 sInitialized = true;
110
Sean Callanan9899f702010-04-13 21:21:57 +0000111 InitializeAllTargetInfos();
112 InitializeAllTargets();
113 InitializeAllAsmPrinters();
114 InitializeAllAsmParsers();
115 InitializeAllDisassemblers();
Sean Callananee5dfd42010-02-01 08:49:35 +0000116}
117
118#undef BRINGUP_TARGET
119
120EDDisassembler *EDDisassembler::getDisassembler(Triple::ArchType arch,
121 EDAssemblySyntax_t syntax) {
122 CPUKey key;
123 key.Arch = arch;
124 key.Syntax = syntax;
125
126 EDDisassembler::DisassemblerMap_t::iterator i = sDisassemblers.find(key);
127
128 if (i != sDisassemblers.end()) {
129 return i->second;
Sean Callanan8f993b82010-04-08 00:48:21 +0000130 } else {
Sean Callananee5dfd42010-02-01 08:49:35 +0000131 EDDisassembler* sdd = new EDDisassembler(key);
Sean Callanan8f993b82010-04-08 00:48:21 +0000132 if (!sdd->valid()) {
Sean Callananee5dfd42010-02-01 08:49:35 +0000133 delete sdd;
134 return NULL;
135 }
136
137 sDisassemblers[key] = sdd;
138
139 return sdd;
140 }
141
142 return NULL;
143}
144
145EDDisassembler *EDDisassembler::getDisassembler(StringRef str,
146 EDAssemblySyntax_t syntax) {
147 Triple triple(str);
148
149 return getDisassembler(triple.getArch(), syntax);
150}
151
Sean Callananee5dfd42010-02-01 08:49:35 +0000152EDDisassembler::EDDisassembler(CPUKey &key) :
Sean Callanan8f993b82010-04-08 00:48:21 +0000153 Valid(false),
154 HasSemantics(false),
155 ErrorStream(nulls()),
156 Key(key) {
Sean Callanan9899f702010-04-13 21:21:57 +0000157 const char *triple = tripleFromArch(key.Arch);
Sean Callanan8f993b82010-04-08 00:48:21 +0000158
Sean Callanan9899f702010-04-13 21:21:57 +0000159 if (!triple)
160 return;
Sean Callananee5dfd42010-02-01 08:49:35 +0000161
Sean Callanan4285b292010-04-09 00:11:15 +0000162 LLVMSyntaxVariant = getLLVMSyntaxVariant(key.Arch, key.Syntax);
Sean Callananee5dfd42010-02-01 08:49:35 +0000163
Sean Callanan4285b292010-04-09 00:11:15 +0000164 if (LLVMSyntaxVariant < 0)
Sean Callananee5dfd42010-02-01 08:49:35 +0000165 return;
166
167 std::string tripleString(triple);
168 std::string errorString;
169
170 Tgt = TargetRegistry::lookupTarget(tripleString,
171 errorString);
172
173 if (!Tgt)
174 return;
175
176 std::string featureString;
177
Daniel Dunbar02612432010-07-19 00:33:43 +0000178 TargetMachine.reset(Tgt->createTargetMachine(tripleString,
179 featureString));
Sean Callananee5dfd42010-02-01 08:49:35 +0000180
Daniel Dunbar02612432010-07-19 00:33:43 +0000181 const TargetRegisterInfo *registerInfo = TargetMachine->getRegisterInfo();
Sean Callananee5dfd42010-02-01 08:49:35 +0000182
183 if (!registerInfo)
184 return;
Sean Callanan8f993b82010-04-08 00:48:21 +0000185
186 initMaps(*registerInfo);
Sean Callananee5dfd42010-02-01 08:49:35 +0000187
188 AsmInfo.reset(Tgt->createAsmInfo(tripleString));
189
190 if (!AsmInfo)
191 return;
192
193 Disassembler.reset(Tgt->createMCDisassembler());
194
195 if (!Disassembler)
196 return;
Sean Callanan9899f702010-04-13 21:21:57 +0000197
198 InstInfos = Disassembler->getEDInfo();
Sean Callananee5dfd42010-02-01 08:49:35 +0000199
200 InstString.reset(new std::string);
201 InstStream.reset(new raw_string_ostream(*InstString));
Sean Callanan4285b292010-04-09 00:11:15 +0000202 InstPrinter.reset(Tgt->createMCInstPrinter(LLVMSyntaxVariant, *AsmInfo));
Sean Callananee5dfd42010-02-01 08:49:35 +0000203
204 if (!InstPrinter)
205 return;
206
207 GenericAsmLexer.reset(new AsmLexer(*AsmInfo));
208 SpecificAsmLexer.reset(Tgt->createAsmLexer(*AsmInfo));
209 SpecificAsmLexer->InstallLexer(*GenericAsmLexer);
Sean Callanand74667e2010-02-02 02:18:20 +0000210
Daniel Dunbar02612432010-07-19 00:33:43 +0000211 initMaps(*TargetMachine->getRegisterInfo());
Sean Callananee5dfd42010-02-01 08:49:35 +0000212
213 Valid = true;
214}
215
216EDDisassembler::~EDDisassembler() {
Sean Callanan8f993b82010-04-08 00:48:21 +0000217 if (!valid())
Sean Callananee5dfd42010-02-01 08:49:35 +0000218 return;
219}
220
221namespace {
222 /// EDMemoryObject - a subclass of MemoryObject that allows use of a callback
223 /// as provided by the sd interface. See MemoryObject.
224 class EDMemoryObject : public llvm::MemoryObject {
225 private:
226 EDByteReaderCallback Callback;
227 void *Arg;
228 public:
229 EDMemoryObject(EDByteReaderCallback callback,
230 void *arg) : Callback(callback), Arg(arg) { }
231 ~EDMemoryObject() { }
232 uint64_t getBase() const { return 0x0; }
233 uint64_t getExtent() const { return (uint64_t)-1; }
234 int readByte(uint64_t address, uint8_t *ptr) const {
Sean Callanan8f993b82010-04-08 00:48:21 +0000235 if (!Callback)
Sean Callananee5dfd42010-02-01 08:49:35 +0000236 return -1;
237
Sean Callanan8f993b82010-04-08 00:48:21 +0000238 if (Callback(ptr, address, Arg))
Sean Callananee5dfd42010-02-01 08:49:35 +0000239 return -1;
240
241 return 0;
242 }
243 };
244}
245
246EDInst *EDDisassembler::createInst(EDByteReaderCallback byteReader,
247 uint64_t address,
248 void *arg) {
249 EDMemoryObject memoryObject(byteReader, arg);
250
251 MCInst* inst = new MCInst;
252 uint64_t byteSize;
253
254 if (!Disassembler->getInstruction(*inst,
255 byteSize,
256 memoryObject,
257 address,
258 ErrorStream)) {
259 delete inst;
260 return NULL;
Sean Callanan8f993b82010-04-08 00:48:21 +0000261 } else {
Sean Callanan9899f702010-04-13 21:21:57 +0000262 const llvm::EDInstInfo *thisInstInfo;
Sean Callanan8f993b82010-04-08 00:48:21 +0000263
264 thisInstInfo = &InstInfos[inst->getOpcode()];
Sean Callananee5dfd42010-02-01 08:49:35 +0000265
266 EDInst* sdInst = new EDInst(inst, byteSize, *this, thisInstInfo);
267 return sdInst;
268 }
269}
270
271void EDDisassembler::initMaps(const TargetRegisterInfo &registerInfo) {
272 unsigned numRegisters = registerInfo.getNumRegs();
273 unsigned registerIndex;
274
275 for (registerIndex = 0; registerIndex < numRegisters; ++registerIndex) {
276 const char* registerName = registerInfo.get(registerIndex).Name;
277
278 RegVec.push_back(registerName);
279 RegRMap[registerName] = registerIndex;
280 }
281
Sean Callanan8f993b82010-04-08 00:48:21 +0000282 switch (Key.Arch) {
283 default:
284 break;
285 case Triple::x86:
286 case Triple::x86_64:
Sean Callananee5dfd42010-02-01 08:49:35 +0000287 stackPointers.insert(registerIDWithName("SP"));
288 stackPointers.insert(registerIDWithName("ESP"));
289 stackPointers.insert(registerIDWithName("RSP"));
290
291 programCounters.insert(registerIDWithName("IP"));
292 programCounters.insert(registerIDWithName("EIP"));
293 programCounters.insert(registerIDWithName("RIP"));
Sean Callanan8f993b82010-04-08 00:48:21 +0000294 break;
295 case Triple::arm:
296 case Triple::thumb:
297 stackPointers.insert(registerIDWithName("SP"));
298
299 programCounters.insert(registerIDWithName("PC"));
300 break;
Sean Callananee5dfd42010-02-01 08:49:35 +0000301 }
302}
303
304const char *EDDisassembler::nameWithRegisterID(unsigned registerID) const {
305 if (registerID >= RegVec.size())
306 return NULL;
307 else
308 return RegVec[registerID].c_str();
309}
310
311unsigned EDDisassembler::registerIDWithName(const char *name) const {
312 regrmap_t::const_iterator iter = RegRMap.find(std::string(name));
313 if (iter == RegRMap.end())
314 return 0;
315 else
316 return (*iter).second;
317}
318
319bool EDDisassembler::registerIsStackPointer(unsigned registerID) {
320 return (stackPointers.find(registerID) != stackPointers.end());
321}
322
323bool EDDisassembler::registerIsProgramCounter(unsigned registerID) {
324 return (programCounters.find(registerID) != programCounters.end());
325}
326
Chris Lattnerd3740872010-04-04 05:04:31 +0000327int EDDisassembler::printInst(std::string &str, MCInst &inst) {
Sean Callananee5dfd42010-02-01 08:49:35 +0000328 PrinterMutex.acquire();
329
Chris Lattnerd3740872010-04-04 05:04:31 +0000330 InstPrinter->printInst(&inst, *InstStream);
Sean Callananee5dfd42010-02-01 08:49:35 +0000331 InstStream->flush();
332 str = *InstString;
333 InstString->clear();
334
335 PrinterMutex.release();
336
337 return 0;
338}
339
340int EDDisassembler::parseInst(SmallVectorImpl<MCParsedAsmOperand*> &operands,
341 SmallVectorImpl<AsmToken> &tokens,
342 const std::string &str) {
343 int ret = 0;
344
Sean Callanan8f993b82010-04-08 00:48:21 +0000345 switch (Key.Arch) {
346 default:
347 return -1;
348 case Triple::x86:
349 case Triple::x86_64:
350 case Triple::arm:
351 case Triple::thumb:
352 break;
353 }
354
Sean Callananee5dfd42010-02-01 08:49:35 +0000355 const char *cStr = str.c_str();
356 MemoryBuffer *buf = MemoryBuffer::getMemBuffer(cStr, cStr + strlen(cStr));
357
358 StringRef instName;
359 SMLoc instLoc;
360
361 SourceMgr sourceMgr;
362 sourceMgr.AddNewSourceBuffer(buf, SMLoc()); // ownership of buf handed over
Chris Lattnerc18409a2010-03-11 22:53:35 +0000363 MCContext context(*AsmInfo);
364 OwningPtr<MCStreamer> streamer(createNullStreamer(context));
Daniel Dunbar9fbb37e2010-07-18 18:31:33 +0000365 OwningPtr<MCAsmParser> genericParser(createMCAsmParser(*Tgt, sourceMgr,
366 context, *streamer,
367 *AsmInfo));
Daniel Dunbard73ada72010-07-19 00:33:49 +0000368 OwningPtr<TargetAsmParser> TargetParser(Tgt->createAsmParser(*genericParser,
369 *TargetMachine));
Sean Callananee5dfd42010-02-01 08:49:35 +0000370
Daniel Dunbar9fbb37e2010-07-18 18:31:33 +0000371 AsmToken OpcodeToken = genericParser->Lex();
372 AsmToken NextToken = genericParser->Lex(); // consume next token, because specificParser expects us to
Sean Callanana8702562010-04-24 01:00:16 +0000373
Sean Callanan8f993b82010-04-08 00:48:21 +0000374 if (OpcodeToken.is(AsmToken::Identifier)) {
Sean Callananee5dfd42010-02-01 08:49:35 +0000375 instName = OpcodeToken.getString();
376 instLoc = OpcodeToken.getLoc();
Sean Callanana8702562010-04-24 01:00:16 +0000377
378 if (NextToken.isNot(AsmToken::Eof) &&
379 TargetParser->ParseInstruction(instName, instLoc, operands))
Sean Callananee5dfd42010-02-01 08:49:35 +0000380 ret = -1;
Sean Callanan8f993b82010-04-08 00:48:21 +0000381 } else {
Sean Callananee5dfd42010-02-01 08:49:35 +0000382 ret = -1;
383 }
384
Sean Callananee5dfd42010-02-01 08:49:35 +0000385 ParserMutex.acquire();
386
387 if (!ret) {
388 GenericAsmLexer->setBuffer(buf);
389
390 while (SpecificAsmLexer->Lex(),
391 SpecificAsmLexer->isNot(AsmToken::Eof) &&
392 SpecificAsmLexer->isNot(AsmToken::EndOfStatement)) {
393 if (SpecificAsmLexer->is(AsmToken::Error)) {
394 ret = -1;
395 break;
396 }
397 tokens.push_back(SpecificAsmLexer->getTok());
398 }
399 }
400
401 ParserMutex.release();
402
403 return ret;
404}
405
406int EDDisassembler::llvmSyntaxVariant() const {
407 return LLVMSyntaxVariant;
408}