diff options
| author | Sean Callanan <scallanan@apple.com> | 2012-09-27 20:38:15 +0000 |
|---|---|---|
| committer | Sean Callanan <scallanan@apple.com> | 2012-09-27 20:38:15 +0000 |
| commit | 2885a7088d0a66c2446e34e731560af9277d689d (patch) | |
| tree | 95e77b6a11d0a31ffe7472193356298f0e1fff5b | |
| parent | dd09c343515dff9742f5c9987752b783d3a731e5 (diff) | |
| download | bcm5719-llvm-2885a7088d0a66c2446e34e731560af9277d689d.tar.gz bcm5719-llvm-2885a7088d0a66c2446e34e731560af9277d689d.zip | |
Fixed some bugs in the runtime reader code. Also
added a parser for method signatures in the
Objective-C @encode format.
llvm-svn: 164792
| -rw-r--r-- | lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp | 15 | ||||
| -rw-r--r-- | lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp | 312 |
2 files changed, 320 insertions, 7 deletions
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 736f245a2cc..b204b466003 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -1084,6 +1084,9 @@ public: 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 @@ private: 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; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp index 78ff9d40bcd..2ad2883882f 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeVendor.cpp @@ -193,7 +193,12 @@ AppleObjCTypeVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa) 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 @@ AppleObjCTypeVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa) 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 @@ AppleObjCTypeVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) interface_decl->startDefinition(); + interface_decl->setHasExternalVisibleStorage(false); + ObjCLanguageRuntime::ClassDescriptorSP descriptor = m_runtime.GetClassDescriptor(objc_isa); if (!descriptor) @@ -227,15 +516,28 @@ AppleObjCTypeVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) 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; } |

