[Lldb-commits] [lldb] r164792 - in /lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime: AppleObjCRuntimeV2.cpp AppleObjCTypeVendor.cpp

Sean Callanan scallanan at apple.com
Thu Sep 27 13:38:15 PDT 2012


Author: spyffe
Date: Thu Sep 27 15:38:15 2012
New Revision: 164792

URL: http://llvm.org/viewvc/llvm-project?rev=164792&view=rev
Log:
Fixed some bugs in the runtime reader code.  Also
added a parser for method signatures in the
Objective-C @encode format.

Modified:
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp?rev=164792&r1=164791&r2=164792&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Thu Sep 27 15:38:15 2012
@@ -1084,6 +1084,9 @@
         if (!base_method_list->Read(process_sp, ro->m_baseMethods_la))
             return false;
         
+        if (base_method_list->m_entsize != method_t::GetSize(process_sp))
+            return false;
+        
         std::auto_ptr <method_t> method;
         method.reset(new method_t);
         
@@ -1462,10 +1465,18 @@
         std::string     m_name;
         std::string     m_types;
         
+        static size_t GetSize(ProcessSP &process_sp)
+        {
+            size_t ptr_size = process_sp->GetAddressByteSize();
+
+            return ptr_size     // SEL name;
+                   + ptr_size   // const char *types;
+                   + ptr_size;  // IMP imp;
+        }
+        
         bool Read(ProcessSP &process_sp, lldb::addr_t addr)
         {
-            size_t size = sizeof(uint32_t)  // uint32_t entsize_NEVER_USE;
-                        + sizeof(uint32_t); // uint32_t count;
+            size_t size = GetSize(process_sp);
             
             DataBufferHeap buffer (size, '\0');
             Error error;

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp?rev=164792&r1=164791&r2=164792&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp Thu Sep 27 15:38:15 2012
@@ -193,7 +193,12 @@
                                                                                 NULL);
     
     m_external_source->SetMetadata((uintptr_t)new_iface_decl, (uint64_t)isa);
-    new_iface_decl->setHasExternalVisibleStorage();
+    
+    static ConstString NSObject_name("NSObject");
+    
+    if (name != NSObject_name)
+        new_iface_decl->setHasExternalVisibleStorage();
+    
     ast_ctx->getTranslationUnitDecl()->addDecl(new_iface_decl);
     
     m_isa_to_interface[isa] = new_iface_decl;
@@ -201,9 +206,291 @@
     return new_iface_decl;
 }
 
