[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