예제 #1
0
_jc_env	*
_jc_support_init()
{
	_jc_mutex_init(&phoney_env, &phoney_loader.mutex);
	_jc_mutex_init(&phoney_env, &phoney_jvm.mutex);
	_jc_uni_alloc_init(&phoney_loader.uni, 0, NULL);
	phoney_jvm.boot.loader = &phoney_loader;
	phoney_env.vm = &phoney_jvm;
	return &phoney_env;
}
예제 #2
0
/*
 * Allocate and link a new classloader structure into a VM.
 *
 * An exception is stored if unsuccessful.
 *
 * NOTE: The global VM mutex must be held when calling this function.
 */
_jc_class_loader *
_jc_create_loader(_jc_env *env)
{
	_jc_jvm *const vm = env->vm;
	_jc_class_loader *loader;

	/* Sanity check */
	_JC_MUTEX_ASSERT(env, vm->mutex);

	/* Create and initialize new structure */
	if ((loader = _jc_vm_zalloc(env, sizeof(*loader)
	    + vm->object_path_len * sizeof(*loader->objects_loaded))) == NULL)
		return NULL;
	loader->objects_loaded = (jboolean *)(loader + 1);

	/* Initialize class loader memory manager */
	_jc_uni_alloc_init(&loader->uni, _JC_CL_ALLOC_MIN_PAGES,
	    &vm->avail_loader_pages);

	/* Initialize mutex and condition variable */
	if (_jc_mutex_init(env, &loader->mutex) != JNI_OK)
		goto fail1;
	if (_jc_cond_init(env, &loader->cond) != JNI_OK)
		goto fail2;

	/* Initialize initiated, defining, and partially derived type trees */
	_jc_splay_init(&loader->initiated_types,
	    _jc_node_cmp, _JC_OFFSETOF(_jc_type_node, node));
	_jc_splay_init(&loader->deriving_types,
	    _jc_node_cmp, _JC_OFFSETOF(_jc_type_node, node));
	_jc_splay_init(&loader->defined_types,
	    _jc_type_cmp, _JC_OFFSETOF(_jc_type, node));

	/* Initialize native library list */
	STAILQ_INIT(&loader->native_libs);

	/* Link new class loader into the VM */
	LIST_INSERT_HEAD(&vm->class_loaders, loader, link);

	/* Done */
	return loader;

	/* Clean up after failure */
fail2:	_jc_mutex_destroy(&loader->mutex);
fail1:	_jc_uni_alloc_free(&loader->uni);
	_jc_vm_free(&loader);
	return NULL;
}
예제 #3
0
파일: elf.c 프로젝트: archiecobbs/jcvm
/*
 * Scan a newly loaded ELF file and do the following:
 *
 * - Find all _jc_type definitions therein by scanning the symbol table
 *   and put them in the ELF file's unloaded types tree.
 *
 * - Compute the ending address of all method functions, which is
 *   computed using the 'size' attribute of the corresponding ELF symbol
 *
 * - Create the PC -> Java line number table index mapping, which is
 *   computed using line number information in the ELF debug section
 *
 * This assumes that the initial intra-file ELF linking has been done.
 *
 * If unsuccessful, an exception is stored.
 */
static jint
_jc_elf_process(_jc_env *env, _jc_elf *elf)
{
	_jc_elf_info *const info = elf->info;
	_jc_method_node *node;
	_jc_method_node key;
	_jc_splay_tree methods;
	_jc_method *method;
	_jc_uni_mem uni;
	int i;

	/* Initialize temporary method info tree */
	_jc_splay_init(&methods, _jc_method_node_compare,
	    _JC_OFFSETOF(_jc_method_node, node));

	/* Create temporary uni-allocator to hold _jc_method_node's */
	_jc_uni_alloc_init(&uni, 0, NULL);

	/* Scan symbol table and gather information about types & methods */
	for (i = 0; i < info->num_symbols; i++) {
		const Elf_Sym *const sym = &info->symbols[i];
		const char *sym_name = info->strings + sym->st_name;
		const _jc_elf_loadable *sym_section = NULL;
		const char *s;
		void *addr;

		/* Check symbol type */
		switch (sym->st_shndx) {
		case SHN_ABS:
			break;
		case SHN_UNDEF:
		case SHN_COMMON:
			continue;
		default:
			/* Sanity check the symbol's section */
			if (sym->st_shndx >= info->ehdr->e_shnum
			    || (sym_section
			      = info->shdr2section[sym->st_shndx]) == NULL)
				continue;
			break;
		}

		/* Check if symbol is a JC symbol */
		if (strncmp(sym_name, "_jc_", 4) != 0
		    || (s = strchr(sym_name + 4, '$')) == NULL)
			continue;

		/* Get symbol's value */
		switch (sym->st_shndx) {
		case SHN_ABS:				/* not likely! */
			addr = (void *)sym->st_value;
			break;
		default:
			addr = sym_section->vaddr + sym->st_value;
			break;
		}

		/* Check if symbol is for a _jc_type */
		if (strcmp(s + 1, "type") == 0) {
			_jc_type *const type = addr;

			_jc_splay_insert(&elf->types, type);
			type->loader = elf->loader;
			type->u.nonarray.u.elf = elf;
			continue;
		}

		/* Check if symbol is for a _jc_method or method function */
		if (strncmp(s + 1, "method", 6) != 0)
			continue;
		key.cname = sym_name + 4;
		key.clen = s - key.cname;
		s += 7;					/* skip "$method" */
		if (*s == '$') {			/* function symbol */
			key.mname = s + 1;
			method = NULL;
		} else if (strncmp(s, "_info$", 6) == 0) {
			key.mname = s + 6;		/* _jc_method symbol */
			method = (_jc_method *)addr;
		} else
			continue;			/* shouldn't happen */
		key.mlen = strlen(key.mname);

		/* Find/create method info node in tree */
		if ((node = _jc_splay_find(&methods, &key)) == NULL) {

			/* Don't create nodes for non-concrete methods */
			if (method != NULL && method->function == NULL)
				continue;

			/* Create new node */
			if ((node = _jc_uni_zalloc(env,
			    &uni, sizeof(*node))) == NULL)
				goto fail;
			node->cname = key.cname;
			node->clen = key.clen;
			node->mname = key.mname;
			node->mlen = key.mlen;
			_jc_splay_insert(&methods, node);
		}

		/* Update node with method function size or method pointer */
		if (method == NULL) {
			_JC_ASSERT(node->size == 0);
			_JC_ASSERT(sym->st_size > 0);
			node->size = sym->st_size;
		} else {
			_JC_ASSERT(node->method == NULL);
			node->method = method;
		}

		/* Compute function ending address if we have all the info */
		if (node->method != NULL && node->size > 0) {
			_JC_ASSERT(node->method->function != NULL);
			_JC_ASSERT(!_JC_ACC_TEST(node->method, INTERP));
			node->method->u.exec.function_end
			    = (const char *)node->method->function + node->size;
		}
	}

	/* Process any debug section containing line number info */
	switch (info->debug_lines.type) {
	case _JC_LINE_DEBUG_DWARF2:
		if (_jc_debug_line_dwarf2(env, elf, &methods) != JNI_OK)
			goto fail;
		break;
	case _JC_LINE_DEBUG_STABS:
		if (_jc_debug_line_stabs(env, elf, &methods) != JNI_OK)
			goto fail;
		break;
	default:
		break;
	}

	/* Done */
	_jc_uni_alloc_free(&uni);
	return JNI_OK;

fail:
	/* Clean up after failure */
	_jc_uni_alloc_free(&uni);
	return JNI_ERR;
}