Error ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) { Error error; ByteOrder byteorder = data.GetByteOrder(); if (GetSize(arch) > data.GetByteSize()) { error.SetErrorStringWithFormat("NT_PRSTATUS size should be %lu, but the remaining bytes are: %lu", GetSize(arch), data.GetByteSize()); return error; } switch(arch.GetCore()) { case ArchSpec::eCore_s390x_generic: case ArchSpec::eCore_x86_64_x86_64: data.ExtractBytes(0, sizeof(ELFLinuxPrStatus), byteorder, this); break; case ArchSpec::eCore_x86_32_i386: case ArchSpec::eCore_x86_32_i486: { // Parsing from a 32 bit ELF core file, and populating/reusing the structure // properly, because the struct is for the 64 bit version offset_t offset = 0; si_signo = data.GetU32(&offset); si_code = data.GetU32(&offset); si_errno = data.GetU32(&offset); pr_cursig = data.GetU16(&offset); offset += 2; // pad pr_sigpend = data.GetU32(&offset); pr_sighold = data.GetU32(&offset); pr_pid = data.GetU32(&offset); pr_ppid = data.GetU32(&offset); pr_pgrp = data.GetU32(&offset); pr_sid = data.GetU32(&offset); pr_utime.tv_sec = data.GetU32(&offset); pr_utime.tv_usec = data.GetU32(&offset); pr_stime.tv_sec = data.GetU32(&offset); pr_stime.tv_usec = data.GetU32(&offset); pr_cutime.tv_sec = data.GetU32(&offset); pr_cutime.tv_usec = data.GetU32(&offset); pr_cstime.tv_sec = data.GetU32(&offset); pr_cstime.tv_usec = data.GetU32(&offset); break; } default: error.SetErrorStringWithFormat("ELFLinuxPrStatus::%s Unknown architecture", __FUNCTION__); break; } return error; }
bool DWARFDebugPubnames::Extract(const DataExtractor& data) { Timer scoped_timer (__PRETTY_FUNCTION__, "DWARFDebugPubnames::Extract (byte_size = %zu)", data.GetByteSize()); LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES)); if (log) log->Printf("DWARFDebugPubnames::Extract (byte_size = %zu)", data.GetByteSize()); if (data.ValidOffset(0)) { uint32_t offset = 0; DWARFDebugPubnamesSet set; while (data.ValidOffset(offset)) { if (set.Extract(data, &offset)) { m_sets.push_back(set); offset = set.GetOffsetOfNextEntry(); } else break; } if (log) Dump (log.get()); return true; } return false; }
Error ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) { Error error; ByteOrder byteorder = data.GetByteOrder(); if (GetSize(arch) > data.GetByteSize()) { error.SetErrorStringWithFormat("NT_PRPSINFO size should be %lu, but the remaining bytes are: %lu", GetSize(arch), data.GetByteSize()); return error; } switch(arch.GetCore()) { case ArchSpec::eCore_s390x_generic: case ArchSpec::eCore_x86_64_x86_64: data.ExtractBytes(0, sizeof(ELFLinuxPrPsInfo), byteorder, this); break; case ArchSpec::eCore_x86_32_i386: case ArchSpec::eCore_x86_32_i486: { // Parsing from a 32 bit ELF core file, and populating/reusing the structure // properly, because the struct is for the 64 bit version size_t size = 0; offset_t offset = 0; pr_state = data.GetU8(&offset); pr_sname = data.GetU8(&offset); pr_zomb = data.GetU8(&offset); pr_nice = data.GetU8(&offset); pr_flag = data.GetU32(&offset); pr_uid = data.GetU16(&offset); pr_gid = data.GetU16(&offset); pr_pid = data.GetU32(&offset); pr_ppid = data.GetU32(&offset); pr_pgrp = data.GetU32(&offset); pr_sid = data.GetU32(&offset); size = 16; data.ExtractBytes(offset, size, byteorder, pr_fname); offset += size; size = 80; data.ExtractBytes(offset, size, byteorder, pr_psargs); offset += size; break; } default: error.SetErrorStringWithFormat("ELFLinuxPrPsInfo::%s Unknown architecture", __FUNCTION__); break; } return error; }
size_t CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock (DataExtractor &packet, uint32_t timeout_usec) { uint8_t buffer[8192]; Error error; LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS | KDP_LOG_VERBOSE)); // Check for a packet from our cache first without trying any reading... if (CheckForPacket (NULL, 0, packet)) return packet.GetByteSize(); bool timed_out = false; while (IsConnected() && !timed_out) { lldb::ConnectionStatus status = eConnectionStatusNoConnection; size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error); if (log) log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64, __PRETTY_FUNCTION__, timeout_usec, Communication::ConnectionStatusAsCString (status), error.AsCString(), (uint64_t)bytes_read); if (bytes_read > 0) { if (CheckForPacket (buffer, bytes_read, packet)) return packet.GetByteSize(); } else { switch (status) { case eConnectionStatusTimedOut: timed_out = true; break; case eConnectionStatusSuccess: //printf ("status = success but error = %s\n", error.AsCString("<invalid>")); break; case eConnectionStatusEndOfFile: case eConnectionStatusNoConnection: case eConnectionStatusLostConnection: case eConnectionStatusError: Disconnect(); break; } } } packet.Clear (); return 0; }
size_t CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock( DataExtractor &packet, uint32_t timeout_usec) { uint8_t buffer[8192]; Status error; Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); // Check for a packet from our cache first without trying any reading... if (CheckForPacket(NULL, 0, packet)) return packet.GetByteSize(); bool timed_out = false; while (IsConnected() && !timed_out) { lldb::ConnectionStatus status = eConnectionStatusNoConnection; size_t bytes_read = Read(buffer, sizeof(buffer), timeout_usec == UINT32_MAX ? Timeout<std::micro>(llvm::None) : std::chrono::microseconds(timeout_usec), status, &error); LLDB_LOGV(log, "Read (buffer, sizeof(buffer), timeout_usec = 0x{0:x}, " "status = {1}, error = {2}) => bytes_read = {4}", timeout_usec, Communication::ConnectionStatusAsCString(status), error, bytes_read); if (bytes_read > 0) { if (CheckForPacket(buffer, bytes_read, packet)) return packet.GetByteSize(); } else { switch (status) { case eConnectionStatusInterrupted: case eConnectionStatusTimedOut: timed_out = true; break; case eConnectionStatusSuccess: // printf ("status = success but error = %s\n", // error.AsCString("<invalid>")); break; case eConnectionStatusEndOfFile: case eConnectionStatusNoConnection: case eConnectionStatusLostConnection: case eConnectionStatusError: Disconnect(); break; } } } packet.Clear(); return 0; }
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()); }
//---------------------------------------------------------------------- // Get the section data the file on disk //---------------------------------------------------------------------- size_t ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data) const { if (IsInMemory()) { ProcessSP process_sp (m_process_wp.lock()); if (process_sp) { DataBufferSP data_sp (ReadMemory (process_sp, section->GetLoadBaseAddress (&process_sp->GetTarget()), section->GetByteSize())); if (data_sp) { section_data.SetData (data_sp, 0, data_sp->GetByteSize()); section_data.SetByteOrder (process_sp->GetByteOrder()); section_data.SetAddressByteSize (process_sp->GetAddressByteSize()); return section_data.GetByteSize(); } } } else { // The object file now contains a full mmap'ed copy of the object file data, so just use this return MemoryMapSectionData (section, section_data); } section_data.Clear(); return 0; }
bool Type::ReadFromMemory(ExecutionContext *exe_ctx, lldb::addr_t addr, AddressType address_type, DataExtractor &data) { if (address_type == eAddressTypeFile) { // Can't convert a file address to anything valid without more // context (which Module it came from) return false; } const uint64_t byte_size = GetByteSize(); if (data.GetByteSize() < byte_size) { lldb::DataBufferSP data_sp(new DataBufferHeap(byte_size, '\0')); data.SetData(data_sp); } uint8_t *dst = const_cast<uint8_t *>(data.PeekData(0, byte_size)); if (dst != nullptr) { if (address_type == eAddressTypeHost) { // The address is an address in this process, so just copy it if (addr == 0) return false; memcpy(dst, (uint8_t *)nullptr + addr, byte_size); return true; } else { if (exe_ctx) { Process *process = exe_ctx->GetProcessPtr(); if (process) { Error error; return exe_ctx->GetProcessPtr()->ReadMemory(addr, dst, byte_size, error) == byte_size; } } } } return false; }
// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details. static void ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data, ArchSpec &arch) { lldb::offset_t offset = 0; bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 || arch.GetMachine() == llvm::Triple::mips64 || arch.GetMachine() == llvm::Triple::ppc64 || arch.GetMachine() == llvm::Triple::x86_64); int pr_version = data.GetU32(&offset); Log *log (GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) { if (pr_version > 1) log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version); } // Skip padding, pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate if (lp64) offset += 32; else offset += 16; thread_data.signo = data.GetU32(&offset); // pr_cursig thread_data.tid = data.GetU32(&offset); // pr_pid if (lp64) offset += 4; size_t len = data.GetByteSize() - offset; thread_data.gpregset = DataExtractor(data, offset, len); }
// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details. static void ParseFreeBSDPrStatus(ThreadData *thread_data, DataExtractor &data, ArchSpec &arch) { lldb::offset_t offset = 0; bool have_padding = (arch.GetMachine() == llvm::Triple::mips64 || arch.GetMachine() == llvm::Triple::x86_64); int pr_version = data.GetU32(&offset); Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); if (log) { if (pr_version > 1) log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version); } if (have_padding) offset += 4; offset += 28; // pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate thread_data->signo = data.GetU32(&offset); // pr_cursig offset += 4; // pr_pid if (have_padding) offset += 4; size_t len = data.GetByteSize() - offset; thread_data->gpregset = DataExtractor(data, offset, len); }
//---------------------------------------------------------------------- // Get the section data the file on disk //---------------------------------------------------------------------- size_t ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data) const { // If some other objectfile owns this data, pass this to them. if (section->GetObjectFile() != this) return section->GetObjectFile()->ReadSectionData (section, section_data); if (IsInMemory()) { ProcessSP process_sp (m_process_wp.lock()); if (process_sp) { const addr_t base_load_addr = section->GetLoadBaseAddress (&process_sp->GetTarget()); if (base_load_addr != LLDB_INVALID_ADDRESS) { DataBufferSP data_sp (ReadMemory (process_sp, base_load_addr, section->GetByteSize())); if (data_sp) { section_data.SetData (data_sp, 0, data_sp->GetByteSize()); section_data.SetByteOrder (process_sp->GetByteOrder()); section_data.SetAddressByteSize (process_sp->GetAddressByteSize()); return section_data.GetByteSize(); } } } } else { // The object file now contains a full mmap'ed copy of the object file data, so just use this return MemoryMapSectionData (section, section_data); } section_data.Clear(); return 0; }
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; }
Scalar & Value::ResolveValue(ExecutionContext *exe_ctx) { const CompilerType &compiler_type = GetCompilerType(); if (compiler_type.IsValid()) { switch (m_value_type) { case eValueTypeScalar: // raw scalar value break; default: case eValueTypeFileAddress: case eValueTypeLoadAddress: // load address value case eValueTypeHostAddress: // host address value (for memory in the process that is using liblldb) { DataExtractor data; lldb::addr_t addr = m_value.ULongLong(LLDB_INVALID_ADDRESS); Error error (GetValueAsData (exe_ctx, data, 0, NULL)); if (error.Success()) { Scalar scalar; if (compiler_type.GetValueAsScalar (data, 0, data.GetByteSize(), scalar)) { m_value = scalar; m_value_type = eValueTypeScalar; } else { if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) { m_value.Clear(); m_value_type = eValueTypeScalar; } } } else { if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) { m_value.Clear(); m_value_type = eValueTypeScalar; } } } break; } } return m_value; }
size_t DisassemblerLLVMC::DecodeInstructions (const Address &base_addr, const DataExtractor& data, lldb::offset_t data_offset, size_t num_instructions, bool append, bool data_from_file) { if (!append) m_instruction_list.Clear(); if (!IsValid()) return 0; m_data_from_file = data_from_file; uint32_t data_cursor = data_offset; const size_t data_byte_size = data.GetByteSize(); uint32_t instructions_parsed = 0; Address inst_addr(base_addr); while (data_cursor < data_byte_size && instructions_parsed < num_instructions) { AddressClass address_class = eAddressClassCode; if (m_alternate_disasm_ap.get() != NULL) address_class = inst_addr.GetAddressClass (); InstructionSP inst_sp(new InstructionLLVMC(*this, inst_addr, address_class)); if (!inst_sp) break; uint32_t inst_size = inst_sp->Decode(*this, data, data_cursor); if (inst_size == 0) break; m_instruction_list.Append(inst_sp); data_cursor += inst_size; inst_addr.Slide(inst_size); instructions_parsed++; } return data_cursor - data_offset; }
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; }
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; }
bool TypeFormatImpl_EnumType::FormatObject (ValueObject *valobj, std::string& dest) const { dest.clear(); if (!valobj) return false; if (!valobj->CanProvideValue()) return false; ProcessSP process_sp; TargetSP target_sp; void* valobj_key = (process_sp = valobj->GetProcessSP()).get(); if (!valobj_key) valobj_key = (target_sp = valobj->GetTargetSP()).get(); else target_sp = process_sp->GetTarget().shared_from_this(); if (!valobj_key) return false; auto iter = m_types.find(valobj_key), end = m_types.end(); CompilerType valobj_enum_type; if (iter == end) { // probably a redundant check if (!target_sp) return false; const ModuleList& images(target_sp->GetImages()); SymbolContext sc; TypeList types; images.FindTypes(sc, m_enum_type, false, UINT32_MAX, types); if (types.GetSize() == 0) return false; for (lldb::TypeSP type_sp : types.Types()) { if (!type_sp) continue; if ( (type_sp->GetForwardCompilerType().GetTypeInfo() & eTypeIsEnumeration) == eTypeIsEnumeration) { valobj_enum_type = type_sp->GetFullCompilerType (); m_types.emplace(valobj_key,valobj_enum_type); break; } } } else valobj_enum_type = iter->second; if (valobj_enum_type.IsValid() == false) return false; DataExtractor data; Error error; valobj->GetData(data, error); if (error.Fail()) return false; ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); StreamString sstr; valobj_enum_type.DumpTypeValue(&sstr, lldb::eFormatEnum, data, 0, data.GetByteSize(), 0, 0, exe_ctx.GetBestExecutionContextScope()); if (!sstr.GetString().empty()) dest.swap(sstr.GetString()); return !dest.empty(); }
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; }
static bool SkinnyMachOFileContainsArchAndUUID ( const FileSpec &file_spec, const ArchSpec *arch, const lldb_private::UUID *uuid, // the UUID we are looking for off_t file_offset, DataExtractor& data, uint32_t data_offset, const uint32_t magic ) { assert(magic == HeaderMagic32 || magic == HeaderMagic32Swapped || magic == HeaderMagic64 || magic == HeaderMagic64Swapped); if (magic == HeaderMagic32 || magic == HeaderMagic64) data.SetByteOrder (lldb::endian::InlHostByteOrder()); else if (lldb::endian::InlHostByteOrder() == eByteOrderBig) data.SetByteOrder (eByteOrderLittle); else data.SetByteOrder (eByteOrderBig); uint32_t i; const uint32_t cputype = data.GetU32(&data_offset); // cpu specifier const uint32_t cpusubtype = data.GetU32(&data_offset); // machine specifier data_offset+=4; // Skip mach file type const uint32_t ncmds = data.GetU32(&data_offset); // number of load commands const uint32_t sizeofcmds = data.GetU32(&data_offset); // the size of all the load commands data_offset+=4; // Skip flags // Check the architecture if we have a valid arch pointer if (arch) { ArchSpec file_arch(eArchTypeMachO, cputype, cpusubtype); if (file_arch != *arch) return false; } // The file exists, and if a valid arch pointer was passed in we know // if already matches, so we can return if we aren't looking for a specific // UUID if (uuid == NULL) return true; if (magic == HeaderMagic64Swapped || magic == HeaderMagic64) data_offset += 4; // Skip reserved field for in mach_header_64 // Make sure we have enough data for all the load commands if (magic == HeaderMagic64Swapped || magic == HeaderMagic64) { if (data.GetByteSize() < sizeof(struct mach_header_64) + sizeofcmds) { DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header_64) + sizeofcmds)); data.SetData (data_buffer_sp); } } else { if (data.GetByteSize() < sizeof(struct mach_header) + sizeofcmds) { DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header) + sizeofcmds)); data.SetData (data_buffer_sp); } } for (i=0; i<ncmds; i++) { const uint32_t cmd_offset = data_offset; // Save this data_offset in case parsing of the segment goes awry! uint32_t cmd = data.GetU32(&data_offset); uint32_t cmd_size = data.GetU32(&data_offset); if (cmd == LoadCommandUUID) { lldb_private::UUID file_uuid (data.GetData(&data_offset, 16), 16); if (file_uuid == *uuid) return true; // Emit some warning messages since the UUIDs do not match! char path_buf[PATH_MAX]; path_buf[0] = '\0'; const char *path = file_spec.GetPath(path_buf, PATH_MAX) ? path_buf : file_spec.GetFilename().AsCString(); Host::SystemLog (Host::eSystemLogWarning, "warning: UUID mismatch detected between binary and:\n\t'%s'\n", path); return false; } data_offset = cmd_offset + cmd_size; } return false; }
bool UniversalMachOFileContainsArchAndUUID ( const FileSpec &file_spec, const ArchSpec *arch, const lldb_private::UUID *uuid, off_t file_offset, DataExtractor& data, uint32_t data_offset, const uint32_t magic ) { assert(magic == UniversalMagic || magic == UniversalMagicSwapped); // Universal mach-o files always have their headers encoded as BIG endian data.SetByteOrder(eByteOrderBig); uint32_t i; const uint32_t nfat_arch = data.GetU32(&data_offset); // number of structs that follow const uint32_t fat_header_and_arch_size = sizeof(struct fat_header) + nfat_arch * sizeof(struct fat_arch); if (data.GetByteSize() < fat_header_and_arch_size) { DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, fat_header_and_arch_size)); data.SetData (data_buffer_sp); } for (i=0; i<nfat_arch; i++) { cpu_type_t arch_cputype = data.GetU32(&data_offset); // cpu specifier (int) cpu_subtype_t arch_cpusubtype = data.GetU32(&data_offset); // machine specifier (int) uint32_t arch_offset = data.GetU32(&data_offset); // file offset to this object file // uint32_t arch_size = data.GetU32(&data_offset); // size of this object file // uint32_t arch_align = data.GetU32(&data_offset); // alignment as a power of 2 data_offset += 8; // Skip size and align as we don't need those // Only process this slice if the cpu type/subtype matches if (arch) { ArchSpec fat_arch(eArchTypeMachO, arch_cputype, arch_cpusubtype); if (fat_arch != *arch) continue; } // Create a buffer with only the arch slice date in it DataExtractor arch_data; DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset + arch_offset, 0x1000)); arch_data.SetData(data_buffer_sp); uint32_t arch_data_offset = 0; uint32_t arch_magic = arch_data.GetU32(&arch_data_offset); switch (arch_magic) { case HeaderMagic32: case HeaderMagic32Swapped: case HeaderMagic64: case HeaderMagic64Swapped: if (SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset + arch_offset, arch_data, arch_data_offset, arch_magic)) return true; break; } } 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()); } } } }
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; }
virtual void CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx) { DataExtractor data; const AddressClass address_class = GetAddressClass (); if (m_opcode.GetData(data, address_class)) { char out_string[512]; ::LLVMDisasmContextRef disasm_context; if (address_class == eAddressClassCodeAlternateISA) disasm_context = m_disasm.m_alternate_disasm_context; else disasm_context = m_disasm.m_disasm_context; lldb::addr_t pc = LLDB_INVALID_ADDRESS; if (exe_ctx) { Target *target = exe_ctx->GetTargetPtr(); if (target) pc = m_address.GetLoadAddress(target); } if (pc == LLDB_INVALID_ADDRESS) pc = m_address.GetFileAddress(); m_disasm.Lock(this, exe_ctx); uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (0, 1)); const size_t opcode_data_len = data.GetByteSize(); size_t inst_size = ::LLVMDisasmInstruction (disasm_context, opcode_data, opcode_data_len, pc, out_string, sizeof(out_string)); m_disasm.Unlock(); if (inst_size == 0) { m_comment.assign ("unknown opcode"); inst_size = m_opcode.GetByteSize(); StreamString mnemonic_strm; uint32_t offset = 0; switch (inst_size) { case 1: { const uint8_t uval8 = data.GetU8 (&offset); m_opcode.SetOpcode8 (uval8); 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); 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); 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); m_opcode_name.assign (".quad"); mnemonic_strm.Printf("0x%16.16llx", 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_mnemocics.swap(mnemonic_strm.GetString()); return; } else { if (m_does_branch == eLazyBoolCalculate) { if (StringRepresentsBranch (out_string, strlen(out_string))) m_does_branch = eLazyBoolYes; else m_does_branch = eLazyBoolNo; } } if (!s_regex_compiled) { ::regcomp(&s_regex, "[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED); s_regex_compiled = true; } ::regmatch_t matches[3]; if (!::regexec(&s_regex, out_string, sizeof(matches) / sizeof(::regmatch_t), matches, 0)) { if (matches[1].rm_so != -1) m_opcode_name.assign(out_string + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so); if (matches[2].rm_so != -1) m_mnemocics.assign(out_string + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so); } } }
static bool SkinnyMachOFileContainsArchAndUUID ( const FileSpec &file_spec, const ArchSpec *arch, const lldb_private::UUID *uuid, // the UUID we are looking for off_t file_offset, DataExtractor& data, lldb::offset_t data_offset, const uint32_t magic ) { assert(magic == HeaderMagic32 || magic == HeaderMagic32Swapped || magic == HeaderMagic64 || magic == HeaderMagic64Swapped); if (magic == HeaderMagic32 || magic == HeaderMagic64) data.SetByteOrder (lldb::endian::InlHostByteOrder()); else if (lldb::endian::InlHostByteOrder() == eByteOrderBig) data.SetByteOrder (eByteOrderLittle); else data.SetByteOrder (eByteOrderBig); uint32_t i; const uint32_t cputype = data.GetU32(&data_offset); // cpu specifier const uint32_t cpusubtype = data.GetU32(&data_offset); // machine specifier data_offset+=4; // Skip mach file type const uint32_t ncmds = data.GetU32(&data_offset); // number of load commands const uint32_t sizeofcmds = data.GetU32(&data_offset); // the size of all the load commands data_offset+=4; // Skip flags // Check the architecture if we have a valid arch pointer if (arch) { ArchSpec file_arch(eArchTypeMachO, cputype, cpusubtype); if (!file_arch.IsCompatibleMatch(*arch)) return false; } // The file exists, and if a valid arch pointer was passed in we know // if already matches, so we can return if we aren't looking for a specific // UUID if (uuid == NULL) return true; if (magic == HeaderMagic64Swapped || magic == HeaderMagic64) data_offset += 4; // Skip reserved field for in mach_header_64 // Make sure we have enough data for all the load commands if (magic == HeaderMagic64Swapped || magic == HeaderMagic64) { if (data.GetByteSize() < sizeof(struct mach_header_64) + sizeofcmds) { DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header_64) + sizeofcmds)); data.SetData (data_buffer_sp); } } else { if (data.GetByteSize() < sizeof(struct mach_header) + sizeofcmds) { DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header) + sizeofcmds)); data.SetData (data_buffer_sp); } } for (i=0; i<ncmds; i++) { const lldb::offset_t cmd_offset = data_offset; // Save this data_offset in case parsing of the segment goes awry! uint32_t cmd = data.GetU32(&data_offset); uint32_t cmd_size = data.GetU32(&data_offset); if (cmd == LoadCommandUUID) { lldb_private::UUID file_uuid (data.GetData(&data_offset, 16), 16); if (file_uuid == *uuid) return true; return false; } data_offset = cmd_offset + cmd_size; } return false; }
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; }
void CommunicationKDP::DumpPacket(Stream &s, const DataExtractor &packet) { const char *error_desc = NULL; if (packet.GetByteSize() < 8) { error_desc = "error: invalid packet (too short): "; } else { lldb::offset_t offset = 0; const uint8_t first_packet_byte = packet.GetU8(&offset); const uint8_t sequence_id = packet.GetU8(&offset); const uint16_t length = packet.GetU16(&offset); const uint32_t key = packet.GetU32(&offset); const CommandType command = ExtractCommand(first_packet_byte); const char *command_name = GetCommandAsCString(command); if (command_name) { const bool is_reply = ExtractIsReply(first_packet_byte); s.Printf("(running=%i) %s %24s: 0x%2.2x 0x%2.2x 0x%4.4x 0x%8.8x ", IsRunning(), is_reply ? "<--" : "-->", command_name, first_packet_byte, sequence_id, length, key); if (is_reply) { // Dump request reply packets switch (command) { // Commands that return a single 32 bit error case KDP_CONNECT: case KDP_WRITEMEM: case KDP_WRITEMEM64: case KDP_BREAKPOINT_SET: case KDP_BREAKPOINT_REMOVE: case KDP_BREAKPOINT_SET64: case KDP_BREAKPOINT_REMOVE64: case KDP_WRITEREGS: case KDP_LOAD: case KDP_WRITEIOPORT: case KDP_WRITEMSR64: { const uint32_t error = packet.GetU32(&offset); s.Printf(" (error=0x%8.8x)", error); } break; case KDP_DISCONNECT: case KDP_REATTACH: case KDP_HOSTREBOOT: case KDP_SUSPEND: case KDP_RESUMECPUS: case KDP_EXCEPTION: case KDP_TERMINATION: // No return value for the reply, just the header to ack s.PutCString(" ()"); break; case KDP_HOSTINFO: { const uint32_t cpu_mask = packet.GetU32(&offset); const uint32_t cpu_type = packet.GetU32(&offset); const uint32_t cpu_subtype = packet.GetU32(&offset); s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)", cpu_mask, cpu_type, cpu_subtype); } break; case KDP_VERSION: { const uint32_t version = packet.GetU32(&offset); const uint32_t feature = packet.GetU32(&offset); s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature); } break; case KDP_REGIONS: { const uint32_t region_count = packet.GetU32(&offset); s.Printf(" (count = %u", region_count); for (uint32_t i = 0; i < region_count; ++i) { const addr_t region_addr = packet.GetPointer(&offset); const uint32_t region_size = packet.GetU32(&offset); const uint32_t region_prot = packet.GetU32(&offset); s.Printf("\n\tregion[%" PRIu64 "] = { range = [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), size = 0x%8.8x, prot = %s }", region_addr, region_addr, region_addr + region_size, region_size, GetPermissionsAsCString(region_prot)); } } break; case KDP_READMEM: case KDP_READMEM64: case KDP_READPHYSMEM64: { const uint32_t error = packet.GetU32(&offset); const uint32_t count = packet.GetByteSize() - offset; s.Printf(" (error = 0x%8.8x:\n", error); if (count > 0) DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within "packet" eFormatBytesWithASCII, // Format to use 1, // Size of each item // in bytes count, // Number of items 16, // Number per line m_last_read_memory_addr, // Don't show addresses // before each line 0, 0); // No bitfields } break; case KDP_READREGS: { const uint32_t error = packet.GetU32(&offset); const uint32_t count = packet.GetByteSize() - offset; s.Printf(" (error = 0x%8.8x regs:\n", error); if (count > 0) DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within "packet" eFormatHex, // Format to use m_addr_byte_size, // Size of each item // in bytes count / m_addr_byte_size, // Number of items 16 / m_addr_byte_size, // Number per line LLDB_INVALID_ADDRESS, // Don't // show addresses before // each line 0, 0); // No bitfields } break; case KDP_KERNELVERSION: { const char *kernel_version = packet.PeekCStr(8); s.Printf(" (version = \"%s\")", kernel_version); } break; case KDP_MAXBYTES: { const uint32_t max_bytes = packet.GetU32(&offset); s.Printf(" (max_bytes = 0x%8.8x (%u))", max_bytes, max_bytes); } break; case KDP_IMAGEPATH: { const char *path = packet.GetCStr(&offset); s.Printf(" (path = \"%s\")", path); } break; case KDP_READIOPORT: case KDP_READMSR64: { const uint32_t error = packet.GetU32(&offset); const uint32_t count = packet.GetByteSize() - offset; s.Printf(" (error = 0x%8.8x io:\n", error); if (count > 0) DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within "packet" eFormatHex, // Format to use 1, // Size of each item in bytes count, // Number of items 16, // Number per line LLDB_INVALID_ADDRESS, // Don't show addresses // before each line 0, 0); // No bitfields } break; case KDP_DUMPINFO: { const uint32_t count = packet.GetByteSize() - offset; s.Printf(" (count = %u, bytes = \n", count); if (count > 0) DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within "packet" eFormatHex, // Format to use 1, // Size of each item in // bytes count, // Number of items 16, // Number per line LLDB_INVALID_ADDRESS, // Don't show addresses // before each line 0, 0); // No bitfields } break; default: s.Printf(" (add support for dumping this packet reply!!!"); break; } } else { // Dump request packets switch (command) { case KDP_CONNECT: { const uint16_t reply_port = ntohs(packet.GetU16(&offset)); const uint16_t exc_port = ntohs(packet.GetU16(&offset)); s.Printf(" (reply_port = %u, exc_port = %u, greeting = \"%s\")", reply_port, exc_port, packet.GetCStr(&offset)); } break; case KDP_DISCONNECT: case KDP_HOSTREBOOT: case KDP_HOSTINFO: case KDP_VERSION: case KDP_REGIONS: case KDP_KERNELVERSION: case KDP_MAXBYTES: case KDP_IMAGEPATH: case KDP_SUSPEND: // No args, just the header in the request... s.PutCString(" ()"); break; case KDP_RESUMECPUS: { const uint32_t cpu_mask = packet.GetU32(&offset); s.Printf(" (cpu_mask = 0x%8.8x)", cpu_mask); } break; case KDP_READMEM: { const uint32_t addr = packet.GetU32(&offset); const uint32_t size = packet.GetU32(&offset); s.Printf(" (addr = 0x%8.8x, size = %u)", addr, size); m_last_read_memory_addr = addr; } break; case KDP_WRITEMEM: { const uint32_t addr = packet.GetU32(&offset); const uint32_t size = packet.GetU32(&offset); s.Printf(" (addr = 0x%8.8x, size = %u, bytes = \n", addr, size); if (size > 0) DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); } break; case KDP_READMEM64: { const uint64_t addr = packet.GetU64(&offset); const uint32_t size = packet.GetU32(&offset); s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u)", addr, size); m_last_read_memory_addr = addr; } break; case KDP_READPHYSMEM64: { const uint64_t addr = packet.GetU64(&offset); const uint32_t size = packet.GetU32(&offset); const uint32_t lcpu = packet.GetU16(&offset); s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u)", addr, size, lcpu); m_last_read_memory_addr = addr; } break; case KDP_WRITEMEM64: { const uint64_t addr = packet.GetU64(&offset); const uint32_t size = packet.GetU32(&offset); s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u, bytes = \n", addr, size); if (size > 0) DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); } break; case KDP_WRITEPHYSMEM64: { const uint64_t addr = packet.GetU64(&offset); const uint32_t size = packet.GetU32(&offset); const uint32_t lcpu = packet.GetU16(&offset); s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u, bytes = \n", addr, size, lcpu); if (size > 0) DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); } break; case KDP_READREGS: { const uint32_t cpu = packet.GetU32(&offset); const uint32_t flavor = packet.GetU32(&offset); s.Printf(" (cpu = %u, flavor = %u)", cpu, flavor); } break; case KDP_WRITEREGS: { const uint32_t cpu = packet.GetU32(&offset); const uint32_t flavor = packet.GetU32(&offset); const uint32_t nbytes = packet.GetByteSize() - offset; s.Printf(" (cpu = %u, flavor = %u, regs = \n", cpu, flavor); if (nbytes > 0) DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within // "packet" eFormatHex, // Format to use m_addr_byte_size, // Size of each item in // bytes nbytes / m_addr_byte_size, // Number of items 16 / m_addr_byte_size, // Number per line LLDB_INVALID_ADDRESS, // Don't show addresses // before each line 0, 0); // No bitfields } break; case KDP_BREAKPOINT_SET: case KDP_BREAKPOINT_REMOVE: { const uint32_t addr = packet.GetU32(&offset); s.Printf(" (addr = 0x%8.8x)", addr); } break; case KDP_BREAKPOINT_SET64: case KDP_BREAKPOINT_REMOVE64: { const uint64_t addr = packet.GetU64(&offset); s.Printf(" (addr = 0x%16.16" PRIx64 ")", addr); } break; case KDP_LOAD: { const char *path = packet.GetCStr(&offset); s.Printf(" (path = \"%s\")", path); } break; case KDP_EXCEPTION: { const uint32_t count = packet.GetU32(&offset); for (uint32_t i = 0; i < count; ++i) { const uint32_t cpu = packet.GetU32(&offset); const uint32_t exc = packet.GetU32(&offset); const uint32_t code = packet.GetU32(&offset); const uint32_t subcode = packet.GetU32(&offset); const char *exc_cstr = NULL; switch (exc) { case 1: exc_cstr = "EXC_BAD_ACCESS"; break; case 2: exc_cstr = "EXC_BAD_INSTRUCTION"; break; case 3: exc_cstr = "EXC_ARITHMETIC"; break; case 4: exc_cstr = "EXC_EMULATION"; break; case 5: exc_cstr = "EXC_SOFTWARE"; break; case 6: exc_cstr = "EXC_BREAKPOINT"; break; case 7: exc_cstr = "EXC_SYSCALL"; break; case 8: exc_cstr = "EXC_MACH_SYSCALL"; break; case 9: exc_cstr = "EXC_RPC_ALERT"; break; case 10: exc_cstr = "EXC_CRASH"; break; default: break; } s.Printf("{ cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), " "subcode = %u (0x%8.8x)} ", cpu, exc_cstr, exc, code, code, subcode, subcode); } } break; case KDP_TERMINATION: { const uint32_t term_code = packet.GetU32(&offset); const uint32_t exit_code = packet.GetU32(&offset); s.Printf(" (term_code = 0x%8.8x (%u), exit_code = 0x%8.8x (%u))", term_code, term_code, exit_code, exit_code); } break; case KDP_REATTACH: { const uint16_t reply_port = ntohs(packet.GetU16(&offset)); s.Printf(" (reply_port = %u)", reply_port); } break; case KDP_READMSR64: { const uint32_t address = packet.GetU32(&offset); const uint16_t lcpu = packet.GetU16(&offset); s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x)", address, lcpu); } break; case KDP_WRITEMSR64: { const uint32_t address = packet.GetU32(&offset); const uint16_t lcpu = packet.GetU16(&offset); const uint32_t nbytes = packet.GetByteSize() - offset; s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x, nbytes=0x%8.8x)", lcpu, address, nbytes); if (nbytes > 0) DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within "packet" eFormatHex, // Format to use 1, // Size of each item in // bytes nbytes, // Number of items 16, // Number per line LLDB_INVALID_ADDRESS, // Don't show addresses // before each line 0, 0); // No bitfields } break; case KDP_READIOPORT: { const uint16_t lcpu = packet.GetU16(&offset); const uint16_t address = packet.GetU16(&offset); const uint16_t nbytes = packet.GetU16(&offset); s.Printf(" (lcpu=0x%4.4x, address=0x%4.4x, nbytes=%u)", lcpu, address, nbytes); } break; case KDP_WRITEIOPORT: { const uint16_t lcpu = packet.GetU16(&offset); const uint16_t address = packet.GetU16(&offset); const uint16_t nbytes = packet.GetU16(&offset); s.Printf(" (lcpu = %u, addr = 0x%4.4x, nbytes = %u, bytes = \n", lcpu, address, nbytes); if (nbytes > 0) DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within "packet" eFormatHex, // Format to use 1, // Size of each item in // bytes nbytes, // Number of items 16, // Number per line LLDB_INVALID_ADDRESS, // Don't show addresses // before each line 0, 0); // No bitfields } break; case KDP_DUMPINFO: { const uint32_t count = packet.GetByteSize() - offset; s.Printf(" (count = %u, bytes = \n", count); if (count > 0) DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within "packet" eFormatHex, // Format to use 1, // Size of each item in bytes count, // Number of items 16, // Number per line LLDB_INVALID_ADDRESS, // Don't show addresses before each line 0, 0); // No bitfields } break; } } } else { error_desc = "error: invalid packet command: "; } } if (error_desc) { s.PutCString(error_desc); DumpDataExtractor(packet, &s, // Stream to dump to 0, // Offset into "packet" eFormatBytes, // Dump as hex bytes 1, // Size of each item is 1 for // single bytes packet.GetByteSize(), // Number of bytes UINT32_MAX, // Num bytes per line LLDB_INVALID_ADDRESS, // Base address 0, 0); // Bitfield info set to not do // anything bitfield related } }