blob: ed7dfb1a4120cb2ef9104004b6a1a6f134a6b71d [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"
21#include "llvm/MC/MCAsmInfo.h"
22#include "llvm/MC/MCContext.h"
23#include "llvm/MC/MCDisassembler.h"
24#include "llvm/MC/MCExpr.h"
25#include "llvm/MC/MCInst.h"
26#include "llvm/MC/MCInstPrinter.h"
27#include "llvm/MC/MCStreamer.h"
28#include "llvm/MC/MCParser/AsmLexer.h"
29#include "llvm/MC/MCParser/AsmParser.h"
30#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 +000042#include "../../lib/Target/X86/X86GenEDInfo.inc"
Sean Callanan8f993b82010-04-08 00:48:21 +000043#include "../../lib/Target/ARM/ARMGenEDInfo.inc"
Sean Callananee5dfd42010-02-01 08:49:35 +000044
45using namespace llvm;
46
47bool EDDisassembler::sInitialized = false;
48EDDisassembler::DisassemblerMap_t EDDisassembler::sDisassemblers;
49
50struct InfoMap {
51 Triple::ArchType Arch;
52 const char *String;
53 const InstInfo *Info;
54};
55
56static struct InfoMap infomap[] = {
57 { Triple::x86, "i386-unknown-unknown", instInfoX86 },
58 { Triple::x86_64, "x86_64-unknown-unknown", instInfoX86 },
Sean Callanan8f993b82010-04-08 00:48:21 +000059 { Triple::arm, "arm-unknown-unknown", instInfoARM },
60 { Triple::thumb, "thumb-unknown-unknown", instInfoARM },
Sean Callananee5dfd42010-02-01 08:49:35 +000061 { Triple::InvalidArch, NULL, NULL }
62};
63
64/// infoFromArch - Returns the InfoMap corresponding to a given architecture,
65/// or NULL if there is an error
66///
67/// @arg arch - The Triple::ArchType for the desired architecture
68static const InfoMap *infoFromArch(Triple::ArchType arch) {
69 unsigned int infoIndex;
70
71 for (infoIndex = 0; infomap[infoIndex].String != NULL; ++infoIndex) {
Sean Callanan8f993b82010-04-08 00:48:21 +000072 if (arch == infomap[infoIndex].Arch)
Sean Callananee5dfd42010-02-01 08:49:35 +000073 return &infomap[infoIndex];
74 }
75
76 return NULL;
77}
78
79/// getLLVMSyntaxVariant - gets the constant to use to get an assembly printer
80/// for the desired assembly syntax, suitable for passing to
81/// Target::createMCInstPrinter()
82///
83/// @arg arch - The target architecture
84/// @arg syntax - The assembly syntax in sd form
85static int getLLVMSyntaxVariant(Triple::ArchType arch,
86 EDAssemblySyntax_t syntax) {
87 switch (syntax) {
88 default:
89 return -1;
90 // Mappings below from X86AsmPrinter.cpp
91 case kEDAssemblySyntaxX86ATT:
92 if (arch == Triple::x86 || arch == Triple::x86_64)
93 return 0;
94 else
95 return -1;
96 case kEDAssemblySyntaxX86Intel:
97 if (arch == Triple::x86 || arch == Triple::x86_64)
98 return 1;
99 else
100 return -1;
Sean Callanan8f993b82010-04-08 00:48:21 +0000101 case kEDAssemblySyntaxARMUAL:
102 if (arch == Triple::arm || arch == Triple::thumb)
103 return 0;
104 else
105 return -1;
Sean Callananee5dfd42010-02-01 08:49:35 +0000106 }
107}
108
109#define BRINGUP_TARGET(tgt) \
110 LLVMInitialize##tgt##TargetInfo(); \
111 LLVMInitialize##tgt##Target(); \
112 LLVMInitialize##tgt##AsmPrinter(); \
113 LLVMInitialize##tgt##AsmParser(); \
114 LLVMInitialize##tgt##Disassembler();
115
116void EDDisassembler::initialize() {
117 if (sInitialized)
118 return;
119
120 sInitialized = true;
121
122 BRINGUP_TARGET(X86)
Sean Callanan8f993b82010-04-08 00:48:21 +0000123 BRINGUP_TARGET(ARM)
Sean Callananee5dfd42010-02-01 08:49:35 +0000124}
125
126#undef BRINGUP_TARGET
127
128EDDisassembler *EDDisassembler::getDisassembler(Triple::ArchType arch,
129 EDAssemblySyntax_t syntax) {
130 CPUKey key;
131 key.Arch = arch;
132 key.Syntax = syntax;
133
134 EDDisassembler::DisassemblerMap_t::iterator i = sDisassemblers.find(key);
135
136 if (i != sDisassemblers.end()) {
137 return i->second;
Sean Callanan8f993b82010-04-08 00:48:21 +0000138 } else {
Sean Callananee5dfd42010-02-01 08:49:35 +0000139 EDDisassembler* sdd = new EDDisassembler(key);
Sean Callanan8f993b82010-04-08 00:48:21 +0000140 if (!sdd->valid()) {
Sean Callananee5dfd42010-02-01 08:49:35 +0000141 delete sdd;
142 return NULL;
143 }
144
145 sDisassemblers[key] = sdd;
146
147 return sdd;
148 }
149
150 return NULL;
151}
152
153EDDisassembler *EDDisassembler::getDisassembler(StringRef str,
154 EDAssemblySyntax_t syntax) {
155 Triple triple(str);
156
157 return getDisassembler(triple.getArch(), syntax);
158}
159
Sean Callananee5dfd42010-02-01 08:49:35 +0000160EDDisassembler::EDDisassembler(CPUKey &key) :
Sean Callanan8f993b82010-04-08 00:48:21 +0000161 Valid(false),
162 HasSemantics(false),
163 ErrorStream(nulls()),
164 Key(key) {
Sean Callananee5dfd42010-02-01 08:49:35 +0000165 const InfoMap *infoMap = infoFromArch(key.Arch);
166
167 if (!infoMap)
168 return;
Sean Callanan8f993b82010-04-08 00:48:21 +0000169
170 InstInfos = infoMap->Info;
Sean Callananee5dfd42010-02-01 08:49:35 +0000171
172 const char *triple = infoMap->String;
173
Sean Callanan4285b292010-04-09 00:11:15 +0000174 LLVMSyntaxVariant = getLLVMSyntaxVariant(key.Arch, key.Syntax);
Sean Callananee5dfd42010-02-01 08:49:35 +0000175
Sean Callanan4285b292010-04-09 00:11:15 +0000176 if (LLVMSyntaxVariant < 0)
Sean Callananee5dfd42010-02-01 08:49:35 +0000177 return;
178
179 std::string tripleString(triple);
180 std::string errorString;
181
182 Tgt = TargetRegistry::lookupTarget(tripleString,
183 errorString);
184
185 if (!Tgt)
186 return;
187
188 std::string featureString;
189
190 OwningPtr<const TargetMachine>
191 targetMachine(Tgt->createTargetMachine(tripleString,
192 featureString));
193
194 const TargetRegisterInfo *registerInfo = targetMachine->getRegisterInfo();
195
196 if (!registerInfo)
197 return;
Sean Callanan8f993b82010-04-08 00:48:21 +0000198
199 initMaps(*registerInfo);
Sean Callananee5dfd42010-02-01 08:49:35 +0000200
201 AsmInfo.reset(Tgt->createAsmInfo(tripleString));
202
203 if (!AsmInfo)
204 return;
205
206 Disassembler.reset(Tgt->createMCDisassembler());
207
208 if (!Disassembler)
209 return;
210
211 InstString.reset(new std::string);
212 InstStream.reset(new raw_string_ostream(*InstString));
Sean Callanan4285b292010-04-09 00:11:15 +0000213 InstPrinter.reset(Tgt->createMCInstPrinter(LLVMSyntaxVariant, *AsmInfo));
Sean Callananee5dfd42010-02-01 08:49:35 +0000214
215 if (!InstPrinter)
216 return;
217
218 GenericAsmLexer.reset(new AsmLexer(*AsmInfo));
219 SpecificAsmLexer.reset(Tgt->createAsmLexer(*AsmInfo));
220 SpecificAsmLexer->InstallLexer(*GenericAsmLexer);
221
222 InstInfos = infoMap->Info;
Sean Callanand74667e2010-02-02 02:18:20 +0000223
224 initMaps(*targetMachine->getRegisterInfo());
Sean Callananee5dfd42010-02-01 08:49:35 +0000225
226 Valid = true;
227}
228
229EDDisassembler::~EDDisassembler() {
Sean Callanan8f993b82010-04-08 00:48:21 +0000230 if (!valid())
Sean Callananee5dfd42010-02-01 08:49:35 +0000231 return;
232}
233
234namespace {
235 /// EDMemoryObject - a subclass of MemoryObject that allows use of a callback
236 /// as provided by the sd interface. See MemoryObject.
237 class EDMemoryObject : public llvm::MemoryObject {
238 private:
239 EDByteReaderCallback Callback;
240 void *Arg;
241 public:
242 EDMemoryObject(EDByteReaderCallback callback,
243 void *arg) : Callback(callback), Arg(arg) { }
244 ~EDMemoryObject() { }
245 uint64_t getBase() const { return 0x0; }
246 uint64_t getExtent() const { return (uint64_t)-1; }
247 int readByte(uint64_t address, uint8_t *ptr) const {
Sean Callanan8f993b82010-04-08 00:48:21 +0000248 if (!Callback)
Sean Callananee5dfd42010-02-01 08:49:35 +0000249 return -1;
250
Sean Callanan8f993b82010-04-08 00:48:21 +0000251 if (Callback(ptr, address, Arg))
Sean Callananee5dfd42010-02-01 08:49:35 +0000252 return -1;
253
254 return 0;
255 }
256 };
257}
258
259EDInst *EDDisassembler::createInst(EDByteReaderCallback byteReader,
260 uint64_t address,
261 void *arg) {
262 EDMemoryObject memoryObject(byteReader, arg);
263
264 MCInst* inst = new MCInst;
265 uint64_t byteSize;
266
267 if (!Disassembler->getInstruction(*inst,
268 byteSize,
269 memoryObject,
270 address,
271 ErrorStream)) {
272 delete inst;
273 return NULL;
Sean Callanan8f993b82010-04-08 00:48:21 +0000274 } else {
275 const InstInfo *thisInstInfo;
276
277 thisInstInfo = &InstInfos[inst->getOpcode()];
Sean Callananee5dfd42010-02-01 08:49:35 +0000278
279 EDInst* sdInst = new EDInst(inst, byteSize, *this, thisInstInfo);
280 return sdInst;
281 }
282}
283
284void EDDisassembler::initMaps(const TargetRegisterInfo &registerInfo) {
285 unsigned numRegisters = registerInfo.getNumRegs();
286 unsigned registerIndex;
287
288 for (registerIndex = 0; registerIndex < numRegisters; ++registerIndex) {
289 const char* registerName = registerInfo.get(registerIndex).Name;
290
291 RegVec.push_back(registerName);
292 RegRMap[registerName] = registerIndex;
293 }
294
Sean Callanan8f993b82010-04-08 00:48:21 +0000295 switch (Key.Arch) {
296 default:
297 break;
298 case Triple::x86:
299 case Triple::x86_64:
Sean Callananee5dfd42010-02-01 08:49:35 +0000300 stackPointers.insert(registerIDWithName("SP"));
301 stackPointers.insert(registerIDWithName("ESP"));
302 stackPointers.insert(registerIDWithName("RSP"));
303
304 programCounters.insert(registerIDWithName("IP"));
305 programCounters.insert(registerIDWithName("EIP"));
306 programCounters.insert(registerIDWithName("RIP"));
Sean Callanan8f993b82010-04-08 00:48:21 +0000307 break;
308 case Triple::arm:
309 case Triple::thumb:
310 stackPointers.insert(registerIDWithName("SP"));
311
312 programCounters.insert(registerIDWithName("PC"));
313 break;
Sean Callananee5dfd42010-02-01 08:49:35 +0000314 }
315}
316
317const char *EDDisassembler::nameWithRegisterID(unsigned registerID) const {
318 if (registerID >= RegVec.size())
319 return NULL;
320 else
321 return RegVec[registerID].c_str();
322}
323
324unsigned EDDisassembler::registerIDWithName(const char *name) const {
325 regrmap_t::const_iterator iter = RegRMap.find(std::string(name));
326 if (iter == RegRMap.end())
327 return 0;
328 else
329 return (*iter).second;
330}
331
332bool EDDisassembler::registerIsStackPointer(unsigned registerID) {
333 return (stackPointers.find(registerID) != stackPointers.end());
334}
335
336bool EDDisassembler::registerIsProgramCounter(unsigned registerID) {
337 return (programCounters.find(registerID) != programCounters.end());
338}
339
Chris Lattnerd3740872010-04-04 05:04:31 +0000340int EDDisassembler::printInst(std::string &str, MCInst &inst) {
Sean Callananee5dfd42010-02-01 08:49:35 +0000341 PrinterMutex.acquire();
342
Chris Lattnerd3740872010-04-04 05:04:31 +0000343 InstPrinter->printInst(&inst, *InstStream);
Sean Callananee5dfd42010-02-01 08:49:35 +0000344 InstStream->flush();
345 str = *InstString;
346 InstString->clear();
347
348 PrinterMutex.release();
349
350 return 0;
351}
352
353int EDDisassembler::parseInst(SmallVectorImpl<MCParsedAsmOperand*> &operands,
354 SmallVectorImpl<AsmToken> &tokens,
355 const std::string &str) {
356 int ret = 0;
357
Sean Callanan8f993b82010-04-08 00:48:21 +0000358 switch (Key.Arch) {
359 default:
360 return -1;
361 case Triple::x86:
362 case Triple::x86_64:
363 case Triple::arm:
364 case Triple::thumb:
365 break;
366 }
367
Sean Callananee5dfd42010-02-01 08:49:35 +0000368 const char *cStr = str.c_str();
369 MemoryBuffer *buf = MemoryBuffer::getMemBuffer(cStr, cStr + strlen(cStr));
370
371 StringRef instName;
372 SMLoc instLoc;
373
374 SourceMgr sourceMgr;
375 sourceMgr.AddNewSourceBuffer(buf, SMLoc()); // ownership of buf handed over
Chris Lattnerc18409a2010-03-11 22:53:35 +0000376 MCContext context(*AsmInfo);
377 OwningPtr<MCStreamer> streamer(createNullStreamer(context));
Sean Callananee5dfd42010-02-01 08:49:35 +0000378 AsmParser genericParser(sourceMgr, context, *streamer, *AsmInfo);
Chris Lattnerc18409a2010-03-11 22:53:35 +0000379 OwningPtr<TargetAsmParser> TargetParser(Tgt->createAsmParser(genericParser));
Sean Callananee5dfd42010-02-01 08:49:35 +0000380
381 AsmToken OpcodeToken = genericParser.Lex();
Sean Callanan8f993b82010-04-08 00:48:21 +0000382 genericParser.Lex(); // consume next token, because specificParser expects us to
Sean Callananee5dfd42010-02-01 08:49:35 +0000383
Sean Callanan8f993b82010-04-08 00:48:21 +0000384 if (OpcodeToken.is(AsmToken::Identifier)) {
Sean Callananee5dfd42010-02-01 08:49:35 +0000385 instName = OpcodeToken.getString();
386 instLoc = OpcodeToken.getLoc();
Chris Lattnerc18409a2010-03-11 22:53:35 +0000387 if (TargetParser->ParseInstruction(instName, instLoc, operands))
Sean Callananee5dfd42010-02-01 08:49:35 +0000388 ret = -1;
Sean Callanan8f993b82010-04-08 00:48:21 +0000389 } else {
Sean Callananee5dfd42010-02-01 08:49:35 +0000390 ret = -1;
391 }
392
Sean Callananee5dfd42010-02-01 08:49:35 +0000393 ParserMutex.acquire();
394
395 if (!ret) {
396 GenericAsmLexer->setBuffer(buf);
397
398 while (SpecificAsmLexer->Lex(),
399 SpecificAsmLexer->isNot(AsmToken::Eof) &&
400 SpecificAsmLexer->isNot(AsmToken::EndOfStatement)) {
401 if (SpecificAsmLexer->is(AsmToken::Error)) {
402 ret = -1;
403 break;
404 }
405 tokens.push_back(SpecificAsmLexer->getTok());
406 }
407 }
408
409 ParserMutex.release();
410
411 return ret;
412}
413
414int EDDisassembler::llvmSyntaxVariant() const {
415 return LLVMSyntaxVariant;
416}