[Lldb-commits] [lldb] r173076 - in /lldb/trunk: include/lldb/Interpreter/OptionGroupFormat.h include/lldb/Target/Target.h source/Commands/CommandObjectMemory.cpp source/Interpreter/OptionGroupFormat.cpp source/Target/Target.cpp
Enrico Granata
egranata at apple.com
Mon Jan 21 11:20:50 PST 2013
Author: enrico
Date: Mon Jan 21 13:20:50 2013
New Revision: 173076
URL: http://llvm.org/viewvc/llvm-project?rev=173076&view=rev
Log:
<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"
Modified:
lldb/trunk/include/lldb/Interpreter/OptionGroupFormat.h
lldb/trunk/include/lldb/Target/Target.h
lldb/trunk/source/Commands/CommandObjectMemory.cpp
lldb/trunk/source/Interpreter/OptionGroupFormat.cpp
lldb/trunk/source/Target/Target.cpp
Modified: lldb/trunk/include/lldb/Interpreter/OptionGroupFormat.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/OptionGroupFormat.h?rev=173076&r1=173075&r2=173076&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/OptionGroupFormat.h (original)
+++ lldb/trunk/include/lldb/Interpreter/OptionGroupFormat.h Mon Jan 21 13:20:50 2013
@@ -97,6 +97,11 @@
return m_count;
}
+ bool
+ HasGDBFormat () const
+ {
+ return m_has_gdb_format;
+ }
bool
AnyOptionWasSet () const
@@ -119,6 +124,8 @@
OptionValueUInt64 m_count;
char m_prev_gdb_format;
char m_prev_gdb_size;
+
+ bool m_has_gdb_format;
};
} // namespace lldb_private
Modified: lldb/trunk/include/lldb/Target/Target.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=173076&r1=173075&r2=173076&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Target.h (original)
+++ lldb/trunk/include/lldb/Target/Target.h Mon Jan 21 13:20:50 2013
@@ -846,7 +846,13 @@
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,
Modified: lldb/trunk/source/Commands/CommandObjectMemory.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectMemory.cpp?rev=173076&r1=173075&r2=173076&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectMemory.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectMemory.cpp Mon Jan 21 13:20:50 2013
@@ -586,7 +586,7 @@
}
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 @@
return false;
}
+
+
DataBufferSP data_sp;
size_t bytes_read = 0;
if (clang_ast_type.GetOpaqueQualType())
@@ -651,7 +653,7 @@
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 @@
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;
Modified: lldb/trunk/source/Interpreter/OptionGroupFormat.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupFormat.cpp?rev=173076&r1=173075&r2=173076&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionGroupFormat.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionGroupFormat.cpp Mon Jan 21 13:20:50 2013
@@ -205,6 +205,7 @@
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 @@
m_format.Clear();
m_byte_size.Clear();
m_count.Clear();
+ m_has_gdb_format = false;
}
Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=173076&r1=173075&r2=173076&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Mon Jan 21 13:20:50 2013
@@ -1327,6 +1327,82 @@
}
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,
More information about the lldb-commits
mailing list