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 if (exe_ctx.target == NULL && name) 103 return false; 104 105 SymbolContextList sc_list; 106 107 if (module) 108 { 109 if (!module->FindFunctions (name, 110 eFunctionNameTypeBase | 111 eFunctionNameTypeFull | 112 eFunctionNameTypeMethod | 113 eFunctionNameTypeSelector, 114 true, 115 sc_list)) 116 return false; 117 } 118 else 119 { 120 if (exe_ctx.target->GetImages().FindFunctions (name, 121 eFunctionNameTypeBase | 122 eFunctionNameTypeFull | 123 eFunctionNameTypeMethod | 124 eFunctionNameTypeSelector, 125 false, 126 sc_list)) 127 { 128 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 138 139 lldb::DisassemblerSP 140 Disassembler::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 164 bool 165 Disassembler::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 { 178 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch)); 179 180 if (disasm_ap.get()) 181 { 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) 189 { 190 if (exe_ctx.target) 191 { 192 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 } 200 } 201 } 202 203 DataExtractor data; 204 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, range, data); 205 if (bytes_disassembled == 0) 206 { 207 return false; 208 } 209 else 210 { 211 // We got some things disassembled... 212 size_t num_instructions = disasm_ap->GetInstructionList().GetSize(); 213 uint32_t offset = 0; 214 SymbolContext sc; 215 SymbolContext prev_sc; 216 AddressRange sc_range; 217 if (num_mixed_context_lines) 218 strm.IndentMore (); 219 220 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 228 for (size_t i=0; i<num_instructions; ++i) 229 { 230 Instruction *inst = disasm_ap->GetInstructionList().GetInstructionAtIndex (i).get(); 231 if (inst) 232 { 233 addr_t file_addr = addr.GetFileAddress(); 234 if (addr_section == NULL || addr_section->ContainsFileAddress (file_addr) == false) 235 { 236 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) 251 { 252 if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol)) 253 { 254 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) 271 { 272 if (offset != 0) 273 strm.EOL(); 274 275 sc.DumpStopContext(&strm, process, addr, false, true, false); 276 strm.EOL(); 277 278 if (sc.comp_unit && sc.line_entry.IsValid()) 279 { 280 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); 286 } 287 } 288 } 289 } 290 else 291 { 292 sc.Clear(); 293 } 294 } 295 if (num_mixed_context_lines) 296 strm.IndentMore (); 297 strm.Indent(); 298 size_t inst_byte_size = inst->GetByteSize(); 299 inst->Dump(&strm, true, show_bytes ? &data : NULL, offset, &exe_ctx, show_bytes); 300 strm.EOL(); 301 offset += inst_byte_size; 302 303 addr.SetOffset (addr.GetOffset() + inst_byte_size); 304 305 if (num_mixed_context_lines) 306 strm.IndentLess (); 307 } 308 else 309 { 310 break; 311 } 312 } 313 if (num_mixed_context_lines) 314 strm.IndentLess (); 315 316 } 317 } 318 return true; 319 } 320 return false; 321 } 322 323 324 bool 325 Disassembler::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 { 349 range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress(); 350 } 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 359 Instruction::Instruction(const Address &addr) : 360 m_addr (addr) 361 { 362 } 363 364 Instruction::~Instruction() 365 { 366 } 367 368 369 InstructionList::InstructionList() : 370 m_instructions() 371 { 372 } 373 374 InstructionList::~InstructionList() 375 { 376 } 377 378 size_t 379 InstructionList::GetSize() const 380 { 381 return m_instructions.size(); 382 } 383 384 385 InstructionSP 386 InstructionList::GetInstructionAtIndex (uint32_t idx) const 387 { 388 InstructionSP inst_sp; 389 if (idx < m_instructions.size()) 390 inst_sp = m_instructions[idx]; 391 return inst_sp; 392 } 393 394 void 395 InstructionList::Clear() 396 { 397 m_instructions.clear(); 398 } 399 400 void 401 InstructionList::Append (lldb::InstructionSP &inst_sp) 402 { 403 if (inst_sp) 404 m_instructions.push_back(inst_sp); 405 } 406 407 408 size_t 409 Disassembler::ParseInstructions 410 ( 411 const ExecutionContext *exe_ctx, 412 const AddressRange &range, 413 DataExtractor& data 414 ) 415 { 416 Target *target = exe_ctx->target; 417 const addr_t byte_size = range.GetByteSize(); 418 if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid()) 419 return 0; 420 421 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0'); 422 DataBufferSP data_sp(heap_buffer); 423 424 Error error; 425 const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(), heap_buffer->GetBytes(), heap_buffer->GetByteSize(), error); 426 427 if (bytes_read > 0) 428 { 429 if (bytes_read != heap_buffer->GetByteSize()) 430 heap_buffer->SetByteSize (bytes_read); 431 432 data.SetData(data_sp); 433 if (exe_ctx->process) 434 { 435 data.SetByteOrder(exe_ctx->process->GetByteOrder()); 436 data.SetAddressByteSize(exe_ctx->process->GetAddressByteSize()); 437 } 438 else 439 { 440 data.SetByteOrder(target->GetArchitecture().GetDefaultEndian()); 441 data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); 442 } 443 return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX); 444 } 445 446 return 0; 447 } 448 449 //---------------------------------------------------------------------- 450 // Disassembler copy constructor 451 //---------------------------------------------------------------------- 452 Disassembler::Disassembler(const ArchSpec& arch) : 453 m_arch (arch), 454 m_instruction_list(), 455 m_base_addr(LLDB_INVALID_ADDRESS) 456 { 457 458 } 459 460 //---------------------------------------------------------------------- 461 // Destructor 462 //---------------------------------------------------------------------- 463 Disassembler::~Disassembler() 464 { 465 } 466 467 InstructionList & 468 Disassembler::GetInstructionList () 469 { 470 return m_instruction_list; 471 } 472 473 const InstructionList & 474 Disassembler::GetInstructionList () const 475 { 476 return m_instruction_list; 477 } 478