[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