blob: fa7f4833d9999ff668b3802423752a2be2781f31 [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)",
Greg Clayton64195a22011-02-23 00:35:02 +000041 arch.GetArchitectureName());
Chris Lattner30fdc8d2010-06-08 16:52:24 +000042
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,
Sean Callananb3396b22011-03-10 23:35:12 +000066 bool raw,
Greg Claytondda4f7b2010-06-30 23:03:03 +000067 Stream &strm
68)
69{
70 size_t success_count = 0;
71 const size_t count = sc_list.GetSize();
72 SymbolContext sc;
73 AddressRange range;
74 for (size_t i=0; i<count; ++i)
75 {
76 if (sc_list.GetContextAtIndex(i, sc) == false)
77 break;
78 if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
79 {
Sean Callananb3396b22011-03-10 23:35:12 +000080 if (Disassemble (debugger, arch, exe_ctx, range, num_mixed_context_lines, show_bytes, raw, strm))
Greg Claytondda4f7b2010-06-30 23:03:03 +000081 {
82 ++success_count;
83 strm.EOL();
84 }
85 }
86 }
87 return success_count;
88}
89
Chris Lattner30fdc8d2010-06-08 16:52:24 +000090bool
91Disassembler::Disassemble
92(
Greg Clayton66111032010-06-23 01:19:29 +000093 Debugger &debugger,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000094 const ArchSpec &arch,
95 const ExecutionContext &exe_ctx,
Greg Claytondda4f7b2010-06-30 23:03:03 +000096 const ConstString &name,
97 Module *module,
98 uint32_t num_mixed_context_lines,
99 bool show_bytes,
Sean Callananb3396b22011-03-10 23:35:12 +0000100 bool raw,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000101 Stream &strm
102)
103{
Greg Claytondda4f7b2010-06-30 23:03:03 +0000104 SymbolContextList sc_list;
Greg Clayton931180e2011-01-27 06:44:37 +0000105 if (name)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000106 {
Greg Clayton931180e2011-01-27 06:44:37 +0000107 const bool include_symbols = true;
108 if (module)
109 {
110 module->FindFunctions (name,
111 eFunctionNameTypeBase |
112 eFunctionNameTypeFull |
113 eFunctionNameTypeMethod |
114 eFunctionNameTypeSelector,
115 include_symbols,
116 true,
117 sc_list);
118 }
119 else if (exe_ctx.target)
120 {
121 exe_ctx.target->GetImages().FindFunctions (name,
Greg Clayton6dbd3982010-09-15 05:51:24 +0000122 eFunctionNameTypeBase |
123 eFunctionNameTypeFull |
124 eFunctionNameTypeMethod |
125 eFunctionNameTypeSelector,
Greg Clayton931180e2011-01-27 06:44:37 +0000126 include_symbols,
Sean Callanan8ade1042010-07-27 00:55:47 +0000127 false,
Greg Clayton931180e2011-01-27 06:44:37 +0000128 sc_list);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000129 }
Greg Clayton931180e2011-01-27 06:44:37 +0000130 }
131
132 if (sc_list.GetSize ())
133 {
134 return Disassemble (debugger,
135 arch,
136 exe_ctx,
137 sc_list,
138 num_mixed_context_lines,
Sean Callananb3396b22011-03-10 23:35:12 +0000139 show_bytes,
140 raw,
Greg Clayton931180e2011-01-27 06:44:37 +0000141 strm);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000142 }
143 return false;
144}
145
Greg Clayton1d273162010-10-06 03:09:58 +0000146
147lldb::DisassemblerSP
148Disassembler::DisassembleRange
149(
150 const ArchSpec &arch,
151 const ExecutionContext &exe_ctx,
152 const AddressRange &range
153)
154{
155 lldb::DisassemblerSP disasm_sp;
156 if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid())
157 {
158 disasm_sp.reset (Disassembler::FindPlugin(arch));
159
160 if (disasm_sp)
161 {
162 DataExtractor data;
163 size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range, data);
164 if (bytes_disassembled == 0)
165 disasm_sp.reset();
166 }
167 }
168 return disasm_sp;
169}
170
171
Greg Claytondda4f7b2010-06-30 23:03:03 +0000172bool
173Disassembler::Disassemble
174(
175 Debugger &debugger,
176 const ArchSpec &arch,
177 const ExecutionContext &exe_ctx,
178 const AddressRange &disasm_range,
179 uint32_t num_mixed_context_lines,
180 bool show_bytes,
Sean Callananb3396b22011-03-10 23:35:12 +0000181 bool raw,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000182 Stream &strm
183)
184{
185 if (disasm_range.GetByteSize())
186 {
Greg Clayton1d273162010-10-06 03:09:58 +0000187 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch));
Greg Claytondda4f7b2010-06-30 23:03:03 +0000188
Greg Clayton1d273162010-10-06 03:09:58 +0000189 if (disasm_ap.get())
Greg Claytondda4f7b2010-06-30 23:03:03 +0000190 {
191 AddressRange range(disasm_range);
192
193 Process *process = exe_ctx.process;
194
195 // If we weren't passed in a section offset address range,
196 // try and resolve it to something
197 if (range.GetBaseAddress().IsSectionOffset() == false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000198 {
Greg Claytonf5e56de2010-09-14 23:36:40 +0000199 if (exe_ctx.target)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000200 {
Greg Claytonf5e56de2010-09-14 23:36:40 +0000201 if (exe_ctx.target->GetSectionLoadList().IsEmpty())
202 {
203 exe_ctx.target->GetImages().ResolveFileAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress());
204 }
205 else
206 {
207 exe_ctx.target->GetSectionLoadList().ResolveLoadAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress());
208 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000209 }
210 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000211
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000212 DataExtractor data;
Greg Clayton1d273162010-10-06 03:09:58 +0000213 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, range, data);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000214 if (bytes_disassembled == 0)
215 {
216 return false;
217 }
218 else
219 {
220 // We got some things disassembled...
Greg Clayton1d273162010-10-06 03:09:58 +0000221 size_t num_instructions = disasm_ap->GetInstructionList().GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000222 uint32_t offset = 0;
223 SymbolContext sc;
224 SymbolContext prev_sc;
225 AddressRange sc_range;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000226 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000227 strm.IndentMore ();
228
Greg Claytondda4f7b2010-06-30 23:03:03 +0000229
230 Address addr(range.GetBaseAddress());
231
232 // We extract the section to make sure we don't transition out
233 // of the current section when disassembling
234 const Section *addr_section = addr.GetSection();
235 Module *range_module = range.GetBaseAddress().GetModule();
236
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000237 for (size_t i=0; i<num_instructions; ++i)
238 {
Greg Clayton1d273162010-10-06 03:09:58 +0000239 Instruction *inst = disasm_ap->GetInstructionList().GetInstructionAtIndex (i).get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000240 if (inst)
241 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000242 addr_t file_addr = addr.GetFileAddress();
243 if (addr_section == NULL || addr_section->ContainsFileAddress (file_addr) == false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000244 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000245 if (range_module)
246 range_module->ResolveFileAddress (file_addr, addr);
247 else if (exe_ctx.target)
248 exe_ctx.target->GetImages().ResolveFileAddress (file_addr, addr);
249
250 addr_section = addr.GetSection();
251 }
252
253 prev_sc = sc;
254
255 if (addr_section)
256 {
257 Module *module = addr_section->GetModule();
258 uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
259 if (resolved_mask)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000260 {
Greg Clayton3c687572010-09-06 23:11:45 +0000261 if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000262 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000263 if (prev_sc.function || prev_sc.symbol)
264 strm.EOL();
265
266 strm << sc.module_sp->GetFileSpec().GetFilename();
267
268 if (sc.function)
269 strm << '`' << sc.function->GetMangled().GetName();
270 else if (sc.symbol)
271 strm << '`' << sc.symbol->GetMangled().GetName();
272 strm << ":\n";
273 }
274
275 if (num_mixed_context_lines && !sc_range.ContainsFileAddress (addr))
276 {
277 sc.GetAddressRange (eSymbolContextEverything, sc_range);
278
279 if (sc != prev_sc)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000280 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000281 if (offset != 0)
282 strm.EOL();
283
Greg Clayton6dbd3982010-09-15 05:51:24 +0000284 sc.DumpStopContext(&strm, process, addr, false, true, false);
285 strm.EOL();
Greg Claytondda4f7b2010-06-30 23:03:03 +0000286
287 if (sc.comp_unit && sc.line_entry.IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000288 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000289 debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
290 sc.line_entry.line,
291 num_mixed_context_lines,
292 num_mixed_context_lines,
293 num_mixed_context_lines ? "->" : "",
294 &strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000295 }
296 }
297 }
298 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000299 else
300 {
301 sc.Clear();
302 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000303 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000304 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000305 strm.IndentMore ();
306 strm.Indent();
307 size_t inst_byte_size = inst->GetByteSize();
Sean Callananb3396b22011-03-10 23:35:12 +0000308 inst->Dump(&strm, true, show_bytes ? &data : NULL, offset, &exe_ctx, raw);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000309 strm.EOL();
310 offset += inst_byte_size;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000311
312 addr.SetOffset (addr.GetOffset() + inst_byte_size);
313
314 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000315 strm.IndentLess ();
316 }
317 else
318 {
319 break;
320 }
321 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000322 if (num_mixed_context_lines)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000323 strm.IndentLess ();
324
325 }
326 }
327 return true;
328 }
329 return false;
330}
331
Greg Claytondda4f7b2010-06-30 23:03:03 +0000332
333bool
334Disassembler::Disassemble
335(
336 Debugger &debugger,
337 const ArchSpec &arch,
338 const ExecutionContext &exe_ctx,
339 uint32_t num_mixed_context_lines,
340 bool show_bytes,
Sean Callananb3396b22011-03-10 23:35:12 +0000341 bool raw,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000342 Stream &strm
343)
344{
345 AddressRange range;
346 if (exe_ctx.frame)
347 {
348 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
349 if (sc.function)
350 {
351 range = sc.function->GetAddressRange();
352 }
353 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
354 {
355 range = *sc.symbol->GetAddressRangePtr();
356 }
357 else
358 {
Greg Clayton9da7bd02010-08-24 21:05:24 +0000359 range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress();
Greg Claytondda4f7b2010-06-30 23:03:03 +0000360 }
361
362 if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
363 range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
364 }
365
Sean Callananb3396b22011-03-10 23:35:12 +0000366 return Disassemble(debugger, arch, exe_ctx, range, num_mixed_context_lines, show_bytes, raw, strm);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000367}
368
Greg Clayton1d273162010-10-06 03:09:58 +0000369Instruction::Instruction(const Address &addr) :
370 m_addr (addr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000371{
372}
373
Greg Clayton1d273162010-10-06 03:09:58 +0000374Instruction::~Instruction()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000375{
376}
377
378
Greg Clayton1d273162010-10-06 03:09:58 +0000379InstructionList::InstructionList() :
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000380 m_instructions()
381{
382}
383
Greg Clayton1d273162010-10-06 03:09:58 +0000384InstructionList::~InstructionList()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000385{
386}
387
388size_t
Greg Clayton1d273162010-10-06 03:09:58 +0000389InstructionList::GetSize() const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000390{
391 return m_instructions.size();
392}
393
394
Greg Clayton1d273162010-10-06 03:09:58 +0000395InstructionSP
396InstructionList::GetInstructionAtIndex (uint32_t idx) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000397{
Greg Clayton1d273162010-10-06 03:09:58 +0000398 InstructionSP inst_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000399 if (idx < m_instructions.size())
Greg Clayton1d273162010-10-06 03:09:58 +0000400 inst_sp = m_instructions[idx];
401 return inst_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000402}
403
404void
Greg Clayton1d273162010-10-06 03:09:58 +0000405InstructionList::Clear()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000406{
407 m_instructions.clear();
408}
409
410void
Greg Clayton1d273162010-10-06 03:09:58 +0000411InstructionList::Append (lldb::InstructionSP &inst_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000412{
413 if (inst_sp)
414 m_instructions.push_back(inst_sp);
415}
416
417
418size_t
419Disassembler::ParseInstructions
420(
421 const ExecutionContext *exe_ctx,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000422 const AddressRange &range,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000423 DataExtractor& data
424)
425{
Greg Claytondda4f7b2010-06-30 23:03:03 +0000426 Target *target = exe_ctx->target;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000427 const addr_t byte_size = range.GetByteSize();
428 if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000429 return 0;
430
Greg Claytondda4f7b2010-06-30 23:03:03 +0000431 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
432 DataBufferSP data_sp(heap_buffer);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000433
434 Error error;
Greg Claytondb598232011-01-07 01:57:07 +0000435 bool prefer_file_cache = true;
436 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 +0000437
438 if (bytes_read > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000439 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000440 if (bytes_read != heap_buffer->GetByteSize())
441 heap_buffer->SetByteSize (bytes_read);
442
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000443 data.SetData(data_sp);
Greg Clayton514487e2011-02-15 21:59:32 +0000444 data.SetByteOrder(target->GetArchitecture().GetByteOrder());
445 data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
Greg Clayton1d273162010-10-06 03:09:58 +0000446 return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000447 }
448
449 return 0;
450}
451
452//----------------------------------------------------------------------
453// Disassembler copy constructor
454//----------------------------------------------------------------------
455Disassembler::Disassembler(const ArchSpec& arch) :
456 m_arch (arch),
457 m_instruction_list(),
458 m_base_addr(LLDB_INVALID_ADDRESS)
459{
460
461}
462
463//----------------------------------------------------------------------
464// Destructor
465//----------------------------------------------------------------------
466Disassembler::~Disassembler()
467{
468}
469
Greg Clayton1d273162010-10-06 03:09:58 +0000470InstructionList &
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000471Disassembler::GetInstructionList ()
472{
473 return m_instruction_list;
474}
475
Greg Clayton1d273162010-10-06 03:09:58 +0000476const InstructionList &
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000477Disassembler::GetInstructionList () const
478{
479 return m_instruction_list;
480}