blob: 4f71a1b339fc77bfb404835c21cdec2909dc8058 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- DisassemblerLLVM.cpp ------------------------------------*- C++ -*-===//
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#include "DisassemblerLLVM.h"
11
12#include "llvm-c/EnhancedDisassembly.h"
13
14#include "lldb/Core/Address.h"
15#include "lldb/Core/DataExtractor.h"
16#include "lldb/Core/Disassembler.h"
17#include "lldb/Core/Module.h"
18#include "lldb/Core/PluginManager.h"
19#include "lldb/Core/Stream.h"
20#include "lldb/Core/StreamString.h"
21#include "lldb/Symbol/SymbolContext.h"
22
23#include "lldb/Target/ExecutionContext.h"
24#include "lldb/Target/Process.h"
25#include "lldb/Target/RegisterContext.h"
26#include "lldb/Target/Target.h"
27
Greg Claytonb01000f2011-01-17 03:46:26 +000028#include <assert.h>
Chris Lattner24943d22010-06-08 16:52:24 +000029
30using namespace lldb;
31using namespace lldb_private;
32
33
Greg Claytonb1888f22011-03-19 01:12:21 +000034static int
Greg Clayton7bc39082011-03-24 23:53:38 +000035DataExtractorByteReader (uint8_t *byte, uint64_t address, void *arg)
Chris Lattner24943d22010-06-08 16:52:24 +000036{
37 DataExtractor &extractor = *((DataExtractor *)arg);
38
39 if (extractor.ValidOffset(address))
40 {
41 *byte = *(extractor.GetDataStart() + address);
42 return 0;
43 }
44 else
45 {
46 return -1;
47 }
48}
49
50namespace {
51 struct RegisterReaderArg {
52 const lldb::addr_t instructionPointer;
53 const EDDisassemblerRef disassembler;
54
55 RegisterReaderArg(lldb::addr_t ip,
56 EDDisassemblerRef dis) :
57 instructionPointer(ip),
58 disassembler(dis)
59 {
60 }
61 };
62}
63
64static int IPRegisterReader(uint64_t *value, unsigned regID, void* arg)
65{
66 uint64_t instructionPointer = ((RegisterReaderArg*)arg)->instructionPointer;
67 EDDisassemblerRef disassembler = ((RegisterReaderArg*)arg)->disassembler;
68
Greg Claytonb1888f22011-03-19 01:12:21 +000069 if (EDRegisterIsProgramCounter(disassembler, regID)) {
Chris Lattner24943d22010-06-08 16:52:24 +000070 *value = instructionPointer;
71 return 0;
72 }
73
74 return -1;
75}
76
Caroline Ticeaf591802011-04-05 23:22:54 +000077InstructionLLVM::InstructionLLVM (const Address &addr,
78 AddressClass addr_class,
79 EDDisassemblerRef disassembler) :
Greg Clayton889fbd02011-03-26 19:14:58 +000080 Instruction (addr, addr_class),
Chris Lattner24943d22010-06-08 16:52:24 +000081 m_disassembler (disassembler)
82{
83}
84
Caroline Ticeaf591802011-04-05 23:22:54 +000085InstructionLLVM::~InstructionLLVM()
Chris Lattner24943d22010-06-08 16:52:24 +000086{
87}
88
89static void
90PadString(Stream *s, const std::string &str, size_t width)
91{
92 int diff = width - str.length();
93
94 if (diff > 0)
95 s->Printf("%s%*.*s", str.c_str(), diff, diff, "");
96 else
97 s->Printf("%s ", str.c_str());
98}
99
100void
Caroline Ticeaf591802011-04-05 23:22:54 +0000101InstructionLLVM::Dump
Chris Lattner24943d22010-06-08 16:52:24 +0000102(
103 Stream *s,
Greg Clayton889fbd02011-03-26 19:14:58 +0000104 uint32_t max_opcode_byte_size,
Greg Clayton5c4c7462010-10-06 03:09:58 +0000105 bool show_address,
Greg Clayton149731c2011-03-25 18:03:16 +0000106 bool show_bytes,
Greg Clayton5c4c7462010-10-06 03:09:58 +0000107 const lldb_private::ExecutionContext* exe_ctx,
Chris Lattner24943d22010-06-08 16:52:24 +0000108 bool raw
109)
110{
111 const size_t opcodeColumnWidth = 7;
112 const size_t operandColumnWidth = 25;
113
Greg Clayton5c4c7462010-10-06 03:09:58 +0000114 ExecutionContextScope *exe_scope = NULL;
115 if (exe_ctx)
116 exe_scope = exe_ctx->GetBestExecutionContextScope();
117
Chris Lattner24943d22010-06-08 16:52:24 +0000118 // If we have an address, print it out
Sean Callanan91557b02010-11-10 01:38:28 +0000119 if (GetAddress().IsValid() && show_address)
Greg Clayton70436352010-06-30 23:03:03 +0000120 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000121 if (GetAddress().Dump (s,
122 exe_scope,
123 Address::DumpStyleLoadAddress,
124 Address::DumpStyleModuleWithFileAddress,
125 0))
Greg Clayton70436352010-06-30 23:03:03 +0000126 s->PutCString(": ");
127 }
Chris Lattner24943d22010-06-08 16:52:24 +0000128
129 // If we are supposed to show bytes, "bytes" will be non-NULL.
Greg Clayton149731c2011-03-25 18:03:16 +0000130 if (show_bytes)
Chris Lattner24943d22010-06-08 16:52:24 +0000131 {
Greg Clayton149731c2011-03-25 18:03:16 +0000132 if (m_opcode.GetType() == Opcode::eTypeBytes)
Chris Lattner24943d22010-06-08 16:52:24 +0000133 {
Greg Clayton149731c2011-03-25 18:03:16 +0000134 // x86_64 and i386 are the only ones that use bytes right now so
135 // pad out the byte dump to be able to always show 15 bytes (3 chars each)
136 // plus a space
Greg Clayton889fbd02011-03-26 19:14:58 +0000137 if (max_opcode_byte_size > 0)
138 m_opcode.Dump (s, max_opcode_byte_size * 3 + 1);
139 else
140 m_opcode.Dump (s, 15 * 3 + 1);
Greg Clayton149731c2011-03-25 18:03:16 +0000141 }
142 else
143 {
144 // Else, we have ARM which can show up to a uint32_t 0x00000000 (10 spaces)
145 // plus two for padding...
Greg Clayton889fbd02011-03-26 19:14:58 +0000146 if (max_opcode_byte_size > 0)
147 m_opcode.Dump (s, max_opcode_byte_size * 3 + 1);
148 else
149 m_opcode.Dump (s, 12);
Chris Lattner24943d22010-06-08 16:52:24 +0000150 }
151 }
152
Greg Claytonf15996e2011-04-07 22:46:35 +0000153 int numTokens = -1;
154
155 if (!raw)
156 numTokens = EDNumTokens(m_inst);
Chris Lattner24943d22010-06-08 16:52:24 +0000157
158 int currentOpIndex = -1;
159
Greg Claytonf15996e2011-04-07 22:46:35 +0000160 bool printTokenized = false;
161
162 if (numTokens != -1 && !raw)
Sean Callanan8541f2f2010-07-23 02:19:15 +0000163 {
164 addr_t base_addr = LLDB_INVALID_ADDRESS;
Greg Claytonf15996e2011-04-07 22:46:35 +0000165
166 RegisterReaderArg rra(base_addr + EDInstByteSize(m_inst), m_disassembler);
167
Greg Clayton5c4c7462010-10-06 03:09:58 +0000168 if (exe_ctx && exe_ctx->target && !exe_ctx->target->GetSectionLoadList().IsEmpty())
169 base_addr = GetAddress().GetLoadAddress (exe_ctx->target);
Sean Callanan8541f2f2010-07-23 02:19:15 +0000170 if (base_addr == LLDB_INVALID_ADDRESS)
Greg Clayton5c4c7462010-10-06 03:09:58 +0000171 base_addr = GetAddress().GetFileAddress ();
Greg Claytonf15996e2011-04-07 22:46:35 +0000172
Chris Lattner24943d22010-06-08 16:52:24 +0000173 printTokenized = true;
174
175 // Handle the opcode column.
176
177 StreamString opcode;
178
179 int tokenIndex = 0;
180
181 EDTokenRef token;
182 const char *tokenStr;
183
184 if (EDGetToken(&token, m_inst, tokenIndex))
185 printTokenized = false;
186
187 if (!printTokenized || !EDTokenIsOpcode(token))
188 printTokenized = false;
189
190 if (!printTokenized || EDGetTokenString(&tokenStr, token))
191 printTokenized = false;
192
193 // Put the token string into our opcode string
194 opcode.PutCString(tokenStr);
195
196 // If anything follows, it probably starts with some whitespace. Skip it.
197
198 tokenIndex++;
199
200 if (printTokenized && tokenIndex < numTokens)
201 {
202 if(!printTokenized || EDGetToken(&token, m_inst, tokenIndex))
203 printTokenized = false;
204
205 if(!printTokenized || !EDTokenIsWhitespace(token))
206 printTokenized = false;
207 }
208
209 tokenIndex++;
210
211 // Handle the operands and the comment.
212
213 StreamString operands;
214 StreamString comment;
215
216 if (printTokenized)
217 {
218 bool show_token;
219
220 for (; tokenIndex < numTokens; ++tokenIndex)
221 {
222 if (EDGetToken(&token, m_inst, tokenIndex))
223 return;
224
225 if (raw)
226 {
227 show_token = true;
228 }
229 else
230 {
231 int operandIndex = EDOperandIndexForToken(token);
232
233 if (operandIndex >= 0)
234 {
235 if (operandIndex != currentOpIndex)
236 {
237 show_token = true;
238
239 currentOpIndex = operandIndex;
240 EDOperandRef operand;
241
242 if (!EDGetOperand(&operand, m_inst, currentOpIndex))
243 {
244 if (EDOperandIsMemory(operand))
245 {
246 uint64_t operand_value;
247
Greg Claytonf15996e2011-04-07 22:46:35 +0000248 if (!EDEvaluateOperand(&operand_value, operand, IPRegisterReader, &rra))
Chris Lattner24943d22010-06-08 16:52:24 +0000249 {
250 if (EDInstIsBranch(m_inst))
251 {
252 operands.Printf("0x%llx ", operand_value);
253 show_token = false;
254 }
255 else
256 {
257 // Put the address value into the comment
258 comment.Printf("0x%llx ", operand_value);
259 }
260
261 lldb_private::Address so_addr;
Greg Clayton5c4c7462010-10-06 03:09:58 +0000262 if (exe_ctx && exe_ctx->target && !exe_ctx->target->GetSectionLoadList().IsEmpty())
Chris Lattner24943d22010-06-08 16:52:24 +0000263 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000264 if (exe_ctx->target->GetSectionLoadList().ResolveLoadAddress (operand_value, so_addr))
Greg Claytoncf7f1ad2010-07-01 01:26:43 +0000265 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
Greg Clayton70436352010-06-30 23:03:03 +0000266 }
Greg Clayton5c4c7462010-10-06 03:09:58 +0000267 else
Greg Clayton70436352010-06-30 23:03:03 +0000268 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000269 Module *module = GetAddress().GetModule();
Greg Clayton70436352010-06-30 23:03:03 +0000270 if (module)
Chris Lattner24943d22010-06-08 16:52:24 +0000271 {
Greg Clayton70436352010-06-30 23:03:03 +0000272 if (module->ResolveFileAddress (operand_value, so_addr))
Greg Claytoncf7f1ad2010-07-01 01:26:43 +0000273 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
Chris Lattner24943d22010-06-08 16:52:24 +0000274 }
275 }
Greg Clayton70436352010-06-30 23:03:03 +0000276
Chris Lattner24943d22010-06-08 16:52:24 +0000277 } // EDEvaluateOperand
278 } // EDOperandIsMemory
279 } // EDGetOperand
280 } // operandIndex != currentOpIndex
281 } // operandIndex >= 0
282 } // else(raw)
283
284 if (show_token)
285 {
286 if(EDGetTokenString(&tokenStr, token))
287 {
288 printTokenized = false;
289 break;
290 }
291
292 operands.PutCString(tokenStr);
293 }
294 } // for (tokenIndex)
295
296 if (printTokenized)
297 {
298 if (operands.GetString().empty())
299 {
300 s->PutCString(opcode.GetString().c_str());
301 }
302 else
303 {
304 PadString(s, opcode.GetString(), opcodeColumnWidth);
305
306 if (comment.GetString().empty())
307 {
308 s->PutCString(operands.GetString().c_str());
309 }
310 else
311 {
312 PadString(s, operands.GetString(), operandColumnWidth);
313
314 s->PutCString("; ");
315 s->PutCString(comment.GetString().c_str());
316 } // else (comment.GetString().empty())
317 } // else (operands.GetString().empty())
318 } // printTokenized
319 } // for (tokenIndex)
320 } // numTokens != -1
321
322 if (!printTokenized)
323 {
324 const char *str;
325
326 if (EDGetInstString(&str, m_inst))
327 return;
328 else
Greg Claytonf15996e2011-04-07 22:46:35 +0000329 s->Write(str, strlen(str) - 1);
Chris Lattner24943d22010-06-08 16:52:24 +0000330 }
331}
332
333bool
Caroline Ticeaf591802011-04-05 23:22:54 +0000334InstructionLLVM::DoesBranch() const
Chris Lattner24943d22010-06-08 16:52:24 +0000335{
336 return EDInstIsBranch(m_inst);
337}
338
339size_t
Caroline Ticeaf591802011-04-05 23:22:54 +0000340InstructionLLVM::Decode (const Disassembler &disassembler,
341 const lldb_private::DataExtractor &data,
342 uint32_t data_offset)
Chris Lattner24943d22010-06-08 16:52:24 +0000343{
344 if (EDCreateInsts(&m_inst, 1, m_disassembler, DataExtractorByteReader, data_offset, (void*)(&data)))
Greg Clayton7bc39082011-03-24 23:53:38 +0000345 {
346 const int byte_size = EDInstByteSize(m_inst);
347 uint32_t offset = data_offset;
348 // Make a copy of the opcode in m_opcode
349 switch (disassembler.GetArchitecture().GetMachine())
350 {
351 case llvm::Triple::x86:
352 case llvm::Triple::x86_64:
353 m_opcode.SetOpcodeBytes (data.PeekData (data_offset, byte_size), byte_size);
354 break;
355
356 case llvm::Triple::arm:
Greg Clayton7bc39082011-03-24 23:53:38 +0000357 case llvm::Triple::thumb:
Greg Clayton149731c2011-03-25 18:03:16 +0000358 switch (byte_size)
359 {
360 case 2:
361 m_opcode.SetOpcode16 (data.GetU16 (&offset));
362 break;
363
364 case 4:
Greg Clayton7bc39082011-03-24 23:53:38 +0000365 m_opcode.SetOpcode32 (data.GetU32 (&offset));
Greg Clayton149731c2011-03-25 18:03:16 +0000366 break;
367
368 default:
369 assert (!"Invalid ARM opcode size");
370 break;
371 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000372 break;
373
374 default:
375 assert (!"This shouldn't happen since we control the architecture we allow DisassemblerLLVM to be created for");
376 break;
377 }
378 return byte_size;
379 }
Chris Lattner24943d22010-06-08 16:52:24 +0000380 else
381 return 0;
382}
383
Chris Lattner24943d22010-06-08 16:52:24 +0000384static inline EDAssemblySyntax_t
Greg Claytoncf015052010-06-11 03:25:34 +0000385SyntaxForArchSpec (const ArchSpec &arch)
Chris Lattner24943d22010-06-08 16:52:24 +0000386{
Greg Clayton940b1032011-02-23 00:35:02 +0000387 switch (arch.GetMachine ())
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000388 {
Greg Clayton940b1032011-02-23 00:35:02 +0000389 case llvm::Triple::x86:
390 case llvm::Triple::x86_64:
Chris Lattner24943d22010-06-08 16:52:24 +0000391 return kEDAssemblySyntaxX86ATT;
Sean Callanand151c8a2011-03-09 01:02:51 +0000392 case llvm::Triple::arm:
Greg Clayton889fbd02011-03-26 19:14:58 +0000393 case llvm::Triple::thumb:
Sean Callanand151c8a2011-03-09 01:02:51 +0000394 return kEDAssemblySyntaxARMUAL;
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000395 default:
396 break;
397 }
Greg Claytoncf015052010-06-11 03:25:34 +0000398 return (EDAssemblySyntax_t)0; // default
Chris Lattner24943d22010-06-08 16:52:24 +0000399}
400
401Disassembler *
402DisassemblerLLVM::CreateInstance(const ArchSpec &arch)
403{
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000404 std::auto_ptr<DisassemblerLLVM> disasm_ap (new DisassemblerLLVM(arch));
405
Caroline Tice080bf612011-04-05 18:46:00 +0000406 if (disasm_ap.get() && disasm_ap->IsValid())
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000407 return disasm_ap.release();
Chris Lattner24943d22010-06-08 16:52:24 +0000408
Greg Claytoncf015052010-06-11 03:25:34 +0000409 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000410}
411
412DisassemblerLLVM::DisassemblerLLVM(const ArchSpec &arch) :
Greg Claytonb01000f2011-01-17 03:46:26 +0000413 Disassembler (arch),
Greg Claytonb1888f22011-03-19 01:12:21 +0000414 m_disassembler (NULL),
415 m_disassembler_thumb (NULL) // For ARM only
Chris Lattner24943d22010-06-08 16:52:24 +0000416{
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000417 const std::string &arch_triple = arch.GetTriple().str();
418 if (!arch_triple.empty())
Greg Claytoncf015052010-06-11 03:25:34 +0000419 {
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000420 if (EDGetDisassembler(&m_disassembler, arch_triple.c_str(), SyntaxForArchSpec (arch)))
421 m_disassembler = NULL;
Greg Claytonb1888f22011-03-19 01:12:21 +0000422 llvm::Triple::ArchType llvm_arch = arch.GetTriple().getArch();
Greg Clayton889fbd02011-03-26 19:14:58 +0000423 // Don't have the lldb::Triple::thumb architecture here. If someone specifies
424 // "thumb" as the architecture, we want a thumb only disassembler. But if any
425 // architecture starting with "arm" if specified, we want to auto detect the
426 // arm/thumb code automatically using the AddressClass from section offset
427 // addresses.
Greg Claytonb1888f22011-03-19 01:12:21 +0000428 if (llvm_arch == llvm::Triple::arm)
429 {
430 if (EDGetDisassembler(&m_disassembler_thumb, "thumb-apple-darwin", kEDAssemblySyntaxARMUAL))
431 m_disassembler_thumb = NULL;
432 }
Greg Claytoncf015052010-06-11 03:25:34 +0000433 }
Chris Lattner24943d22010-06-08 16:52:24 +0000434}
435
436DisassemblerLLVM::~DisassemblerLLVM()
437{
438}
439
440size_t
Greg Clayton70436352010-06-30 23:03:03 +0000441DisassemblerLLVM::DecodeInstructions
Chris Lattner24943d22010-06-08 16:52:24 +0000442(
Greg Clayton5c4c7462010-10-06 03:09:58 +0000443 const Address &base_addr,
Chris Lattner24943d22010-06-08 16:52:24 +0000444 const DataExtractor& data,
445 uint32_t data_offset,
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000446 uint32_t num_instructions,
447 bool append
Chris Lattner24943d22010-06-08 16:52:24 +0000448)
449{
Greg Claytonb01000f2011-01-17 03:46:26 +0000450 if (m_disassembler == NULL)
451 return 0;
452
Chris Lattner24943d22010-06-08 16:52:24 +0000453 size_t total_inst_byte_size = 0;
454
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000455 if (!append)
456 m_instruction_list.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000457
458 while (data.ValidOffset(data_offset) && num_instructions)
459 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000460 Address inst_addr (base_addr);
461 inst_addr.Slide(data_offset);
Greg Claytonb1888f22011-03-19 01:12:21 +0000462
463 bool use_thumb = false;
464 // If we have a thumb disassembler, then we have an ARM architecture
465 // so we need to check what the instruction address class is to make
466 // sure we shouldn't be disassembling as thumb...
Greg Clayton889fbd02011-03-26 19:14:58 +0000467 AddressClass inst_address_class = eAddressClassInvalid;
Greg Claytonb1888f22011-03-19 01:12:21 +0000468 if (m_disassembler_thumb)
469 {
Greg Clayton889fbd02011-03-26 19:14:58 +0000470 inst_address_class = inst_addr.GetAddressClass ();
471 if (inst_address_class == eAddressClassCodeAlternateISA)
Greg Claytonb1888f22011-03-19 01:12:21 +0000472 use_thumb = true;
473 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000474 InstructionSP inst_sp (new InstructionLLVM (inst_addr,
Greg Clayton889fbd02011-03-26 19:14:58 +0000475 inst_address_class,
Greg Clayton7bc39082011-03-24 23:53:38 +0000476 use_thumb ? m_disassembler_thumb : m_disassembler));
Chris Lattner24943d22010-06-08 16:52:24 +0000477
Greg Clayton889fbd02011-03-26 19:14:58 +0000478 size_t inst_byte_size = inst_sp->Decode (*this, data, data_offset);
Chris Lattner24943d22010-06-08 16:52:24 +0000479
480 if (inst_byte_size == 0)
481 break;
482
Greg Clayton5c4c7462010-10-06 03:09:58 +0000483 m_instruction_list.Append (inst_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000484
485 total_inst_byte_size += inst_byte_size;
486 data_offset += inst_byte_size;
487 num_instructions--;
488 }
489
490 return total_inst_byte_size;
491}
492
493void
494DisassemblerLLVM::Initialize()
495{
496 PluginManager::RegisterPlugin (GetPluginNameStatic(),
497 GetPluginDescriptionStatic(),
498 CreateInstance);
499}
500
501void
502DisassemblerLLVM::Terminate()
503{
504 PluginManager::UnregisterPlugin (CreateInstance);
505}
506
507
508const char *
509DisassemblerLLVM::GetPluginNameStatic()
510{
Greg Clayton149731c2011-03-25 18:03:16 +0000511 return "llvm";
Chris Lattner24943d22010-06-08 16:52:24 +0000512}
513
514const char *
515DisassemblerLLVM::GetPluginDescriptionStatic()
516{
Greg Clayton149731c2011-03-25 18:03:16 +0000517 return "Disassembler that uses LLVM opcode tables to disassemble i386, x86_64 and ARM.";
Chris Lattner24943d22010-06-08 16:52:24 +0000518}
519
520//------------------------------------------------------------------
521// PluginInterface protocol
522//------------------------------------------------------------------
523const char *
524DisassemblerLLVM::GetPluginName()
525{
526 return "DisassemblerLLVM";
527}
528
529const char *
530DisassemblerLLVM::GetShortPluginName()
531{
532 return GetPluginNameStatic();
533}
534
535uint32_t
536DisassemblerLLVM::GetPluginVersion()
537{
538 return 1;
539}
540