blob: 5674dde79f69ccef4b2599bf0d30c34a6eb47434 [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,
110 eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeMethod | eFunctionNameTypeSelector,
111 true,
112 sc_list))
113 return false;
114 }
115 else
116 {
117 if (exe_ctx.target->GetImages().FindFunctions (name,
Sean Callanan8ade1042010-07-27 00:55:47 +0000118 eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeMethod | eFunctionNameTypeSelector,
119 false,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000120 sc_list))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000121 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000122 return Disassemble (debugger, arch, exe_ctx, sc_list, num_mixed_context_lines, show_bytes, strm);
123 }
124 else if (exe_ctx.target->GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeCode, sc_list))
125 {
126 return Disassemble (debugger, arch, exe_ctx, sc_list, num_mixed_context_lines, show_bytes, strm);
127 }
128 }
129 return false;
130}
131
132bool
133Disassembler::Disassemble
134(
135 Debugger &debugger,
136 const ArchSpec &arch,
137 const ExecutionContext &exe_ctx,
138 const AddressRange &disasm_range,
139 uint32_t num_mixed_context_lines,
140 bool show_bytes,
141 Stream &strm
142)
143{
144 if (disasm_range.GetByteSize())
145 {
146 Disassembler *disassembler = Disassembler::FindPlugin(arch);
147
148 if (disassembler)
149 {
150 AddressRange range(disasm_range);
151
152 Process *process = exe_ctx.process;
153
154 // If we weren't passed in a section offset address range,
155 // try and resolve it to something
156 if (range.GetBaseAddress().IsSectionOffset() == false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000157 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000158 if (process && process->IsAlive())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000159 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000160 process->ResolveLoadAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress());
161 }
162 else if (exe_ctx.target)
163 {
164 exe_ctx.target->GetImages().ResolveFileAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000165 }
166 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000167
Greg Claytondda4f7b2010-06-30 23:03:03 +0000168
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000169 DataExtractor data;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000170 size_t bytes_disassembled = disassembler->ParseInstructions (&exe_ctx, range, data);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000171 if (bytes_disassembled == 0)
172 {
173 return false;
174 }
175 else
176 {
177 // We got some things disassembled...
178 size_t num_instructions = disassembler->GetInstructionList().GetSize();
179 uint32_t offset = 0;
180 SymbolContext sc;
181 SymbolContext prev_sc;
182 AddressRange sc_range;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000183 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000184 strm.IndentMore ();
185
Greg Claytondda4f7b2010-06-30 23:03:03 +0000186
187 Address addr(range.GetBaseAddress());
188
189 // We extract the section to make sure we don't transition out
190 // of the current section when disassembling
191 const Section *addr_section = addr.GetSection();
192 Module *range_module = range.GetBaseAddress().GetModule();
193
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000194 for (size_t i=0; i<num_instructions; ++i)
195 {
196 Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
197 if (inst)
198 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000199 addr_t file_addr = addr.GetFileAddress();
200 if (addr_section == NULL || addr_section->ContainsFileAddress (file_addr) == false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000201 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000202 if (range_module)
203 range_module->ResolveFileAddress (file_addr, addr);
204 else if (exe_ctx.target)
205 exe_ctx.target->GetImages().ResolveFileAddress (file_addr, addr);
206
207 addr_section = addr.GetSection();
208 }
209
210 prev_sc = sc;
211
212 if (addr_section)
213 {
214 Module *module = addr_section->GetModule();
215 uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
216 if (resolved_mask)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000217 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000218 if (prev_sc.function != sc.function || prev_sc.symbol != sc.symbol)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000219 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000220 if (prev_sc.function || prev_sc.symbol)
221 strm.EOL();
222
223 strm << sc.module_sp->GetFileSpec().GetFilename();
224
225 if (sc.function)
226 strm << '`' << sc.function->GetMangled().GetName();
227 else if (sc.symbol)
228 strm << '`' << sc.symbol->GetMangled().GetName();
229 strm << ":\n";
230 }
231
232 if (num_mixed_context_lines && !sc_range.ContainsFileAddress (addr))
233 {
234 sc.GetAddressRange (eSymbolContextEverything, sc_range);
235
236 if (sc != prev_sc)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000237 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000238 if (offset != 0)
239 strm.EOL();
240
241 sc.DumpStopContext(&strm, process, addr);
242
243 if (sc.comp_unit && sc.line_entry.IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000244 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000245 debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
246 sc.line_entry.line,
247 num_mixed_context_lines,
248 num_mixed_context_lines,
249 num_mixed_context_lines ? "->" : "",
250 &strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000251 }
252 }
253 }
254 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000255 else
256 {
257 sc.Clear();
258 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000259 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000260 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000261 strm.IndentMore ();
262 strm.Indent();
263 size_t inst_byte_size = inst->GetByteSize();
Greg Claytondda4f7b2010-06-30 23:03:03 +0000264 inst->Dump(&strm, &addr, show_bytes ? &data : NULL, offset, exe_ctx, show_bytes);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000265 strm.EOL();
266 offset += inst_byte_size;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000267
268 addr.SetOffset (addr.GetOffset() + inst_byte_size);
269
270 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000271 strm.IndentLess ();
272 }
273 else
274 {
275 break;
276 }
277 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000278 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000279 strm.IndentLess ();
280
281 }
282 }
283 return true;
284 }
285 return false;
286}
287
Greg Claytondda4f7b2010-06-30 23:03:03 +0000288
289bool
290Disassembler::Disassemble
291(
292 Debugger &debugger,
293 const ArchSpec &arch,
294 const ExecutionContext &exe_ctx,
295 uint32_t num_mixed_context_lines,
296 bool show_bytes,
297 Stream &strm
298)
299{
300 AddressRange range;
301 if (exe_ctx.frame)
302 {
303 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
304 if (sc.function)
305 {
306 range = sc.function->GetAddressRange();
307 }
308 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
309 {
310 range = *sc.symbol->GetAddressRangePtr();
311 }
312 else
313 {
314 range.GetBaseAddress() = exe_ctx.frame->GetPC();
315 }
316
317 if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
318 range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
319 }
320
321 return Disassemble(debugger, arch, exe_ctx, range, num_mixed_context_lines, show_bytes, strm);
322}
323
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000324Disassembler::Instruction::Instruction()
325{
326}
327
328Disassembler::Instruction::~Instruction()
329{
330}
331
332
333Disassembler::InstructionList::InstructionList() :
334 m_instructions()
335{
336}
337
338Disassembler::InstructionList::~InstructionList()
339{
340}
341
342size_t
343Disassembler::InstructionList::GetSize() const
344{
345 return m_instructions.size();
346}
347
348
349Disassembler::Instruction *
350Disassembler::InstructionList::GetInstructionAtIndex (uint32_t idx)
351{
352 if (idx < m_instructions.size())
353 return m_instructions[idx].get();
354 return NULL;
355}
356
357const Disassembler::Instruction *
358Disassembler::InstructionList::GetInstructionAtIndex (uint32_t idx) const
359{
360 if (idx < m_instructions.size())
361 return m_instructions[idx].get();
362 return NULL;
363}
364
365void
366Disassembler::InstructionList::Clear()
367{
368 m_instructions.clear();
369}
370
371void
372Disassembler::InstructionList::AppendInstruction (Instruction::shared_ptr &inst_sp)
373{
374 if (inst_sp)
375 m_instructions.push_back(inst_sp);
376}
377
378
379size_t
380Disassembler::ParseInstructions
381(
382 const ExecutionContext *exe_ctx,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000383 const AddressRange &range,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000384 DataExtractor& data
385)
386{
Greg Claytondda4f7b2010-06-30 23:03:03 +0000387 Target *target = exe_ctx->target;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000388
Greg Claytondda4f7b2010-06-30 23:03:03 +0000389 const addr_t byte_size = range.GetByteSize();
390 if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000391 return 0;
392
Greg Claytondda4f7b2010-06-30 23:03:03 +0000393 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
394 DataBufferSP data_sp(heap_buffer);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000395
396 Error error;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000397 const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(), heap_buffer->GetBytes(), heap_buffer->GetByteSize(), error);
398
399 if (bytes_read > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000400 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000401 if (bytes_read != heap_buffer->GetByteSize())
402 heap_buffer->SetByteSize (bytes_read);
403
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000404 data.SetData(data_sp);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000405 if (exe_ctx->process)
406 {
407 data.SetByteOrder(exe_ctx->process->GetByteOrder());
408 data.SetAddressByteSize(exe_ctx->process->GetAddressByteSize());
409 }
410 else
411 {
412 data.SetByteOrder(target->GetArchitecture().GetDefaultEndian());
413 data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
414 }
415 return DecodeInstructions (data, 0, UINT32_MAX);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000416 }
417
418 return 0;
419}
420
421//----------------------------------------------------------------------
422// Disassembler copy constructor
423//----------------------------------------------------------------------
424Disassembler::Disassembler(const ArchSpec& arch) :
425 m_arch (arch),
426 m_instruction_list(),
427 m_base_addr(LLDB_INVALID_ADDRESS)
428{
429
430}
431
432//----------------------------------------------------------------------
433// Destructor
434//----------------------------------------------------------------------
435Disassembler::~Disassembler()
436{
437}
438
439Disassembler::InstructionList &
440Disassembler::GetInstructionList ()
441{
442 return m_instruction_list;
443}
444
445const Disassembler::InstructionList &
446Disassembler::GetInstructionList () const
447{
448 return m_instruction_list;
449}