static bool DumpUInt (ExecutionContextScope *exe_scope, const Address &address, uint32_t byte_size, Stream* strm) { if (exe_scope == NULL || byte_size == 0) return 0; std::vector<uint8_t> buf(byte_size, 0); if (ReadBytes (exe_scope, address, &buf[0], buf.size()) == buf.size()) { ByteOrder byte_order = eByteOrderInvalid; uint32_t addr_size = 0; if (GetByteOrderAndAddressSize (exe_scope, address, byte_order, addr_size)) { DataExtractor data (&buf.front(), buf.size(), byte_order, addr_size); data.Dump (strm, 0, // Start offset in "data" eFormatHex, // Print as characters buf.size(), // Size of item 1, // Items count UINT32_MAX, // num per line LLDB_INVALID_ADDRESS,// base address 0, // bitfield bit size 0); // bitfield bit offset return true; } } return false; }
bool RegisterValue::Dump(Stream *s, const RegisterInfo *reg_info, bool prefix_with_name, bool prefix_with_alt_name, Format format, uint32_t reg_name_right_align_at) const { DataExtractor data; if (GetData(data)) { bool name_printed = false; // For simplicity, alignment of the register name printing applies only // in the most common case where: // // prefix_with_name^prefix_with_alt_name is true // StreamString format_string; if (reg_name_right_align_at && (prefix_with_name ^ prefix_with_alt_name)) format_string.Printf("%%%us", reg_name_right_align_at); else format_string.Printf("%%s"); const char *fmt = format_string.GetData(); if (prefix_with_name) { if (reg_info->name) { s->Printf(fmt, reg_info->name); name_printed = true; } else if (reg_info->alt_name) { s->Printf(fmt, reg_info->alt_name); prefix_with_alt_name = false; name_printed = true; } } if (prefix_with_alt_name) { if (name_printed) s->PutChar('/'); if (reg_info->alt_name) { s->Printf(fmt, reg_info->alt_name); name_printed = true; } else if (!name_printed) { // No alternate name but we were asked to display a name, so show the // main name s->Printf(fmt, reg_info->name); name_printed = true; } } if (name_printed) s->PutCString(" = "); if (format == eFormatDefault) format = reg_info->format; data.Dump(s, 0, // Offset in "data" format, // Format to use when dumping reg_info->byte_size, // item_byte_size 1, // item_count UINT32_MAX, // num_per_line LLDB_INVALID_ADDRESS, // base_addr 0, // item_bit_size 0); // item_bit_offset return true; } return false; }
void EventDataBytes::Dump(Stream *s) const { size_t num_printable_chars = std::count_if(m_bytes.begin(), m_bytes.end(), isprint); if (num_printable_chars == m_bytes.size()) { s->Printf("\"%s\"", m_bytes.c_str()); } else if (!m_bytes.empty()) { DataExtractor data; data.SetData(m_bytes.data(), m_bytes.size(), endian::InlHostByteOrder()); data.Dump(s, 0, eFormatBytes, 1, m_bytes.size(), 32, LLDB_INVALID_ADDRESS, 0, 0); } }
static size_t ReadCStringFromMemory (ExecutionContextScope *exe_scope, const Address &address, Stream *strm) { if (exe_scope == NULL) return 0; const size_t k_buf_len = 256; char buf[k_buf_len+1]; buf[k_buf_len] = '\0'; // NULL terminate // Byte order and address size don't matter for C string dumping.. DataExtractor data (buf, sizeof(buf), endian::InlHostByteOrder(), 4); size_t total_len = 0; size_t bytes_read; Address curr_address(address); strm->PutChar ('"'); while ((bytes_read = ReadBytes (exe_scope, curr_address, buf, k_buf_len)) > 0) { size_t len = strlen(buf); if (len == 0) break; if (len > bytes_read) len = bytes_read; data.Dump (strm, 0, // Start offset in "data" eFormatChar, // Print as characters 1, // Size of item (1 byte for a char!) len, // How many bytes to print? UINT32_MAX, // num per line LLDB_INVALID_ADDRESS,// base address 0, // bitfield bit size 0); // bitfield bit offset total_len += bytes_read; if (len < k_buf_len) break; curr_address.SetOffset (curr_address.GetOffset() + bytes_read); } strm->PutChar ('"'); return total_len; }
bool TypeFormatImpl_Format::FormatObject (ValueObject *valobj, std::string& dest) const { if (!valobj) return false; if (valobj->CanProvideValue()) { Value& value(valobj->GetValue()); const Value::ContextType context_type = value.GetContextType(); ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); DataExtractor data; if (context_type == Value::eContextTypeRegisterInfo) { const RegisterInfo *reg_info = value.GetRegisterInfo(); if (reg_info) { Error error; valobj->GetData(data, error); if (error.Fail()) return false; StreamString reg_sstr; data.Dump (®_sstr, 0, GetFormat(), reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0, exe_ctx.GetBestExecutionContextScope()); dest.swap(reg_sstr.GetString()); } } else { CompilerType compiler_type = value.GetCompilerType (); if (compiler_type) { // put custom bytes to display in the DataExtractor to override the default value logic if (GetFormat() == eFormatCString) { lldb_private::Flags type_flags(compiler_type.GetTypeInfo(NULL)); // disambiguate w.r.t. TypeFormatImpl::Flags if (type_flags.Test(eTypeIsPointer) && !type_flags.Test(eTypeIsObjC)) { // if we are dumping a pointer as a c-string, get the pointee data as a string TargetSP target_sp(valobj->GetTargetSP()); if (target_sp) { size_t max_len = target_sp->GetMaximumSizeOfStringSummary(); Error error; DataBufferSP buffer_sp(new DataBufferHeap(max_len+1,0)); Address address(valobj->GetPointerValue()); if (target_sp->ReadCStringFromMemory(address, (char*)buffer_sp->GetBytes(), max_len, error) && error.Success()) data.SetData(buffer_sp); } } } else { Error error; valobj->GetData(data, error); if (error.Fail()) return false; } StreamString sstr; compiler_type.DumpTypeValue (&sstr, // The stream to use for display GetFormat(), // Format to display this type with data, // Data to extract from 0, // Byte offset into "m_data" valobj->GetByteSize(), // Byte size of item in "m_data" valobj->GetBitfieldBitSize(), // Bitfield bit size valobj->GetBitfieldBitOffset(), // Bitfield bit offset exe_ctx.GetBestExecutionContextScope()); // Given that we do not want to set the ValueObject's m_error // for a formatting error (or else we wouldn't be able to reformat // until a next update), an empty string is treated as a "false" // return from here, but that's about as severe as we get // CompilerType::DumpTypeValue() should always return // something, even if that something is an error message if (sstr.GetString().empty()) dest.clear(); else dest.swap(sstr.GetString()); } } return !dest.empty(); } else return false; }
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 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; uint32_t generic_regnum = LLDB_INVALID_REGNUM; if (context.info_type == EmulateInstruction::eInfoTypeRegisterToRegisterPlusOffset) { const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind(); reg_num = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[unwind_reg_kind]; generic_regnum = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[eRegisterKindGeneric]; } else assert (!"unhandled case, add code to handle this!"); if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP) { 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; } } } break; } return dst_len; }
virtual bool Execute (Args& command, CommandReturnObject &result) { Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; if (process == NULL) { result.AppendError("need a process to read memory"); result.SetStatus(eReturnStatusFailed); return false; } const size_t argc = command.GetArgumentCount(); if (argc == 0 || argc > 2) { result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); return false; } size_t item_byte_size = m_options.m_byte_size; if (item_byte_size == 0) { if (m_options.m_format == eFormatPointer) item_byte_size = process->GetTarget().GetArchitecture().GetAddressByteSize(); else item_byte_size = 1; } size_t item_count = m_options.m_count; size_t num_per_line = m_options.m_num_per_line; if (num_per_line == 0) { num_per_line = (16/item_byte_size); if (num_per_line == 0) num_per_line = 1; } size_t total_byte_size = m_options.m_count * item_byte_size; if (total_byte_size == 0) total_byte_size = 32; lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0); if (addr == LLDB_INVALID_ADDRESS) { result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0)); result.SetStatus(eReturnStatusFailed); return false; } if (argc == 2) { lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); if (end_addr == LLDB_INVALID_ADDRESS) { result.AppendErrorWithFormat("Invalid end address string '%s'.\n", command.GetArgumentAtIndex(1)); result.SetStatus(eReturnStatusFailed); return false; } else if (end_addr <= addr) { result.AppendErrorWithFormat("End address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr); result.SetStatus(eReturnStatusFailed); return false; } else if (item_count != 0) { result.AppendErrorWithFormat("Specify either the end address (0x%llx) or the count (--count %u), not both.\n", end_addr, item_count); result.SetStatus(eReturnStatusFailed); return false; } total_byte_size = end_addr - addr; item_count = total_byte_size / item_byte_size; } else { if (item_count == 0) item_count = 32; } DataBufferSP data_sp(new DataBufferHeap (total_byte_size, '\0')); Error error; size_t bytes_read = process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error); if (bytes_read == 0) { result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr); result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); return false; } if (bytes_read < total_byte_size) result.AppendWarningWithFormat("Not all bytes (%u/%u) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr); result.SetStatus(eReturnStatusSuccessFinishResult); DataExtractor data (data_sp, process->GetTarget().GetArchitecture().GetByteOrder(), process->GetTarget().GetArchitecture().GetAddressByteSize()); StreamFile outfile_stream; Stream *output_stream = NULL; if (m_options.m_outfile_filespec) { char path[PATH_MAX]; m_options.m_outfile_filespec.GetPath (path, sizeof(path)); char mode[16] = { 'w', '\0' }; if (m_options.m_append_to_outfile) mode[0] = 'a'; if (outfile_stream.GetFile ().Open (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success()) { if (m_options.m_output_as_binary) { int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); if (bytes_written > 0) { result.GetOutputStream().Printf ("%i bytes %s to '%s'\n", bytes_written, m_options.m_append_to_outfile ? "appended" : "written", path); return true; } else { result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path); result.SetStatus(eReturnStatusFailed); return false; } } else { // We are going to write ASCII to the file just point the // output_stream to our outfile_stream... output_stream = &outfile_stream; } } else { result.AppendErrorWithFormat("Failed to open file '%s' with a mode of '%s'.\n", path, mode); result.SetStatus(eReturnStatusFailed); return false; } } else { output_stream = &result.GetOutputStream(); } assert (output_stream); data.Dump (output_stream, 0, m_options.m_format, item_byte_size, item_count, num_per_line, addr, 0, 0); output_stream->EOL(); return true; }
bool GoASTContext::DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format, const DataExtractor &data, lldb::offset_t byte_offset, size_t byte_size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope, bool is_base_class) { if (!type) return false; if (IsAggregateType(type)) { return false; } else { GoType *t = static_cast<GoType *>(type); if (t->IsTypedef()) { CompilerType typedef_compiler_type = t->GetElementType(); if (format == eFormatDefault) format = typedef_compiler_type.GetFormat(); uint64_t typedef_byte_size = typedef_compiler_type.GetByteSize(exe_scope); return typedef_compiler_type.DumpTypeValue( s, format, // The format with which to display the element data, // Data buffer containing all bytes for this type byte_offset, // Offset into "data" where to grab value from typedef_byte_size, // Size of this type in bytes bitfield_bit_size, // Size in bits of a bitfield value, if zero don't treat as a bitfield bitfield_bit_offset, // Offset in bits of a bitfield value if bitfield_bit_size != 0 exe_scope, is_base_class); } uint32_t item_count = 1; // A few formats, we might need to modify our size and count for depending // on how we are trying to display the value... switch (format) { default: case eFormatBoolean: case eFormatBinary: case eFormatComplex: case eFormatCString: // NULL terminated C strings case eFormatDecimal: case eFormatEnum: case eFormatHex: case eFormatHexUppercase: case eFormatFloat: case eFormatOctal: case eFormatOSType: case eFormatUnsigned: case eFormatPointer: case eFormatVectorOfChar: case eFormatVectorOfSInt8: case eFormatVectorOfUInt8: case eFormatVectorOfSInt16: case eFormatVectorOfUInt16: case eFormatVectorOfSInt32: case eFormatVectorOfUInt32: case eFormatVectorOfSInt64: case eFormatVectorOfUInt64: case eFormatVectorOfFloat32: case eFormatVectorOfFloat64: case eFormatVectorOfUInt128: break; case eFormatChar: case eFormatCharPrintable: case eFormatCharArray: case eFormatBytes: case eFormatBytesWithASCII: item_count = byte_size; byte_size = 1; break; case eFormatUnicode16: item_count = byte_size / 2; byte_size = 2; break; case eFormatUnicode32: item_count = byte_size / 4; byte_size = 4; break; } return data.Dump(s, byte_offset, format, byte_size, item_count, UINT32_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size, bitfield_bit_offset, exe_scope); } return 0; }
const char * ValueObject::GetSummaryAsCString (ExecutionContextScope *exe_scope) { if (UpdateValueIfNeeded (exe_scope)) { if (m_summary_str.empty()) { void *clang_type = GetOpaqueClangQualType(); // See if this is a pointer to a C string? uint32_t fixed_length = 0; if (clang_type && ClangASTContext::IsCStringType (clang_type, fixed_length)) { Process *process = exe_scope->CalculateProcess(); if (process != NULL) { StreamString sstr; lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS; lldb::AddressType cstr_address_type = eAddressTypeInvalid; switch (GetValue().GetValueType()) { case Value::eValueTypeScalar: cstr_address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); cstr_address_type = eAddressTypeLoad; break; case Value::eValueTypeLoadAddress: case Value::eValueTypeFileAddress: case Value::eValueTypeHostAddress: { uint32_t data_offset = 0; cstr_address = m_data.GetPointer(&data_offset); cstr_address_type = m_value.GetValueAddressType(); if (cstr_address_type == eAddressTypeInvalid) cstr_address_type = eAddressTypeLoad; } break; } if (cstr_address != LLDB_INVALID_ADDRESS) { DataExtractor data; size_t bytes_read = 0; std::vector<char> data_buffer; std::vector<char> cstr_buffer; size_t cstr_length; Error error; if (fixed_length > 0) { data_buffer.resize(fixed_length); // Resize the formatted buffer in case every character // uses the "\xXX" format and one extra byte for a NULL cstr_buffer.resize(data_buffer.size() * 4 + 1); data.SetData (data_buffer.data(), data_buffer.size(), eByteOrderHost); bytes_read = process->ReadMemory (cstr_address, data_buffer.data(), fixed_length, error); if (bytes_read > 0) { sstr << '"'; cstr_length = data.Dump (&sstr, 0, // Start offset in "data" eFormatChar, // Print as characters 1, // Size of item (1 byte for a char!) bytes_read, // How many bytes to print? UINT32_MAX, // num per line LLDB_INVALID_ADDRESS,// base address 0, // bitfield bit size 0); // bitfield bit offset sstr << '"'; } } else { const size_t k_max_buf_size = 256; data_buffer.resize (k_max_buf_size + 1); // NULL terminate in case we don't get the entire C string data_buffer.back() = '\0'; // Make a formatted buffer that can contain take 4 // bytes per character in case each byte uses the // "\xXX" format and one extra byte for a NULL cstr_buffer.resize (k_max_buf_size * 4 + 1); data.SetData (data_buffer.data(), data_buffer.size(), eByteOrderHost); size_t total_cstr_len = 0; while ((bytes_read = process->ReadMemory (cstr_address, data_buffer.data(), k_max_buf_size, error)) > 0) { size_t len = strlen(data_buffer.data()); if (len == 0) break; if (len > bytes_read) len = bytes_read; if (sstr.GetSize() == 0) sstr << '"'; cstr_length = data.Dump (&sstr, 0, // Start offset in "data" eFormatChar, // Print as characters 1, // Size of item (1 byte for a char!) len, // How many bytes to print? UINT32_MAX, // num per line LLDB_INVALID_ADDRESS,// base address 0, // bitfield bit size 0); // bitfield bit offset if (len < k_max_buf_size) break; cstr_address += total_cstr_len; } if (sstr.GetSize() > 0) sstr << '"'; } if (sstr.GetSize() > 0) m_summary_str.assign (sstr.GetData(), sstr.GetSize()); } } } } } if (m_summary_str.empty()) return NULL; return m_summary_str.c_str(); }
virtual bool DoExecute (Args& command, CommandReturnObject &result) { ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); Target *target = exe_ctx.GetTargetPtr(); if (target == NULL) { result.AppendError("need at least a target to read memory"); result.SetStatus(eReturnStatusFailed); return false; } const size_t argc = command.GetArgumentCount(); if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2) { result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); return false; } ClangASTType clang_ast_type; Error error; Format format = m_format_options.GetFormat(); const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue(); if (view_as_type_cstr && view_as_type_cstr[0]) { // We are viewing memory as a type SymbolContext sc; const bool exact_match = false; TypeList type_list; uint32_t reference_count = 0; uint32_t pointer_count = 0; size_t idx; #define ALL_KEYWORDS \ KEYWORD("const") \ KEYWORD("volatile") \ KEYWORD("restrict") \ KEYWORD("struct") \ KEYWORD("class") \ KEYWORD("union") #define KEYWORD(s) s, static const char *g_keywords[] = { ALL_KEYWORDS }; #undef KEYWORD #define KEYWORD(s) (sizeof(s) - 1), static const int g_keyword_lengths[] = { ALL_KEYWORDS }; #undef KEYWORD #undef ALL_KEYWORDS static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *); std::string type_str(view_as_type_cstr); // Remove all instances of g_keywords that are followed by spaces for (size_t i = 0; i < g_num_keywords; ++i) { const char *keyword = g_keywords[i]; int keyword_len = g_keyword_lengths[i]; idx = 0; while ((idx = type_str.find (keyword, idx)) != std::string::npos) { if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t') { type_str.erase(idx, keyword_len+1); idx = 0; } else { idx += keyword_len; } } } bool done = type_str.empty(); // idx = type_str.find_first_not_of (" \t"); if (idx > 0 && idx != std::string::npos) type_str.erase (0, idx); while (!done) { // Strip trailing spaces if (type_str.empty()) done = true; else { switch (type_str[type_str.size()-1]) { case '*': ++pointer_count; // fall through... case ' ': case '\t': type_str.erase(type_str.size()-1); break; case '&': if (reference_count == 0) { reference_count = 1; type_str.erase(type_str.size()-1); } else { result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr); result.SetStatus(eReturnStatusFailed); return false; } break; default: done = true; break; } } } ConstString lookup_type_name(type_str.c_str()); StackFrame *frame = exe_ctx.GetFramePtr(); if (frame) { sc = frame->GetSymbolContext (eSymbolContextModule); if (sc.module_sp) { sc.module_sp->FindTypes (sc, lookup_type_name, exact_match, 1, type_list); } } if (type_list.GetSize() == 0) { target->GetImages().FindTypes (sc, lookup_type_name, exact_match, 1, type_list); } if (type_list.GetSize() == 0) { result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n", lookup_type_name.GetCString(), view_as_type_cstr); result.SetStatus(eReturnStatusFailed); return false; } TypeSP type_sp (type_list.GetTypeAtIndex(0)); clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType()); while (pointer_count > 0) { clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType()); if (pointer_type) clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type); else { result.AppendError ("unable make a pointer type\n"); result.SetStatus(eReturnStatusFailed); return false; } --pointer_count; } m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8; if (m_format_options.GetByteSizeValue() == 0) { result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n", view_as_type_cstr); result.SetStatus(eReturnStatusFailed); return false; } if (!m_format_options.GetCountValue().OptionWasSet()) m_format_options.GetCountValue() = 1; } else { error = m_memory_options.FinalizeSettings (target, m_format_options); } // Look for invalid combinations of settings if (error.Fail()) { result.AppendErrorWithFormat("%s", error.AsCString()); result.SetStatus(eReturnStatusFailed); return false; } lldb::addr_t addr; size_t total_byte_size = 0; if (argc == 0) { // Use the last address and byte size and all options as they were // if no options have been set addr = m_next_addr; total_byte_size = m_prev_byte_size; if (!m_format_options.AnyOptionWasSet() && !m_memory_options.AnyOptionWasSet() && !m_outfile_options.AnyOptionWasSet() && !m_varobj_options.AnyOptionWasSet()) { m_format_options = m_prev_format_options; m_memory_options = m_prev_memory_options; m_outfile_options = m_prev_outfile_options; m_varobj_options = m_prev_varobj_options; } } size_t item_count = m_format_options.GetCountValue().GetCurrentValue(); const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue(); if (total_byte_size == 0) { total_byte_size = item_count * item_byte_size; if (total_byte_size == 0) total_byte_size = 32; } if (argc > 0) addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0); if (addr == LLDB_INVALID_ADDRESS) { result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0)); result.SetStatus(eReturnStatusFailed); return false; } if (argc == 2) { lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); if (end_addr == LLDB_INVALID_ADDRESS) { result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1)); result.SetStatus(eReturnStatusFailed); return false; } else if (end_addr <= addr) { result.AppendErrorWithFormat("end address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr); result.SetStatus(eReturnStatusFailed); return false; } else if (m_format_options.GetCountValue().OptionWasSet()) { result.AppendErrorWithFormat("specify either the end address (0x%llx) or the count (--count %lu), not both.\n", end_addr, item_count); result.SetStatus(eReturnStatusFailed); return false; } total_byte_size = end_addr - addr; item_count = total_byte_size / item_byte_size; } if (total_byte_size > 1024 && !m_memory_options.m_force) { result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n"); result.AppendErrorWithFormat("Please use --force to override this restriction.\n"); return false; } DataBufferSP data_sp; size_t bytes_read = 0; if (!clang_ast_type.GetOpaqueQualType()) { data_sp.reset (new DataBufferHeap (total_byte_size, '\0')); Address address(addr, NULL); bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error); if (bytes_read == 0) { const char *error_cstr = error.AsCString(); if (error_cstr && error_cstr[0]) { result.AppendError(error_cstr); } else { result.AppendErrorWithFormat("failed to read memory from 0x%llx.\n", addr); } result.SetStatus(eReturnStatusFailed); return false; } if (bytes_read < total_byte_size) result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr); else { m_next_addr = addr + bytes_read; m_prev_byte_size = bytes_read; m_prev_format_options = m_format_options; m_prev_memory_options = m_memory_options; m_prev_outfile_options = m_outfile_options; m_prev_varobj_options = m_varobj_options; } } StreamFile outfile_stream; Stream *output_stream = NULL; const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); if (outfile_spec) { char path[PATH_MAX]; outfile_spec.GetPath (path, sizeof(path)); uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; const bool append = m_outfile_options.GetAppend().GetCurrentValue(); if (append) open_options |= File::eOpenOptionAppend; if (outfile_stream.GetFile ().Open (path, open_options).Success()) { if (m_memory_options.m_output_as_binary) { int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); if (bytes_written > 0) { result.GetOutputStream().Printf ("%i bytes %s to '%s'\n", bytes_written, append ? "appended" : "written", path); return true; } else { result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path); result.SetStatus(eReturnStatusFailed); return false; } } else { // We are going to write ASCII to the file just point the // output_stream to our outfile_stream... output_stream = &outfile_stream; } } else { result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write"); result.SetStatus(eReturnStatusFailed); return false; } } else { output_stream = &result.GetOutputStream(); } ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope(); if (clang_ast_type.GetOpaqueQualType()) { for (uint32_t i = 0; i<item_count; ++i) { addr_t item_addr = addr + (i * item_byte_size); Address address (item_addr); StreamString name_strm; name_strm.Printf ("0x%llx", item_addr); ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope, name_strm.GetString().c_str(), address, clang_ast_type)); if (valobj_sp) { if (format != eFormatDefault) valobj_sp->SetFormat (format); bool scope_already_checked = true; ValueObject::DumpValueObjectOptions options; options.SetMaximumPointerDepth(m_varobj_options.ptr_depth) .SetMaximumDepth(m_varobj_options.max_depth) .SetShowLocation(m_varobj_options.show_location) .SetShowTypes(m_varobj_options.show_types) .SetUseObjectiveC(m_varobj_options.use_objc) .SetScopeChecked(scope_already_checked) .SetFlatOutput(m_varobj_options.flat_output) .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth) .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth) .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap) .SetFormat(format) .SetSummary(); ValueObject::DumpValueObject (*output_stream, valobj_sp.get(), options); } else { result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", view_as_type_cstr, name_strm.GetString().c_str()); result.SetStatus(eReturnStatusFailed); return false; } } return true; } result.SetStatus(eReturnStatusSuccessFinishResult); DataExtractor data (data_sp, target->GetArchitecture().GetByteOrder(), target->GetArchitecture().GetAddressByteSize()); assert (output_stream); uint32_t bytes_dumped = data.Dump (output_stream, 0, m_format_options.GetFormat(), item_byte_size, item_count, num_per_line, addr, 0, 0, exe_scope); m_next_addr = addr + bytes_dumped; output_stream->EOL(); 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 { uint32_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: { 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: { 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) packet.Dump (&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) packet.Dump (&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; 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 = packet.GetU16 (&offset); const uint16_t exc_port = 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) DataExtractor::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_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) DataExtractor::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) packet.Dump (&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 = packet.GetU16 (&offset); s.Printf(" (reply_port = %u)", reply_port); } break; } } } else { error_desc = "error: invalid packet command: "; } } if (error_desc) { s.PutCString (error_desc); packet.Dump (&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 } }