diff options
Diffstat (limited to 'lldb/source/Core/DumpDataExtractor.cpp')
-rw-r--r-- | lldb/source/Core/DumpDataExtractor.cpp | 246 |
1 files changed, 106 insertions, 140 deletions
diff --git a/lldb/source/Core/DumpDataExtractor.cpp b/lldb/source/Core/DumpDataExtractor.cpp index b5e1071b72ae7..dbfedfae27a8c 100644 --- a/lldb/source/Core/DumpDataExtractor.cpp +++ b/lldb/source/Core/DumpDataExtractor.cpp @@ -1,4 +1,4 @@ -//===-- DumpDataExtractor.cpp -----------------------------------*- C++ -*-===// +//===-- DumpDataExtractor.cpp ---------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -128,6 +128,104 @@ static lldb::offset_t DumpAPInt(Stream *s, const DataExtractor &data, return offset; } +/// Dumps decoded instructions to a stream. +static lldb::offset_t DumpInstructions(const DataExtractor &DE, Stream *s, + ExecutionContextScope *exe_scope, + offset_t start_offset, + uint64_t base_addr, + size_t number_of_instructions) { + offset_t offset = start_offset; + + TargetSP target_sp; + if (exe_scope) + target_sp = exe_scope->CalculateTarget(); + if (target_sp) { + DisassemblerSP disassembler_sp( + Disassembler::FindPlugin(target_sp->GetArchitecture(), + target_sp->GetDisassemblyFlavor(), nullptr)); + if (disassembler_sp) { + lldb::addr_t addr = base_addr + start_offset; + lldb_private::Address so_addr; + bool data_from_file = true; + if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) { + data_from_file = false; + } else { + if (target_sp->GetSectionLoadList().IsEmpty() || + !target_sp->GetImages().ResolveFileAddress(addr, so_addr)) + so_addr.SetRawAddress(addr); + } + + size_t bytes_consumed = disassembler_sp->DecodeInstructions( + so_addr, DE, start_offset, number_of_instructions, false, + data_from_file); + + if (bytes_consumed) { + offset += bytes_consumed; + const bool show_address = base_addr != LLDB_INVALID_ADDRESS; + const bool show_bytes = true; + ExecutionContext exe_ctx; + exe_scope->CalculateExecutionContext(exe_ctx); + disassembler_sp->GetInstructionList().Dump(s, show_address, show_bytes, + &exe_ctx); + } + } + } else + s->Printf("invalid target"); + + return offset; +} + +/// Prints the specific escape sequence of the given character to the stream. +/// If the character doesn't have a known specific escape sequence (e.g., '\a', +/// '\n' but not generic escape sequences such as'\x12'), this function will +/// not modify the stream and return false. +static bool TryDumpSpecialEscapedChar(Stream &s, const char c) { + switch (c) { + case '\033': + // Common non-standard escape code for 'escape'. + s.Printf("\\e"); + return true; + case '\a': + s.Printf("\\a"); + return true; + case '\b': + s.Printf("\\b"); + return true; + case '\f': + s.Printf("\\f"); + return true; + case '\n': + s.Printf("\\n"); + return true; + case '\r': + s.Printf("\\r"); + return true; + case '\t': + s.Printf("\\t"); + return true; + case '\v': + s.Printf("\\v"); + return true; + case '\0': + s.Printf("\\0"); + return true; + default: + return false; + } +} + +/// Dump the character to a stream. A character that is not printable will be +/// represented by its escape sequence. +static void DumpCharacter(Stream &s, const char c) { + if (TryDumpSpecialEscapedChar(s, c)) + return; + if (llvm::isPrint(c)) { + s.PutChar(c); + return; + } + s.Printf("\\x%2.2x", c); +} + lldb::offset_t lldb_private::DumpDataExtractor( const DataExtractor &DE, Stream *s, offset_t start_offset, lldb::Format item_format, size_t item_byte_size, size_t item_count, @@ -147,44 +245,9 @@ lldb::offset_t lldb_private::DumpDataExtractor( offset_t offset = start_offset; - if (item_format == eFormatInstruction) { - TargetSP target_sp; - if (exe_scope) - target_sp = exe_scope->CalculateTarget(); - if (target_sp) { - DisassemblerSP disassembler_sp(Disassembler::FindPlugin( - target_sp->GetArchitecture(), - target_sp->GetDisassemblyFlavor(), nullptr)); - if (disassembler_sp) { - lldb::addr_t addr = base_addr + start_offset; - lldb_private::Address so_addr; - bool data_from_file = true; - if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) { - data_from_file = false; - } else { - if (target_sp->GetSectionLoadList().IsEmpty() || - !target_sp->GetImages().ResolveFileAddress(addr, so_addr)) - so_addr.SetRawAddress(addr); - } - - size_t bytes_consumed = disassembler_sp->DecodeInstructions( - so_addr, DE, start_offset, item_count, false, data_from_file); - - if (bytes_consumed) { - offset += bytes_consumed; - const bool show_address = base_addr != LLDB_INVALID_ADDRESS; - const bool show_bytes = true; - ExecutionContext exe_ctx; - exe_scope->CalculateExecutionContext(exe_ctx); - disassembler_sp->GetInstructionList().Dump(s, show_address, - show_bytes, &exe_ctx); - } - } - } else - s->Printf("invalid target"); - - return offset; - } + if (item_format == eFormatInstruction) + return DumpInstructions(DE, s, exe_scope, start_offset, base_addr, + item_count); if ((item_format == eFormatOSType || item_format == eFormatAddressInfo) && item_byte_size > 8) @@ -284,43 +347,14 @@ lldb::offset_t lldb_private::DumpDataExtractor( const uint64_t ch = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset); - if (isprint(ch)) + if (llvm::isPrint(ch)) s->Printf("%c", (char)ch); else if (item_format != eFormatCharPrintable) { - switch (ch) { - case '\033': - s->Printf("\\e"); - break; - case '\a': - s->Printf("\\a"); - break; - case '\b': - s->Printf("\\b"); - break; - case '\f': - s->Printf("\\f"); - break; - case '\n': - s->Printf("\\n"); - break; - case '\r': - s->Printf("\\r"); - break; - case '\t': - s->Printf("\\t"); - break; - case '\v': - s->Printf("\\v"); - break; - case '\0': - s->Printf("\\0"); - break; - default: + if (!TryDumpSpecialEscapedChar(*s, ch)) { if (item_byte_size == 1) s->Printf("\\x%2.2x", (uint8_t)ch); else s->Printf("%" PRIu64, ch); - break; } } else { s->PutChar(NON_PRINTABLE_CHAR); @@ -375,42 +409,7 @@ lldb::offset_t lldb_private::DumpDataExtractor( s->PutChar('\''); for (uint32_t i = 0; i < item_byte_size; ++i) { uint8_t ch = (uint8_t)(uval64 >> ((item_byte_size - i - 1) * 8)); - if (isprint(ch)) - s->Printf("%c", ch); - else { - switch (ch) { - case '\033': - s->Printf("\\e"); - break; - case '\a': - s->Printf("\\a"); - break; - case '\b': - s->Printf("\\b"); - break; - case '\f': - s->Printf("\\f"); - break; - case '\n': - s->Printf("\\n"); - break; - case '\r': - s->Printf("\\r"); - break; - case '\t': - s->Printf("\\t"); - break; - case '\v': - s->Printf("\\v"); - break; - case '\0': - s->Printf("\\0"); - break; - default: - s->Printf("\\x%2.2x", ch); - break; - } - } + DumpCharacter(*s, ch); } s->PutChar('\''); } break; @@ -425,40 +424,7 @@ lldb::offset_t lldb_private::DumpDataExtractor( s->PutChar('\"'); while (const char c = *cstr) { - if (isprint(c)) { - s->PutChar(c); - } else { - switch (c) { - case '\033': - s->Printf("\\e"); - break; - case '\a': - s->Printf("\\a"); - break; - case '\b': - s->Printf("\\b"); - break; - case '\f': - s->Printf("\\f"); - break; - case '\n': - s->Printf("\\n"); - break; - case '\r': - s->Printf("\\r"); - break; - case '\t': - s->Printf("\\t"); - break; - case '\v': - s->Printf("\\v"); - break; - default: - s->Printf("\\x%2.2x", c); - break; - } - } - + DumpCharacter(*s, c); ++cstr; } |