diff options
author | Enrico Granata <egranata@apple.com> | 2013-01-21 19:20:50 +0000 |
---|---|---|
committer | Enrico Granata <egranata@apple.com> | 2013-01-21 19:20:50 +0000 |
commit | 6b4ddc655a3dafc53e98efd9560ee8185ae717fc (patch) | |
tree | 754719972dbd38cab3e3dec13af9478ade7e9561 | |
parent | 2cec01916c47a097f8777c85c22e66a88b684949 (diff) | |
download | bcm5719-llvm-6b4ddc655a3dafc53e98efd9560ee8185ae717fc.tar.gz bcm5719-llvm-6b4ddc655a3dafc53e98efd9560ee8185ae717fc.zip |
<rdar://problem/12437929>
Providing a special mode of operator for "memory read -f c-str" which actually works in most common cases
Where the old behavior would provide:
(lldb) mem read --format s `foo`
0x100000f5d: NULL
Now we do:
(lldb) mem read --format s `foo`
0x100000f5d: "hello world"
You can also specify a count and that many strings will be showed starting at the initial address:
(lldb) mem read -c 2 -f c-str `foo`
0x100000f1d: "hello world"
0x100000f29: "short"
llvm-svn: 173076
-rw-r--r-- | lldb/include/lldb/Interpreter/OptionGroupFormat.h | 7 | ||||
-rw-r--r-- | lldb/include/lldb/Target/Target.h | 8 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectMemory.cpp | 46 | ||||
-rw-r--r-- | lldb/source/Interpreter/OptionGroupFormat.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Target/Target.cpp | 76 |
5 files changed, 136 insertions, 3 deletions
diff --git a/lldb/include/lldb/Interpreter/OptionGroupFormat.h b/lldb/include/lldb/Interpreter/OptionGroupFormat.h index b721644845b..7419b049666 100644 --- a/lldb/include/lldb/Interpreter/OptionGroupFormat.h +++ b/lldb/include/lldb/Interpreter/OptionGroupFormat.h @@ -97,6 +97,11 @@ public: return m_count; } + bool + HasGDBFormat () const + { + return m_has_gdb_format; + } bool AnyOptionWasSet () const @@ -119,6 +124,8 @@ protected: OptionValueUInt64 m_count; char m_prev_gdb_format; char m_prev_gdb_size; + + bool m_has_gdb_format; }; } // namespace lldb_private diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 7e47012adac..79d94a714a8 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -846,7 +846,13 @@ public: size_t dst_len, Error &error, lldb::addr_t *load_addr_ptr = NULL); - + + size_t + ReadCStringFromMemory (const Address& addr, std::string &out_str, Error &error); + + size_t + ReadCStringFromMemory (const Address& addr, char *dst, size_t dst_max_len, Error &result_error); + size_t ReadScalarIntegerFromMemory (const Address& addr, bool prefer_file_cache, diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp index 947fc27a3c0..cbff45ccbcf 100644 --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -586,7 +586,7 @@ protected: } size_t item_count = m_format_options.GetCountValue().GetCurrentValue(); - const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); + 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) @@ -641,6 +641,8 @@ protected: return false; } + + DataBufferSP data_sp; size_t bytes_read = 0; if (clang_ast_type.GetOpaqueQualType()) @@ -651,7 +653,7 @@ protected: bytes_read = clang_ast_type.GetTypeByteSize() * m_format_options.GetCountValue().GetCurrentValue(); } - else + else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString) { data_sp.reset (new DataBufferHeap (total_byte_size, '\0')); Address address(addr, NULL); @@ -674,6 +676,46 @@ protected: if (bytes_read < total_byte_size) result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%" PRIx64 ".", bytes_read, total_byte_size, addr); } + else + { + // we treat c-strings as a special case because they do not have a fixed size + if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat()) + item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); + else + item_byte_size = target->GetMaximumSizeOfStringSummary(); + if (!m_format_options.GetCountValue().OptionWasSet()) + item_count = 1; + data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary + uint8_t *data_ptr = data_sp->GetBytes(); + auto data_addr = addr; + auto count = item_count; + item_count = 0; + while (item_count < count) + { + std::string buffer; + buffer.resize(item_byte_size+1,0); + Error error; + size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error); + if (error.Fail()) + { + result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr); + result.SetStatus(eReturnStatusFailed); + return false; + } + if (item_byte_size == read) + { + result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr); + break; + } + read+=1; // account for final NULL byte + memcpy(data_ptr, &buffer[0], read); + data_ptr += read; + data_addr += read; + bytes_read += read; + item_count++; // if we break early we know we only read item_count strings + } + data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1)); + } m_next_addr = addr + bytes_read; m_prev_byte_size = bytes_read; diff --git a/lldb/source/Interpreter/OptionGroupFormat.cpp b/lldb/source/Interpreter/OptionGroupFormat.cpp index 226f5a16f98..944bb18107d 100644 --- a/lldb/source/Interpreter/OptionGroupFormat.cpp +++ b/lldb/source/Interpreter/OptionGroupFormat.cpp @@ -205,6 +205,7 @@ OptionGroupFormat::SetOptionValue (CommandInterpreter &interpreter, bool OptionGroupFormat::ParserGDBFormatLetter (CommandInterpreter &interpreter, char format_letter, Format &format, uint32_t &byte_size) { + m_has_gdb_format = true; switch (format_letter) { case 'o': format = eFormatOctal; m_prev_gdb_format = format_letter; return true; @@ -242,4 +243,5 @@ OptionGroupFormat::OptionParsingStarting (CommandInterpreter &interpreter) m_format.Clear(); m_byte_size.Clear(); m_count.Clear(); + m_has_gdb_format = false; } diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 6238d2e337f..435081c8bba 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -1327,6 +1327,82 @@ Target::ReadMemory (const Address& addr, } size_t +Target::ReadCStringFromMemory (const Address& addr, std::string &out_str, Error &error) +{ + char buf[256]; + out_str.clear(); + addr_t curr_addr = addr.GetLoadAddress(this); + Address address(addr); + while (1) + { + size_t length = ReadCStringFromMemory (address, buf, sizeof(buf), error); + if (length == 0) + break; + out_str.append(buf, length); + // If we got "length - 1" bytes, we didn't get the whole C string, we + // need to read some more characters + if (length == sizeof(buf) - 1) + curr_addr += length; + else + break; + address = Address(curr_addr); + } + return out_str.size(); +} + + +size_t +Target::ReadCStringFromMemory (const Address& addr, char *dst, size_t dst_max_len, Error &result_error) +{ + size_t total_cstr_len = 0; + if (dst && dst_max_len) + { + result_error.Clear(); + // NULL out everything just to be safe + memset (dst, 0, dst_max_len); + Error error; + addr_t curr_addr = addr.GetLoadAddress(this); + Address address(addr); + const size_t cache_line_size = 512; + size_t bytes_left = dst_max_len - 1; + char *curr_dst = dst; + + while (bytes_left > 0) + { + addr_t cache_line_bytes_left = cache_line_size - (curr_addr % cache_line_size); + addr_t bytes_to_read = std::min<addr_t>(bytes_left, cache_line_bytes_left); + size_t bytes_read = ReadMemory (address, false, curr_dst, bytes_to_read, error); + + if (bytes_read == 0) + { + result_error = error; + dst[total_cstr_len] = '\0'; + break; + } + const size_t len = strlen(curr_dst); + + total_cstr_len += len; + + if (len < bytes_to_read) + break; + + curr_dst += bytes_read; + curr_addr += bytes_read; + bytes_left -= bytes_read; + address = Address(curr_addr); + } + } + else + { + if (dst == NULL) + result_error.SetErrorString("invalid arguments"); + else + result_error.Clear(); + } + return total_cstr_len; +} + +size_t Target::ReadScalarIntegerFromMemory (const Address& addr, bool prefer_file_cache, uint32_t byte_size, |