Initial checkin of lldb code from internal Apple repo.


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@105619 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Target/ObjCObjectPrinter.cpp b/source/Target/ObjCObjectPrinter.cpp
new file mode 100644
index 0000000..81c73aa
--- /dev/null
+++ b/source/Target/ObjCObjectPrinter.cpp
@@ -0,0 +1,120 @@
+//===-- ObjCObjectPrinter.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/StreamString.h"
+#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "ObjCObjectPrinter.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ObjCObjectPrinter constructor
+//----------------------------------------------------------------------
+ObjCObjectPrinter::ObjCObjectPrinter (Process &process) :
+    m_process(process)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ObjCObjectPrinter::~ObjCObjectPrinter ()
+{
+}
+
+bool
+ObjCObjectPrinter::PrintObject (ConstString &str, Value &object_ptr, ExecutionContext &exe_ctx)
+{
+    if (!exe_ctx.process)
+        return false;
+    
+    const Address *function_address = GetPrintForDebuggerAddr();
+
+    if (!function_address)
+        return false;
+    
+    const char *target_triple = exe_ctx.process->GetTargetTriple().GetCString();
+    ClangASTContext *ast_context = exe_ctx.target->GetScratchClangASTContext();
+    
+    void *return_qualtype = ast_context->GetCStringType(true);
+    Value ret;
+    ret.SetContext(Value::eContextTypeOpaqueClangQualType, return_qualtype);
+    
+    ValueList arg_value_list;
+    arg_value_list.PushValue(object_ptr);
+    
+    ClangFunction func(target_triple, ast_context, return_qualtype, *function_address, arg_value_list);
+    StreamString error_stream;
+    
+    lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS;
+    func.InsertFunction(exe_ctx, wrapper_struct_addr, error_stream);
+    // FIXME: Check result of ExecuteFunction.
+    func.ExecuteFunction(exe_ctx, &wrapper_struct_addr, error_stream, true, 1000, true, ret);
+        
+    addr_t result_ptr = ret.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+    
+    // poor man's strcpy
+    
+    size_t len = 0;
+    bool keep_reading = true;
+    Error error;
+    while (keep_reading)
+    {
+        char byte;
+        
+        if (exe_ctx.process->ReadMemory(result_ptr + len, &byte, 1, error) != 1)
+            return false;
+        
+        if (byte == '\0')
+            keep_reading = false;
+        else
+            ++len;
+    }
+    
+    char desc[len + 1];
+    
+    if (exe_ctx.process->ReadMemory(result_ptr, &desc[0], len + 1, error) != len + 1)
+        return false;
+    
+    str.SetCString(desc);
+    
+    return true;
+}
+
+Address *
+ObjCObjectPrinter::GetPrintForDebuggerAddr()
+{
+    if (!m_PrintForDebugger_addr.get())
+    {
+        ModuleList &modules = m_process.GetTarget().GetImages();
+        
+        SymbolContextList contexts;
+        SymbolContext context;
+        
+        if((!modules.FindSymbolsWithNameAndType(ConstString ("_NSPrintForDebugger"), eSymbolTypeCode, contexts)) &&
+           (!modules.FindSymbolsWithNameAndType(ConstString ("_CFPrintForDebugger"), eSymbolTypeCode, contexts)))
+            return NULL;
+        
+        contexts.GetContextAtIndex(0, context);
+        
+        m_PrintForDebugger_addr.reset(new Address(context.symbol->GetValue()));
+    }
+    
+    return m_PrintForDebugger_addr.get();
+}
+