+class ObjCRuntimeMethodType
+{
+public:
+    ObjCRuntimeMethodType (const char *types) : m_is_valid(false)
+    {
+        const char *cursor = types;
+        enum ParserState {
+            Start = 0,
+            InType,
+            InPos
+        } state = Start;
+        const char *type = NULL;
+        int brace_depth = 0;
+        
+        uint32_t stepsLeft = 256;
+        
+        while (1)
+        {
+            if (--stepsLeft == 0)
+            {
+                m_is_valid = false;
+                return;
+            }
+            
+            switch (state)
+            {
+            case Start:
+                {
+                    switch (*cursor)
+                    {
+                    default:
+                        state = InType;
+                        type = cursor;
+                        break;
+                    case '\0':
+                        m_is_valid = true;
+                        return;
+                    case '0': case '1': case '2': case '3': case '4':
+                    case '5': case '6': case '7': case '8': case '9':
+                        m_is_valid = false;
+                        return;
+                    }
+                }
+                break;
+            case InType:
+                {
+                    switch (*cursor)
+                    {
+                    default:
+                        ++cursor;
+                        break;
+                    case '0': case '1': case '2': case '3': case '4':
+                    case '5': case '6': case '7': case '8': case '9':
+                        if (!brace_depth)
+                        {
+                            state = InPos;
+                            if (type)
+                            {
+                                m_type_vector.push_back(std::string(type, (cursor - type)));
+                            }
+                            else
+                            {
+                                m_is_valid = false;
+                                return;
+                            }
+                            type = NULL;
+                        }
+                        else
+                        {
+                            ++cursor;
+                        }
+                        break;
+                    case '[': case '{': case '(':
+                        ++brace_depth;
+                        ++cursor;
+                        break;
+                    case ']': case '}': case ')':
+                        if (!brace_depth)
+                        {
+                            m_is_valid = false;
+                            return;
+                        }
+                        --brace_depth;
+                        ++cursor;
+                        break;
+                    case '\0':
+                        m_is_valid = false;
+                        return;
+                    }
+                }
+                break;
+            case InPos:
+                {
+                    switch (*cursor)
+                    {
+                    default:
+                        state = InType;
+                        type = cursor;
+                        break;
+                    case '0': case '1': case '2': case '3': case '4':
+                    case '5': case '6': case '7': case '8': case '9':
+                        ++cursor;
+                        break;
+                    case '\0':
+                        m_is_valid = true;
+                        return;
+                    }
+                }
+                break;
+            }
+        }
+    }
+    
+    clang::ObjCMethodDecl *BuildMethod (clang::ObjCInterfaceDecl *interface_decl, const char *name)
+    {
+        lldb::LogSP log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));  // FIXME - a more appropriate log channel?
+        
+        if (!m_is_valid || m_type_vector.size() < 3)
+            return NULL;
+        
+        clang::ASTContext &ast_ctx(interface_decl->getASTContext());
+        
+        clang::QualType return_qual_type;
+        
+        const bool isInstance = true;
+        const bool isVariadic = false;
+        const bool isSynthesized = false;
+        const bool isImplicitlyDeclared = true;
+        const bool isDefined = false;
+        const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None;
+        const bool HasRelatedResultType = false;
+        
+        std::vector <clang::IdentifierInfo *> selector_components;
+        
+        const char *name_cursor = name;
+        bool is_zero_argument = true;
+        
+        while (*name_cursor != '\0')
+        {
+            char *colon_loc = strchr(name_cursor, ':');
+            if (!colon_loc)
+            {
+                selector_components.push_back(&ast_ctx.Idents.get(llvm::StringRef(name_cursor)));
+                break;
+            }
+            else
+            {
+                is_zero_argument = true;
+                selector_components.push_back(&ast_ctx.Idents.get(llvm::StringRef(name_cursor, colon_loc - name_cursor)));
+                name_cursor = colon_loc + 1;
+            }
+        }
+        
+        clang::Selector sel = ast_ctx.Selectors.getSelector(is_zero_argument ? 0 : selector_components.size(), selector_components.data());
+        
+        clang::QualType ret_type = BuildType(ast_ctx, m_type_vector[0].c_str());
+        
+        if (ret_type.isNull())
+            return NULL;
+        
+        clang::ObjCMethodDecl *ret = clang::ObjCMethodDecl::Create(ast_ctx,
+                                                                   clang::SourceLocation(),
+                                                                   clang::SourceLocation(),
+                                                                   sel,
+                                                                   ret_type,
+                                                                   NULL,
+                                                                   interface_decl,
+                                                                   isInstance,
+                                                                   isVariadic,
+                                                                   isSynthesized,
+                                                                   isImplicitlyDeclared,
+                                                                   isDefined,
+                                                                   impControl,
+                                                                   HasRelatedResultType);
+        
+        std::vector <clang::ParmVarDecl*> parm_vars;
+        
+        for (size_t ai = 3, ae = m_type_vector.size();
+             ai != ae;
+             ++ai)
+        {
+            clang::QualType arg_type = BuildType(ast_ctx, m_type_vector[ai].c_str());
+            
+            if (arg_type.isNull())
+                return NULL; // well, we just wasted a bunch of time.  Wish we could delete the stuff we'd just made!
+
+            parm_vars.push_back(clang::ParmVarDecl::Create(ast_ctx,
+                                                           ret,
+                                                           clang::SourceLocation(),
+                                                           clang::SourceLocation(),
+                                                           NULL,
+                                                           arg_type,
+                                                           NULL,
+                                                           clang::SC_None,
+                                                           clang::SC_None,
+                                                           NULL));
+        }
+        
+        ret->setMethodParams(ast_ctx, llvm::ArrayRef<clang::ParmVarDecl*>(parm_vars), llvm::ArrayRef<clang::SourceLocation>());
+        
+        return ret;
+    }
+private:
+    clang::QualType BuildType (clang::ASTContext &ast_ctx, const char *type)
+    {
+        if (!type)
+            return clang::QualType();
+        
+        switch (*type)
+        {
+        default:
+            return ast_ctx.UnknownAnyTy;
+        case 'r':
+            {
+                clang::QualType target_type = BuildType(ast_ctx, type+1);
+                if (target_type.isNull())
+                    return clang::QualType();
+                else
+                    return ast_ctx.getConstType(target_type);
+            }
+        case '^':
+        {
+            clang::QualType target_type = BuildType(ast_ctx, type+1);
+            if (target_type.isNull())
+                return clang::QualType();
+            else
+                return ast_ctx.getPointerType(target_type);
+        }
+        case 'c':
+            return ast_ctx.CharTy;
+        case 'i':
+            return ast_ctx.IntTy;
+        case 's':
+            return ast_ctx.ShortTy;
+        case 'l':
+            if (ast_ctx.getTypeSize(ast_ctx.VoidTy) == 64)
+                return ast_ctx.IntTy;
+            else
+                return ast_ctx.LongTy;
+        case 'q':
+            return ast_ctx.LongLongTy;
+        case 'C':
+            return ast_ctx.UnsignedCharTy;
+        case 'I':
+            return ast_ctx.UnsignedIntTy;
+        case 'S':
+            return ast_ctx.UnsignedShortTy;
+        case 'L':
+            if (ast_ctx.getTypeSize(ast_ctx.VoidTy) == 64)
+                return ast_ctx.UnsignedIntTy;
+            else
+                return ast_ctx.UnsignedLongTy;
+        case 'Q':
+            return ast_ctx.UnsignedLongLongTy;
+        case 'f':
+            return ast_ctx.FloatTy;
+        case 'd':
+            return ast_ctx.DoubleTy;
+        case 'B':
+            return ast_ctx.BoolTy;
+        case 'v':
+            return ast_ctx.VoidTy;
+        case '*':
+            return ast_ctx.getPointerType(ast_ctx.CharTy);
+        case '@':
+            return ast_ctx.getObjCIdType();
+        case '#':
+            return ast_ctx.getObjCClassType();
+        case ':':
+            return ast_ctx.getObjCSelType();
+        }
+        return clang::QualType();
+    }
+    
+    typedef std::vector <std::string> TypeVector;
+    
+    TypeVector  m_type_vector;
+    bool        m_is_valid;
+};
+
 bool
 AppleObjCTypeVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl)
 {
+    lldb::LogSP log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));  // FIXME - a more appropriate log channel?
+    
     ObjCLanguageRuntime::ObjCISA objc_isa = (ObjCLanguageRuntime::ObjCISA)m_external_source->GetMetadata((uintptr_t)interface_decl);
     
     if (!objc_isa)
