diff options
-rw-r--r-- | include/lldb/Target/Process.h | 36 | ||||
-rw-r--r-- | source/DataFormatters/CXXFormatterFunctions.cpp | 11 | ||||
-rw-r--r-- | source/Target/Process.cpp | 54 | ||||
-rw-r--r-- | test/lang/cpp/char1632_t/TestChar1632T.py | 1 | ||||
-rw-r--r-- | test/lang/cpp/wchar_t/TestCxxWCharT.py | 1 |
5 files changed, 97 insertions, 6 deletions
diff --git a/include/lldb/Target/Process.h b/include/lldb/Target/Process.h index 833e1b1ec..82e668fe7 100644 --- a/include/lldb/Target/Process.h +++ b/include/lldb/Target/Process.h @@ -2682,6 +2682,42 @@ public: Error &error); //------------------------------------------------------------------ + /// Read a NULL terminated string from memory + /// + /// This function will read a cache page at a time until a NULL + /// string terminator is found. It will stop reading if an aligned + /// sequence of NULL termination \a type_width bytes is not found + /// before reading \a cstr_max_len bytes. The results are always + /// guaranteed to be NULL terminated, and that no more than + /// (max_bytes - type_width) bytes will be read. + /// + /// @param[in] vm_addr + /// The virtual load address to start the memory read. + /// + /// @param[in] str + /// A character buffer containing at least max_bytes. + /// + /// @param[in] max_bytes + /// The maximum number of bytes to read. + /// + /// @param[in] error + /// The error status of the read operation. + /// + /// @param[in] type_width + /// The size of the null terminator (1 to 4 bytes per + /// character). Defaults to 1. + /// + /// @return + /// The error status or the number of bytes prior to the null terminator. + //------------------------------------------------------------------ + size_t + ReadStringFromMemory (lldb::addr_t vm_addr, + char *str, + size_t max_bytes, + Error &error, + size_t type_width = 1); + + //------------------------------------------------------------------ /// Read a NULL terminated C string from memory /// /// This function will read a cache page at a time until the NULL diff --git a/source/DataFormatters/CXXFormatterFunctions.cpp b/source/DataFormatters/CXXFormatterFunctions.cpp index 072649d94..4f3c6d85f 100644 --- a/source/DataFormatters/CXXFormatterFunctions.cpp +++ b/source/DataFormatters/CXXFormatterFunctions.cpp @@ -264,7 +264,8 @@ ReadUTFBufferAndDumpToStream (ConversionResult (*ConvertFunction) (const SourceD if (!process_sp) return false; - const int origin_encoding = 8*sizeof(SourceDataType); + const int type_width = sizeof(SourceDataType); + const int origin_encoding = 8 * type_width ; if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32) return false; // if not UTF8, I need a conversion function to return proper UTF8 @@ -276,15 +277,17 @@ ReadUTFBufferAndDumpToStream (ConversionResult (*ConvertFunction) (const SourceD else sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary()); - const int bufferSPSize = sourceSize * (origin_encoding >> 2); + const int bufferSPSize = sourceSize * type_width; - Error error; lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0)); if (!buffer_sp->GetBytes()) return false; - size_t data_read = process_sp->ReadMemoryFromInferior(location, (char*)buffer_sp->GetBytes(), bufferSPSize, error); + Error error; + char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes()); + + size_t data_read = process_sp->ReadStringFromMemory(location, buffer, bufferSPSize, error, type_width); if (error.Fail() || data_read == 0) { stream.Printf("unable to read data"); diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp index 3fe92a325..b9abee68d 100644 --- a/source/Target/Process.cpp +++ b/source/Target/Process.cpp @@ -2357,6 +2357,60 @@ Process::ReadCStringFromMemory (addr_t addr, std::string &out_str, Error &error) size_t +Process::ReadStringFromMemory (addr_t addr, char *dst, size_t max_bytes, Error &error, + size_t type_width) +{ + size_t total_bytes_read = 0; + if (dst && max_bytes && type_width && max_bytes >= type_width) + { + // Ensure a null terminator independent of the number of bytes that is read. + memset (dst, 0, max_bytes); + size_t bytes_left = max_bytes - type_width; + + const char terminator[4] = {'\0', '\0', '\0', '\0'}; + assert(sizeof(terminator) >= type_width && + "Attempting to validate a string with more than 4 bytes per character!"); + + addr_t curr_addr = addr; + const size_t cache_line_size = m_memory_cache.GetMemoryCacheLineSize(); + char *curr_dst = dst; + + error.Clear(); + while (bytes_left > 0 && error.Success()) + { + 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 (curr_addr, curr_dst, bytes_to_read, error); + + if (bytes_read == 0) + break; + + // Search for a null terminator of correct size and alignment in bytes_read + size_t aligned_start = total_bytes_read - total_bytes_read % type_width; + for (size_t i = aligned_start; i + type_width <= total_bytes_read + bytes_read; i += type_width) + if (::strncmp(&dst[i], terminator, type_width) == 0) + { + error.Clear(); + return i; + } + + total_bytes_read += bytes_read; + curr_dst += bytes_read; + curr_addr += bytes_read; + bytes_left -= bytes_read; + } + } + else + { + if (max_bytes) + error.SetErrorString("invalid arguments"); + } + return total_bytes_read; +} + +// Deprecated in favor of ReadStringFromMemory which has wchar support and correct code to find +// null terminators. +size_t Process::ReadCStringFromMemory (addr_t addr, char *dst, size_t dst_max_len, Error &result_error) { size_t total_cstr_len = 0; diff --git a/test/lang/cpp/char1632_t/TestChar1632T.py b/test/lang/cpp/char1632_t/TestChar1632T.py index 17a6d7c59..bd93ce827 100644 --- a/test/lang/cpp/char1632_t/TestChar1632T.py +++ b/test/lang/cpp/char1632_t/TestChar1632T.py @@ -20,7 +20,6 @@ class Char1632TestCase(TestBase): self.buildDsym() self.char1632() - @expectedFailureLinux # bugzilla 15038: missing wide char support on Linux @dwarf_test def test_with_dwarf(self): """Test that the C++11 support for char16_t and char32_t works correctly.""" diff --git a/test/lang/cpp/wchar_t/TestCxxWCharT.py b/test/lang/cpp/wchar_t/TestCxxWCharT.py index 734f77b48..52fab1f98 100644 --- a/test/lang/cpp/wchar_t/TestCxxWCharT.py +++ b/test/lang/cpp/wchar_t/TestCxxWCharT.py @@ -20,7 +20,6 @@ class CxxWCharTTestCase(TestBase): self.buildDsym() self.wchar_t() - @expectedFailureLinux # bugzilla 15038: missing wide char support on Linux @dwarf_test def test_with_dwarf(self): """Test that C++ supports wchar_t correctly.""" |