//===-- 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(); }