summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEnrico Granata <egranata@apple.com>2013-01-21 19:20:50 +0000
committerEnrico Granata <egranata@apple.com>2013-01-21 19:20:50 +0000
commit6b4ddc655a3dafc53e98efd9560ee8185ae717fc (patch)
tree754719972dbd38cab3e3dec13af9478ade7e9561
parent2cec01916c47a097f8777c85c22e66a88b684949 (diff)
downloadbcm5719-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.h7
-rw-r--r--lldb/include/lldb/Target/Target.h8
-rw-r--r--lldb/source/Commands/CommandObjectMemory.cpp46
-rw-r--r--lldb/source/Interpreter/OptionGroupFormat.cpp2
-rw-r--r--lldb/source/Target/Target.cpp76
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,
OpenPOWER on IntegriCloud