blob: 64a4c2c762b9bfdf15e93a4b6cca050ce1bd6f42 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Disassembler.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 "lldb/Core/Disassembler.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/lldb-private.h"
17#include "lldb/Core/Error.h"
18#include "lldb/Core/DataBufferHeap.h"
19#include "lldb/Core/DataExtractor.h"
20#include "lldb/Core/Debugger.h"
21#include "lldb/Core/Module.h"
22#include "lldb/Core/PluginManager.h"
23#include "lldb/Core/Timer.h"
24#include "lldb/Symbol/ObjectFile.h"
25#include "lldb/Target/ExecutionContext.h"
26#include "lldb/Target/Process.h"
27#include "lldb/Target/StackFrame.h"
28#include "lldb/Target/Target.h"
29
30#define DEFAULT_DISASM_BYTE_SIZE 32
31
32using namespace lldb;
33using namespace lldb_private;
34
35
36Disassembler*
37Disassembler::FindPlugin (const ArchSpec &arch)
38{
39 Timer scoped_timer (__PRETTY_FUNCTION__,
40 "Disassembler::FindPlugin (arch = %s)",
41 arch.AsCString());
42
43 std::auto_ptr<Disassembler> disassembler_ap;
44 DisassemblerCreateInstance create_callback;
45 for (uint32_t idx = 0; (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(idx)) != NULL; ++idx)
46 {
47 disassembler_ap.reset (create_callback(arch));
48
49 if (disassembler_ap.get())
50 return disassembler_ap.release();
51 }
52 return NULL;
53}
54
Greg Claytondda4f7b2010-06-30 23:03:03 +000055
56
57size_t
58Disassembler::Disassemble
59(
60 Debugger &debugger,
61 const ArchSpec &arch,
62 const ExecutionContext &exe_ctx,
63 SymbolContextList &sc_list,
64 uint32_t num_mixed_context_lines,
65 bool show_bytes,
66 Stream &strm
67)
68{
69 size_t success_count = 0;
70 const size_t count = sc_list.GetSize();
71 SymbolContext sc;
72 AddressRange range;
73 for (size_t i=0; i<count; ++i)
74 {
75 if (sc_list.GetContextAtIndex(i, sc) == false)
76 break;
77 if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
78 {
79 if (Disassemble (debugger, arch, exe_ctx, range, num_mixed_context_lines, show_bytes, strm))
80 {
81 ++success_count;
82 strm.EOL();
83 }
84 }
85 }
86 return success_count;
87}
88
Chris Lattner30fdc8d2010-06-08 16:52:24 +000089bool
90Disassembler::Disassemble
91(
Greg Clayton66111032010-06-23 01:19:29 +000092 Debugger &debugger,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000093 const ArchSpec &arch,
94 const ExecutionContext &exe_ctx,
Greg Claytondda4f7b2010-06-30 23:03:03 +000095 const ConstString &name,
96 Module *module,
97 uint32_t num_mixed_context_lines,
98 bool show_bytes,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000099 Stream &strm
100)
101{
Greg Claytondda4f7b2010-06-30 23:03:03 +0000102 SymbolContextList sc_list;
Greg Clayton931180e2011-01-27 06:44:37 +0000103 if (name)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000104 {
Greg Clayton931180e2011-01-27 06:44:37 +0000105 const bool include_symbols = true;
106 if (module)
107 {
108 module->FindFunctions (name,
109 eFunctionNameTypeBase |
110 eFunctionNameTypeFull |
111 eFunctionNameTypeMethod |
112 eFunctionNameTypeSelector,
113 include_symbols,
114 true,
115 sc_list);
116 }
117 else if (exe_ctx.target)
118 {
119 exe_ctx.target->GetImages().FindFunctions (name,
Greg Clayton6dbd3982010-09-15 05:51:24 +0000120 eFunctionNameTypeBase |
121 eFunctionNameTypeFull |
122 eFunctionNameTypeMethod |
123 eFunctionNameTypeSelector,
Greg Clayton931180e2011-01-27 06:44:37 +0000124 include_symbols,
Sean Callanan8ade1042010-07-27 00:55:47 +0000125 false,
Greg Clayton931180e2011-01-27 06:44:37 +0000126 sc_list);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000127 }
Greg Clayton931180e2011-01-27 06:44:37 +0000128 }
129
130 if (sc_list.GetSize ())
131 {
132 return Disassemble (debugger,
133 arch,
134 exe_ctx,
135 sc_list,
136 num_mixed_context_lines,
137 show_bytes,
138 strm);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000139 }
140 return false;
141}
142
Greg Clayton1d273162010-10-06 03:09:58 +0000143
144lldb::DisassemblerSP
145Disassembler::DisassembleRange
146(
147 const ArchSpec &arch,
148 const ExecutionContext &exe_ctx,
149 const AddressRange &range
150)
151{
152 lldb::DisassemblerSP disasm_sp;
153 if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid())
154 {
155 disasm_sp.reset (Disassembler::FindPlugin(arch));
156
157 if (disasm_sp)
158 {
159 DataExtractor data;
160 size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range, data);
161 if (bytes_disassembled == 0)
162 disasm_sp.reset();
163 }
164 }
165 return disasm_sp;
166}
167
168
Greg Claytondda4f7b2010-06-30 23:03:03 +0000169bool
170Disassembler::Disassemble
171(
172 Debugger &debugger,
173 const ArchSpec &arch,
174 const ExecutionContext &exe_ctx,
175 const AddressRange &disasm_range,
176 uint32_t num_mixed_context_lines,
177 bool show_bytes,
178 Stream &strm
179)
180{
181 if (disasm_range.GetByteSize())
182 {
Greg Clayton1d273162010-10-06 03:09:58 +0000183 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch));
Greg Claytondda4f7b2010-06-30 23:03:03 +0000184
Greg Clayton1d273162010-10-06 03:09:58 +0000185 if (disasm_ap.get())
Greg Claytondda4f7b2010-06-30 23:03:03 +0000186 {
187 AddressRange range(disasm_range);
188
189 Process *process = exe_ctx.process;
190
191 // If we weren't passed in a section offset address range,
192 // try and resolve it to something
193 if (range.GetBaseAddress().IsSectionOffset() == false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000194 {
Greg Claytonf5e56de2010-09-14 23:36:40 +0000195 if (exe_ctx.target)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000196 {
Greg Claytonf5e56de2010-09-14 23:36:40 +0000197 if (exe_ctx.target->GetSectionLoadList().IsEmpty())
198 {
199 exe_ctx.target->GetImages().ResolveFileAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress());
200 }
201 else
202 {
203 exe_ctx.target->GetSectionLoadList().ResolveLoadAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress());
204 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000205 }
206 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000207
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000208 DataExtractor data;
Greg Clayton1d273162010-10-06 03:09:58 +0000209 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, range, data);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000210 if (bytes_disassembled == 0)
211 {
212 return false;
213 }
214 else
215 {
216 // We got some things disassembled...
Greg Clayton1d273162010-10-06 03:09:58 +0000217 size_t num_instructions = disasm_ap->GetInstructionList().GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000218 uint32_t offset = 0;
219 SymbolContext sc;
220 SymbolContext prev_sc;
221 AddressRange sc_range;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000222 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000223 strm.IndentMore ();
224
Greg Claytondda4f7b2010-06-30 23:03:03 +0000225
226 Address addr(range.GetBaseAddress());
227
228 // We extract the section to make sure we don't transition out
229 // of the current section when disassembling
230 const Section *addr_section = addr.GetSection();
231 Module *range_module = range.GetBaseAddress().GetModule();
232
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000233 for (size_t i=0; i<num_instructions; ++i)
234 {
Greg Clayton1d273162010-10-06 03:09:58 +0000235 Instruction *inst = disasm_ap->GetInstructionList().GetInstructionAtIndex (i).get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000236 if (inst)
237 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000238 addr_t file_addr = addr.GetFileAddress();
239 if (addr_section == NULL || addr_section->ContainsFileAddress (file_addr) == false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000240 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000241 if (range_module)
242 range_module->ResolveFileAddress (file_addr, addr);
243 else if (exe_ctx.target)
244 exe_ctx.target->GetImages().ResolveFileAddress (file_addr, addr);
245
246 addr_section = addr.GetSection();
247 }
248
249 prev_sc = sc;
250
251 if (addr_section)
252 {
253 Module *module = addr_section->GetModule();
254 uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
255 if (resolved_mask)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000256 {
Greg Clayton3c687572010-09-06 23:11:45 +0000257 if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000258 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000259 if (prev_sc.function || prev_sc.symbol)
260 strm.EOL();
261
262 strm << sc.module_sp->GetFileSpec().GetFilename();
263
264 if (sc.function)
265 strm << '`' << sc.function->GetMangled().GetName();
266 else if (sc.symbol)
267 strm << '`' << sc.symbol->GetMangled().GetName();
268 strm << ":\n";
269 }
270
271 if (num_mixed_context_lines && !sc_range.ContainsFileAddress (addr))
272 {
273 sc.GetAddressRange (eSymbolContextEverything, sc_range);
274
275 if (sc != prev_sc)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000276 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000277 if (offset != 0)
278 strm.EOL();
279
Greg Clayton6dbd3982010-09-15 05:51:24 +0000280 sc.DumpStopContext(&strm, process, addr, false, true, false);
281 strm.EOL();
Greg Claytondda4f7b2010-06-30 23:03:03 +0000282
283 if (sc.comp_unit && sc.line_entry.IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000284 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000285 debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
286 sc.line_entry.line,
287 num_mixed_context_lines,
288 num_mixed_context_lines,
289 num_mixed_context_lines ? "->" : "",
290 &strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000291 }
292 }
293 }
294 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000295 else
296 {
297 sc.Clear();
298 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000299 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000300 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000301 strm.IndentMore ();
302 strm.Indent();
303 size_t inst_byte_size = inst->GetByteSize();
Greg Clayton1d273162010-10-06 03:09:58 +0000304 inst->Dump(&strm, true, show_bytes ? &data : NULL, offset, &exe_ctx, show_bytes);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000305 strm.EOL();
306 offset += inst_byte_size;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000307
308 addr.SetOffset (addr.GetOffset() + inst_byte_size);
309
310 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000311 strm.IndentLess ();
312 }
313 else
314 {
315 break;
316 }
317 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000318 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000319 strm.IndentLess ();
320
321 }
322 }
323 return true;
324 }
325 return false;
326}
327
Greg Claytondda4f7b2010-06-30 23:03:03 +0000328
329bool
330Disassembler::Disassemble
331(
332 Debugger &debugger,
333 const ArchSpec &arch,
334 const ExecutionContext &exe_ctx,
335 uint32_t num_mixed_context_lines,
336 bool show_bytes,
337 Stream &strm
338)
339{
340 AddressRange range;
341 if (exe_ctx.frame)
342 {
343 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
344 if (sc.function)
345 {
346 range = sc.function->GetAddressRange();
347 }
348 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
349 {
350 range = *sc.symbol->GetAddressRangePtr();
351 }
352 else
353 {
Greg Clayton9da7bd02010-08-24 21:05:24 +0000354 range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress();
Greg Claytondda4f7b2010-06-30 23:03:03 +0000355 }
356
357 if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
358 range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
359 }
360
361 return Disassemble(debugger, arch, exe_ctx, range, num_mixed_context_lines, show_bytes, strm);
362}
363
Greg Clayton1d273162010-10-06 03:09:58 +0000364Instruction::Instruction(const Address &addr) :
365 m_addr (addr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000366{
367}
368
Greg Clayton1d273162010-10-06 03:09:58 +0000369Instruction::~Instruction()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000370{
371}
372
373
Greg Clayton1d273162010-10-06 03:09:58 +0000374InstructionList::InstructionList() :
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000375 m_instructions()
376{
377}
378
Greg Clayton1d273162010-10-06 03:09:58 +0000379InstructionList::~InstructionList()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000380{
381}
382
383size_t
Greg Clayton1d273162010-10-06 03:09:58 +0000384InstructionList::GetSize() const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000385{
386 return m_instructions.size();
387}
388
389
Greg Clayton1d273162010-10-06 03:09:58 +0000390InstructionSP
391InstructionList::GetInstructionAtIndex (uint32_t idx) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000392{
Greg Clayton1d273162010-10-06 03:09:58 +0000393 InstructionSP inst_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000394 if (idx < m_instructions.size())
Greg Clayton1d273162010-10-06 03:09:58 +0000395 inst_sp = m_instructions[idx];
396 return inst_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000397}
398
399void
Greg Clayton1d273162010-10-06 03:09:58 +0000400InstructionList::Clear()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000401{
402 m_instructions.clear();
403}
404
405void
Greg Clayton1d273162010-10-06 03:09:58 +0000406InstructionList::Append (lldb::InstructionSP &inst_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000407{
408 if (inst_sp)
409 m_instructions.push_back(inst_sp);
410}
411
412
413size_t
414Disassembler::ParseInstructions
415(
416 const ExecutionContext *exe_ctx,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000417 const AddressRange &range,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000418 DataExtractor& data
419)
420{
Greg Claytondda4f7b2010-06-30 23:03:03 +0000421 Target *target = exe_ctx->target;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000422 const addr_t byte_size = range.GetByteSize();
423 if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000424 return 0;
425
Greg Claytondda4f7b2010-06-30 23:03:03 +0000426 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
427 DataBufferSP data_sp(heap_buffer);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000428
429 Error error;
Greg Claytondb598232011-01-07 01:57:07 +0000430 bool prefer_file_cache = true;
431 const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(), prefer_file_cache, heap_buffer->GetBytes(), heap_buffer->GetByteSize(), error);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000432
433 if (bytes_read > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000434 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000435 if (bytes_read != heap_buffer->GetByteSize())
436 heap_buffer->SetByteSize (bytes_read);
437
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000438 data.SetData(data_sp);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000439 if (exe_ctx->process)
440 {
441 data.SetByteOrder(exe_ctx->process->GetByteOrder());
442 data.SetAddressByteSize(exe_ctx->process->GetAddressByteSize());
443 }
444 else
445 {
446 data.SetByteOrder(target->GetArchitecture().GetDefaultEndian());
447 data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
448 }
Greg Clayton1d273162010-10-06 03:09:58 +0000449 return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000450 }
451
452 return 0;
453}
454
455//----------------------------------------------------------------------
456// Disassembler copy constructor
457//----------------------------------------------------------------------
458Disassembler::Disassembler(const ArchSpec& arch) :
459 m_arch (arch),
460 m_instruction_list(),
461 m_base_addr(LLDB_INVALID_ADDRESS)
462{
463
464}
465
466//----------------------------------------------------------------------
467// Destructor
468//----------------------------------------------------------------------
469Disassembler::~Disassembler()
470{
471}
472
Greg Clayton1d273162010-10-06 03:09:58 +0000473InstructionList &
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000474Disassembler::GetInstructionList ()
475{
476 return m_instruction_list;
477}
478
Greg Clayton1d273162010-10-06 03:09:58 +0000479const InstructionList &
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000480Disassembler::GetInstructionList () const
481{
482 return m_instruction_list;
483}