void Options::OutputFormattedUsageText(Stream &strm, const OptionDefinition &option_def, uint32_t output_max_columns) { std::string actual_text; if (option_def.validator) { const char *condition = option_def.validator->ShortConditionString(); if (condition) { actual_text = "["; actual_text.append(condition); actual_text.append("] "); } } actual_text.append(option_def.usage_text); // Will it all fit on one line? if (static_cast<uint32_t>(actual_text.length() + strm.GetIndentLevel()) < output_max_columns) { // Output it as a single line. strm.Indent(actual_text.c_str()); strm.EOL(); } else { // We need to break it up into multiple lines. int text_width = output_max_columns - strm.GetIndentLevel() - 1; int start = 0; int end = start; int final_end = actual_text.length(); int sub_len; while (end < final_end) { // Don't start the 'text' on a space, since we're already outputting the // indentation. while ((start < final_end) && (actual_text[start] == ' ')) start++; end = start + text_width; if (end > final_end) end = final_end; else { // If we're not at the end of the text, make sure we break the line on // white space. while (end > start && actual_text[end] != ' ' && actual_text[end] != '\t' && actual_text[end] != '\n') end--; } sub_len = end - start; if (start != 0) strm.EOL(); strm.Indent(); assert(start < final_end); assert(start + sub_len <= final_end); strm.Write(actual_text.c_str() + start, sub_len); start = end + 1; } strm.EOL(); } }
void Options::OutputFormattedUsageText ( Stream &strm, const char *text, uint32_t output_max_columns ) { int len = strlen (text); // Will it all fit on one line? if (static_cast<uint32_t>(len + strm.GetIndentLevel()) < output_max_columns) { // Output it as a single line. strm.Indent (text); strm.EOL(); } else { // We need to break it up into multiple lines. int text_width = output_max_columns - strm.GetIndentLevel() - 1; int start = 0; int end = start; int final_end = strlen (text); int sub_len; while (end < final_end) { // Don't start the 'text' on a space, since we're already outputting the indentation. while ((start < final_end) && (text[start] == ' ')) start++; end = start + text_width; if (end > final_end) end = final_end; else { // If we're not at the end of the text, make sure we break the line on white space. while (end > start && text[end] != ' ' && text[end] != '\t' && text[end] != '\n') end--; } sub_len = end - start; if (start != 0) strm.EOL(); strm.Indent(); assert (start < final_end); assert (start + sub_len <= final_end); strm.Write(text + start, sub_len); start = end + 1; } strm.EOL(); } }
bool DumpRegister(const ExecutionContext &exe_ctx, Stream &strm, RegisterContext *reg_ctx, const RegisterInfo *reg_info) { if (reg_info) { RegisterValue reg_value; if (reg_ctx->ReadRegister(reg_info, reg_value)) { strm.Indent(); bool prefix_with_altname = (bool)m_command_options.alternate_name; bool prefix_with_name = !prefix_with_altname; reg_value.Dump(&strm, reg_info, prefix_with_name, prefix_with_altname, m_format_options.GetFormat(), 8); if ((reg_info->encoding == eEncodingUint) || (reg_info->encoding == eEncodingSint)) { Process *process = exe_ctx.GetProcessPtr(); if (process && reg_info->byte_size == process->GetAddressByteSize()) { addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS); if (reg_addr != LLDB_INVALID_ADDRESS) { Address so_reg_addr; if (exe_ctx.GetTargetRef() .GetSectionLoadList() .ResolveLoadAddress(reg_addr, so_reg_addr)) { strm.PutCString(" "); so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription); } } } } strm.EOL(); return true; } } return false; }
void Property::Dump (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) const { if (m_value_sp) { const bool dump_desc = dump_mask & OptionValue::eDumpOptionDescription; const bool transparent = m_value_sp->ValueIsTransparent (); if (dump_desc || !transparent) { if ((dump_mask & OptionValue::eDumpOptionName) && m_name) { DumpQualifiedName(strm); if (dump_mask & ~OptionValue::eDumpOptionName) strm.PutChar(' '); } } if (dump_desc) { const char *desc = GetDescription(); if (desc) strm.Printf ("-- %s", desc); if (transparent && (dump_mask == (OptionValue::eDumpOptionName | OptionValue::eDumpOptionDescription))) strm.EOL(); } m_value_sp->DumpValue(exe_ctx, strm, dump_mask); } }
void StructuredData::Array::Dump(Stream &s, bool pretty_print) const { bool first = true; s << "["; if (pretty_print) { s << "\n"; s.IndentMore(); } for (const auto &item_sp : m_items) { if (first) { first = false; } else { s << ","; if (pretty_print) s << "\n"; } if (pretty_print) s.Indent(); item_sp->Dump(s, pretty_print); } if (pretty_print) { s.IndentLess(); s.EOL(); s.Indent(); } s << "]"; }
void StructuredData::Dictionary::Dump(Stream &s, bool pretty_print) const { bool first = true; s << "{"; if (pretty_print) { s << "\n"; s.IndentMore(); } for (const auto &pair : m_dict) { if (first) first = false; else { s << ","; if (pretty_print) s << "\n"; } if (pretty_print) s.Indent(); s << "\"" << pair.first.AsCString() << "\" : "; pair.second->Dump(s, pretty_print); } if (pretty_print) { s.IndentLess(); s.EOL(); s.Indent(); } s << "}"; }
void UnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, addr_t base_addr) const { const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo (thread, GetCFARegister()); if (base_addr != LLDB_INVALID_ADDRESS) s.Printf ("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset()); else s.Printf ("0x%8.8" PRIx64 ": CFA=", GetOffset()); if (reg_info) s.Printf ("%s", reg_info->name); else s.Printf ("reg(%u)", GetCFARegister()); s.Printf ("%+3d => ", GetCFAOffset ()); for (collection::const_iterator idx = m_register_locations.begin (); idx != m_register_locations.end (); ++idx) { reg_info = unwind_plan->GetRegisterInfo (thread, idx->first); if (reg_info) s.Printf ("%s", reg_info->name); else s.Printf ("reg(%u)", idx->first); const bool verbose = false; idx->second.Dump(s, unwind_plan, this, thread, verbose); s.PutChar (' '); } s.EOL(); }
size_t Disassembler::Disassemble ( Debugger &debugger, const ArchSpec &arch, const ExecutionContext &exe_ctx, SymbolContextList &sc_list, uint32_t num_mixed_context_lines, bool show_bytes, Stream &strm ) { size_t success_count = 0; const size_t count = sc_list.GetSize(); SymbolContext sc; AddressRange range; for (size_t i=0; i<count; ++i) { if (sc_list.GetContextAtIndex(i, sc) == false) break; if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range)) { if (Disassemble (debugger, arch, exe_ctx, range, num_mixed_context_lines, show_bytes, strm)) { ++success_count; strm.EOL(); } } } return success_count; }
void UnwindPlan::Dump (Stream& s, Thread *thread, lldb::addr_t base_addr) const { if (!m_source_name.IsEmpty()) { s.Printf ("This UnwindPlan originally sourced from %s\n", m_source_name.GetCString()); } if (m_lsda_address.IsValid() && m_personality_func_addr.IsValid()) { TargetSP target_sp(thread->CalculateTarget()); addr_t lsda_load_addr = m_lsda_address.GetLoadAddress (target_sp.get()); addr_t personality_func_load_addr = m_personality_func_addr.GetLoadAddress (target_sp.get()); if (lsda_load_addr != LLDB_INVALID_ADDRESS && personality_func_load_addr != LLDB_INVALID_ADDRESS) { s.Printf("LSDA address 0x%" PRIx64 ", personality routine is at address 0x%" PRIx64 "\n", lsda_load_addr, personality_func_load_addr); } } s.Printf ("This UnwindPlan is sourced from the compiler: "); switch (m_plan_is_sourced_from_compiler) { case eLazyBoolYes: s.Printf ("yes.\n"); break; case eLazyBoolNo: s.Printf ("no.\n"); break; case eLazyBoolCalculate: s.Printf ("not specified.\n"); break; } s.Printf ("This UnwindPlan is valid at all instruction locations: "); switch (m_plan_is_valid_at_all_instruction_locations) { case eLazyBoolYes: s.Printf ("yes.\n"); break; case eLazyBoolNo: s.Printf ("no.\n"); break; case eLazyBoolCalculate: s.Printf ("not specified.\n"); break; } if (m_plan_valid_address_range.GetBaseAddress().IsValid() && m_plan_valid_address_range.GetByteSize() > 0) { s.PutCString ("Address range of this UnwindPlan: "); TargetSP target_sp(thread->CalculateTarget()); m_plan_valid_address_range.Dump (&s, target_sp.get(), Address::DumpStyleSectionNameOffset); s.EOL(); } collection::const_iterator pos, begin = m_row_list.begin(), end = m_row_list.end(); for (pos = begin; pos != end; ++pos) { s.Printf ("row[%u]: ", (uint32_t)std::distance (begin, pos)); (*pos)->Dump(s, this, thread, base_addr); } }
bool DumpToStream(Stream &stream, bool print_help_if_available) override { if (IsValid()) { m_compiler_type.DumpTypeDescription(&stream); stream.EOL(); return true; } return false; }
void OptionValueDictionary::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) { const Type dict_type = ConvertTypeMaskToType (m_type_mask); if (dump_mask & eDumpOptionType) { if (m_type_mask != eTypeInvalid) strm.Printf ("(%s of %ss)", GetTypeAsCString(), GetBuiltinTypeAsCString(dict_type)); else strm.Printf ("(%s)", GetTypeAsCString()); } if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) strm.PutCString (" ="); collection::iterator pos, end = m_values.end(); strm.IndentMore(); for (pos = m_values.begin(); pos != end; ++pos) { OptionValue *option_value = pos->second.get(); strm.EOL(); strm.Indent(pos->first.GetCString()); const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0; switch (dict_type) { default: case eTypeArray: case eTypeDictionary: case eTypeProperties: case eTypeFileSpecList: case eTypePathMap: strm.PutChar (' '); option_value->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options); break; case eTypeBoolean: case eTypeChar: case eTypeEnum: case eTypeFileSpec: case eTypeFormat: case eTypeSInt64: case eTypeString: case eTypeUInt64: case eTypeUUID: // No need to show the type for dictionaries of simple items strm.PutCString("="); option_value->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options); break; } } strm.IndentLess(); } }
void Platform::GetStatus (Stream &strm) { uint32_t major = UINT32_MAX; uint32_t minor = UINT32_MAX; uint32_t update = UINT32_MAX; std::string s; strm.Printf (" Platform: %s\n", GetPluginName().GetCString()); ArchSpec arch (GetSystemArchitecture()); if (arch.IsValid()) { if (!arch.GetTriple().str().empty()) strm.Printf(" Triple: %s\n", arch.GetTriple().str().c_str()); } if (GetOSVersion(major, minor, update)) { strm.Printf("OS Version: %u", major); if (minor != UINT32_MAX) strm.Printf(".%u", minor); if (update != UINT32_MAX) strm.Printf(".%u", update); if (GetOSBuildString (s)) strm.Printf(" (%s)", s.c_str()); strm.EOL(); } if (GetOSKernelDescription (s)) strm.Printf(" Kernel: %s\n", s.c_str()); if (IsHost()) { strm.Printf(" Hostname: %s\n", GetHostname()); } else { const bool is_connected = IsConnected(); if (is_connected) strm.Printf(" Hostname: %s\n", GetHostname()); strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no"); } if (GetWorkingDirectory()) { strm.Printf("WorkingDir: %s\n", GetWorkingDirectory().GetCString()); } if (!IsConnected()) return; std::string specific_info(GetPlatformSpecificConnectionInformation()); if (specific_info.empty() == false) strm.Printf("Platform-specific connection: %s\n", specific_info.c_str()); }
void SectionLoadHistory::Dump(Stream &s, Target *target) { std::lock_guard<std::recursive_mutex> guard(m_mutex); StopIDToSectionLoadList::iterator pos, end = m_stop_id_to_section_load_list.end(); for (pos = m_stop_id_to_section_load_list.begin(); pos != end; ++pos) { s.Printf("StopID = %u:\n", pos->first); pos->second->Dump(s, target); s.EOL(); } }
void UnwindTable::Dump (Stream &s) { s.Printf("UnwindTable for %s/%s:\n", m_object_file.GetFileSpec().GetDirectory().GetCString(), m_object_file.GetFileSpec().GetFilename().GetCString()); const_iterator begin = m_unwinds.begin(); const_iterator end = m_unwinds.end(); for (const_iterator pos = begin; pos != end; ++pos) { s.Printf ("[%u] 0x%16.16llx\n", (unsigned)std::distance (begin, pos), pos->first); } s.EOL(); }
void UnwindTable::Dump (Stream &s) { s.Printf("UnwindTable for '%s':\n", m_object_file.GetFileSpec().GetPath().c_str()); const_iterator begin = m_unwinds.begin(); const_iterator end = m_unwinds.end(); for (const_iterator pos = begin; pos != end; ++pos) { s.Printf ("[%u] 0x%16.16" PRIx64 "\n", (unsigned)std::distance (begin, pos), pos->first); } s.EOL(); }
void OptionValueArray::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) { const Type array_element_type = ConvertTypeMaskToType (m_type_mask); if (dump_mask & eDumpOptionType) { if ((GetType() == eTypeArray) && (m_type_mask != eTypeInvalid)) strm.Printf ("(%s of %ss)", GetTypeAsCString(), GetBuiltinTypeAsCString(array_element_type)); else strm.Printf ("(%s)", GetTypeAsCString()); } if (dump_mask & eDumpOptionValue) { if (dump_mask & eDumpOptionType) strm.Printf (" =%s", (m_values.size() > 0) ? "\n" : ""); strm.IndentMore(); const uint32_t size = m_values.size(); for (uint32_t i = 0; i<size; ++i) { strm.Indent(); strm.Printf("[%u]: ", i); const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0; switch (array_element_type) { default: case eTypeArray: case eTypeDictionary: case eTypeProperties: case eTypeFileSpecList: case eTypePathMap: m_values[i]->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options); break; case eTypeBoolean: case eTypeChar: case eTypeEnum: case eTypeFileSpec: case eTypeFormat: case eTypeSInt64: case eTypeString: case eTypeUInt64: case eTypeUUID: // No need to show the type for dictionaries of simple items m_values[i]->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options); break; } if (i < (size - 1)) strm.EOL(); } strm.IndentLess(); } }
void Property::DumpDescription (CommandInterpreter &interpreter, Stream &strm, uint32_t output_width, bool display_qualified_name) const { if (m_value_sp) { const char *desc = GetDescription(); if (desc) { StreamString qualified_name; const OptionValueProperties *sub_properties = m_value_sp->GetAsProperties(); if (sub_properties) { strm.EOL(); if (m_value_sp->DumpQualifiedName(qualified_name)) strm.Printf("'%s' variables:\n\n", qualified_name.GetString().c_str()); sub_properties->DumpAllDescriptions(interpreter, strm); } else { if (desc) { if (display_qualified_name) { StreamString qualified_name; DumpQualifiedName(qualified_name); interpreter.OutputFormattedHelpText (strm, qualified_name.GetString().c_str(), "--", desc, output_width); } else { interpreter.OutputFormattedHelpText (strm, m_name.GetCString(), "--", desc, output_width); } } } } } }
void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) { const size_t num_properties = m_properties.size(); for (size_t i = 0; i < num_properties; ++i) { const Property *property = GetPropertyAtIndex(exe_ctx, false, i); if (property) { OptionValue *option_value = property->GetValue().get(); assert(option_value); const bool transparent_value = option_value->ValueIsTransparent(); property->Dump(exe_ctx, strm, dump_mask); if (!transparent_value) strm.EOL(); } } }
size_t Disassembler::Disassemble ( Debugger &debugger, const ArchSpec &arch, const char *plugin_name, const char *flavor, const ExecutionContext &exe_ctx, SymbolContextList &sc_list, uint32_t num_instructions, uint32_t num_mixed_context_lines, uint32_t options, Stream &strm ) { size_t success_count = 0; const size_t count = sc_list.GetSize(); SymbolContext sc; AddressRange range; const uint32_t scope = eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol; const bool use_inline_block_range = true; for (size_t i=0; i<count; ++i) { if (sc_list.GetContextAtIndex(i, sc) == false) break; for (uint32_t range_idx = 0; sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); ++range_idx) { if (Disassemble (debugger, arch, plugin_name, flavor, exe_ctx, range, num_instructions, num_mixed_context_lines, options, strm)) { ++success_count; strm.EOL(); } } } return success_count; }
void UnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, addr_t base_addr) const { if (base_addr != LLDB_INVALID_ADDRESS) s.Printf ("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset()); else s.Printf ("%4" PRId64 ": CFA=", GetOffset()); m_cfa_value.Dump(s, unwind_plan, thread); s.Printf(" => "); for (collection::const_iterator idx = m_register_locations.begin (); idx != m_register_locations.end (); ++idx) { DumpRegisterName(s, unwind_plan, thread, idx->first); const bool verbose = false; idx->second.Dump(s, unwind_plan, this, thread, verbose); s.PutChar (' '); } s.EOL(); }
bool DumpRegisterSet (const ExecutionContext &exe_ctx, Stream &strm, RegisterContext *reg_ctx, size_t set_idx, bool primitive_only=false) { uint32_t unavailable_count = 0; uint32_t available_count = 0; if (!reg_ctx) return false; // thread has no registers (i.e. core files are corrupt, incomplete crash logs...) const RegisterSet * const reg_set = reg_ctx->GetRegisterSet(set_idx); if (reg_set) { strm.Printf ("%s:\n", reg_set->name); strm.IndentMore (); const size_t num_registers = reg_set->num_registers; for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) { const uint32_t reg = reg_set->registers[reg_idx]; const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg); // Skip the dumping of derived register if primitive_only is true. if (primitive_only && reg_info && reg_info->value_regs) continue; if (DumpRegister (exe_ctx, strm, reg_ctx, reg_info)) ++available_count; else ++unavailable_count; } strm.IndentLess (); if (unavailable_count) { strm.Indent (); strm.Printf("%u registers were unavailable.\n", unavailable_count); } strm.EOL(); } return available_count > 0; }
void UnwindPlan::Dump (Stream& s, Thread *thread, lldb::addr_t base_addr) const { if (!m_source_name.IsEmpty()) { s.Printf ("This UnwindPlan originally sourced from %s\n", m_source_name.GetCString()); } if (m_plan_valid_address_range.GetBaseAddress().IsValid() && m_plan_valid_address_range.GetByteSize() > 0) { s.PutCString ("Address range of this UnwindPlan: "); TargetSP target_sp(thread->CalculateTarget()); m_plan_valid_address_range.Dump (&s, target_sp.get(), Address::DumpStyleSectionNameOffset); s.EOL(); } collection::const_iterator pos, begin = m_row_list.begin(), end = m_row_list.end(); for (pos = begin; pos != end; ++pos) { s.Printf ("row[%u]: ", (uint32_t)std::distance (begin, pos)); (*pos)->Dump(s, this, thread, base_addr); } }
static void DumpStringToStreamWithNewline (Stream &strm, const std::string &s, bool add_newline_if_empty) { bool add_newline = false; if (s.empty()) { add_newline = add_newline_if_empty; } else { // We already checked for empty above, now make sure there is a newline // in the error, and if there isn't one, add one. strm.Write(s.c_str(), s.size()); const char last_char = *s.rbegin(); add_newline = last_char != '\n' && last_char != '\r'; } if (add_newline) strm.EOL(); }
void StructuredData::Array::Dump(Stream &s) const { bool first = true; s << "[\n"; s.IndentMore(); for (const auto &item_sp : m_items) { if (first) first = false; else s << ",\n"; s.Indent(); item_sp->Dump(s); } s.IndentLess(); s.EOL(); s.Indent(); s << "]"; }
void StructuredData::Dictionary::Dump (Stream &s) const { bool first = true; s << "{\n"; s.IndentMore(); for (const auto &pair : m_dict) { if (first) first = false; else s << ",\n"; s.Indent(); s << "\"" << pair.first.AsCString() << "\" : "; pair.second->Dump(s); } s.IndentLess(); s.EOL(); s.Indent(); s << "}"; }
void ThreadPlanAssemblyTracer::Log() { Stream *stream = GetLogStream(); if (!stream) return; RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); lldb::addr_t pc = reg_ctx->GetPC(); ProcessSP process_sp(m_thread.GetProcess()); Address pc_addr; bool addr_valid = false; uint8_t buffer[16] = {0}; // Must be big enough for any single instruction addr_valid = process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress( pc, pc_addr); pc_addr.Dump(stream, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress); stream->PutCString(" "); Disassembler *disassembler = GetDisassembler(); if (disassembler) { Status err; process_sp->ReadMemory(pc, buffer, sizeof(buffer), err); if (err.Success()) { DataExtractor extractor(buffer, sizeof(buffer), process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); bool data_from_file = false; if (addr_valid) disassembler->DecodeInstructions(pc_addr, extractor, 0, 1, false, data_from_file); else disassembler->DecodeInstructions(Address(pc), extractor, 0, 1, false, data_from_file); InstructionList &instruction_list = disassembler->GetInstructionList(); const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize(); if (instruction_list.GetSize()) { const bool show_bytes = true; const bool show_address = true; Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get(); const FormatEntity::Entry *disassemble_format = m_thread.GetProcess() ->GetTarget() .GetDebugger() .GetDisassemblyFormat(); instruction->Dump(stream, max_opcode_byte_size, show_address, show_bytes, nullptr, nullptr, nullptr, disassemble_format, 0); } } } const ABI *abi = process_sp->GetABI().get(); TypeFromUser intptr_type = GetIntPointerType(); if (abi && intptr_type.IsValid()) { ValueList value_list; const int num_args = 1; for (int arg_index = 0; arg_index < num_args; ++arg_index) { Value value; value.SetValueType(Value::eValueTypeScalar); // value.SetContext (Value::eContextTypeClangType, // intptr_type.GetOpaqueQualType()); value.SetCompilerType(intptr_type); value_list.PushValue(value); } if (abi->GetArgumentValues(m_thread, value_list)) { for (int arg_index = 0; arg_index < num_args; ++arg_index) { stream->Printf( "\n\targ[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong()); if (arg_index + 1 < num_args) stream->PutCString(", "); } } } RegisterValue reg_value; for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount(); reg_num < num_registers; ++reg_num) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num); if (reg_ctx->ReadRegister(reg_info, reg_value)) { assert(reg_num < m_register_values.size()); if (m_register_values[reg_num].GetType() == RegisterValue::eTypeInvalid || reg_value != m_register_values[reg_num]) { if (reg_value.GetType() != RegisterValue::eTypeInvalid) { stream->PutCString("\n\t"); reg_value.Dump(stream, reg_info, true, false, eFormatDefault); } } m_register_values[reg_num] = reg_value; } } stream->EOL(); stream->Flush(); }
bool Disassembler::PrintInstructions ( Disassembler *disasm_ptr, Debugger &debugger, const ArchSpec &arch, const ExecutionContext &exe_ctx, uint32_t num_instructions, uint32_t num_mixed_context_lines, uint32_t options, Stream &strm ) { // We got some things disassembled... size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize(); if (num_instructions > 0 && num_instructions < num_instructions_found) num_instructions_found = num_instructions; const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize (); uint32_t offset = 0; SymbolContext sc; SymbolContext prev_sc; AddressRange sc_range; const Address *pc_addr_ptr = NULL; ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope(); Frame *frame = exe_ctx.GetFramePtr(); TargetSP target_sp (exe_ctx.GetTargetSP()); SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager(); if (frame) pc_addr_ptr = &frame->GetFrameCodeAddress(); const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; const bool use_inline_block_range = false; for (size_t i=0; i<num_instructions_found; ++i) { Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get(); if (inst) { const Address &addr = inst->GetAddress(); const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr; prev_sc = sc; ModuleSP module_sp (addr.GetModule()); if (module_sp) { uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); if (resolved_mask) { if (num_mixed_context_lines) { if (!sc_range.ContainsFileAddress (addr)) { sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range); if (sc != prev_sc) { if (offset != 0) strm.EOL(); sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false); strm.EOL(); if (sc.comp_unit && sc.line_entry.IsValid()) { source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file, sc.line_entry.line, num_mixed_context_lines, num_mixed_context_lines, ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""), &strm); } } } } else if ((sc.function || sc.symbol) && (sc.function != prev_sc.function || sc.symbol != prev_sc.symbol)) { if (prev_sc.function || prev_sc.symbol) strm.EOL(); bool show_fullpaths = false; bool show_module = true; bool show_inlined_frames = true; sc.DumpStopContext (&strm, exe_scope, addr, show_fullpaths, show_module, show_inlined_frames); strm << ":\n"; } } else { sc.Clear(true); } } if ((options & eOptionMarkPCAddress) && pc_addr_ptr) { strm.PutCString(inst_is_at_pc ? "-> " : " "); } const bool show_bytes = (options & eOptionShowBytes) != 0; inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx); strm.EOL(); } else { break; } } return true; }
bool Disassembler::PrintInstructions ( Disassembler *disasm_ptr, Debugger &debugger, const ArchSpec &arch, const ExecutionContext &exe_ctx, uint32_t num_instructions, uint32_t num_mixed_context_lines, uint32_t options, Stream &strm ) { // We got some things disassembled... size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize(); if (num_instructions > 0 && num_instructions < num_instructions_found) num_instructions_found = num_instructions; const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize (); uint32_t offset = 0; SymbolContext sc; SymbolContext prev_sc; AddressRange sc_range; const Address *pc_addr_ptr = NULL; StackFrame *frame = exe_ctx.GetFramePtr(); TargetSP target_sp (exe_ctx.GetTargetSP()); SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager(); if (frame) { pc_addr_ptr = &frame->GetFrameCodeAddress(); } const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; const bool use_inline_block_range = false; const FormatEntity::Entry *disassembly_format = NULL; FormatEntity::Entry format; if (exe_ctx.HasTargetScope()) { disassembly_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat (); } else { FormatEntity::Parse("${addr}: ", format); disassembly_format = &format; } // First pass: step through the list of instructions, // find how long the initial addresses strings are, insert padding // in the second pass so the opcodes all line up nicely. size_t address_text_size = 0; for (size_t i = 0; i < num_instructions_found; ++i) { Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get(); if (inst) { const Address &addr = inst->GetAddress(); ModuleSP module_sp (addr.GetModule()); if (module_sp) { const uint32_t resolve_mask = eSymbolContextFunction | eSymbolContextSymbol; uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc); if (resolved_mask) { StreamString strmstr; Debugger::FormatDisassemblerAddress (disassembly_format, &sc, NULL, &exe_ctx, &addr, strmstr); size_t cur_line = strmstr.GetSizeOfLastLine(); if (cur_line > address_text_size) address_text_size = cur_line; } sc.Clear(false); } } } for (size_t i = 0; i < num_instructions_found; ++i) { Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get(); if (inst) { const Address &addr = inst->GetAddress(); const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr; prev_sc = sc; ModuleSP module_sp (addr.GetModule()); if (module_sp) { uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); if (resolved_mask) { if (num_mixed_context_lines) { if (!sc_range.ContainsFileAddress (addr)) { sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range); if (sc != prev_sc) { if (offset != 0) strm.EOL(); sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false, false, true); strm.EOL(); if (sc.comp_unit && sc.line_entry.IsValid()) { source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file, sc.line_entry.line, num_mixed_context_lines, num_mixed_context_lines, ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""), &strm); } } } } } else { sc.Clear(true); } } const bool show_bytes = (options & eOptionShowBytes) != 0; inst->Dump (&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, &prev_sc, NULL, address_text_size); strm.EOL(); } else { break; } } return true; }
void CommandInterpreter::OutputFormattedHelpText (Stream &strm, const char *word_text, const char *separator, const char *help_text, uint32_t max_word_len) { StateVariable *var = GetStateVariable ("term-width"); int max_columns = var->GetIntValue(); // Sanity check max_columns, to cope with emacs shell mode with TERM=dumb // (0 rows; 0 columns;). if (max_columns <= 0) max_columns = 80; int indent_size = max_word_len + strlen (separator) + 2; strm.IndentMore (indent_size); int len = indent_size + strlen (help_text) + 1; char *text = (char *) malloc (len); sprintf (text, "%-*s %s %s", max_word_len, word_text, separator, help_text); if (text[len - 1] == '\n') text[--len] = '\0'; if (len < max_columns) { // Output it as a single line. strm.Printf ("%s", text); } else { // We need to break it up into multiple lines. bool first_line = true; int text_width; int start = 0; int end = start; int final_end = strlen (text); int sub_len; while (end < final_end) { if (first_line) text_width = max_columns - 1; else text_width = max_columns - indent_size - 1; // Don't start the 'text' on a space, since we're already outputting the indentation. if (!first_line) { while ((start < final_end) && (text[start] == ' ')) start++; } end = start + text_width; if (end > final_end) end = final_end; else { // If we're not at the end of the text, make sure we break the line on white space. while (end > start && text[end] != ' ' && text[end] != '\t' && text[end] != '\n') end--; } sub_len = end - start; if (start != 0) strm.EOL(); if (!first_line) strm.Indent(); else first_line = false; assert (start <= final_end); assert (start + sub_len <= final_end); if (sub_len > 0) strm.Write (text + start, sub_len); start = end + 1; } } strm.EOL(); strm.IndentLess(indent_size); free (text); }
void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd, uint32_t screen_width) { const bool only_print_args = cmd->IsDashDashCommand(); auto opt_defs = GetDefinitions(); const uint32_t save_indent_level = strm.GetIndentLevel(); llvm::StringRef name; StreamString arguments_str; if (cmd) { name = cmd->GetCommandName(); cmd->GetFormattedCommandArguments(arguments_str); } else name = ""; strm.PutCString("\nCommand Options Usage:\n"); strm.IndentMore(2); // First, show each usage level set of options, e.g. <cmd> // [options-for-level-0] // <cmd> // [options-for-level-1] // etc. const uint32_t num_options = NumCommandOptions(); if (num_options == 0) return; uint32_t num_option_sets = GetRequiredOptions().size(); uint32_t i; if (!only_print_args) { for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set) { uint32_t opt_set_mask; opt_set_mask = 1 << opt_set; if (opt_set > 0) strm.Printf("\n"); strm.Indent(name); // Different option sets may require different args. StreamString args_str; if (cmd) cmd->GetFormattedCommandArguments(args_str, opt_set_mask); // First go through and print all options that take no arguments as // a single string. If a command has "-a" "-b" and "-c", this will show // up as [-abc] std::set<int> options; std::set<int>::const_iterator options_pos, options_end; for (auto &def : opt_defs) { if (def.usage_mask & opt_set_mask && isprint8(def.short_option)) { // Add current option to the end of out_stream. if (def.required && def.option_has_arg == OptionParser::eNoArgument) { options.insert(def.short_option); } } } if (options.empty() == false) { // We have some required options with no arguments strm.PutCString(" -"); for (i = 0; i < 2; ++i) for (options_pos = options.begin(), options_end = options.end(); options_pos != options_end; ++options_pos) { if (i == 0 && ::islower(*options_pos)) continue; if (i == 1 && ::isupper(*options_pos)) continue; strm << (char)*options_pos; } } options.clear(); for (auto &def : opt_defs) { if (def.usage_mask & opt_set_mask && isprint8(def.short_option)) { // Add current option to the end of out_stream. if (def.required == false && def.option_has_arg == OptionParser::eNoArgument) { options.insert(def.short_option); } } } if (options.empty() == false) { // We have some required options with no arguments strm.PutCString(" [-"); for (i = 0; i < 2; ++i) for (options_pos = options.begin(), options_end = options.end(); options_pos != options_end; ++options_pos) { if (i == 0 && ::islower(*options_pos)) continue; if (i == 1 && ::isupper(*options_pos)) continue; strm << (char)*options_pos; } strm.PutChar(']'); } // First go through and print the required options (list them up front). for (auto &def : opt_defs) { if (def.usage_mask & opt_set_mask && isprint8(def.short_option)) { if (def.required && def.option_has_arg != OptionParser::eNoArgument) PrintOption(def, eDisplayBestOption, " ", nullptr, true, strm); } } // Now go through again, and this time only print the optional options. for (auto &def : opt_defs) { if (def.usage_mask & opt_set_mask) { // Add current option to the end of out_stream. if (!def.required && def.option_has_arg != OptionParser::eNoArgument) PrintOption(def, eDisplayBestOption, " ", nullptr, true, strm); } } if (args_str.GetSize() > 0) { if (cmd->WantsRawCommandString() && !only_print_args) strm.Printf(" --"); strm << " " << args_str.GetString(); if (only_print_args) break; } } } if (cmd && (only_print_args || cmd->WantsRawCommandString()) && arguments_str.GetSize() > 0) { if (!only_print_args) strm.PutChar('\n'); strm.Indent(name); strm << " " << arguments_str.GetString(); } strm.Printf("\n\n"); if (!only_print_args) { // Now print out all the detailed information about the various options: // long form, short form and help text: // -short <argument> ( --long_name <argument> ) // help text // This variable is used to keep track of which options' info we've printed // out, because some options can be in // more than one usage level, but we only want to print the long form of its // information once. std::multimap<int, uint32_t> options_seen; strm.IndentMore(5); // Put the unique command options in a vector & sort it, so we can output // them alphabetically (by short_option) // when writing out detailed help for each option. i = 0; for (auto &def : opt_defs) options_seen.insert(std::make_pair(def.short_option, i++)); // Go through the unique'd and alphabetically sorted vector of options, find // the table entry for each option // and write out the detailed help information for that option. bool first_option_printed = false; for (auto pos : options_seen) { i = pos.second; // Print out the help information for this option. // Put a newline separation between arguments if (first_option_printed) strm.EOL(); else first_option_printed = true; CommandArgumentType arg_type = opt_defs[i].argument_type; StreamString arg_name_str; arg_name_str.Printf("<%s>", CommandObject::GetArgumentName(arg_type)); strm.Indent(); if (opt_defs[i].short_option && isprint8(opt_defs[i].short_option)) { PrintOption(opt_defs[i], eDisplayShortOption, nullptr, nullptr, false, strm); PrintOption(opt_defs[i], eDisplayLongOption, " ( ", " )", false, strm); } else { // Short option is not printable, just print long option PrintOption(opt_defs[i], eDisplayLongOption, nullptr, nullptr, false, strm); } strm.EOL(); strm.IndentMore(5); if (opt_defs[i].usage_text) OutputFormattedUsageText(strm, opt_defs[i], screen_width); if (opt_defs[i].enum_values != nullptr) { strm.Indent(); strm.Printf("Values: "); for (int k = 0; opt_defs[i].enum_values[k].string_value != nullptr; k++) { if (k == 0) strm.Printf("%s", opt_defs[i].enum_values[k].string_value); else strm.Printf(" | %s", opt_defs[i].enum_values[k].string_value); } strm.EOL(); } strm.IndentLess(5); } } // Restore the indent level strm.SetIndentLevel(save_indent_level); }