size_t ObjCLanguage::MethodName::GetFullNames (std::vector<ConstString> &names, bool append) { if (!append) names.clear(); if (IsValid(false)) { StreamString strm; const bool is_class_method = m_type == eTypeClassMethod; const bool is_instance_method = m_type == eTypeInstanceMethod; const ConstString &category = GetCategory(); if (is_class_method || is_instance_method) { names.push_back (m_full); if (category) { strm.Printf("%c[%s %s]", is_class_method ? '+' : '-', GetClassName().GetCString(), GetSelector().GetCString()); names.push_back(ConstString(strm.GetString().c_str())); } } else { const ConstString &class_name = GetClassName(); const ConstString &selector = GetSelector(); strm.Printf("+[%s %s]", class_name.GetCString(), selector.GetCString()); names.push_back(ConstString(strm.GetString().c_str())); strm.Clear(); strm.Printf("-[%s %s]", class_name.GetCString(), selector.GetCString()); names.push_back(ConstString(strm.GetString().c_str())); strm.Clear(); if (category) { strm.Printf("+[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString()); names.push_back(ConstString(strm.GetString().c_str())); strm.Clear(); strm.Printf("-[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString()); names.push_back(ConstString(strm.GetString().c_str())); } } } return names.size(); }
size_t UnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction, const EmulateInstruction::Context &context, lldb::addr_t addr, const void *dst, size_t dst_len) { DataExtractor data (dst, dst_len, instruction->GetArchitecture ().GetByteOrder(), instruction->GetArchitecture ().GetAddressByteSize()); Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); if (log && log->GetVerbose ()) { StreamString strm; strm.PutCString ("UnwindAssemblyInstEmulation::WriteMemory ("); data.Dump(&strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX, addr, 0, 0); strm.PutCString (", context = "); context.Dump(strm, instruction); log->PutCString (strm.GetData()); } const bool can_replace = true; const bool cant_replace = false; switch (context.type) { default: case EmulateInstruction::eContextInvalid: case EmulateInstruction::eContextReadOpcode: case EmulateInstruction::eContextImmediate: case EmulateInstruction::eContextAdjustBaseRegister: case EmulateInstruction::eContextRegisterPlusOffset: case EmulateInstruction::eContextAdjustPC: case EmulateInstruction::eContextRegisterStore: case EmulateInstruction::eContextRegisterLoad: case EmulateInstruction::eContextRelativeBranchImmediate: case EmulateInstruction::eContextAbsoluteBranchRegister: case EmulateInstruction::eContextSupervisorCall: case EmulateInstruction::eContextTableBranchReadMemory: case EmulateInstruction::eContextWriteRegisterRandomBits: case EmulateInstruction::eContextWriteMemoryRandomBits: case EmulateInstruction::eContextArithmetic: case EmulateInstruction::eContextAdvancePC: case EmulateInstruction::eContextReturnFromException: case EmulateInstruction::eContextPopRegisterOffStack: case EmulateInstruction::eContextAdjustStackPointer: break; case EmulateInstruction::eContextPushRegisterOnStack: { uint32_t reg_num = LLDB_INVALID_REGNUM; bool is_return_address_reg = false; const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind(); if (context.info_type == EmulateInstruction::eInfoTypeRegisterToRegisterPlusOffset) { reg_num = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[unwind_reg_kind]; if (context.info.RegisterToRegisterPlusOffset.data_reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA) is_return_address_reg = true; } else { assert (!"unhandled case, add code to handle this!"); } if (reg_num != LLDB_INVALID_REGNUM) { if (m_pushed_regs.find (reg_num) == m_pushed_regs.end()) { m_pushed_regs[reg_num] = addr; const int32_t offset = addr - m_initial_sp; m_curr_row->SetRegisterLocationToAtCFAPlusOffset (reg_num, offset, cant_replace); m_curr_row_modified = true; if (is_return_address_reg) { // This push was pushing the return address register, // so this is also how we will unwind the PC... RegisterInfo pc_reg_info; if (instruction->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info)) { uint32_t pc_reg_num = pc_reg_info.kinds[unwind_reg_kind]; if (pc_reg_num != LLDB_INVALID_REGNUM) { m_curr_row->SetRegisterLocationToAtCFAPlusOffset (pc_reg_num, offset, can_replace); m_curr_row_modified = true; } } } } } } break; } return dst_len; }
bool UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction, const EmulateInstruction::Context &context, const RegisterInfo *reg_info, const RegisterValue ®_value) { Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); if (log && log->GetVerbose ()) { StreamString strm; strm.Printf ("UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ", reg_info->name); reg_value.Dump(&strm, reg_info, false, false, eFormatDefault); strm.PutCString (", context = "); context.Dump(strm, instruction); log->PutCString(strm.GetData()); } const bool must_replace = true; SetRegisterValue (*reg_info, reg_value); switch (context.type) { case EmulateInstruction::eContextInvalid: case EmulateInstruction::eContextReadOpcode: case EmulateInstruction::eContextImmediate: case EmulateInstruction::eContextAdjustBaseRegister: case EmulateInstruction::eContextRegisterPlusOffset: case EmulateInstruction::eContextAdjustPC: case EmulateInstruction::eContextRegisterStore: case EmulateInstruction::eContextRegisterLoad: case EmulateInstruction::eContextAbsoluteBranchRegister: case EmulateInstruction::eContextSupervisorCall: case EmulateInstruction::eContextTableBranchReadMemory: case EmulateInstruction::eContextWriteRegisterRandomBits: case EmulateInstruction::eContextWriteMemoryRandomBits: case EmulateInstruction::eContextArithmetic: case EmulateInstruction::eContextAdvancePC: case EmulateInstruction::eContextReturnFromException: case EmulateInstruction::eContextPushRegisterOnStack: // { // const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; // if (reg_num != LLDB_INVALID_REGNUM) // { // const bool can_replace_only_if_unspecified = true; // // m_curr_row.SetRegisterLocationToUndefined (reg_num, // can_replace_only_if_unspecified, // can_replace_only_if_unspecified); // m_curr_row_modified = true; // } // } break; case EmulateInstruction::eContextRelativeBranchImmediate: { { m_curr_insn_is_branch_immediate = true; } } break; case EmulateInstruction::eContextPopRegisterOffStack: { const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; if (reg_num != LLDB_INVALID_REGNUM) { m_curr_row->SetRegisterLocationToSame (reg_num, must_replace); m_curr_row_modified = true; m_curr_insn_restored_a_register = true; } } break; case EmulateInstruction::eContextSetFramePointer: if (!m_fp_is_cfa) { m_fp_is_cfa = true; m_cfa_reg_info = *reg_info; const uint32_t cfa_reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; assert (cfa_reg_num != LLDB_INVALID_REGNUM); m_curr_row->SetCFARegister(cfa_reg_num); m_curr_row->SetCFAOffset(m_initial_sp - reg_value.GetAsUInt64()); m_curr_row_modified = true; } break; case EmulateInstruction::eContextAdjustStackPointer: // If we have created a frame using the frame pointer, don't follow // subsequent adjustments to the stack pointer. if (!m_fp_is_cfa) { m_curr_row->SetCFAOffset (m_initial_sp - reg_value.GetAsUInt64()); m_curr_row_modified = true; } break; } return true; }
const char * StopInfoMachException::GetDescription () { if (m_description.empty() && m_value != 0) { ExecutionContext exe_ctx (m_thread_wp.lock()); Target *target = exe_ctx.GetTargetPtr(); const llvm::Triple::ArchType cpu = target ? target->GetArchitecture().GetMachine() : llvm::Triple::UnknownArch; const char *exc_desc = NULL; const char *code_label = "code"; const char *code_desc = NULL; const char *subcode_label = "subcode"; const char *subcode_desc = NULL; switch (m_value) { case 1: // EXC_BAD_ACCESS exc_desc = "EXC_BAD_ACCESS"; subcode_label = "address"; switch (cpu) { case llvm::Triple::x86: case llvm::Triple::x86_64: switch (m_exc_code) { case 0xd: code_desc = "EXC_I386_GPFLT"; m_exc_data_count = 1; break; } break; case llvm::Triple::arm: switch (m_exc_code) { case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break; case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break; } break; case llvm::Triple::ppc: case llvm::Triple::ppc64: switch (m_exc_code) { case 0x101: code_desc = "EXC_PPC_VM_PROT_READ"; break; case 0x102: code_desc = "EXC_PPC_BADSPACE"; break; case 0x103: code_desc = "EXC_PPC_UNALIGNED"; break; } break; default: break; } break; case 2: // EXC_BAD_INSTRUCTION exc_desc = "EXC_BAD_INSTRUCTION"; switch (cpu) { case llvm::Triple::x86: case llvm::Triple::x86_64: if (m_exc_code == 1) code_desc = "EXC_I386_INVOP"; break; case llvm::Triple::ppc: case llvm::Triple::ppc64: switch (m_exc_code) { case 1: code_desc = "EXC_PPC_INVALID_SYSCALL"; break; case 2: code_desc = "EXC_PPC_UNIPL_INST"; break; case 3: code_desc = "EXC_PPC_PRIVINST"; break; case 4: code_desc = "EXC_PPC_PRIVREG"; break; case 5: code_desc = "EXC_PPC_TRACE"; break; case 6: code_desc = "EXC_PPC_PERFMON"; break; } break; case llvm::Triple::arm: if (m_exc_code == 1) code_desc = "EXC_ARM_UNDEFINED"; break; default: break; } break; case 3: // EXC_ARITHMETIC exc_desc = "EXC_ARITHMETIC"; switch (cpu) { case llvm::Triple::x86: case llvm::Triple::x86_64: switch (m_exc_code) { case 1: code_desc = "EXC_I386_DIV"; break; case 2: code_desc = "EXC_I386_INTO"; break; case 3: code_desc = "EXC_I386_NOEXT"; break; case 4: code_desc = "EXC_I386_EXTOVR"; break; case 5: code_desc = "EXC_I386_EXTERR"; break; case 6: code_desc = "EXC_I386_EMERR"; break; case 7: code_desc = "EXC_I386_BOUND"; break; case 8: code_desc = "EXC_I386_SSEEXTERR"; break; } break; case llvm::Triple::ppc: case llvm::Triple::ppc64: switch (m_exc_code) { case 1: code_desc = "EXC_PPC_OVERFLOW"; break; case 2: code_desc = "EXC_PPC_ZERO_DIVIDE"; break; case 3: code_desc = "EXC_PPC_FLT_INEXACT"; break; case 4: code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; break; case 5: code_desc = "EXC_PPC_FLT_UNDERFLOW"; break; case 6: code_desc = "EXC_PPC_FLT_OVERFLOW"; break; case 7: code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; break; } break; default: break; } break; case 4: // EXC_EMULATION exc_desc = "EXC_EMULATION"; break; case 5: // EXC_SOFTWARE exc_desc = "EXC_SOFTWARE"; if (m_exc_code == 0x10003) { subcode_desc = "EXC_SOFT_SIGNAL"; subcode_label = "signo"; } break; case 6: // EXC_BREAKPOINT { exc_desc = "EXC_BREAKPOINT"; switch (cpu) { case llvm::Triple::x86: case llvm::Triple::x86_64: switch (m_exc_code) { case 1: code_desc = "EXC_I386_SGL"; break; case 2: code_desc = "EXC_I386_BPT"; break; } break; case llvm::Triple::ppc: case llvm::Triple::ppc64: switch (m_exc_code) { case 1: code_desc = "EXC_PPC_BREAKPOINT"; break; } break; case llvm::Triple::arm: switch (m_exc_code) { case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break; case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break; case 1: code_desc = "EXC_ARM_BREAKPOINT"; break; // FIXME temporary workaround, exc_code 0 does not really mean EXC_ARM_BREAKPOINT case 0: code_desc = "EXC_ARM_BREAKPOINT"; break; } break; default: break; } } break; case 7: exc_desc = "EXC_SYSCALL"; break; case 8: exc_desc = "EXC_MACH_SYSCALL"; break; case 9: exc_desc = "EXC_RPC_ALERT"; break; case 10: exc_desc = "EXC_CRASH"; break; case 11: exc_desc = "EXC_RESOURCE"; break; case 12: exc_desc = "EXC_GUARD"; break; } StreamString strm; if (exc_desc) strm.PutCString(exc_desc); else strm.Printf("EXC_??? (%" PRIu64 ")", m_value); if (m_exc_data_count >= 1) { if (code_desc) strm.Printf(" (%s=%s", code_label, code_desc); else strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code); } if (m_exc_data_count >= 2) { if (subcode_desc) strm.Printf(", %s=%s", subcode_label, subcode_desc); else strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode); } if (m_exc_data_count > 0) strm.PutChar(')'); m_description.swap (strm.GetString()); } return m_description.c_str(); }
bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& range, Thread& thread, UnwindPlan& unwind_plan) { if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid() && m_inst_emulator_ap.get()) { // The the instruction emulation subclass setup the unwind plan for the // first instruction. m_inst_emulator_ap->CreateFunctionEntryUnwind (unwind_plan); // CreateFunctionEntryUnwind should have created the first row. If it // doesn't, then we are done. if (unwind_plan.GetRowCount() == 0) return false; ExecutionContext exe_ctx; thread.CalculateExecutionContext(exe_ctx); DisassemblerSP disasm_sp (Disassembler::DisassembleRange (m_arch, NULL, NULL, exe_ctx, range)); Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); if (disasm_sp) { m_range_ptr = ⦥ m_thread_ptr = &thread; m_unwind_plan_ptr = &unwind_plan; const uint32_t addr_byte_size = m_arch.GetAddressByteSize(); const bool show_address = true; const bool show_bytes = true; m_inst_emulator_ap->GetRegisterInfo (unwind_plan.GetRegisterKind(), unwind_plan.GetInitialCFARegister(), m_cfa_reg_info); m_fp_is_cfa = false; m_register_values.clear(); m_pushed_regs.clear(); // Initialize the CFA with a known value. In the 32 bit case // it will be 0x80000000, and in the 64 bit case 0x8000000000000000. // We use the address byte size to be safe for any future addresss sizes m_initial_sp = (1ull << ((addr_byte_size * 8) - 1)); RegisterValue cfa_reg_value; cfa_reg_value.SetUInt (m_initial_sp, m_cfa_reg_info.byte_size); SetRegisterValue (m_cfa_reg_info, cfa_reg_value); const InstructionList &inst_list = disasm_sp->GetInstructionList (); const size_t num_instructions = inst_list.GetSize(); if (num_instructions > 0) { Instruction *inst = inst_list.GetInstructionAtIndex (0).get(); const addr_t base_addr = inst->GetAddress().GetFileAddress(); // Make a copy of the current instruction Row and save it in m_curr_row // so we can add updates as we process the instructions. UnwindPlan::RowSP last_row = unwind_plan.GetLastRow(); UnwindPlan::Row *newrow = new UnwindPlan::Row; if (last_row.get()) *newrow = *last_row.get(); m_curr_row.reset(newrow); // Once we've seen the initial prologue instructions complete, save a // copy of the CFI at that point into prologue_completed_row for possible // use later. int instructions_since_last_prologue_insn = 0; // # of insns since last CFI was update bool reinstate_prologue_next_instruction = false; // Next iteration, re-install the prologue row of CFI bool last_instruction_restored_return_addr_reg = false; // re-install the prologue row of CFI if the next instruction is a branch immediate bool return_address_register_has_been_saved = false; // if we've seen the ra register get saved yet UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI // cache the pc register number (in whatever register numbering this UnwindPlan uses) for // quick reference during instruction parsing. uint32_t pc_reg_num = LLDB_INVALID_REGNUM; RegisterInfo pc_reg_info; if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info)) pc_reg_num = pc_reg_info.kinds[unwind_plan.GetRegisterKind()]; else pc_reg_num = LLDB_INVALID_REGNUM; // cache the return address register number (in whatever register numbering this UnwindPlan uses) for // quick reference during instruction parsing. uint32_t ra_reg_num = LLDB_INVALID_REGNUM; RegisterInfo ra_reg_info; if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info)) ra_reg_num = ra_reg_info.kinds[unwind_plan.GetRegisterKind()]; else ra_reg_num = LLDB_INVALID_REGNUM; for (size_t idx=0; idx<num_instructions; ++idx) { m_curr_row_modified = false; m_curr_insn_restored_a_register = false; inst = inst_list.GetInstructionAtIndex (idx).get(); if (inst) { if (log && log->GetVerbose ()) { StreamString strm; inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL); log->PutCString (strm.GetData()); } m_inst_emulator_ap->SetInstruction (inst->GetOpcode(), inst->GetAddress(), exe_ctx.GetTargetPtr()); m_inst_emulator_ap->EvaluateInstruction (eEmulateInstructionOptionIgnoreConditions); // Were there any changes to the CFI while evaluating this instruction? if (m_curr_row_modified) { reinstate_prologue_next_instruction = false; m_curr_row->SetOffset (inst->GetAddress().GetFileAddress() + inst->GetOpcode().GetByteSize() - base_addr); // Append the new row unwind_plan.AppendRow (m_curr_row); // Allocate a new Row for m_curr_row, copy the current state into it UnwindPlan::Row *newrow = new UnwindPlan::Row; *newrow = *m_curr_row.get(); m_curr_row.reset(newrow); // If m_curr_insn_restored_a_register == true, we're looking at an epilogue instruction. // Set instructions_since_last_prologue_insn to a very high number so we don't append // any of these epilogue instructions to our prologue_complete row. if (m_curr_insn_restored_a_register == false && instructions_since_last_prologue_insn < 8) instructions_since_last_prologue_insn = 0; else instructions_since_last_prologue_insn = 99; UnwindPlan::Row::RegisterLocation pc_regloc; UnwindPlan::Row::RegisterLocation ra_regloc; // While parsing the instructions of this function, if we've ever // seen the return address register (aka lr on arm) in a non-IsSame() state, // it has been saved on the stack. If it's evern back to IsSame(), we've // executed an epilogue. if (ra_reg_num != LLDB_INVALID_REGNUM && m_curr_row->GetRegisterInfo (ra_reg_num, ra_regloc) && !ra_regloc.IsSame()) { return_address_register_has_been_saved = true; } // If the caller's pc is "same", we've just executed an epilogue and we return to the caller // after this instruction completes executing. // If there are any instructions past this, there must have been flow control over this // epilogue so we'll reinstate the original prologue setup instructions. if (prologue_completed_row.get() && pc_reg_num != LLDB_INVALID_REGNUM && m_curr_row->GetRegisterInfo (pc_reg_num, pc_regloc) && pc_regloc.IsSame()) { if (log && log->GetVerbose()) log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- pc is <same>, restore prologue instructions."); reinstate_prologue_next_instruction = true; } else if (prologue_completed_row.get() && return_address_register_has_been_saved && ra_reg_num != LLDB_INVALID_REGNUM && m_curr_row->GetRegisterInfo (ra_reg_num, ra_regloc) && ra_regloc.IsSame()) { if (log && log->GetVerbose()) log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- lr is <same>, restore prologue instruction if the next instruction is a branch immediate."); last_instruction_restored_return_addr_reg = true; } } else { // If the previous instruction was a return-to-caller (epilogue), and we're still executing // instructions in this function, there must be a code path that jumps over that epilogue. // Also detect the case where we epilogue & branch imm to another function (tail-call opt) // instead of a normal pop lr-into-pc exit. // Reinstate the frame setup from the prologue. if (reinstate_prologue_next_instruction || (m_curr_insn_is_branch_immediate && last_instruction_restored_return_addr_reg)) { if (log && log->GetVerbose()) log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- Reinstating prologue instruction set"); UnwindPlan::Row *newrow = new UnwindPlan::Row; *newrow = *prologue_completed_row.get(); m_curr_row.reset(newrow); m_curr_row->SetOffset (inst->GetAddress().GetFileAddress() + inst->GetOpcode().GetByteSize() - base_addr); unwind_plan.AppendRow(m_curr_row); newrow = new UnwindPlan::Row; *newrow = *m_curr_row.get(); m_curr_row.reset(newrow); reinstate_prologue_next_instruction = false; last_instruction_restored_return_addr_reg = false; m_curr_insn_is_branch_immediate = false; } // clear both of these if either one wasn't set if (last_instruction_restored_return_addr_reg) { last_instruction_restored_return_addr_reg = false; } if (m_curr_insn_is_branch_immediate) { m_curr_insn_is_branch_immediate = false; } // Stop updating the prologue instructions if we've seen 8 non-prologue instructions // in a row. if (instructions_since_last_prologue_insn++ < 8) { UnwindPlan::Row *newrow = new UnwindPlan::Row; *newrow = *m_curr_row.get(); prologue_completed_row.reset(newrow); if (log && log->GetVerbose()) log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- saving a copy of the current row as the prologue row."); } } } } } } if (log && log->GetVerbose ()) { StreamString strm; lldb::addr_t base_addr = range.GetBaseAddress().GetLoadAddress(thread.CalculateTarget().get()); strm.Printf ("Resulting unwind rows for [0x%" PRIx64 " - 0x%" PRIx64 "):", base_addr, base_addr + range.GetByteSize()); unwind_plan.Dump(strm, &thread, base_addr); log->PutCString (strm.GetData()); } return unwind_plan.GetRowCount() > 0; } return false; }
void Instruction::Dump (lldb_private::Stream *s, uint32_t max_opcode_byte_size, bool show_address, bool show_bytes, const ExecutionContext* exe_ctx) { const size_t opcode_column_width = 7; const size_t operand_column_width = 25; CalculateMnemonicOperandsAndCommentIfNeeded (exe_ctx); StreamString ss; if (show_address) { m_address.Dump(&ss, exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0); ss.PutCString(": "); } if (show_bytes) { if (m_opcode.GetType() == Opcode::eTypeBytes) { // x86_64 and i386 are the only ones that use bytes right now so // pad out the byte dump to be able to always show 15 bytes (3 chars each) // plus a space if (max_opcode_byte_size > 0) m_opcode.Dump (&ss, max_opcode_byte_size * 3 + 1); else m_opcode.Dump (&ss, 15 * 3 + 1); } else { // Else, we have ARM which can show up to a uint32_t 0x00000000 (10 spaces) // plus two for padding... if (max_opcode_byte_size > 0) m_opcode.Dump (&ss, max_opcode_byte_size * 3 + 1); else m_opcode.Dump (&ss, 12); } } const size_t opcode_pos = ss.GetSize(); ss.PutCString (m_opcode_name.c_str()); ss.FillLastLineToColumn (opcode_pos + opcode_column_width, ' '); ss.PutCString (m_mnemocics.c_str()); if (!m_comment.empty()) { ss.FillLastLineToColumn (opcode_pos + opcode_column_width + operand_column_width, ' '); ss.PutCString (" ; "); ss.PutCString (m_comment.c_str()); } s->Write (ss.GetData(), ss.GetSize()); }
const std::string &getErrorString() { return m_error_stream.GetString(); }
void FormatManager::GetPossibleMatches (ValueObject& valobj, CompilerType compiler_type, uint32_t reason, lldb::DynamicValueType use_dynamic, FormattersMatchVector& entries, bool did_strip_ptr, bool did_strip_ref, bool did_strip_typedef, bool root_level) { compiler_type = compiler_type.GetTypeForFormatters(); ConstString type_name(compiler_type.GetConstTypeName()); if (valobj.GetBitfieldBitSize() > 0) { StreamString sstring; sstring.Printf("%s:%d",type_name.AsCString(),valobj.GetBitfieldBitSize()); ConstString bitfieldname = ConstString(sstring.GetData()); entries.push_back({bitfieldname,0,did_strip_ptr,did_strip_ref,did_strip_typedef}); reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField; } if (!compiler_type.IsMeaninglessWithoutDynamicResolution()) { entries.push_back({type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef}); ConstString display_type_name(compiler_type.GetDisplayTypeName()); if (display_type_name != type_name) entries.push_back({display_type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef}); } for (bool is_rvalue_ref = true, j = true; j && compiler_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false) { CompilerType non_ref_type = compiler_type.GetNonReferenceType(); GetPossibleMatches(valobj, non_ref_type, reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference, use_dynamic, entries, did_strip_ptr, true, did_strip_typedef); if (non_ref_type.IsTypedefType()) { CompilerType deffed_referenced_type = non_ref_type.GetTypedefedType(); deffed_referenced_type = is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType() : deffed_referenced_type.GetLValueReferenceType(); GetPossibleMatches(valobj, deffed_referenced_type, reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs, use_dynamic, entries, did_strip_ptr, did_strip_ref, true); // this is not exactly the usual meaning of stripping typedefs } } if (compiler_type.IsPointerType()) { CompilerType non_ptr_type = compiler_type.GetPointeeType(); GetPossibleMatches(valobj, non_ptr_type, reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference, use_dynamic, entries, true, did_strip_ref, did_strip_typedef); if (non_ptr_type.IsTypedefType()) { CompilerType deffed_pointed_type = non_ptr_type.GetTypedefedType().GetPointerType(); GetPossibleMatches(valobj, deffed_pointed_type, reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs, use_dynamic, entries, did_strip_ptr, did_strip_ref, true); // this is not exactly the usual meaning of stripping typedefs } } for (lldb::LanguageType language_type : GetCandidateLanguages(valobj)) { if (Language* language = Language::FindPlugin(language_type)) { for (ConstString candidate : language->GetPossibleFormattersMatches(valobj, use_dynamic)) { entries.push_back({candidate, reason | lldb_private::eFormatterChoiceCriterionLanguagePlugin, did_strip_ptr, did_strip_ref, did_strip_typedef}); } } } // try to strip typedef chains if (compiler_type.IsTypedefType()) { CompilerType deffed_type = compiler_type.GetTypedefedType(); GetPossibleMatches(valobj, deffed_type, reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs, use_dynamic, entries, did_strip_ptr, did_strip_ref, true); } if (root_level) { do { if (!compiler_type.IsValid()) break; CompilerType unqual_compiler_ast_type = compiler_type.GetFullyUnqualifiedType(); if (!unqual_compiler_ast_type.IsValid()) break; if (unqual_compiler_ast_type.GetOpaqueQualType() != compiler_type.GetOpaqueQualType()) GetPossibleMatches (valobj, unqual_compiler_ast_type, reason, use_dynamic, entries, did_strip_ptr, did_strip_ref, did_strip_typedef); } while(false); // if all else fails, go to static type if (valobj.IsDynamic()) { lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue()); if (static_value_sp) GetPossibleMatches(*static_value_sp.get(), static_value_sp->GetCompilerType(), reason | lldb_private::eFormatterChoiceCriterionWentToStaticValue, use_dynamic, entries, did_strip_ptr, did_strip_ref, did_strip_typedef, true); } } }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qHostInfo (StringExtractorGDBRemote &packet) { StreamString response; // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00 ArchSpec host_arch(HostInfo::GetArchitecture()); const llvm::Triple &host_triple = host_arch.GetTriple(); response.PutCString("triple:"); response.PutCStringAsRawHex8(host_triple.getTriple().c_str()); response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize()); const char* distribution_id = host_arch.GetDistributionId ().AsCString (); if (distribution_id) { response.PutCString("distribution_id:"); response.PutCStringAsRawHex8(distribution_id); response.PutCString(";"); } // Only send out MachO info when lldb-platform/llgs is running on a MachO host. #if defined(__APPLE__) uint32_t cpu = host_arch.GetMachOCPUType(); uint32_t sub = host_arch.GetMachOCPUSubType(); if (cpu != LLDB_INVALID_CPUTYPE) response.Printf ("cputype:%u;", cpu); if (sub != LLDB_INVALID_CPUTYPE) response.Printf ("cpusubtype:%u;", sub); if (cpu == ArchSpec::kCore_arm_any) response.Printf("watchpoint_exceptions_received:before;"); // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes. else response.Printf("watchpoint_exceptions_received:after;"); #else if (host_arch.GetMachine() == llvm::Triple::aarch64 || host_arch.GetMachine() == llvm::Triple::aarch64_be || host_arch.GetMachine() == llvm::Triple::arm || host_arch.GetMachine() == llvm::Triple::armeb || host_arch.GetMachine() == llvm::Triple::mips64 || host_arch.GetMachine() == llvm::Triple::mips64el || host_arch.GetMachine() == llvm::Triple::mips || host_arch.GetMachine() == llvm::Triple::mipsel) response.Printf("watchpoint_exceptions_received:before;"); else response.Printf("watchpoint_exceptions_received:after;"); #endif switch (endian::InlHostByteOrder()) { case eByteOrderBig: response.PutCString ("endian:big;"); break; case eByteOrderLittle: response.PutCString ("endian:little;"); break; case eByteOrderPDP: response.PutCString ("endian:pdp;"); break; default: response.PutCString ("endian:unknown;"); break; } uint32_t major = UINT32_MAX; uint32_t minor = UINT32_MAX; uint32_t update = UINT32_MAX; if (HostInfo::GetOSVersion(major, minor, update)) { if (major != UINT32_MAX) { response.Printf("os_version:%u", major); if (minor != UINT32_MAX) { response.Printf(".%u", minor); if (update != UINT32_MAX) response.Printf(".%u", update); } response.PutChar(';'); } } std::string s; if (HostInfo::GetOSBuildString(s)) { response.PutCString ("os_build:"); response.PutCStringAsRawHex8(s.c_str()); response.PutChar(';'); } if (HostInfo::GetOSKernelDescription(s)) { response.PutCString ("os_kernel:"); response.PutCStringAsRawHex8(s.c_str()); response.PutChar(';'); } #if defined(__APPLE__) #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) // For iOS devices, we are connected through a USB Mux so we never pretend // to actually have a hostname as far as the remote lldb that is connecting // to this lldb-platform is concerned response.PutCString ("hostname:"); response.PutCStringAsRawHex8("127.0.0.1"); response.PutChar(';'); #else // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) if (HostInfo::GetHostname(s)) { response.PutCString ("hostname:"); response.PutCStringAsRawHex8(s.c_str()); response.PutChar(';'); } #endif // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) #else // #if defined(__APPLE__) if (HostInfo::GetHostname(s)) { response.PutCString ("hostname:"); response.PutCStringAsRawHex8(s.c_str()); response.PutChar(';'); } #endif // #if defined(__APPLE__) if (g_default_packet_timeout_sec > 0) response.Printf ("default_packet_timeout:%u;", g_default_packet_timeout_sec); return SendPacketNoLock (response.GetData(), response.GetSize()); }
void GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse_DebugServerStyle ( const ProcessInstanceInfo &proc_info, StreamString &response) { response.Printf ("pid:%" PRIx64 ";parent-pid:%" PRIx64 ";real-uid:%x;real-gid:%x;effective-uid:%x;effective-gid:%x;", proc_info.GetProcessID(), proc_info.GetParentProcessID(), proc_info.GetUserID(), proc_info.GetGroupID(), proc_info.GetEffectiveUserID(), proc_info.GetEffectiveGroupID()); const ArchSpec &proc_arch = proc_info.GetArchitecture(); if (proc_arch.IsValid()) { const llvm::Triple &proc_triple = proc_arch.GetTriple(); #if defined(__APPLE__) // We'll send cputype/cpusubtype. const uint32_t cpu_type = proc_arch.GetMachOCPUType(); if (cpu_type != 0) response.Printf ("cputype:%" PRIx32 ";", cpu_type); const uint32_t cpu_subtype = proc_arch.GetMachOCPUSubType(); if (cpu_subtype != 0) response.Printf ("cpusubtype:%" PRIx32 ";", cpu_subtype); const std::string vendor = proc_triple.getVendorName (); if (!vendor.empty ()) response.Printf ("vendor:%s;", vendor.c_str ()); #else // We'll send the triple. response.PutCString("triple:"); response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); response.PutChar(';'); #endif std::string ostype = proc_triple.getOSName (); // Adjust so ostype reports ios for Apple/ARM and Apple/ARM64. if (proc_triple.getVendor () == llvm::Triple::Apple) { switch (proc_triple.getArch ()) { case llvm::Triple::arm: case llvm::Triple::thumb: case llvm::Triple::aarch64: ostype = "ios"; break; default: // No change. break; } } response.Printf ("ostype:%s;", ostype.c_str ()); switch (proc_arch.GetByteOrder ()) { case lldb::eByteOrderLittle: response.PutCString ("endian:little;"); break; case lldb::eByteOrderBig: response.PutCString ("endian:big;"); break; case lldb::eByteOrderPDP: response.PutCString ("endian:pdp;"); break; default: // Nothing. break; } if (proc_triple.isArch64Bit ()) response.PutCString ("ptrsize:8;"); else if (proc_triple.isArch32Bit ()) response.PutCString ("ptrsize:4;"); else if (proc_triple.isArch16Bit ()) response.PutCString ("ptrsize:2;"); } }