[Lldb-commits] [lldb] r180141 - The new ReadStringFromMemory() API does not work correctly with NSStrings that have an explicit length and no NULL terminator

Enrico Granata egranata at apple.com
Tue Apr 23 13:05:05 PDT 2013


Author: enrico
Date: Tue Apr 23 15:05:05 2013
New Revision: 180141

URL: http://llvm.org/viewvc/llvm-project?rev=180141&view=rev
Log:
The new ReadStringFromMemory() API does not work correctly with NSStrings that have an explicit length and no NULL terminator
This checkin reverts NSString to the old behavior when appropriate, and cleans up the syntax to call the UTF Reader&Dumper function
Incidentally, add a "-d" command-line flag to redo.py with the same semantics as "-d" in dotest.py


Modified:
    lldb/trunk/source/DataFormatters/CXXFormatterFunctions.cpp
    lldb/trunk/test/redo.py

Modified: lldb/trunk/source/DataFormatters/CXXFormatterFunctions.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/DataFormatters/CXXFormatterFunctions.cpp?rev=180141&r1=180140&r2=180141&view=diff
==============================================================================
--- lldb/trunk/source/DataFormatters/CXXFormatterFunctions.cpp (original)
+++ lldb/trunk/source/DataFormatters/CXXFormatterFunctions.cpp Tue Apr 23 15:05:05 2013
@@ -216,9 +216,9 @@ DumpUTFBufferToStream (ConversionResult
         
         if (ConvertFunction)
         {
-            utf8_data_buffer_sp.reset(new DataBufferHeap(bufferSPSize,0));
+            utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0));
             utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes();
-            utf8_data_end_ptr = utf8_data_ptr + bufferSPSize;
+            utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize();
             ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion );
             utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr
         }
@@ -246,21 +246,151 @@ DumpUTFBufferToStream (ConversionResult
 }
 
 template<typename SourceDataType>
+class ReadUTFBufferAndDumpToStreamOptions
+{
+public:
+    typedef ConversionResult (*ConvertFunctionType) (const SourceDataType**,
+                                                     const SourceDataType*,
+                                                     UTF8**,
+                                                     UTF8*,
+                                                     ConversionFlags);
+    
+    ReadUTFBufferAndDumpToStreamOptions () :
+    m_conversion_function(NULL),
+    m_location(0),
+    m_process_sp(),
+    m_stream(NULL),
+    m_prefix_token('@'),
+    m_quote('"'),
+    m_source_size(0),
+    m_needs_zero_termination(true)
+    {
+    }
+    
+    ReadUTFBufferAndDumpToStreamOptions&
+    SetConversionFunction (ConvertFunctionType f)
+    {
+        m_conversion_function = f;
+        return *this;
+    }
+    
+    ConvertFunctionType
+    GetConversionFunction () const
+    {
+        return m_conversion_function;
+    }
+    
+    ReadUTFBufferAndDumpToStreamOptions&
+    SetLocation (uint64_t l)
+    {
+        m_location = l;
+        return *this;
+    }
+    
+    uint64_t
+    GetLocation () const
+    {
+        return m_location;
+    }
+    
+    ReadUTFBufferAndDumpToStreamOptions&
+    SetProcessSP (ProcessSP p)
+    {
+        m_process_sp = p;
+        return *this;
+    }
+    
+    ProcessSP
+    GetProcessSP () const
+    {
+        return m_process_sp;
+    }
+    
+    ReadUTFBufferAndDumpToStreamOptions&
+    SetStream (Stream* s)
+    {
+        m_stream = s;
+        return *this;
+    }
+    
+    Stream*
+    GetStream () const
+    {
+        return m_stream;
+    }
+    
+    ReadUTFBufferAndDumpToStreamOptions&
+    SetPrefixToken (char p)
+    {
+        m_prefix_token = p;
+        return *this;
+    }
+    
+    char
+    GetPrefixToken () const
+    {
+        return m_prefix_token;
+    }
+    
+    ReadUTFBufferAndDumpToStreamOptions&
+    SetQuote (char q)
+    {
+        m_quote = q;
+        return *this;
+    }
+    
+    char
+    GetQuote () const
+    {
+        return m_quote;
+    }
+    
+    ReadUTFBufferAndDumpToStreamOptions&
+    SetSourceSize (uint32_t s)
+    {
+        m_source_size = s;
+        return *this;
+    }
+    
+    uint32_t
+    GetSourceSize () const
+    {
+        return m_source_size;
+    }
+    
+    ReadUTFBufferAndDumpToStreamOptions&
+    SetNeedsZeroTermination (bool z)
+    {
+        m_needs_zero_termination = z;
+        return *this;
+    }
+    
+    bool
+    GetNeedsZeroTermination () const
+    {
+        return m_needs_zero_termination;
+    }
+    
+private:
+    ConvertFunctionType m_conversion_function;
+    uint64_t m_location;
+    ProcessSP m_process_sp;
+    Stream* m_stream;
+    char m_prefix_token;
+    char m_quote;
+    uint32_t m_source_size;
+    bool m_needs_zero_termination;
+};
+
+template<typename SourceDataType>
 static bool
-ReadUTFBufferAndDumpToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
-                                                                   const SourceDataType*,
-                                                                   UTF8**,
-                                                                   UTF8*,
-                                                                   ConversionFlags),
-                              uint64_t location,
-                              const ProcessSP& process_sp,
-                              Stream& stream,
-                              char prefix_token = '@',
-                              char quote = '"',
-                              uint32_t sourceSize = 0)
+ReadUTFBufferAndDumpToStream (const ReadUTFBufferAndDumpToStreamOptions<SourceDataType>& options)
 {
-    if (location == 0 || location == LLDB_INVALID_ADDRESS)
+    if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS)
         return false;
+    
+    ProcessSP process_sp(options.GetProcessSP());
+    
     if (!process_sp)
         return false;
 
@@ -269,11 +399,20 @@ ReadUTFBufferAndDumpToStream (Conversion
     if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32)
         return false;
     // if not UTF8, I need a conversion function to return proper UTF8
-    if (origin_encoding != 8 && !ConvertFunction)
+    if (origin_encoding != 8 && !options.GetConversionFunction())
+        return false;
+    
+    if (!options.GetStream())
         return false;
 
+    uint32_t sourceSize = options.GetSourceSize();
+    bool needs_zero_terminator = options.GetNeedsZeroTermination();
+    
     if (!sourceSize)
+    {
         sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
+        needs_zero_terminator = true;
+    }
     else
         sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
     
@@ -287,16 +426,21 @@ ReadUTFBufferAndDumpToStream (Conversion
     Error error;
     char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes()); 
 
-    size_t data_read = process_sp->ReadStringFromMemory(location, buffer, bufferSPSize, error, type_width);
+    size_t data_read = 0;
+    if (needs_zero_terminator)
+        data_read = process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width);
+    else
+        data_read = process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error);
+
     if (error.Fail() || data_read == 0)
     {
-        stream.Printf("unable to read data");
+        options.GetStream()->Printf("unable to read data");
         return true;
     }
     
     DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
     
-    return DumpUTFBufferToStream(ConvertFunction, data, stream, prefix_token, quote, sourceSize);
+    return DumpUTFBufferToStream(options.GetConversionFunction(), data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize);
 }
 
 bool
@@ -311,10 +455,14 @@ lldb_private::formatters::Char16StringSu
     if (!valobj_addr)
         return false;
     
