1 //===-- 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 32 using namespace lldb; 33 using namespace lldb_private; 34 35 36 Disassembler* 37 Disassembler::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 55 56 57 size_t 58 Disassembler::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 89 bool 90 Disassembler::Disassemble 91 ( 92 Debugger &debugger, 93 const ArchSpec &arch, 94 const ExecutionContext &exe_ctx, 95 const ConstString &name, 96 Module *module, 97 uint32_t num_mixed_context_lines, 98 bool show_bytes, 99 Stream &strm 100 ) 101 { 102 SymbolContextList sc_list; 103 if (name) 104 { 105 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, 120 eFunctionNameTypeBase | 121 eFunctionNameTypeFull | 122 eFunctionNameTypeMethod | 123 eFunctionNameTypeSelector, 124 include_symbols, 125 false, 126 sc_list); 127 } 128 } 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); 139 } 140 return false; 141 } 142 143 144 lldb::DisassemblerSP 145 Disassembler::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 169 bool 170 Disassembler::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 { 183 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch)); 184 185 if (disasm_ap.get()) 186 { 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) 194 { 195 if (exe_ctx.target) 196 { 197 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 } 205 } 206 } 207 208 DataExtractor data; 209 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, range, data); 210 if (bytes_disassembled == 0) 211 { 212 return false; 213 } 214 else 215 { 216 // We got some things disassembled... 217 size_t num_instructions = disasm_ap->GetInstructionList().GetSize(); 218 uint32_t offset = 0; 219 SymbolContext sc; 220 SymbolContext prev_sc; 221 AddressRange sc_range; 222 if (num_mixed_context_lines) 223 strm.IndentMore (); 224 225 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 233 for (size_t i=0; i<num_instructions; ++i) 234 { 235 Instruction *inst = disasm_ap->GetInstructionList().GetInstructionAtIndex (i).get(); 236 if (inst) 237 { 238 addr_t file_addr = addr.GetFileAddress(); 239 if (addr_section == NULL || addr_section->ContainsFileAddress (file_addr) == false) 240 { 241 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) 256 { 257 if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol)) 258 { 259 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) 276 { 277 if (offset != 0) 278 strm.EOL(); 279 280 sc.DumpStopContext(&strm, process, addr, false, true, false); 281 strm.EOL(); 282 283 if (sc.comp_unit && sc.line_entry.IsValid()) 284 { 285 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); 291 } 292 } 293 } 294 } 295 else 296 { 297 sc.Clear(); 298 } 299 } 300 if (num_mixed_context_lines) 301 strm.IndentMore (); 302 strm.Indent(); 303 size_t inst_byte_size = inst->GetByteSize(); 304 inst->Dump(&strm, true, show_bytes ? &data : NULL, offset, &exe_ctx, show_bytes); 305 strm.EOL(); 306 offset += inst_byte_size; 307 308 addr.SetOffset (addr.GetOffset() + inst_byte_size); 309 310 if (num_mixed_context_lines) 311 strm.IndentLess (); 312 } 313 else 314 { 315 break; 316 } 317 } 318 if (num_mixed_context_lines) 319 strm.IndentLess (); 320 321 } 322 } 323 return true; 324 } 325 return false; 326 } 327 328 329 bool 330 Disassembler::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 { 354 range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress(); 355 } 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 364 Instruction::Instruction(const Address &addr) : 365 m_addr (addr) 366 { 367 } 368 369 Instruction::~Instruction() 370 { 371 } 372 373 374 InstructionList::InstructionList() : 375 m_instructions() 376 { 377 } 378 379 InstructionList::~InstructionList() 380 { 381 } 382 383 size_t 384 InstructionList::GetSize() const 385 { 386 return m_instructions.size(); 387 } 388 389 390 InstructionSP 391 InstructionList::GetInstructionAtIndex (uint32_t idx) const 392 { 393 InstructionSP inst_sp; 394 if (idx < m_instructions.size()) 395 inst_sp = m_instructions[idx]; 396 return inst_sp; 397 } 398 399 void 400 InstructionList::Clear() 401 { 402 m_instructions.clear(); 403 } 404 405 void 406 InstructionList::Append (lldb::InstructionSP &inst_sp) 407 { 408 if (inst_sp) 409 m_instructions.push_back(inst_sp); 410 } 411 412 413 size_t 414 Disassembler::ParseInstructions 415 ( 416 const ExecutionContext *exe_ctx, 417 const AddressRange &range, 418 DataExtractor& data 419 ) 420 { 421 Target *target = exe_ctx->target; 422 const addr_t byte_size = range.GetByteSize(); 423 if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid()) 424 return 0; 425 426 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0'); 427 DataBufferSP data_sp(heap_buffer); 428 429 Error error; 430 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); 432 433 if (bytes_read > 0) 434 { 435 if (bytes_read != heap_buffer->GetByteSize()) 436 heap_buffer->SetByteSize (bytes_read); 437 438 data.SetData(data_sp); 439 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 } 449 return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX); 450 } 451 452 return 0; 453 } 454 455 //---------------------------------------------------------------------- 456 // Disassembler copy constructor 457 //---------------------------------------------------------------------- 458 Disassembler::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 //---------------------------------------------------------------------- 469 Disassembler::~Disassembler() 470 { 471 } 472 473 InstructionList & 474 Disassembler::GetInstructionList () 475 { 476 return m_instruction_list; 477 } 478 479 const InstructionList & 480 Disassembler::GetInstructionList () const 481 { 482 return m_instruction_list; 483 } 484