Exemplo n.º 1
0
extern "C" __declspec(dllexport) void objc_exception_throw(void *exception)
{
    int typeCount = 0;

    //  Get count of all types in exception
    Class curType = object_getClass((id) exception);
    while (curType != nil) {
        typeCount++;

        curType = class_getSuperclass(curType);
    }

    typeCount++; //  For id

    __ObjC_CatchableTypeArray *exceptTypes = (__ObjC_CatchableTypeArray *)_alloca(sizeof(__ObjC_CatchableTypeArray) + sizeof(__ObjC_CatchableType *) * typeCount);

	//  Add exception type and all base types to throw information
    typeCount = 0;
    curType = object_getClass((id)exception);
    while (curType != nil) {
        exceptTypes->types[typeCount] = (__ObjC_CatchableType *)_alloca(sizeof(__ObjC_CatchableType));
        memset(exceptTypes->types[typeCount], 0, sizeof(__ObjC_CatchableType));
        exceptTypes->types[typeCount]->flags = 1;
        exceptTypes->types[typeCount]->mdisp = 0;
        exceptTypes->types[typeCount]->pdisp = -1;
        exceptTypes->types[typeCount]->vdisp = 0;
        exceptTypes->types[typeCount]->type = (const char *) alloca(32);
        memset((void *) exceptTypes->types[typeCount]->type, 0, 32);
        memcpy((char *)exceptTypes->types[typeCount]->type, class_getName(curType), strlen(class_getName(curType)));
        exceptTypes->types[typeCount]->size = 4;
        typeCount++;

        curType = class_getSuperclass(curType);
    }

    //  Add id
    exceptTypes->types[typeCount] = (__ObjC_CatchableType *)_alloca(sizeof(__ObjC_CatchableType));
    memset(exceptTypes->types[typeCount], 0, sizeof(__ObjC_CatchableType));
    exceptTypes->types[typeCount]->flags = 1;
    exceptTypes->types[typeCount]->mdisp = 0;
    exceptTypes->types[typeCount]->pdisp = -1;
    exceptTypes->types[typeCount]->vdisp = 0;
    exceptTypes->types[typeCount]->type = (const char *)alloca(32);
    memset((void *)exceptTypes->types[typeCount]->type, 0, 32);
    exceptTypes->types[typeCount]->size = 4;
    typeCount++;

    exceptTypes->count = typeCount;

    _ThrowInfo ti = 
    {
     0,
     NULL,
     NULL,
     (_CatchableTypeArray *) exceptTypes
    };

    _CxxThrowException(&exception, &ti);
}
Exemplo n.º 2
0
void objc_register_all_classes(struct objc_abi_symtab* symtab) {
    uint_fast32_t i;

    for (i = 0; i < symtab->cls_def_cnt; i++) {
        struct objc_abi_class* cls = (struct objc_abi_class*)symtab->defs[i];

        register_class(cls);
        register_selectors(cls);
        register_selectors((struct objc_abi_class*)object_getClass((id)cls));
    }

    for (i = 0; i < symtab->cls_def_cnt; i++) {
        Class cls = (Class)symtab->defs[i];

        if (has_load(cls)) {
            setup_class(cls);

            if (cls->info & OBJC_CLASS_INFO_SETUP)
                call_load(cls);
            else {
                if (load_queue == NULL)
                    load_queue = malloc(sizeof(Class));
                else
                    load_queue = realloc(load_queue, sizeof(Class) * (load_queue_cnt + 1));

                if (load_queue == NULL)
                    OBJC_ERROR(
                        "Not enough memory for load "
                        "queue!");

                load_queue[load_queue_cnt++] = cls;
            }
        } else
            cls->info |= OBJC_CLASS_INFO_LOADED;
    }

    /* Process load queue */
    for (i = 0; i < load_queue_cnt; i++) {
        setup_class(load_queue[i]);

        if (load_queue[i]->info & OBJC_CLASS_INFO_SETUP) {
            call_load(load_queue[i]);

            load_queue_cnt--;

            if (load_queue_cnt == 0) {
                free(load_queue);
                load_queue = NULL;
                continue;
            }

            load_queue[i] = load_queue[load_queue_cnt];

            load_queue = realloc(load_queue, sizeof(Class) * load_queue_cnt);

            if (load_queue == NULL)
                OBJC_ERROR("Not enough memory for load queue!");
        }
    }
}
Exemplo n.º 3
0
OBJCRT_EXPORT BOOL object_isMethodFromClass(id dwObj, SEL pSel, const char* fromClass) {
    Class pClass = object_getClass(dwObj);
    char* clsname = NULL;

    while (pClass != NULL) {
        clsname = (char*)pClass->name;

        struct objc_method_list* methodList = pClass->methodlist;

        while (methodList != NULL) {
            for (unsigned i = 0; i < methodList->count; i++) {
                if (methodList->methods[i].sel.uid == pSel->uid) {
                    if (strcmp(clsname, fromClass) == 0) {
                        return TRUE;
                    } else {
                        return FALSE;
                    }
                }
            }

            methodList = methodList->next;
        }

        pClass = pClass->superclass;
    }

    return FALSE;
}
Exemplo n.º 4
0
void __darwin_objc_exception_throw(objc_object* object)
{
	TRACE1(object);

	if (!object)
	{
		std::cerr << "NULL Objective-C exception thrown!\n";
		abort();
	}

	if (!m_lastBlock)
	{
		std::cerr << "Unhandled Objective-C exception: " << class_getName(object_getClass(object)) << '(' << object << ")\n";
		abort();
	}
	else
	{
		TryBlock* currentBlock = m_lastBlock;
		
		currentBlock->exceptionObject = object;
		m_lastBlock = m_lastBlock->previousBlock;

		longjmp(currentBlock->buffer, true);
	}
}
Exemplo n.º 5
0
id object_copy(id obj, size_t size)
{
	Class cls = object_getClass(obj);
	id cpy = class_createInstance(cls, size - class_getInstanceSize(cls));
	memcpy(((char*)cpy + sizeof(id)), ((char*)obj + sizeof(id)), size - sizeof(id));
	return cpy;
}
Exemplo n.º 6
0
Ivar object_getInstanceVariable(id obj, const char *name, void **outValue)
{
  Ivar ivar = class_getInstanceVariable(object_getClass(obj), name);
  if (NULL != outValue)
    {
      *outValue = object_getIvar(obj, ivar);
    }
  return ivar;
}
Exemplo n.º 7
0
Class RegisterClass(const class_t* cls, intptr_t slide)
{
	LOG << "Processing ObjC class " << cls->data()->className << std::endl;
	
	const class_t* meta = cls->isa;
	Class conv, super;
	auto itSuper = g_classPointers.find(cls->superclass);

	if (itSuper != g_classPointers.end())
		super = itSuper->second;
	else
		super = reinterpret_cast<Class>(cls->superclass);
	
	LOG << "...superclass is @" << super << std::endl;
	assert(objc_getClass(cls->data()->className) == nullptr);
	conv = objc_allocateClassPair(super, cls->data()->className, 0);
	
	const class_ro_t* ro = cls->data();
	const class_ro_t* roMeta = meta->data();
	
	if (ro->baseMethods)
		ConvertMethodListGen(conv, ro->baseMethods);
	if (roMeta->baseMethods)
		ConvertMethodListGen(object_getClass(id(conv)), roMeta->baseMethods);
	if (ro->ivars)
		ConvertIvarList(conv, ro->ivars);
	if (ro->baseProtocols)
		AddClassProtocols(conv, ro->baseProtocols, slide);
	if (ro->baseProperties)
	{
		ConvertProperties(ro->baseProperties, [conv](const char* name, const objc_property_attribute_t* attr, unsigned int count) { class_addProperty(conv, name, attr, count); bug_gnustepFixPropertyCount(conv); });
	}
	
	// conv->instance_size = ro->instSize;
	// conv->isa->instance_size = roMeta->instSize;
	
	objc_registerClassPair(conv);
	
	LOG << "ObjC class " << cls->data()->className << " now @" << conv << std::endl;
	g_classPointers[cls] = conv;
	g_classPointers[cls->isa] = object_getClass(id(conv));
	
	return conv;
}
Exemplo n.º 8
0
Class RegisterClass(old_class* cls, bool hasExt)
{
	LOG << "Processing old ObjC class " << cls->name << std::endl;
	
	const old_class* meta = cls->isa.cls;
	Class conv, super;
	auto & g_classPointers = getClassPointers();
	/*
	old_class* psuper = cls->super_class.cls;
	auto itSuper = g_classPointers.find(psuper); // TODO: may not be needed, should always be a string

	if (itSuper != g_classPointers.end())
		super = itSuper->second;
	else
		super = reinterpret_cast<Class>(psuper);
	*/

	super = (Class) objc_getClass(cls->super_class.name);
	LOG << "...with superclass @" << super << std::endl;
	conv = objc_allocateClassPair(super, cls->name, 0);
	
	if (cls->methodList)
		ConvertMethodListGen(conv, cls->methodList);
	if (meta->methodList)
		ConvertMethodListGen(object_getClass(id(conv)), meta->methodList);
	if (cls->ivars)
		ConvertIvarList(conv, cls->ivars);
	if (cls->protocols)
		AddClassProtocols(conv, cls->protocols);
	
	if (hasExt && cls->ext && cls->ext->propertyLists)
	{
		LOG << "Class has EXT and a property list/lists\n";
		//if (cls->info & CLS_NO_PROPERTY_ARRAY)
		if (true)
		{
			ConvertProperties(cls->ext->propertyList, [conv](const char* name, const objc_property_attribute_t* attr, unsigned int count) { class_addProperty(conv, name, attr, count); bug_gnustepFixPropertyCount(conv); });
		}
		else
		{
			for (size_t i = 0; cls->ext->propertyLists[i] != nullptr; i++)
			{
				const old_property_list* l = cls->ext->propertyLists[i];
				ConvertProperties(l, [conv](const char* name, const objc_property_attribute_t* attr, unsigned int count) { class_addProperty(conv, name, attr, count); bug_gnustepFixPropertyCount(conv); });
			}
		}
	}
	
	objc_registerClassPair(conv);
	g_classPointers[cls] = conv;
	g_classPointers[cls->name] = conv;

	LOG << "ObjC class " << cls->name << " @" << conv << std::endl;
	
	return conv;
}
Exemplo n.º 9
0
static void call_method(Class cls, const char* method) {
    struct objc_method_list* ml;
    SEL selector;
    unsigned int i;

    selector = sel_registerName(method);

    for (ml = object_getClass((id)cls)->methodlist; ml != NULL; ml = ml->next)
        for (i = 0; i < ml->count; i++)
            if (sel_isEqual((SEL)&ml->methods[i].sel, selector))
                ((void (*)(id, SEL))ml->methods[i].imp)((id)cls, selector);
}
Exemplo n.º 10
0
void SwizzClassMethod(Class origClass, Class replaceClass, SEL origSel, SEL replaceSel)
{
    Method origMethod = class_getClassMethod(origClass, origSel);
    Method newMethod = class_getClassMethod(replaceClass, replaceSel);
    
    origClass = object_getClass((id)origClass);
    
    if(class_addMethod(origClass, origSel, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
        class_replaceMethod(origClass, replaceSel, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
    else
        method_exchangeImplementations(origMethod, newMethod);
}
Exemplo n.º 11
0
// BAF:  This seems to be some garbage collection magic.  Not for us mortals to look at!
__private_extern__ Boolean __CFRuntimeIsFreedObject(id anObject) {
    if (!anObject) return false;
    static Class freedClass = Nil;
    if (!freedClass) freedClass = _objc_getFreedObjectClass();
    Class cls = object_getClass(anObject);
    if (cls == freedClass) return true;
    // in 64-bit, a future class has nil isa, and calling class_getName() on
    // such will crash so we do this test; zombie classes are not future classes
    if (objc_getClass((id)cls) == nil) return false;
    const char *cname = class_getName(cls);
    if (cname && 0 == strncmp(cname, "_NSZombie_", 10)) return true;
    return false;
}
Exemplo n.º 12
0
static void initialize_class(Class cls) {
    if (cls->info & OBJC_CLASS_INFO_INITIALIZED)
        return;

    if (cls->superclass)
        initialize_class(cls->superclass);

    cls->info |= OBJC_CLASS_INFO_DTABLE;
    object_getClass((id)cls)->info |= OBJC_CLASS_INFO_DTABLE;

    objc_update_dtable(cls);
    objc_update_dtable(object_getClass((id)cls));

    /*
     * Set it first to prevent calling it recursively due to message sends
     * in the initialize method
     */
    cls->info |= OBJC_CLASS_INFO_INITIALIZED;
    object_getClass((id)cls)->info |= OBJC_CLASS_INFO_INITIALIZED;

    call_method(cls, "initialize");
}
Exemplo n.º 13
0
static BOOL has_load(Class cls) {
    struct objc_method_list* ml;
    SEL selector;
    unsigned int i;

    selector = sel_registerName("load");

    for (ml = object_getClass((id)cls)->methodlist; ml != NULL; ml = ml->next)
        for (i = 0; i < ml->count; i++)
            if (sel_isEqual((SEL)&ml->methods[i].sel, selector))
                return YES;

    return NO;
}
Exemplo n.º 14
0
int objc_exception_match(objc_class* cls, objc_object* object)
{
	TRACE2(cls, object);
	objc_class* objClass = object_getClass(object);

	while (objClass)
	{
		if (objClass == cls)
			return true;
		else
			objClass = class_getSuperclass(objClass);
	}

	return false;
}
Exemplo n.º 15
0
void objc_free_all_classes(void) {
    uint32_t i;

    if (classes == NULL)
        return;

    for (i = 0; i <= classes->last_idx; i++) {
        if (classes->data[i] != NULL) {
            free_class((Class)classes->data[i]->obj);
            free_class(object_getClass((id)classes->data[i]->obj));
        }
    }

    objc_hashtable_free(classes);
    classes = NULL;
}
Exemplo n.º 16
0
Arquivo: gc.c Projeto: 1nueve/MacRuby
static void 
print_memory_object(task_t task, void *context, unsigned type_mask,
	vm_range_t *ranges, unsigned range_count)
{
    const size_t min_size = *(size_t *)context;
    for (vm_range_t *r = ranges, *end = ranges + range_count; r < end; r++) {
	const size_t size = auto_zone_size(__auto_zone, (void *)r->address);
	if (size >= min_size) {
	    printf("address %p size %ld rc %d layout type ",
		    (void *)r->address, size,
		    auto_zone_retain_count(__auto_zone, (void *)r->address));
	    switch (auto_zone_get_layout_type(__auto_zone,
			(void *)r->address)) {
		case AUTO_OBJECT:
		    printf("object (class %s)\n",
			    class_getName(object_getClass((void *)r->address)));
		    break;
		default:
		    printf("memory\n");
		    break;
	    }
	}
    }
}
Exemplo n.º 17
0
Ivar object_setInstanceVariable(id obj, const char *name, void *value)
{
  Ivar ivar = class_getInstanceVariable(object_getClass(obj), name);
  object_setIvar(obj, ivar, value);
  return ivar;
}
Exemplo n.º 18
0
VALUE
rb_vm_dispatch(void *_vm, struct mcache *cache, VALUE top, VALUE self,
	Class klass, SEL sel, rb_vm_block_t *block, unsigned char opt,
	int argc, const VALUE *argv)
{
    RoxorVM *vm = (RoxorVM *)_vm;

#if ROXOR_VM_DEBUG
    bool cached = true;
#endif
    bool cache_method = true;

    Class current_super_class = vm->get_current_super_class();
    SEL current_super_sel = vm->get_current_super_sel();

    if (opt & DISPATCH_SUPER) {
	// TODO
	goto recache;
    }

    if (cache->sel != sel || cache->klass != klass || cache->flag == 0) {
recache:
#if ROXOR_VM_DEBUG
	cached = false;
#endif

	Method method;
	if (opt & DISPATCH_SUPER) {
	    if (!sel_equal(klass, current_super_sel, sel)) {
		current_super_sel = sel;
		current_super_class = klass;
	    }
	    else {
		// Let's make sure the current_super_class is valid before
		// using it; we check this by verifying that it's a real
		// super class of the current class, as we may be calling
		// a super method of the same name but on a totally different
		// class hierarchy.
		Class k = klass;
		bool current_super_class_ok = false;
		while (k != NULL) {
		    if (k == current_super_class) {
			current_super_class_ok = true;
			break;
		    }
		    k = class_getSuperclass(k);
		}
		if (!current_super_class_ok) {
		    current_super_class = klass;
		}
	    }
	    method = rb_vm_super_lookup(current_super_class, sel,
		    &current_super_class);
	}
	else {
	    current_super_sel = 0;
	    method = class_getInstanceMethod(klass, sel);
	}

	if (method != NULL) {
recache2:
	    IMP imp = method_getImplementation(method);

	    if (UNAVAILABLE_IMP(imp)) {
		// Method was undefined.
		goto call_method_missing;
	    }

	    rb_vm_method_node_t *node = GET_CORE()->method_node_get(method);

	    if (node != NULL) {
		// ruby call
		fill_rcache(cache, klass, sel, node);
	    }
	    else {
		// objc call
		fill_ocache(cache, self, klass, imp, sel, method, argc);
	    }

	    if (opt & DISPATCH_SUPER) {
		cache->flag |= MCACHE_SUPER;
	    }
	}
	else {
	    // Method is not found...

#if !defined(MACRUBY_STATIC)
	    // Force a method resolving, because the objc cache might be
	    // wrong.
	    if (rb_vm_resolve_method(klass, sel)) {
		goto recache;
	    }
#endif

	    // Does the receiver implements -forwardInvocation:?
	    if ((opt & DISPATCH_SUPER) == 0
		    && rb_objc_supports_forwarding(self, sel)) {

//#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
		// In earlier versions of the Objective-C runtime, there seems
		// to be a bug where class_getInstanceMethod isn't atomic,
		// and might return NULL while at the exact same time another
		// thread registers the related method.
		// As a work-around, we double-check if the method still does
		// not exist here. If he does, we can dispatch it properly.

		// note: OS X 10.7 also, this workaround is required. see #1476
		method = class_getInstanceMethod(klass, sel);
		if (method != NULL) {
		    goto recache2;
		}
//#endif
		fill_ocache(cache, self, klass, (IMP)objc_msgSend, sel, NULL,
			argc);
		goto dispatch;
	    }

	    // Let's see if are not trying to call a Ruby method that accepts
	    // a regular argument then an optional Hash argument, to be
	    // compatible with the Ruby specification.
	    const char *selname = (const char *)sel;
	    size_t selname_len = strlen(selname);
	    if (argc > 1) {
		const char *p = strchr(selname, ':');
		if (p != NULL && p + 1 != '\0') {
		    char *tmp = (char *)malloc(selname_len + 1);
		    assert(tmp != NULL);
		    strncpy(tmp, selname, p - selname + 1);
		    tmp[p - selname + 1] = '\0';
		    sel = sel_registerName(tmp);
		    VALUE h = rb_hash_new();
		    bool ok = true;
		    p += 1;
		    for (int i = 1; i < argc; i++) {
			const char *p2 = strchr(p, ':');
			if (p2 == NULL) {
			    ok = false;
			    break;
			}
			strlcpy(tmp, p, selname_len);
			tmp[p2 - p] = '\0';
			p = p2 + 1; 
			rb_hash_aset(h, ID2SYM(rb_intern(tmp)), argv[i]);
		    }
		    free(tmp);
		    tmp = NULL;
		    if (ok) {
			argc = 2;
			((VALUE *)argv)[1] = h; // bad, I know...
			Method m = class_getInstanceMethod(klass, sel);
			if (m != NULL) {	
			    method = m;
			    cache_method = false;
			    goto recache2;
			}
		    }
		}
	    }

	    // Enable helpers for classes which are not RubyObject based.
	    if ((RCLASS_VERSION(klass) & RCLASS_IS_OBJECT_SUBCLASS)
		    != RCLASS_IS_OBJECT_SUBCLASS) {
		// Let's try to see if we are not given a helper selector.
		SEL new_sel = helper_sel(selname, selname_len);
		if (new_sel != NULL) {
		    Method m = class_getInstanceMethod(klass, new_sel);
		    if (m != NULL) {
		    	sel = new_sel;
		    	method = m;
		    	// We need to invert arguments because
		    	// #[]= and setObject:forKey: take arguments
		    	// in a reverse order
		    	if (new_sel == selSetObjectForKey && argc == 2) {
		    	    VALUE swap = argv[0];
		    	    ((VALUE *)argv)[0] = argv[1];
		    	    ((VALUE *)argv)[1] = swap;
		    	    cache_method = false;
		    	}
		    	goto recache2;
		    }
		}
	    }

	    // Let's see if we are not trying to call a BridgeSupport function.
	    if (selname[selname_len - 1] == ':') {
		selname_len--;
	    }
	    std::string name(selname, selname_len);
	    bs_element_function_t *bs_func = GET_CORE()->find_bs_function(name);
	    if (bs_func != NULL) {
		if ((unsigned)argc < bs_func->args_count
			|| ((unsigned)argc > bs_func->args_count
				&& bs_func->variadic == false)) {
		    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
			argc, bs_func->args_count);
		}
		std::string types;
		vm_gen_bs_func_types(argc, argv, bs_func, types);

		cache->flag = MCACHE_FCALL;
		cache->sel = sel;
		cache->klass = klass;
		cache->as.fcall.bs_function = bs_func;
		cache->as.fcall.imp = (IMP)dlsym(RTLD_DEFAULT, bs_func->name);
		assert(cache->as.fcall.imp != NULL);
		cache->as.fcall.stub = (rb_vm_c_stub_t *)GET_CORE()->gen_stub(
			types, bs_func->variadic, bs_func->args_count, false);
	    }
	    else {
		// Still nothing, then let's call #method_missing.
		goto call_method_missing;
	    }
	}
    }

dispatch:
    if (cache->flag & MCACHE_RCALL) {
	if (!cache_method) {
	    cache->flag = 0;
	}

#if ROXOR_VM_DEBUG
	printf("ruby dispatch %c[<%s %p> %s] (imp %p block %p argc %d opt %d cache %p cached %s)\n",
		class_isMetaClass(klass) ? '+' : '-',
		class_getName(klass),
		(void *)self,
		sel_getName(sel),
		cache->as.rcall.node->ruby_imp,
		block,
		argc,
		opt,
		cache,
		cached ? "true" : "false");
#endif

	bool block_already_current = vm->is_block_current(block);
	Class current_klass = vm->get_current_class();
	if (!block_already_current) {
	    vm->add_current_block(block);
	}
	vm->set_current_class(NULL);

	Class old_current_super_class = vm->get_current_super_class();
	vm->set_current_super_class(current_super_class);
	SEL old_current_super_sel = vm->get_current_super_sel();
	vm->set_current_super_sel(current_super_sel);

	const bool should_pop_broken_with =
	    sel != selInitialize && sel != selInitialize2;

	struct Finally {
	    bool block_already_current;
	    Class current_class;
	    Class current_super_class;
	    SEL current_super_sel;
	    bool should_pop_broken_with;
	    RoxorVM *vm;
	    Finally(bool _block_already_current, Class _current_class,
		    Class _current_super_class, SEL _current_super_sel,
		    bool _should_pop_broken_with, RoxorVM *_vm) {
		block_already_current = _block_already_current;
		current_class = _current_class;
		current_super_class = _current_super_class;
		current_super_sel = _current_super_sel;
		should_pop_broken_with = _should_pop_broken_with;
		vm = _vm;
	    }
	    ~Finally() {
		if (!block_already_current) {
		    vm->pop_current_block();
		}
		vm->set_current_class(current_class);
		if (should_pop_broken_with) {
		    vm->pop_broken_with();
		}
		vm->set_current_super_class(current_super_class);
		vm->set_current_super_sel(current_super_sel);
		vm->pop_current_binding();
	    }
	} finalizer(block_already_current, current_klass,
		old_current_super_class, old_current_super_sel,
		should_pop_broken_with, vm);

	// DTrace probe: method__entry
	if (MACRUBY_METHOD_ENTRY_ENABLED()) {
	    char *class_name = (char *)rb_class2name((VALUE)klass);
	    char *method_name = (char *)sel_getName(sel);
	    char file[PATH_MAX];
	    unsigned long line = 0;
	    GET_CORE()->symbolize_backtrace_entry(1, file, sizeof file, &line,
		    NULL, 0);
	    MACRUBY_METHOD_ENTRY(class_name, method_name, file, line);
	}

	VALUE v = ruby_dispatch(top, self, sel, cache->as.rcall.node,
		opt, argc, argv);

	// DTrace probe: method__return
	if (MACRUBY_METHOD_RETURN_ENABLED()) {
	    char *class_name = (char *)rb_class2name((VALUE)klass);
	    char *method_name = (char *)sel_getName(sel);
	    char file[PATH_MAX];
	    unsigned long line = 0;
	    GET_CORE()->symbolize_backtrace_entry(1, file, sizeof file, &line,
		    NULL, 0);
	    MACRUBY_METHOD_RETURN(class_name, method_name, file, line);
	}

	return v;
    }
    else if (cache->flag & MCACHE_OCALL) {
	if (cache->as.ocall.argc != argc) {
	    goto recache;
	}
	if (!cache_method) {
	    cache->flag = 0;
	}

	if (block != NULL) {
	    rb_warn("passing a block to an Objective-C method - " \
		    "will be ignored");
	}
	else if (sel == selNew) {
	    if (self == rb_cNSMutableArray) {
		self = rb_cRubyArray;
	    }
	}
	else if (sel == selClass) {
	    // Because +[NSObject class] returns self.
	    if (RCLASS_META(klass)) {
		return RCLASS_MODULE(self) ? rb_cModule : rb_cClass;
	    }
	    // Because the CF classes should be hidden, for Ruby compat.
	    if (self == Qnil) {
		return rb_cNilClass;
	    }
	    if (self == Qtrue) {
		return rb_cTrueClass;
	    }
	    if (self == Qfalse) {
		return rb_cFalseClass;
	    }
	    return rb_class_real((VALUE)klass, true);
	}

#if ROXOR_VM_DEBUG
	printf("objc dispatch %c[<%s %p> %s] imp=%p cache=%p argc=%d (cached=%s)\n",
		class_isMetaClass(klass) ? '+' : '-',
		class_getName(klass),
		(void *)self,
		sel_getName(sel),
		cache->as.ocall.imp,
		cache,
		argc,
		cached ? "true" : "false");
#endif

	id ocrcv = RB2OC(self);

 	if (cache->as.ocall.bs_method != NULL) {
	    Class ocklass = object_getClass(ocrcv);
	    for (int i = 0; i < (int)cache->as.ocall.bs_method->args_count;
		    i++) {
		bs_element_arg_t *arg = &cache->as.ocall.bs_method->args[i];
		if (arg->sel_of_type != NULL) {
		    // BridgeSupport tells us that this argument contains a
		    // selector of the given type, but we don't have any
		    // information regarding the target. RubyCocoa and the
		    // other ObjC bridges do not really require it since they
		    // use the NSObject message forwarding mechanism, but
		    // MacRuby registers all methods in the runtime.
		    //
		    // Therefore, we apply here a naive heuristic by assuming
		    // that either the receiver or one of the arguments of this
		    // call is the future target.
		    const int arg_i = arg->index;
		    assert(arg_i >= 0 && arg_i < argc);
		    if (argv[arg_i] != Qnil) {
			ID arg_selid = rb_to_id(argv[arg_i]);
			SEL arg_sel = sel_registerName(rb_id2name(arg_selid));

			if (reinstall_method_maybe(ocklass, arg_sel,
				    arg->sel_of_type)) {
			    goto sel_target_found;
			}
			for (int j = 0; j < argc; j++) {
			    if (j != arg_i && !SPECIAL_CONST_P(argv[j])) {
				if (reinstall_method_maybe(*(Class *)argv[j],
					    arg_sel, arg->sel_of_type)) {
				    goto sel_target_found;
				}
			    }
			}
		    }

sel_target_found:
		    // There can only be one sel_of_type argument.
		    break; 
		}
	    }
	}

	return __rb_vm_objc_dispatch(cache->as.ocall.stub, cache->as.ocall.imp,
		ocrcv, sel, argc, argv);
    }
    else if (cache->flag & MCACHE_FCALL) {
#if ROXOR_VM_DEBUG
	printf("C dispatch %s() imp=%p argc=%d (cached=%s)\n",
		cache->as.fcall.bs_function->name,
		cache->as.fcall.imp,
		argc,
		cached ? "true" : "false");
#endif
	return (*cache->as.fcall.stub)(cache->as.fcall.imp, argc, argv);
    }

    printf("method dispatch is b0rked\n");
    abort();

call_method_missing:
    // Before calling method_missing, let's check if we are not in the following
    // cases:
    //
    //    def foo; end; foo(42)
    //    def foo(x); end; foo
    //
    // If yes, we need to raise an ArgumentError exception instead.
    const char *selname = sel_getName(sel);
    const size_t selname_len = strlen(selname);
    SEL new_sel = 0;

    if (argc > 0 && selname[selname_len - 1] == ':') {
	char buf[100];
	assert(sizeof buf > selname_len - 1);
	strlcpy(buf, selname, sizeof buf);
	buf[selname_len - 1] = '\0';
	new_sel = sel_registerName(buf);
    }
    else if (argc == 0) {
	char buf[100];
	snprintf(buf, sizeof buf, "%s:", selname);
	new_sel = sel_registerName(buf);
    }
    if (new_sel != 0) {
	Method m = class_getInstanceMethod(klass, new_sel);
	if (m != NULL) {
	    IMP mimp = method_getImplementation(m);
	    if (!UNAVAILABLE_IMP(mimp)) {
		unsigned expected_argc;
		rb_vm_method_node_t *node = GET_CORE()->method_node_get(m);
		if (node != NULL) {
		    expected_argc = node->arity.min;
		}
		else {
		    expected_argc = rb_method_getNumberOfArguments(m);
		    expected_argc -= 2; // removing receiver and selector
		}
		rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
			argc, expected_argc);
	    }
	}
    }

    rb_vm_method_missing_reason_t status;
    if (opt & DISPATCH_VCALL) {
	status = METHOD_MISSING_VCALL;
    }
    else if (opt & DISPATCH_SUPER) {
	status = METHOD_MISSING_SUPER;
    }
    else {
	status = METHOD_MISSING_DEFAULT;
    }
    return method_missing((VALUE)self, sel, block, argc, argv, status);
}
Exemplo n.º 19
0
Class metaclassForName(const char *className)
{
  return object_getClass((id)objc_lookUpClass(className));
}
Exemplo n.º 20
0
Method class_getClassMethod(Class aClass, SEL aSelector)
{
	return class_getInstanceMethod(object_getClass((id)aClass), aSelector);
}
Exemplo n.º 21
0
Ivar class_getClassVariable(Class cls, const char* name)
{
	// Note: We don't have compiler support for cvars in ObjC
	return class_getInstanceVariable(object_getClass((id)cls), name);
}
Exemplo n.º 22
0
const char* object_getClassName(id obj) {
    return class_getName(object_getClass(obj));
}
Exemplo n.º 23
0
const char *object_getClassName(id obj)
{
	CHECK_ARG(obj);
	return class_getName(object_getClass(obj));
}
Exemplo n.º 24
0
Class RegisterClass(const class_t* cls, intptr_t slide, uint32_t image_index)
{
	if (nullptr == cls)
	{
		return nullptr;
	}

	auto & g_classPointers = getClassPointers();
	auto itClass = g_classPointers.find(cls);
	if (itClass != g_classPointers.end())
	{
		LOG << "Found existing class @" << itClass->second << std::endl;
		return itClass->second;
	}

	Class super = RegisterClass(cls->superclass, slide, image_index);

	LOG << "...superclass is @" << super << std::endl;
	if (nullptr != super)
	{
		LOG << "...superclass name " << (((uintptr_t)super != (uintptr_t)cls->superclass) ? cls->superclass->data()->className : class_getName(super)) << std::endl;
		LOG << "...super name " << class_getName(super) << std::endl;
	}

	if (nullptr == cls->data())
	{
		// TODO: Is this a bad pointer filled in, or are we supposed to do something different with this?
		// This is from when we call RegisterClass recursively sometimes...
		std::cerr << "Error - Null class data at class @" << cls << std::endl;
		return nullptr;
	}

	if (nullptr == cls->data()->className)
	{
		// TODO: Is this a bad pointer filled in, or are we supposed to do something different with this?
		// This is from when we call RegisterClass recursively sometimes...
		std::cerr << "Error - Null class name at class @" << cls << std::endl;
		return nullptr;
	}

	LOG << "Processing ObjC class " << cls->data()->className << std::endl;

	Class sameClass = (Class)objc_getClass(cls->data()->className);
	if (nullptr != sameClass)
	{
		LOG << "Found a class with the same name @" << sameClass << std::endl;
		return sameClass;
	}

	LOG << "obj_allocateClassPair(" << super << ", " << cls->data()->className << ")" << std::endl;

	Class conv = objc_allocateClassPair(super, cls->data()->className, 0);

	if (nullptr == conv)
	{
		std::cerr << "Failed to allocate class " << cls->data()->className << std::endl;
		return nullptr;
	}

	Class meta = object_getClass(id(conv));

	const class_ro_t* ro = cls->data();

	if (ro->baseMethods)
		ConvertMethodListGen(conv, ro->baseMethods, image_index);
	if (g_classPointers.find(cls->isa) == g_classPointers.end())
	{
		const class_ro_t* roMeta = cls->isa->data();
		if (roMeta->baseMethods)
			ConvertMethodListGen(meta, roMeta->baseMethods, image_index);
	}
	if (ro->ivars)
		ConvertIvarList(conv, ro->ivars);
	if (ro->baseProtocols)
		AddClassProtocols(conv, ro->baseProtocols, slide);
	if (ro->baseProperties)
	{
		ConvertProperties(ro->baseProperties, [conv](const char* name, const objc_property_attribute_t* attr, unsigned int count) { class_addProperty(conv, name, attr, count); bug_gnustepFixPropertyCount(conv); });
	}

	// conv->instance_size = ro->instSize;

	objc_registerClassPair(conv);
	
	LOG << "ObjC class " << cls->data()->className << " now @" << conv << std::endl;
	g_classPointers[cls] = conv;
	g_classPointers[conv] = conv;
	g_classPointers[meta] = meta;

	return conv;
}
Exemplo n.º 25
0
id UndefinedClassInitialize(id obj, SEL sel)
{
	fprintf(stderr, "Undefined class %s used\n", class_getName(object_getClass(obj)));
	return obj;
}
Exemplo n.º 26
0
static void setup_class(Class cls) {
    const char* superclass;
    Class metaclass = object_getClass((id)cls);

    if (cls->info & OBJC_CLASS_INFO_SETUP)
        return;

    if ((superclass = ((struct objc_abi_class*)cls)->superclass) != NULL) {
        Class super = Nil;
        // Classes loaded from the image contain a superclass name instead of a superclass. Resolve it.
        if ((cls->info & OBJC_CLASS_INFO_CREATED_RUNTIME) == 0) {
            super = objc_classname_to_class(superclass);
        } else {
            super = (Class)superclass;
        }

        if (super == (Class)nil)
            return;

        setup_class(super);

        if (!(super->info & OBJC_CLASS_INFO_SETUP))
            return;

        cls->superclass = super;
        metaclass->superclass = object_getClass((id)super);

        add_subclass(cls);
        add_subclass(metaclass);
    } else
        metaclass->superclass = cls;

    //  Calculate size based on ivars
    int slide = 0;
    cls->instance_size = -(int)cls->instance_size;
    if (cls->superclass) {
        slide = cls->superclass->instance_size;
    }

    if (slide) {
        struct objc_ivar_list* list = (struct objc_ivar_list*)cls->ivars;
        if (list) {
            //  If first ivar has a negative offset (???) .. increase slide by that amount
            if (list->count > 0) {
                if ((int)list->ivars[0].offset < 0) {
                    printf("Warning: Class %s has first ivar %s with a negative offset of %d!\n",
                           cls->name,
                           list->ivars[0].name,
                           list->ivars[0].offset);
                    slide += -(int)list->ivars[0].offset;
                }
            }

            for (unsigned i = 0; i < list->count; i++) {
                struct objc_ivar* curIvar = &list->ivars[i];
                curIvar->offset += slide;
                *((int**)cls->ivar_offsets)[i] += slide;
                assert(*((int**)cls->ivar_offsets)[i] == curIvar->offset);
            }
        }
    }
    cls->instance_size += slide;

    cls->info |= OBJC_CLASS_INFO_SETUP;
    metaclass->info |= OBJC_CLASS_INFO_SETUP;
    metaclass->instance_size = sizeof(struct objc_class);
}
Exemplo n.º 27
0
void* UndefMgr::generateNew(const char* name)
{
	bool isClass = (strncmp(name, "OBJC_CLASS", 10) == 0);
	bool isMetaClass = (strncmp(name, "OBJC_METACLASS", 14) == 0);

	if (isClass || isMetaClass)
	{
		// Strip the OBJC_CLASS_$_ or OBJC_METACLASS_$_
		name =  &name[(isMetaClass) ? 17 : 13];

		// Objective-C class or metaclass info
		static std::map<std::string, Class> undefClasses;
		Class classStub = nullptr;
		auto classIter = undefClasses.find(name);
		if (classIter != undefClasses.end())
		{
			classStub = classIter->second;
		}
		else if (NULL == (classStub = (Class)objc_getClass(name)))
		{
			classStub = objc_allocateClassPair(nullptr, name, 0);
			if (isMetaClass)
			{
				// Put in a dummy initialize method that lets us know the class got used
				IMP imp = reinterpret_cast<IMP>(&UndefinedClassInitialize);
				SEL sel = sel_registerTypedName_np("initialize", NULL);
				class_addMethod(object_getClass(reinterpret_cast<id>(classStub)), sel, imp, NULL);
			}
			objc_registerClassPair(classStub);
			Darling::MachOMgr::instance()->registerNativeClass(object_getClass(reinterpret_cast<id>(classStub)));
			Darling::MachOMgr::instance()->registerNativeClass(classStub);
			fprintf(stderr, "Undef class for class %s at %p\n", class_getName(classStub), classStub);
			undefClasses[name] = classStub;
		}

		return (isClass) ? classStub : object_getClass(reinterpret_cast<id>(classStub));
	}
	else if (strncmp(name, "OBJC_IVAR", 9) == 0)
	{
		// Objective-C ivar
		typedef struct 
		{
			const char *name;
			const char *type;
			int         offset;
		} objc_ivar;

		objc_ivar *ivarStub = new objc_ivar;
		ivarStub->name = &name[12];
		ivarStub->type = "";
		ivarStub->offset = 0;
		return ivarStub;
	}
	else
	{
		// Generate a function stub
		UndefinedFunction * uf = new UndefinedFunction();
		uf->init(name);
		return uf->getPointer();
	}
}
Exemplo n.º 28
0
OBJCRT_EXPORT void* object_getIndexedIvars(id obj) {
    return (void*)((uint8_t*)obj + OBJC_ID_PADDED(class_getInstanceSize(object_getClass(obj))));
}