-    if (!ReadUTFBufferAndDumpToStream<UTF16>(ConvertUTF16toUTF8,valobj_addr,
-                                                                 process_sp,
-                                                                 stream,
-                                                                 'u'))
+    ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
+    options.SetLocation(valobj_addr);
+    options.SetConversionFunction(ConvertUTF16toUTF8);
+    options.SetProcessSP(process_sp);
+    options.SetStream(&stream);
+    options.SetPrefixToken('u');
+    
+    if (!ReadUTFBufferAndDumpToStream(options))
     {
         stream.Printf("Summary Unavailable");
         return true;
@@ -335,10 +483,14 @@ lldb_private::formatters::Char32StringSu
     if (!valobj_addr)
         return false;
     
-    if (!ReadUTFBufferAndDumpToStream<UTF32>(ConvertUTF32toUTF8,valobj_addr,
-                                                                 process_sp,
-                                                                 stream,
-                                                                 'U'))
+    ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
+    options.SetLocation(valobj_addr);
+    options.SetConversionFunction(ConvertUTF32toUTF8);
+    options.SetProcessSP(process_sp);
+    options.SetStream(&stream);
+    options.SetPrefixToken('u');
+    
+    if (!ReadUTFBufferAndDumpToStream(options))
     {
         stream.Printf("Summary Unavailable");
         return true;
@@ -374,23 +526,42 @@ lldb_private::formatters::WCharStringSum
     switch (wchar_size)
     {
         case 8:
+        {
             // utf 8
-            return ReadUTFBufferAndDumpToStream<UTF8>(nullptr, data_addr,
-                                                               process_sp,
-                                                               stream,
-                                                               'L');
+            
+            ReadUTFBufferAndDumpToStreamOptions<UTF8> options;
+            options.SetLocation(data_addr);
+            options.SetConversionFunction(nullptr);
+            options.SetProcessSP(process_sp);
+            options.SetStream(&stream);
+            options.SetPrefixToken('L');
+
+            return ReadUTFBufferAndDumpToStream(options);
+        }
         case 16:
+        {
             // utf 16
-            return ReadUTFBufferAndDumpToStream<UTF16>(ConvertUTF16toUTF8, data_addr,
-                                                                           process_sp,
-                                                                           stream,
-                                                                           'L');
+            ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
+            options.SetLocation(data_addr);
+            options.SetConversionFunction(ConvertUTF16toUTF8);
+            options.SetProcessSP(process_sp);
+            options.SetStream(&stream);
+            options.SetPrefixToken('L');
+            
+            return ReadUTFBufferAndDumpToStream(options);
+        }
         case 32:
+        {
             // utf 32
-            return ReadUTFBufferAndDumpToStream<UTF32>(ConvertUTF32toUTF8, data_addr,
-                                                                           process_sp,
-                                                                           stream,
-                                                                           'L');
+            ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
+            options.SetLocation(data_addr);
+            options.SetConversionFunction(ConvertUTF32toUTF8);
+            options.SetProcessSP(process_sp);
+            options.SetStream(&stream);
+            options.SetPrefixToken('L');
+            
+            return ReadUTFBufferAndDumpToStream(options);
+        }
         default:
             stream.Printf("size for wchar_t is not valid");
             return true;
@@ -825,7 +996,7 @@ lldb_private::formatters::NSStringSummar
 #endif
                    void* contentsAllocator = %p
                }
-           } variants;
+           } variants; ==> (M:%dI:%dL:%zuU:%dS:%dN:%d)
            };\n)",
     my_string_data._cfisa,
     my_string_data._cfinfo[0],my_string_data._cfinfo[1],my_string_data._cfinfo[2],my_string_data._cfinfo[3],
@@ -845,7 +1016,13 @@ lldb_private::formatters::NSStringSummar
     my_string_data.variants.notInlineMutable.capacityProvidedExternally,
     my_string_data.variants.notInlineMutable.desiredCapacity,
     my_string_data.variants.notInlineMutable.desiredCapacity,
-    my_string_data.variants.notInlineMutable.contentsAllocator);
+    my_string_data.variants.notInlineMutable.contentsAllocator,
+    is_mutable,
+    is_inline,
+    explicit_length,
+    is_unicode,
+    is_special,
+    has_null);
 #endif
     
     if (strcmp(class_name,"NSString") &&
@@ -862,16 +1039,6 @@ lldb_private::formatters::NSStringSummar
         return true;
     }
     
-#ifdef WANT_DEEP_PRNT
-    stream.Printf("(M:%dI:%dL:%zuU:%dS:%dN:%d) ",
-                  is_mutable,
-                  is_inline,
-                  explicit_length,
-                  is_unicode,
-                  is_special,
-                  has_null);
-#endif
-    
     if (is_mutable)
     {
         uint64_t location = 2 * ptr_size + valobj_addr;
@@ -879,7 +1046,18 @@ lldb_private::formatters::NSStringSummar
         if (error.Fail())
             return false;
         if (has_explicit_length and is_unicode)
-            return ReadUTFBufferAndDumpToStream<UTF16> (ConvertUTF16toUTF8,location, process_sp, stream, '@', '"', explicit_length);
+        {
+            ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
+            options.SetConversionFunction(ConvertUTF16toUTF8);
+            options.SetLocation(location);
+            options.SetProcessSP(process_sp);
+            options.SetStream(&stream);
+            options.SetPrefixToken('@');
+            options.SetQuote('"');
+            options.SetSourceSize(explicit_length);
+            options.SetNeedsZeroTermination(false);
+            return ReadUTFBufferAndDumpToStream (options);
+        }
         else
             return ReadAsciiBufferAndDumpToStream(location+1,process_sp,stream, explicit_length);
     }
