blob: 456c63f4bdd110853358ee6199d490fadee49c1b [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
28#include <memory>
29#include <string>
30
31using namespace lldb;
32using namespace lldb_private;
33
34
35static
36int DataExtractorByteReader(uint8_t *byte, uint64_t address, void *arg)
37{
38 DataExtractor &extractor = *((DataExtractor *)arg);
39
40 if (extractor.ValidOffset(address))
41 {
42 *byte = *(extractor.GetDataStart() + address);
43 return 0;
44 }
45 else
46 {
47 return -1;
48 }
49}
50
51namespace {
52 struct RegisterReaderArg {
53 const lldb::addr_t instructionPointer;
54 const EDDisassemblerRef disassembler;
55
56 RegisterReaderArg(lldb::addr_t ip,
57 EDDisassemblerRef dis) :
58 instructionPointer(ip),
59 disassembler(dis)
60 {
61 }
62 };
63}
64
65static int IPRegisterReader(uint64_t *value, unsigned regID, void* arg)
66{
67 uint64_t instructionPointer = ((RegisterReaderArg*)arg)->instructionPointer;
68 EDDisassemblerRef disassembler = ((RegisterReaderArg*)arg)->disassembler;
69
70 if(EDRegisterIsProgramCounter(disassembler, regID)) {
71 *value = instructionPointer;
72 return 0;
73 }
74
75 return -1;
76}
77
Greg Clayton5c4c7462010-10-06 03:09:58 +000078DisassemblerLLVM::InstructionLLVM::InstructionLLVM (EDDisassemblerRef disassembler, const Address &addr) :
79 Instruction (addr),
Chris Lattner24943d22010-06-08 16:52:24 +000080 m_disassembler (disassembler)
81{
82}
83
Greg Clayton5c4c7462010-10-06 03:09:58 +000084DisassemblerLLVM::InstructionLLVM::~InstructionLLVM()
Chris Lattner24943d22010-06-08 16:52:24 +000085{
86}
87
88static void
89PadString(Stream *s, const std::string &str, size_t width)
90{
91 int diff = width - str.length();
92
93 if (diff > 0)
94 s->Printf("%s%*.*s", str.c_str(), diff, diff, "");
95 else
96 s->Printf("%s ", str.c_str());
97}
98
99void
Greg Clayton5c4c7462010-10-06 03:09:58 +0000100DisassemblerLLVM::InstructionLLVM::Dump
Chris Lattner24943d22010-06-08 16:52:24 +0000101(
102 Stream *s,
Greg Clayton5c4c7462010-10-06 03:09:58 +0000103 bool show_address,
Greg Clayton70436352010-06-30 23:03:03 +0000104 const DataExtractor *bytes,
Chris Lattner24943d22010-06-08 16:52:24 +0000105 uint32_t bytes_offset,
Greg Clayton5c4c7462010-10-06 03:09:58 +0000106 const lldb_private::ExecutionContext* exe_ctx,
Chris Lattner24943d22010-06-08 16:52:24 +0000107 bool raw
108)
109{
110 const size_t opcodeColumnWidth = 7;
111 const size_t operandColumnWidth = 25;
112
Greg Clayton5c4c7462010-10-06 03:09:58 +0000113 ExecutionContextScope *exe_scope = NULL;
114 if (exe_ctx)
115 exe_scope = exe_ctx->GetBestExecutionContextScope();
116
Chris Lattner24943d22010-06-08 16:52:24 +0000117 // If we have an address, print it out
Sean Callanan91557b02010-11-10 01:38:28 +0000118 if (GetAddress().IsValid() && show_address)
Greg Clayton70436352010-06-30 23:03:03 +0000119 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000120 if (GetAddress().Dump (s,
121 exe_scope,
122 Address::DumpStyleLoadAddress,
123 Address::DumpStyleModuleWithFileAddress,
124 0))
Greg Clayton70436352010-06-30 23:03:03 +0000125 s->PutCString(": ");
126 }
Chris Lattner24943d22010-06-08 16:52:24 +0000127
128 // If we are supposed to show bytes, "bytes" will be non-NULL.
129 if (bytes)
130 {
131 uint32_t bytes_dumped = bytes->Dump(s, bytes_offset, eFormatBytes, 1, EDInstByteSize(m_inst), UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0) - bytes_offset;
Greg Clayton1e2e2712011-01-08 22:55:04 +0000132 // Allow for 15 bytes of opcodes since this is the max for x86_64.
133 // TOOD: We need to taylor this better for different architectures. For
134 // ARM we would want to show 16 bit opcodes for Thumb as properly byte
135 // swapped uint16_t values, or 32 bit values swapped values for ARM.
136 const uint32_t default_num_opcode_bytes = 15;
Chris Lattner24943d22010-06-08 16:52:24 +0000137 if (bytes_dumped * 3 < (default_num_opcode_bytes*3))
138 {
Greg Clayton1e2e2712011-01-08 22:55:04 +0000139 uint32_t indent_level = (default_num_opcode_bytes*3) - (bytes_dumped * 3) + 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000140 s->Printf("%*.*s", indent_level, indent_level, "");
141 }
142 }
143
144 int numTokens = EDNumTokens(m_inst);
145
146 int currentOpIndex = -1;
147
Sean Callanan8541f2f2010-07-23 02:19:15 +0000148 std::auto_ptr<RegisterReaderArg> rra;
149
150 if (!raw)
151 {
152 addr_t base_addr = LLDB_INVALID_ADDRESS;
Greg Clayton5c4c7462010-10-06 03:09:58 +0000153 if (exe_ctx && exe_ctx->target && !exe_ctx->target->GetSectionLoadList().IsEmpty())
154 base_addr = GetAddress().GetLoadAddress (exe_ctx->target);
Sean Callanan8541f2f2010-07-23 02:19:15 +0000155 if (base_addr == LLDB_INVALID_ADDRESS)
Greg Clayton5c4c7462010-10-06 03:09:58 +0000156 base_addr = GetAddress().GetFileAddress ();
Sean Callanan8541f2f2010-07-23 02:19:15 +0000157
158 rra.reset(new RegisterReaderArg(base_addr + EDInstByteSize(m_inst), m_disassembler));
159 }
Chris Lattner24943d22010-06-08 16:52:24 +0000160
161 bool printTokenized = false;
162
163 if (numTokens != -1)
164 {
165 printTokenized = true;
166
167 // Handle the opcode column.
168
169 StreamString opcode;
170
171 int tokenIndex = 0;
172
173 EDTokenRef token;
174 const char *tokenStr;
175
176 if (EDGetToken(&token, m_inst, tokenIndex))
177 printTokenized = false;
178
179 if (!printTokenized || !EDTokenIsOpcode(token))
180 printTokenized = false;
181
182 if (!printTokenized || EDGetTokenString(&tokenStr, token))
183 printTokenized = false;
184
185 // Put the token string into our opcode string
186 opcode.PutCString(tokenStr);
187
188 // If anything follows, it probably starts with some whitespace. Skip it.
189
190 tokenIndex++;
191
192 if (printTokenized && tokenIndex < numTokens)
193 {
194 if(!printTokenized || EDGetToken(&token, m_inst, tokenIndex))
195 printTokenized = false;
196
197 if(!printTokenized || !EDTokenIsWhitespace(token))
198 printTokenized = false;
199 }
200
201 tokenIndex++;
202
203 // Handle the operands and the comment.
204
205 StreamString operands;
206 StreamString comment;
207
208 if (printTokenized)
209 {
210 bool show_token;
211
212 for (; tokenIndex < numTokens; ++tokenIndex)
213 {
214 if (EDGetToken(&token, m_inst, tokenIndex))
215 return;
216
217 if (raw)
218 {
219 show_token = true;
220 }
221 else
222 {
223 int operandIndex = EDOperandIndexForToken(token);
224
225 if (operandIndex >= 0)
226 {
227 if (operandIndex != currentOpIndex)
228 {
229 show_token = true;
230
231 currentOpIndex = operandIndex;
232 EDOperandRef operand;
233
234 if (!EDGetOperand(&operand, m_inst, currentOpIndex))
235 {
236 if (EDOperandIsMemory(operand))
237 {
238 uint64_t operand_value;
239
Sean Callanan8541f2f2010-07-23 02:19:15 +0000240 if (!EDEvaluateOperand(&operand_value, operand, IPRegisterReader, rra.get()))
Chris Lattner24943d22010-06-08 16:52:24 +0000241 {
242 if (EDInstIsBranch(m_inst))
243 {
244 operands.Printf("0x%llx ", operand_value);
245 show_token = false;
246 }
247 else
248 {
249 // Put the address value into the comment
250 comment.Printf("0x%llx ", operand_value);
251 }
252
253 lldb_private::Address so_addr;
Greg Clayton5c4c7462010-10-06 03:09:58 +0000254 if (exe_ctx && exe_ctx->target && !exe_ctx->target->GetSectionLoadList().IsEmpty())
Chris Lattner24943d22010-06-08 16:52:24 +0000255 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000256 if (exe_ctx->target->GetSectionLoadList().ResolveLoadAddress (operand_value, so_addr))
Greg Claytoncf7f1ad2010-07-01 01:26:43 +0000257 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
Greg Clayton70436352010-06-30 23:03:03 +0000258 }
Greg Clayton5c4c7462010-10-06 03:09:58 +0000259 else
Greg Clayton70436352010-06-30 23:03:03 +0000260 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000261 Module *module = GetAddress().GetModule();
Greg Clayton70436352010-06-30 23:03:03 +0000262 if (module)
Chris Lattner24943d22010-06-08 16:52:24 +0000263 {
Greg Clayton70436352010-06-30 23:03:03 +0000264 if (module->ResolveFileAddress (operand_value, so_addr))
Greg Claytoncf7f1ad2010-07-01 01:26:43 +0000265 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
Chris Lattner24943d22010-06-08 16:52:24 +0000266 }
267 }
Greg Clayton70436352010-06-30 23:03:03 +0000268
Chris Lattner24943d22010-06-08 16:52:24 +0000269 } // EDEvaluateOperand
270 } // EDOperandIsMemory
271 } // EDGetOperand
272 } // operandIndex != currentOpIndex
273 } // operandIndex >= 0
274 } // else(raw)
275
276 if (show_token)
277 {
278 if(EDGetTokenString(&tokenStr, token))
279 {
280 printTokenized = false;
281 break;
282 }
283
284 operands.PutCString(tokenStr);
285 }
286 } // for (tokenIndex)
287
288 if (printTokenized)
289 {
290 if (operands.GetString().empty())
291 {
292 s->PutCString(opcode.GetString().c_str());
293 }
294 else
295 {
296 PadString(s, opcode.GetString(), opcodeColumnWidth);
297
298 if (comment.GetString().empty())
299 {
300 s->PutCString(operands.GetString().c_str());
301 }
302 else
303 {
304 PadString(s, operands.GetString(), operandColumnWidth);
305
306 s->PutCString("; ");
307 s->PutCString(comment.GetString().c_str());
308 } // else (comment.GetString().empty())
309 } // else (operands.GetString().empty())
310 } // printTokenized
311 } // for (tokenIndex)
312 } // numTokens != -1
313
314 if (!printTokenized)
315 {
316 const char *str;
317
318 if (EDGetInstString(&str, m_inst))
319 return;
320 else
321 s->PutCString(str);
322 }
323}
324
325bool
Greg Clayton5c4c7462010-10-06 03:09:58 +0000326DisassemblerLLVM::InstructionLLVM::DoesBranch() const
Chris Lattner24943d22010-06-08 16:52:24 +0000327{
328 return EDInstIsBranch(m_inst);
329}
330
331size_t
Greg Clayton5c4c7462010-10-06 03:09:58 +0000332DisassemblerLLVM::InstructionLLVM::GetByteSize() const
Chris Lattner24943d22010-06-08 16:52:24 +0000333{
334 return EDInstByteSize(m_inst);
335}
336
337size_t
Greg Clayton5c4c7462010-10-06 03:09:58 +0000338DisassemblerLLVM::InstructionLLVM::Extract(const DataExtractor &data, uint32_t data_offset)
Chris Lattner24943d22010-06-08 16:52:24 +0000339{
340 if (EDCreateInsts(&m_inst, 1, m_disassembler, DataExtractorByteReader, data_offset, (void*)(&data)))
341 return EDInstByteSize(m_inst);
342 else
343 return 0;
344}
345
346static inline const char *
Greg Claytoncf015052010-06-11 03:25:34 +0000347TripleForArchSpec (const ArchSpec &arch, char *triple, size_t triple_len)
Chris Lattner24943d22010-06-08 16:52:24 +0000348{
Greg Claytoncf015052010-06-11 03:25:34 +0000349 const char *arch_name = arch.AsCString();
350
351 if (arch_name)
Chris Lattner24943d22010-06-08 16:52:24 +0000352 {
Greg Claytoncf015052010-06-11 03:25:34 +0000353 snprintf(triple, triple_len, "%s-unknown-unknown", arch_name);
354 return triple;
Chris Lattner24943d22010-06-08 16:52:24 +0000355 }
Greg Claytoncf015052010-06-11 03:25:34 +0000356 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000357}
358
359static inline EDAssemblySyntax_t
Greg Claytoncf015052010-06-11 03:25:34 +0000360SyntaxForArchSpec (const ArchSpec &arch)
Chris Lattner24943d22010-06-08 16:52:24 +0000361{
Greg Claytoncf015052010-06-11 03:25:34 +0000362 const char *arch_name = arch.AsCString();
363
364 if (arch_name != NULL &&
365 ((strcasestr (arch_name, "i386") == arch_name) ||
366 (strcasestr (arch_name, "x86_64") == arch_name)))
Chris Lattner24943d22010-06-08 16:52:24 +0000367 return kEDAssemblySyntaxX86ATT;
Greg Claytoncf015052010-06-11 03:25:34 +0000368
369 return (EDAssemblySyntax_t)0; // default
Chris Lattner24943d22010-06-08 16:52:24 +0000370}
371
372Disassembler *
373DisassemblerLLVM::CreateInstance(const ArchSpec &arch)
374{
Greg Claytoncf015052010-06-11 03:25:34 +0000375 char triple[256];
Chris Lattner24943d22010-06-08 16:52:24 +0000376
Greg Claytoncf015052010-06-11 03:25:34 +0000377 if (TripleForArchSpec (arch, triple, sizeof(triple)))
Sean Callanan0a298dc2010-06-16 22:19:05 +0000378 return new DisassemblerLLVM(arch);
Greg Claytoncf015052010-06-11 03:25:34 +0000379 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000380}
381
382DisassemblerLLVM::DisassemblerLLVM(const ArchSpec &arch) :
383 Disassembler(arch)
384{
Greg Claytoncf015052010-06-11 03:25:34 +0000385 char triple[256];
386 if (TripleForArchSpec (arch, triple, sizeof(triple)))
387 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000388 assert(!EDGetDisassembler(&m_disassembler, triple, SyntaxForArchSpec (arch)) && "No disassembler created!");
Greg Claytoncf015052010-06-11 03:25:34 +0000389 }
Chris Lattner24943d22010-06-08 16:52:24 +0000390}
391
392DisassemblerLLVM::~DisassemblerLLVM()
393{
394}
395
396size_t
Greg Clayton70436352010-06-30 23:03:03 +0000397DisassemblerLLVM::DecodeInstructions
Chris Lattner24943d22010-06-08 16:52:24 +0000398(
Greg Clayton5c4c7462010-10-06 03:09:58 +0000399 const Address &base_addr,
Chris Lattner24943d22010-06-08 16:52:24 +0000400 const DataExtractor& data,
401 uint32_t data_offset,
Greg Clayton70436352010-06-30 23:03:03 +0000402 uint32_t num_instructions
Chris Lattner24943d22010-06-08 16:52:24 +0000403)
404{
405 size_t total_inst_byte_size = 0;
406
407 m_instruction_list.Clear();
408
409 while (data.ValidOffset(data_offset) && num_instructions)
410 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000411 Address inst_addr (base_addr);
412 inst_addr.Slide(data_offset);
413 InstructionSP inst_sp (new InstructionLLVM(m_disassembler, inst_addr));
Chris Lattner24943d22010-06-08 16:52:24 +0000414
Greg Clayton5c4c7462010-10-06 03:09:58 +0000415 size_t inst_byte_size = inst_sp->Extract (data, data_offset);
Chris Lattner24943d22010-06-08 16:52:24 +0000416
417 if (inst_byte_size == 0)
418 break;
419
Greg Clayton5c4c7462010-10-06 03:09:58 +0000420 m_instruction_list.Append (inst_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000421
422 total_inst_byte_size += inst_byte_size;
423 data_offset += inst_byte_size;
424 num_instructions--;
425 }
426
427 return total_inst_byte_size;
428}
429
430void
431DisassemblerLLVM::Initialize()
432{
433 PluginManager::RegisterPlugin (GetPluginNameStatic(),
434 GetPluginDescriptionStatic(),
435 CreateInstance);
436}
437
438void
439DisassemblerLLVM::Terminate()
440{
441 PluginManager::UnregisterPlugin (CreateInstance);
442}
443
444
445const char *
446DisassemblerLLVM::GetPluginNameStatic()
447{
448 return "disassembler.llvm";
449}
450
451const char *
452DisassemblerLLVM::GetPluginDescriptionStatic()
453{
454 return "Disassembler that uses LLVM opcode tables to disassemble i386 and x86_64.";
455}
456
457//------------------------------------------------------------------
458// PluginInterface protocol
459//------------------------------------------------------------------
460const char *
461DisassemblerLLVM::GetPluginName()
462{
463 return "DisassemblerLLVM";
464}
465
466const char *
467DisassemblerLLVM::GetShortPluginName()
468{
469 return GetPluginNameStatic();
470}
471
472uint32_t
473DisassemblerLLVM::GetPluginVersion()
474{
475 return 1;
476}
477
478void
479DisassemblerLLVM::GetPluginCommandHelp (const char *command, Stream *strm)
480{
481}
482
483Error
484DisassemblerLLVM::ExecutePluginCommand (Args &command, Stream *strm)
485{
486 Error error;
487 error.SetErrorString("No plug-in command are currently supported.");
488 return error;
489}
490
491Log *
492DisassemblerLLVM::EnablePluginLogging (Stream *strm, Args &command)
493{
494 return NULL;
495}
496