blob: e6fe1b018a5e9668d1ee905a35f736634ef9935e [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 if (exe_ctx.target == NULL && name)
103 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000104
Greg Claytondda4f7b2010-06-30 23:03:03 +0000105 SymbolContextList sc_list;
106
107 if (module)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000108 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000109 if (!module->FindFunctions (name,
Greg Clayton6dbd3982010-09-15 05:51:24 +0000110 eFunctionNameTypeBase |
111 eFunctionNameTypeFull |
112 eFunctionNameTypeMethod |
113 eFunctionNameTypeSelector,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000114 true,
115 sc_list))
116 return false;
117 }
118 else
119 {
120 if (exe_ctx.target->GetImages().FindFunctions (name,
Greg Clayton6dbd3982010-09-15 05:51:24 +0000121 eFunctionNameTypeBase |
122 eFunctionNameTypeFull |
123 eFunctionNameTypeMethod |
124 eFunctionNameTypeSelector,
Sean Callanan8ade1042010-07-27 00:55:47 +0000125 false,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000126 sc_list))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000127 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000128 return Disassemble (debugger, arch, exe_ctx, sc_list, num_mixed_context_lines, show_bytes, strm);
129 }
130 else if (exe_ctx.target->GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeCode, sc_list))
131 {
132 return Disassemble (debugger, arch, exe_ctx, sc_list, num_mixed_context_lines, show_bytes, strm);
133 }
134 }
135 return false;
136}
137
Greg Clayton1d273162010-10-06 03:09:58 +0000138
139lldb::DisassemblerSP
140Disassembler::DisassembleRange
141(
142 const ArchSpec &arch,
143 const ExecutionContext &exe_ctx,
144 const AddressRange &range
145)
146{
147 lldb::DisassemblerSP disasm_sp;
148 if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid())
149 {
150 disasm_sp.reset (Disassembler::FindPlugin(arch));
151
152 if (disasm_sp)
153 {
154 DataExtractor data;
155 size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range, data);
156 if (bytes_disassembled == 0)
157 disasm_sp.reset();
158 }
159 }
160 return disasm_sp;
161}
162
163
Greg Claytondda4f7b2010-06-30 23:03:03 +0000164bool
165Disassembler::Disassemble
166(
167 Debugger &debugger,
168 const ArchSpec &arch,
169 const ExecutionContext &exe_ctx,
170 const AddressRange &disasm_range,
171 uint32_t num_mixed_context_lines,
172 bool show_bytes,
173 Stream &strm
174)
175{
176 if (disasm_range.GetByteSize())
177 {
Greg Clayton1d273162010-10-06 03:09:58 +0000178 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch));
Greg Claytondda4f7b2010-06-30 23:03:03 +0000179
Greg Clayton1d273162010-10-06 03:09:58 +0000180 if (disasm_ap.get())
Greg Claytondda4f7b2010-06-30 23:03:03 +0000181 {
182 AddressRange range(disasm_range);
183
184 Process *process = exe_ctx.process;
185
186 // If we weren't passed in a section offset address range,
187 // try and resolve it to something
188 if (range.GetBaseAddress().IsSectionOffset() == false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000189 {
Greg Claytonf5e56de2010-09-14 23:36:40 +0000190 if (exe_ctx.target)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000191 {
Greg Claytonf5e56de2010-09-14 23:36:40 +0000192 if (exe_ctx.target->GetSectionLoadList().IsEmpty())
193 {
194 exe_ctx.target->GetImages().ResolveFileAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress());
195 }
196 else
197 {
198 exe_ctx.target->GetSectionLoadList().ResolveLoadAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress());
199 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000200 }
201 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000202
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000203 DataExtractor data;
Greg Clayton1d273162010-10-06 03:09:58 +0000204 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, range, data);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000205 if (bytes_disassembled == 0)
206 {
207 return false;
208 }
209 else
210 {
211 // We got some things disassembled...
Greg Clayton1d273162010-10-06 03:09:58 +0000212 size_t num_instructions = disasm_ap->GetInstructionList().GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000213 uint32_t offset = 0;
214 SymbolContext sc;
215 SymbolContext prev_sc;
216 AddressRange sc_range;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000217 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000218 strm.IndentMore ();
219
Greg Claytondda4f7b2010-06-30 23:03:03 +0000220
221 Address addr(range.GetBaseAddress());
222
223 // We extract the section to make sure we don't transition out
224 // of the current section when disassembling
225 const Section *addr_section = addr.GetSection();
226 Module *range_module = range.GetBaseAddress().GetModule();
227
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000228 for (size_t i=0; i<num_instructions; ++i)
229 {
Greg Clayton1d273162010-10-06 03:09:58 +0000230 Instruction *inst = disasm_ap->GetInstructionList().GetInstructionAtIndex (i).get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000231 if (inst)
232 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000233 addr_t file_addr = addr.GetFileAddress();
234 if (addr_section == NULL || addr_section->ContainsFileAddress (file_addr) == false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000235 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000236 if (range_module)
237 range_module->ResolveFileAddress (file_addr, addr);
238 else if (exe_ctx.target)
239 exe_ctx.target->GetImages().ResolveFileAddress (file_addr, addr);
240
241 addr_section = addr.GetSection();
242 }
243
244 prev_sc = sc;
245
246 if (addr_section)
247 {
248 Module *module = addr_section->GetModule();
249 uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
250 if (resolved_mask)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000251 {
Greg Clayton3c687572010-09-06 23:11:45 +0000252 if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000253 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000254 if (prev_sc.function || prev_sc.symbol)
255 strm.EOL();
256
257 strm << sc.module_sp->GetFileSpec().GetFilename();
258
259 if (sc.function)
260 strm << '`' << sc.function->GetMangled().GetName();
261 else if (sc.symbol)
262 strm << '`' << sc.symbol->GetMangled().GetName();
263 strm << ":\n";
264 }
265
266 if (num_mixed_context_lines && !sc_range.ContainsFileAddress (addr))
267 {
268 sc.GetAddressRange (eSymbolContextEverything, sc_range);
269
270 if (sc != prev_sc)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000271 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000272 if (offset != 0)
273 strm.EOL();
274
Greg Clayton6dbd3982010-09-15 05:51:24 +0000275 sc.DumpStopContext(&strm, process, addr, false, true, false);
276 strm.EOL();
Greg Claytondda4f7b2010-06-30 23:03:03 +0000277
278 if (sc.comp_unit && sc.line_entry.IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000279 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000280 debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
281 sc.line_entry.line,
282 num_mixed_context_lines,
283 num_mixed_context_lines,
284 num_mixed_context_lines ? "->" : "",
285 &strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000286 }
287 }
288 }
289 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000290 else
291 {
292 sc.Clear();
293 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000294 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000295 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000296 strm.IndentMore ();
297 strm.Indent();
298 size_t inst_byte_size = inst->GetByteSize();
Greg Clayton1d273162010-10-06 03:09:58 +0000299 inst->Dump(&strm, true, show_bytes ? &data : NULL, offset, &exe_ctx, show_bytes);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000300 strm.EOL();
301 offset += inst_byte_size;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000302
303 addr.SetOffset (addr.GetOffset() + inst_byte_size);
304
305 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000306 strm.IndentLess ();
307 }
308 else
309 {
310 break;
311 }
312 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000313 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000314 strm.IndentLess ();
315
316 }
317 }
318 return true;
319 }
320 return false;
321}
322
Greg Claytondda4f7b2010-06-30 23:03:03 +0000323
324bool
325Disassembler::Disassemble
326(
327 Debugger &debugger,
328 const ArchSpec &arch,
329 const ExecutionContext &exe_ctx,
330 uint32_t num_mixed_context_lines,
331 bool show_bytes,
332 Stream &strm
333)
334{
335 AddressRange range;
336 if (exe_ctx.frame)
337 {
338 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
339 if (sc.function)
340 {
341 range = sc.function->GetAddressRange();
342 }
343 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
344 {
345 range = *sc.symbol->GetAddressRangePtr();
346 }
347 else
348 {
Greg Clayton9da7bd02010-08-24 21:05:24 +0000349 range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress();
Greg Claytondda4f7b2010-06-30 23:03:03 +0000350 }
351
352 if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
353 range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
354 }
355
356 return Disassemble(debugger, arch, exe_ctx, range, num_mixed_context_lines, show_bytes, strm);
357}
358
Greg Clayton1d273162010-10-06 03:09:58 +0000359Instruction::Instruction(const Address &addr) :
360 m_addr (addr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000361{
362}
363
Greg Clayton1d273162010-10-06 03:09:58 +0000364Instruction::~Instruction()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000365{
366}
367
368
Greg Clayton1d273162010-10-06 03:09:58 +0000369InstructionList::InstructionList() :
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000370 m_instructions()
371{
372}
373
Greg Clayton1d273162010-10-06 03:09:58 +0000374InstructionList::~InstructionList()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000375{
376}
377
378size_t
Greg Clayton1d273162010-10-06 03:09:58 +0000379InstructionList::GetSize() const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000380{
381 return m_instructions.size();
382}
383
384
Greg Clayton1d273162010-10-06 03:09:58 +0000385InstructionSP
386InstructionList::GetInstructionAtIndex (uint32_t idx) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000387{
Greg Clayton1d273162010-10-06 03:09:58 +0000388 InstructionSP inst_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000389 if (idx < m_instructions.size())
Greg Clayton1d273162010-10-06 03:09:58 +0000390 inst_sp = m_instructions[idx];
391 return inst_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000392}
393
394void
Greg Clayton1d273162010-10-06 03:09:58 +0000395InstructionList::Clear()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000396{
397 m_instructions.clear();
398}
399
400void
Greg Clayton1d273162010-10-06 03:09:58 +0000401InstructionList::Append (lldb::InstructionSP &inst_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000402{
403 if (inst_sp)
404 m_instructions.push_back(inst_sp);
405}
406
407
408size_t
409Disassembler::ParseInstructions
410(
411 const ExecutionContext *exe_ctx,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000412 const AddressRange &range,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000413 DataExtractor& data
414)
415{
Greg Claytondda4f7b2010-06-30 23:03:03 +0000416 Target *target = exe_ctx->target;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000417 const addr_t byte_size = range.GetByteSize();
418 if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000419 return 0;
420
Greg Claytondda4f7b2010-06-30 23:03:03 +0000421 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
422 DataBufferSP data_sp(heap_buffer);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000423
424 Error error;
Greg Claytondb598232011-01-07 01:57:07 +0000425 bool prefer_file_cache = true;
426 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 +0000427
428 if (bytes_read > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000429 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000430 if (bytes_read != heap_buffer->GetByteSize())
431 heap_buffer->SetByteSize (bytes_read);
432
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000433 data.SetData(data_sp);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000434 if (exe_ctx->process)
435 {
436 data.SetByteOrder(exe_ctx->process->GetByteOrder());
437 data.SetAddressByteSize(exe_ctx->process->GetAddressByteSize());
438 }
439 else
440 {
441 data.SetByteOrder(target->GetArchitecture().GetDefaultEndian());
442 data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
443 }
Greg Clayton1d273162010-10-06 03:09:58 +0000444 return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000445 }
446
447 return 0;
448}
449
450//----------------------------------------------------------------------
451// Disassembler copy constructor
452//----------------------------------------------------------------------
453Disassembler::Disassembler(const ArchSpec& arch) :
454 m_arch (arch),
455 m_instruction_list(),
456 m_base_addr(LLDB_INVALID_ADDRESS)
457{
458
459}
460
461//----------------------------------------------------------------------
462// Destructor
463//----------------------------------------------------------------------
464Disassembler::~Disassembler()
465{
466}
467
Greg Clayton1d273162010-10-06 03:09:58 +0000468InstructionList &
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000469Disassembler::GetInstructionList ()
470{
471 return m_instruction_list;
472}
473
Greg Clayton1d273162010-10-06 03:09:58 +0000474const InstructionList &
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000475Disassembler::GetInstructionList () const
476{
477 return m_instruction_list;
478}