aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/lldb/Target/Process.h36
-rw-r--r--source/DataFormatters/CXXFormatterFunctions.cpp11
-rw-r--r--source/Target/Process.cpp54
-rw-r--r--test/lang/cpp/char1632_t/TestChar1632T.py1
-rw-r--r--test/lang/cpp/wchar_t/TestCxxWCharT.py1
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."""