@@ -900,19 +1078,37 @@ lldb_private::formatters::NSStringSummar
             }
             else
                 location += ptr_size;
-                }
+        }
         else
         {
             location = process_sp->ReadPointerFromMemory(location, error);
             if (error.Fail())
                 return false;
         }
-        return ReadUTFBufferAndDumpToStream<UTF16> (ConvertUTF16toUTF8, location, process_sp, stream, '@', '"', explicit_length);
+        ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
+        options.SetConversionFunction(ConvertUTF16toUTF8);
+        options.SetLocation(location);
+        options.SetProcessSP(process_sp);
+        options.SetStream(&stream);
+        options.SetPrefixToken('@');
+        options.SetQuote('"');
+        options.SetSourceSize(explicit_length);
+        options.SetNeedsZeroTermination(has_explicit_length == false);
+        return ReadUTFBufferAndDumpToStream (options);
     }
     else if (is_special)
     {
         uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8);
-        return ReadUTFBufferAndDumpToStream<UTF16> (ConvertUTF16toUTF8, location, process_sp, stream, '@', '"', explicit_length);
+        ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
+        options.SetConversionFunction(ConvertUTF16toUTF8);
+        options.SetLocation(location);
+        options.SetProcessSP(process_sp);
+        options.SetStream(&stream);
+        options.SetPrefixToken('@');
+        options.SetQuote('"');
+        options.SetSourceSize(explicit_length);
+        options.SetNeedsZeroTermination(has_explicit_length == false);
+        return ReadUTFBufferAndDumpToStream (options);
     }
     else if (is_inline)
     {

Modified: lldb/trunk/test/redo.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/redo.py?rev=180141&r1=180140&r2=180141&view=diff
==============================================================================
--- lldb/trunk/test/redo.py (original)
+++ lldb/trunk/test/redo.py Tue Apr 23 15:05:05 2013
@@ -28,6 +28,8 @@ redo_specs = []
 # will be considered for re-run.  Examples: ['X86_64', 'clang'].
 filename_components = []
 
+do_delay = False
+
 # There is a known bug with respect to comp_specs and arch_specs, in that if we
 # encountered "-C clang" and "-C gcc" when visiting the session files, both
 # compilers will end up in the invocation of the test driver when rerunning.
@@ -40,12 +42,13 @@ arch_specs = set()
 
 def usage():
     print"""\
-Usage: redo.py [-F filename_component] [-n] [session_dir]
+Usage: redo.py [-F filename_component] [-n] [session_dir] [-d]
 where options:
 -F : only consider the test for re-run if the session filename conatins the filename component
      for example: -F x86_64
 -n : when running the tests, do not turn on trace mode, i.e, no '-t' option
      is passed to the test driver (this will run the tests faster)
+-d : pass -d down to the test driver (introduces a delay so you can attach with a debugger)
 
 and session_dir specifies the session directory which contains previously
 recorded session infos for all the test cases which either failed or errored.
@@ -81,6 +84,7 @@ def redo(suffix, dir, names):
     global comp_pattern
     global arch_pattern
     global filename_components
+    global do_delay
 
     for name in names:
         if name.endswith(suffix):
@@ -111,6 +115,7 @@ def main():
     global no_trace
     global redo_specs
     global filename_components
+    global do_delay
 
     test_dir = sys.path[0]
     if not test_dir:
@@ -139,6 +144,8 @@ def main():
             filename_components.append(sys.argv[index])
         elif sys.argv[index] == '-n':
             no_trace = True
+        elif sys.argv[index] == '-d':
+            do_delay = True
 
         index += 1
 
@@ -176,7 +183,7 @@ def main():
     for arch in arch_specs:
         archs += "--arch %s " % (arch)
 
-    command = "./dotest.py %s %s -v %s -f " % (compilers, archs, "" if no_trace else "-t")
+    command = "./dotest.py %s %s -v %s %s -f " % (compilers, archs, "" if no_trace else "-t", "-d" if do_delay else "")
 
 
     print "Running %s" % (command + filters)





More information about the lldb-commits mailing list