RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc(Thread &thread, RegisterInfoInterface *register_info, const DataExtractor &gpregset, const DataExtractor &fpregset) : RegisterContextPOSIX_powerpc(thread, 0, register_info) { m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); m_gpr.SetData(m_gpr_buffer); m_gpr.SetByteOrder(gpregset.GetByteOrder()); m_fpr_buffer.reset(new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); m_fpr.SetData(m_fpr_buffer); m_fpr.SetByteOrder(fpregset.GetByteOrder()); }
ValueObjectConstResult::ValueObjectConstResult ( ExecutionContextScope *exe_scope, clang::ASTContext *clang_ast, void *clang_type, const ConstString &name, const DataExtractor &data, lldb::addr_t address ) : ValueObject (exe_scope), m_clang_ast (clang_ast), m_type_name (), m_byte_size (0), m_impl(this, address) { m_data = data; if (!m_data.GetSharedDataBuffer()) { DataBufferSP shared_data_buffer(new DataBufferHeap(data.GetDataStart(), data.GetByteSize())); m_data.SetData(shared_data_buffer); } m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); m_value.SetValueType(Value::eValueTypeHostAddress); m_value.SetContext(Value::eContextTypeClangType, clang_type); m_name = name; SetIsConstant (); SetValueIsValid(true); SetAddressTypeOfChildren(eAddressTypeLoad); }
RegisterContextCorePOSIX_mips64::RegisterContextCorePOSIX_mips64(Thread &thread, RegisterInfoInterface *register_info, const DataExtractor &gpregset, const DataExtractor &fpregset, const DataExtractor &capregset) : RegisterContextPOSIX_mips64(thread, 0, register_info) { m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); m_gpr.SetData(m_gpr_buffer); m_gpr.SetByteOrder(gpregset.GetByteOrder()); m_cr_buffer.reset(new DataBufferHeap(capregset.GetDataStart(), capregset.GetByteSize())); m_cr.SetData(m_cr_buffer); m_cr.SetByteOrder(capregset.GetByteOrder()); m_in_bd = lldb_private::eLazyBoolCalculate; }
RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64( Thread &thread, RegisterInfoInterface *register_info, const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) : RegisterContextPOSIX_arm64(thread, 0, register_info) { m_gpr_buffer.reset( new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); m_gpr.SetData(m_gpr_buffer); m_gpr.SetByteOrder(gpregset.GetByteOrder()); }
bool RegisterContextMacOSXFrameBackchain::ReadRegisterBytes (uint32_t reg, DataExtractor &data) { Scalar reg_value; if (ReadRegisterValue (reg, reg_value)) { if (reg_value.GetData(data)) { // "reg_value" is local and now "data" points to the data within // "reg_value", so we must make a copy that will live within "data" DataBufferSP data_sp (new DataBufferHeap (data.GetDataStart(), data.GetByteSize())); data.SetData (data_sp, 0, data.GetByteSize()); return true; } } return false; }
virtual bool DoesBranch () { if (m_does_branch == eLazyBoolCalculate) { GetDisassemblerLLVMC().Lock(this, NULL); DataExtractor data; if (m_opcode.GetData(data)) { bool is_alternate_isa; lldb::addr_t pc = m_address.GetFileAddress(); DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa); const uint8_t *opcode_data = data.GetDataStart(); const size_t opcode_data_len = data.GetByteSize(); llvm::MCInst inst; const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, opcode_data_len, pc, inst); // Be conservative, if we didn't understand the instruction, say it might branch... if (inst_size == 0) m_does_branch = eLazyBoolYes; else { const bool can_branch = mc_disasm_ptr->CanBranch(inst); if (can_branch) m_does_branch = eLazyBoolYes; else m_does_branch = eLazyBoolNo; } } GetDisassemblerLLVMC().Unlock(); } return m_does_branch == eLazyBoolYes; }
bool EmulateInstructionMIPS::EvaluateInstruction (uint32_t evaluate_options) { bool success = false; llvm::MCInst mc_insn; uint64_t insn_size; DataExtractor data; /* Keep the complexity of the decode logic with the llvm::MCDisassembler class. */ if (m_opcode.GetData (data)) { llvm::MCDisassembler::DecodeStatus decode_status; llvm::ArrayRef<uint8_t> raw_insn (data.GetDataStart(), data.GetByteSize()); decode_status = m_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls()); if (decode_status != llvm::MCDisassembler::Success) return false; } /* * mc_insn.getOpcode() returns decoded opcode. However to make use * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc". */ const char *op_name = m_insn_info->getName (mc_insn.getOpcode ()); if (op_name == NULL) return false; /* * Decoding has been done already. Just get the call-back function * and emulate the instruction. */ MipsOpcode *opcode_data = GetOpcodeForInstruction (op_name); if (opcode_data == NULL) return false; uint64_t old_pc = 0, new_pc = 0; const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC; if (auto_advance_pc) { old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); if (!success) return false; } /* emulate instruction */ success = (this->*opcode_data->callback) (mc_insn); if (!success) return false; if (auto_advance_pc) { new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); if (!success) return false; /* If we haven't changed the PC, change it here */ if (old_pc == new_pc) { new_pc += 4; Context context; if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, new_pc)) return false; } } return true; }
static bool DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**, const SourceDataType*, UTF8**, UTF8*, ConversionFlags), const DataExtractor& data, Stream& stream, char prefix_token, char quote, uint32_t sourceSize, bool escapeNonPrintables) { if (prefix_token != 0) stream.Printf("%c",prefix_token); if (quote != 0) stream.Printf("%c",quote); if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd()) { const int bufferSPSize = data.GetByteSize(); if (sourceSize == 0) { const int origin_encoding = 8*sizeof(SourceDataType); sourceSize = bufferSPSize/(origin_encoding / 4); } const SourceDataType *data_ptr = (const SourceDataType*)data.GetDataStart(); const SourceDataType *data_end_ptr = data_ptr + sourceSize; while (data_ptr < data_end_ptr) { if (!*data_ptr) { data_end_ptr = data_ptr; break; } data_ptr++; } data_ptr = (const SourceDataType*)data.GetDataStart(); lldb::DataBufferSP utf8_data_buffer_sp; UTF8* utf8_data_ptr = nullptr; UTF8* utf8_data_end_ptr = nullptr; if (ConvertFunction) { utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0)); utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize(); ConvertFunction ( &data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion ); utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr } else { // just copy the pointers - the cast is necessary to make the compiler happy // but this should only happen if we are reading UTF8 data utf8_data_ptr = (UTF8*)data_ptr; utf8_data_end_ptr = (UTF8*)data_end_ptr; } // since we tend to accept partial data (and even partially malformed data) // we might end up with no NULL terminator before the end_ptr // hence we need to take a slower route and ensure we stay within boundaries for (; utf8_data_ptr < utf8_data_end_ptr;) { if (!*utf8_data_ptr) break; if (escapeNonPrintables) { uint8_t* next_data = nullptr; auto printable = GetPrintable(StringElementType::UTF8, utf8_data_ptr, utf8_data_end_ptr, next_data); auto printable_bytes = printable.GetBytes(); auto printable_size = printable.GetSize(); if (!printable_bytes || !next_data) { // GetPrintable() failed on us - print one byte in a desperate resync attempt printable_bytes = utf8_data_ptr; printable_size = 1; next_data = utf8_data_ptr+1; } for (unsigned c = 0; c < printable_size; c++) stream.Printf("%c", *(printable_bytes+c)); utf8_data_ptr = (uint8_t*)next_data; } else { stream.Printf("%c",*utf8_data_ptr); utf8_data_ptr++; } } } if (quote != 0) stream.Printf("%c",quote); return true; }
static bool DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**, const SourceDataType*, UTF8**, UTF8*, ConversionFlags), DataExtractor& data, Stream& stream, char prefix_token = '@', char quote = '"', uint32_t sourceSize = 0) { if (prefix_token != 0) stream.Printf("%c",prefix_token); if (quote != 0) stream.Printf("%c",quote); if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd()) { const int bufferSPSize = data.GetByteSize(); if (sourceSize == 0) { const int origin_encoding = 8*sizeof(SourceDataType); sourceSize = bufferSPSize/(origin_encoding / 4); } SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart(); SourceDataType *data_end_ptr = data_ptr + sourceSize; while (data_ptr < data_end_ptr) { if (!*data_ptr) { data_end_ptr = data_ptr; break; } data_ptr++; } data_ptr = (SourceDataType*)data.GetDataStart(); lldb::DataBufferSP utf8_data_buffer_sp; UTF8* utf8_data_ptr = nullptr; UTF8* utf8_data_end_ptr = nullptr; if (ConvertFunction) { utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0)); utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize(); ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion ); utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr } else { // just copy the pointers - the cast is necessary to make the compiler happy // but this should only happen if we are reading UTF8 data utf8_data_ptr = (UTF8*)data_ptr; utf8_data_end_ptr = (UTF8*)data_end_ptr; } // since we tend to accept partial data (and even partially malformed data) // we might end up with no NULL terminator before the end_ptr // hence we need to take a slower route and ensure we stay within boundaries for (;utf8_data_ptr != utf8_data_end_ptr; utf8_data_ptr++) { if (!*utf8_data_ptr) break; stream.Printf("%c",*utf8_data_ptr); } } if (quote != 0) stream.Printf("%c",quote); return true; }
virtual void CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx) { DataExtractor data; const AddressClass address_class = GetAddressClass (); if (m_opcode.GetData(data)) { char out_string[512]; DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC(); DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr; if (address_class == eAddressClassCodeAlternateISA) mc_disasm_ptr = llvm_disasm.m_alternate_disasm_ap.get(); else mc_disasm_ptr = llvm_disasm.m_disasm_ap.get(); lldb::addr_t pc = m_address.GetFileAddress(); m_using_file_addr = true; const bool data_from_file = GetDisassemblerLLVMC().m_data_from_file; bool use_hex_immediates = true; Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC; if (exe_ctx) { Target *target = exe_ctx->GetTargetPtr(); if (target) { use_hex_immediates = target->GetUseHexImmediates(); hex_style = target->GetHexImmediateStyle(); if (!data_from_file) { const lldb::addr_t load_addr = m_address.GetLoadAddress(target); if (load_addr != LLDB_INVALID_ADDRESS) { pc = load_addr; m_using_file_addr = false; } } } } llvm_disasm.Lock(this, exe_ctx); const uint8_t *opcode_data = data.GetDataStart(); const size_t opcode_data_len = data.GetByteSize(); llvm::MCInst inst; size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, opcode_data_len, pc, inst); if (inst_size > 0) { mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string)); } llvm_disasm.Unlock(); if (inst_size == 0) { m_comment.assign ("unknown opcode"); inst_size = m_opcode.GetByteSize(); StreamString mnemonic_strm; lldb::offset_t offset = 0; lldb::ByteOrder byte_order = data.GetByteOrder(); switch (inst_size) { case 1: { const uint8_t uval8 = data.GetU8 (&offset); m_opcode.SetOpcode8 (uval8, byte_order); m_opcode_name.assign (".byte"); mnemonic_strm.Printf("0x%2.2x", uval8); } break; case 2: { const uint16_t uval16 = data.GetU16(&offset); m_opcode.SetOpcode16(uval16, byte_order); m_opcode_name.assign (".short"); mnemonic_strm.Printf("0x%4.4x", uval16); } break; case 4: { const uint32_t uval32 = data.GetU32(&offset); m_opcode.SetOpcode32(uval32, byte_order); m_opcode_name.assign (".long"); mnemonic_strm.Printf("0x%8.8x", uval32); } break; case 8: { const uint64_t uval64 = data.GetU64(&offset); m_opcode.SetOpcode64(uval64, byte_order); m_opcode_name.assign (".quad"); mnemonic_strm.Printf("0x%16.16" PRIx64, uval64); } break; default: if (inst_size == 0) return; else { const uint8_t *bytes = data.PeekData(offset, inst_size); if (bytes == NULL) return; m_opcode_name.assign (".byte"); m_opcode.SetOpcodeBytes(bytes, inst_size); mnemonic_strm.Printf("0x%2.2x", bytes[0]); for (uint32_t i=1; i<inst_size; ++i) mnemonic_strm.Printf(" 0x%2.2x", bytes[i]); } break; } m_mnemonics.swap(mnemonic_strm.GetString()); return; } else { if (m_does_branch == eLazyBoolCalculate) { const bool can_branch = mc_disasm_ptr->CanBranch(inst); if (can_branch) m_does_branch = eLazyBoolYes; else m_does_branch = eLazyBoolNo; } } static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED); RegularExpression::Match matches(3); if (s_regex.Execute(out_string, &matches)) { matches.GetMatchAtIndex(out_string, 1, m_opcode_name); matches.GetMatchAtIndex(out_string, 2, m_mnemonics); } } }
bool DoExecute (Args& command, CommandReturnObject &result) { const size_t argc = command.GetArgumentCount(); if (argc == 0) { if (!m_command_byte.GetOptionValue().OptionWasSet()) { result.AppendError ("the --command option must be set to a valid command byte"); result.SetStatus (eReturnStatusFailed); } else { const uint64_t command_byte = m_command_byte.GetOptionValue().GetUInt64Value(0); if (command_byte > 0 && command_byte <= UINT8_MAX) { ProcessKDP *process = (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr(); if (process) { const StateType state = process->GetState(); if (StateIsStoppedState (state, true)) { std::vector<uint8_t> payload_bytes; const char *ascii_hex_bytes_cstr = m_packet_data.GetOptionValue().GetCurrentValue(); if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) { StringExtractor extractor(ascii_hex_bytes_cstr); const size_t ascii_hex_bytes_cstr_len = extractor.GetStringRef().size(); if (ascii_hex_bytes_cstr_len & 1) { result.AppendErrorWithFormat ("payload data must contain an even number of ASCII hex characters: '%s'", ascii_hex_bytes_cstr); result.SetStatus (eReturnStatusFailed); return false; } payload_bytes.resize(ascii_hex_bytes_cstr_len/2); if (extractor.GetHexBytes(&payload_bytes[0], payload_bytes.size(), '\xdd') != payload_bytes.size()) { result.AppendErrorWithFormat ("payload data must only contain ASCII hex characters (no spaces or hex prefixes): '%s'", ascii_hex_bytes_cstr); result.SetStatus (eReturnStatusFailed); return false; } } Error error; DataExtractor reply; process->GetCommunication().SendRawRequest (command_byte, payload_bytes.empty() ? NULL : payload_bytes.data(), payload_bytes.size(), reply, error); if (error.Success()) { // Copy the binary bytes into a hex ASCII string for the result StreamString packet; packet.PutBytesAsRawHex8(reply.GetDataStart(), reply.GetByteSize(), lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder()); result.AppendMessage(packet.GetString().c_str()); result.SetStatus (eReturnStatusSuccessFinishResult); return true; } else { const char *error_cstr = error.AsCString(); if (error_cstr && error_cstr[0]) result.AppendError (error_cstr); else result.AppendErrorWithFormat ("unknown error 0x%8.8x", error.GetError()); result.SetStatus (eReturnStatusFailed); return false; } } else { result.AppendErrorWithFormat ("process must be stopped in order to send KDP packets, state is %s", StateAsCString (state)); result.SetStatus (eReturnStatusFailed); } } else { result.AppendError ("invalid process"); result.SetStatus (eReturnStatusFailed); } } else { result.AppendErrorWithFormat ("invalid command byte 0x%" PRIx64 ", valid values are 1 - 255", command_byte); result.SetStatus (eReturnStatusFailed); } } } else { result.AppendErrorWithFormat ("'%s' takes no arguments, only options.", m_cmd_name.c_str()); result.SetStatus (eReturnStatusFailed); } return false; }
void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Status &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); const lldb::addr_t load_addr = process_address + m_offset; if (log) { log->Printf("EntityVariable::Materialize [address = 0x%" PRIx64 ", m_variable_sp = %s]", (uint64_t)load_addr, m_variable_sp->GetName().AsCString()); } ExecutionContextScope *scope = frame_sp.get(); if (!scope) scope = map.GetBestExecutionContextScope(); lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp); if (!valobj_sp) { err.SetErrorStringWithFormat( "couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString()); return; } Status valobj_error = valobj_sp->GetError(); if (valobj_error.Fail()) { err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s", m_variable_sp->GetName().AsCString(), valobj_error.AsCString()); return; } if (m_is_reference) { DataExtractor valobj_extractor; Status extract_error; valobj_sp->GetData(valobj_extractor, extract_error); if (!extract_error.Success()) { err.SetErrorStringWithFormat( "couldn't read contents of reference variable %s: %s", m_variable_sp->GetName().AsCString(), extract_error.AsCString()); return; } lldb::offset_t offset = 0; lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset); Status write_error; map.WritePointerToMemory(load_addr, reference_addr, write_error); if (!write_error.Success()) { err.SetErrorStringWithFormat("couldn't write the contents of reference " "variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); return; } } else { AddressType address_type = eAddressTypeInvalid; const bool scalar_is_load_address = false; lldb::addr_t addr_of_valobj = valobj_sp->GetAddressOf(scalar_is_load_address, &address_type); if (addr_of_valobj != LLDB_INVALID_ADDRESS) { Status write_error; map.WritePointerToMemory(load_addr, addr_of_valobj, write_error); if (!write_error.Success()) { err.SetErrorStringWithFormat( "couldn't write the address of variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); return; } } else { DataExtractor data; Status extract_error; valobj_sp->GetData(data, extract_error); if (!extract_error.Success()) { err.SetErrorStringWithFormat("couldn't get the value of %s: %s", m_variable_sp->GetName().AsCString(), extract_error.AsCString()); return; } if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { err.SetErrorStringWithFormat( "trying to create a temporary region for %s but one exists", m_variable_sp->GetName().AsCString()); return; } if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize()) { if (data.GetByteSize() == 0 && m_variable_sp->LocationExpression().IsValid() == false) { err.SetErrorStringWithFormat("the variable '%s' has no location, " "it may have been optimized out", m_variable_sp->GetName().AsCString()); } else { err.SetErrorStringWithFormat( "size of variable %s (%" PRIu64 ") is larger than the ValueObject's size (%" PRIu64 ")", m_variable_sp->GetName().AsCString(), m_variable_sp->GetType()->GetByteSize(), data.GetByteSize()); } return; } size_t bit_align = m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign(); size_t byte_align = (bit_align + 7) / 8; if (!byte_align) byte_align = 1; Status alloc_error; const bool zero_memory = false; m_temporary_allocation = map.Malloc( data.GetByteSize(), byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error); m_temporary_allocation_size = data.GetByteSize(); m_original_data.reset( new DataBufferHeap(data.GetDataStart(), data.GetByteSize())); if (!alloc_error.Success()) { err.SetErrorStringWithFormat( "couldn't allocate a temporary region for %s: %s", m_variable_sp->GetName().AsCString(), alloc_error.AsCString()); return; } Status write_error; map.WriteMemory(m_temporary_allocation, data.GetDataStart(), data.GetByteSize(), write_error); if (!write_error.Success()) { err.SetErrorStringWithFormat( "couldn't write to the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); return; } Status pointer_write_error; map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error); if (!pointer_write_error.Success()) { err.SetErrorStringWithFormat( "couldn't write the address of the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), pointer_write_error.AsCString()); } } } }