@@ -214,6 +501,8 @@
     
     interface_decl->startDefinition();
     
+    interface_decl->setHasExternalVisibleStorage(false);
+    
     ObjCLanguageRuntime::ClassDescriptorSP descriptor = m_runtime.GetClassDescriptor(objc_isa);
     
     if (!descriptor)
@@ -227,15 +516,28 @@
         interface_decl->setSuperClass(superclass_decl);
     };
     
-    auto method_func = [interface_decl, this](const char *name, const char *types)
-    {
+    auto method_func = [log, interface_decl, this](const char *name, const char *types)
+    {        
+        ObjCRuntimeMethodType method_type(types);
         
+        clang::ObjCMethodDecl *method_decl = method_type.BuildMethod (interface_decl, name);
+        
+        if (method_decl)
+            interface_decl->addDecl(method_decl);
     };
     
     if (!descriptor->Describe(superclass_func, method_func))
         return false;
-            
-    interface_decl->setHasExternalVisibleStorage(false);
+    
+    if (log)
+    {
+        ASTDumper method_dumper ((clang::Decl*)interface_decl);
+        
+        log->Printf("[AppleObjCTypeVendor::FinishDecl] Finished Objective-C interface");
+        
+        method_dumper.ToLog(log, "  [AOTV::FD] ");
+    }
+    
     return true;
 }
 





More information about the lldb-commits mailing list