Exemple #1
0
/*
 * static final native String mapLibraryName(String)
 */
_jc_object * _JC_JCNI_ATTR
JCNI_java_lang_VMRuntime_mapLibraryName(_jc_env *env, _jc_object *string)
{
	size_t name_len;
	char *fname;
	char *name;

	/* Check for null */
	if (string == NULL) {
		_jc_post_exception(env, _JC_NullPointerException);
		_jc_throw_exception(env);
	}

	/* Decode string */
	name_len = _jc_decode_string_utf8(env, string, NULL);
	if ((name = _JC_STACK_ALLOC(env, name_len + 1)) == NULL) {
		_jc_post_exception_info(env);
		_jc_throw_exception(env);
	}
	_jc_decode_string_utf8(env, string, name);

	/* Format filename */
	if ((fname = _JC_FORMAT_STRING(env, _JC_LIBRARY_FMT, name)) == NULL) {
		_jc_post_exception_info(env);
		_jc_throw_exception(env);
	}

	/* Create new String object */
	if ((string = _jc_new_string(env, fname, strlen(fname))) == NULL)
		_jc_throw_exception(env);

	/* Done */
	return string;
}
Exemple #2
0
/*
 * static final native void gc()
 */
void _JC_JCNI_ATTR
JCNI_java_lang_VMRuntime_gc(_jc_env *env)
{
	if (_jc_gc(env, JNI_FALSE) != JNI_OK) {
		_jc_post_exception_info(env);
		_jc_throw_exception(env);
	}
}
Exemple #3
0
/*
 * Create a subdirectory under 'root' if it doesn't already exist.
 * The pathname is the name of any file in the subdirectory.
 */
jint
_jc_create_subdir(_jc_env *env, const char *root, const char *pathname)
{
	const size_t rlen = strlen(root);
	const char *error_path;
	struct stat info;
	char *next;
	char *buf;
	char *s;

	/* The root directory must exist */
	error_path = root;
	if (stat(root, &info) == -1)
		goto io_err;
	if ((info.st_mode & S_IFMT) != S_IFDIR) {
		errno = ENOTDIR;
		goto io_err;
	}

	/* Check successive subdirectories */
	if ((buf = _JC_FORMAT_STRING(env, "%s%s%s",
	    root, _JC_FILE_SEPARATOR, pathname)) == NULL) {
		_jc_post_exception_info(env);
		return JNI_ERR;
	}
	error_path = buf;
	for (s = buf + rlen + 1; ; s = next) {

		/* Another directory in path? If not, we're done */
		if ((next = strstr(s, _JC_FILE_SEPARATOR)) == NULL)
			return JNI_OK;

		/* Check directory status; create if not found */
		*next = '\0';
		if (stat(buf, &info) == -1) {
			if (errno != ENOENT)
				goto io_err;
			if (mkdir(buf, 0755) == -1)
				goto io_err;
		} else if ((info.st_mode & S_IFMT) != S_IFDIR) {
			errno = ENOTDIR;
			goto io_err;
		}
		strcpy(next, _JC_FILE_SEPARATOR);
		next += strlen(_JC_FILE_SEPARATOR);
	}

io_err:
	/* Failed; throw an error */
	_jc_post_exception_msg(env, _JC_InternalError,
	    "%s: %s", error_path, strerror(errno));
	return JNI_ERR;
}
Exemple #4
0
/*
 * static final native int nativeLoad(String, ClassLoader)
 */
jint _JC_JCNI_ATTR
JCNI_java_lang_VMRuntime_nativeLoad(_jc_env *env,
	_jc_object *string, _jc_object *clobj)
{
	_jc_jvm *const vm = env->vm;
	_jc_class_loader *loader;
	char *filename;
	size_t len;

	/* Check for null */
	if (string == NULL) {
		_jc_post_exception(env, _JC_NullPointerException);
		_jc_throw_exception(env);
	}

	/* Convert String to UTF-8 */
	len = _jc_decode_string_utf8(env, string, NULL);
	if ((filename = _JC_STACK_ALLOC(env, len + 1)) == NULL) {
		_jc_post_exception_info(env);
		_jc_throw_exception(env);
	}
	_jc_decode_string_utf8(env, string, filename);

	/* Get class loader */
	if (clobj == NULL)
		loader = vm->boot.loader;
	else if ((loader = _jc_get_loader(env, clobj)) == NULL)
		_jc_throw_exception(env);

	/* Open native library */
	if (_jc_load_native_library(env, loader, filename) != JNI_OK) {
		_jc_post_exception_info(env);
		_jc_throw_exception(env);
	}

	/* OK */
	return 1;
}
/*
 * public static final native boolean compileClasses(String)
 */
jboolean _JC_JCNI_ATTR
JCNI_java_lang_VMCompiler_compileClasses(_jc_env *env, _jc_object *string)
{
	_jc_jvm *const vm = env->vm;
	size_t slen;
	char *name;

	/* Decode string */
	slen = _jc_decode_string_utf8(env, string, NULL);
	if ((name = _JC_STACK_ALLOC(env, slen + 1)) == NULL) {
		_jc_post_exception_info(env);
		_jc_throw_exception(env);
	}
	_jc_decode_string_utf8(env, string, name);

	/* XXX we are supposed to do some kind of pattern matching... */

	/* Generate ELF object */
	if (_jc_generate_object(env, vm->boot.loader, name) != JNI_OK)
		_jc_throw_exception(env);
	return JNI_TRUE;
}
Exemple #6
0
/*
 * Resolve a symbol in an ELF object. There are two cases here.
 *
 * If 'resolver' is NULL, only symbols resolvable internally are
 * resolved, and exceptions are stored, not posted. Otherwise,
 * only symbols resolvable externally are resolved, 'resolver' is
 * used to resolve them, and exceptions are posted.
 */
static inline jint
_jc_elf_resolve_sym(_jc_env *env, _jc_elf *elf, _jc_elf_loadable *loadable,
	const Elf_Rela *rela, _jc_elf_resolver *resolver, void *arg)
{
	const Elf_Word type = ELF_R_TYPE(rela->r_info);
	_jc_elf_info *const info = elf->info;
	const Elf_Sym *const sym = &info->symbols[ELF_R_SYM(rela->r_info)];
	const char *name = info->strings + sym->st_name;

	switch (sym->st_shndx) {
	case SHN_ABS:
		if (resolver != NULL)
			break;
		if (_jc_elf_arch_reloc(env, elf->pathname,
		    loadable->vaddr, rela->r_offset, type,
		    sym->st_value, rela->r_addend) != JNI_OK)
			return JNI_ERR;
		break;
	case SHN_UNDEF:
	    {
		Elf_Addr value;

		if (resolver == NULL)
			break;
		if ((*resolver)(env, arg,
		    info->strings + sym->st_name, &value) != JNI_OK)
			return JNI_ERR;
		if (_jc_elf_arch_reloc(env, elf->pathname, loadable->vaddr,
		    rela->r_offset, type, value, rela->r_addend) != JNI_OK) {
			_jc_post_exception_info(env);
			return JNI_ERR;
		}
		break;
	    }
	case SHN_COMMON:
		_JC_ASSERT(resolver == NULL);
		_JC_EX_STORE(env, LinkageError,
		    "%s: ELF symbol `%s' is common (not supported)",
		    elf->pathname, name);
		return JNI_ERR;
	default:
	    {
		const _jc_elf_loadable *sym_section;

		/* Skip if only resolving externals */
		if (resolver != NULL)
			break;

		/* Sanity check the symbol's section */
		if (sym->st_shndx >= info->ehdr->e_shnum
		    || (sym_section
		      = info->shdr2section[sym->st_shndx]) == NULL) {
			_JC_EX_STORE(env, LinkageError,
			    "%s: invalid section index %d for symbol `%s'",
			    elf->pathname, sym->st_shndx, name);
			return JNI_ERR;
		}

		/* Apply relocation */
		if (_jc_elf_arch_reloc(env, elf->pathname,
		    loadable->vaddr, rela->r_offset, type,
		    (Elf_Addr)(sym_section->vaddr + sym->st_value),
		    rela->r_addend) != JNI_OK)
			return JNI_ERR;
		break;
	    }
	}

	/* Done */
	return JNI_OK;
}
Exemple #7
0
/*
 * Find the internal _jc_class_loader structure corresponding to
 * a ClassLoader object. Create one if it doesn't already exist,
 * but do so atomically.
 *
 * Posts an exception on failure.
 */
_jc_class_loader *
_jc_get_loader(_jc_env *env, _jc_object *obj)
{
	_jc_jvm *const vm = env->vm;
	jboolean vm_locked = JNI_FALSE;
	_jc_class_loader *loader;
	_jc_resolve_info info;

	/* Check for null */
	if (obj == NULL) {
		_jc_post_exception(env, _JC_NullPointerException);
		return NULL;
	}
	_JC_ASSERT(_jc_subclass_of(obj, vm->boot.types.ClassLoader));

	/* Lock VM */
	_JC_MUTEX_LOCK(env, vm->mutex);
	vm_locked = JNI_TRUE;

	/* See if loader structure already exists */
	if ((loader = _jc_get_vm_pointer(vm, obj,
	    vm->boot.fields.ClassLoader.vmdata)) != NULL)
		goto done;

	/* Create a new loader structure */
	if ((loader = _jc_create_loader(env)) == NULL) {
		_jc_post_exception_info(env);
		goto done;
	}
	loader->instance = obj;

	/* Set the ClassLoader.vmdata field */
	if (_jc_set_vm_pointer(env, obj,
	    vm->boot.fields.ClassLoader.vmdata, loader) != JNI_OK) {
	    	_jc_destroy_loader(vm, &loader);
	    	goto done;
	}

	/* Unlock VM */
	_JC_MUTEX_UNLOCK(env, vm->mutex);
	vm_locked = JNI_FALSE;

	/* Create reference list with one reference */
	memset(&info, 0, sizeof(info));
	info.loader = loader,
	info.implicit_refs = &loader->instance;
	info.num_implicit_refs = 1;

	/* Put ClassLoader object on implicit reference list */
	if (_jc_merge_implicit_refs(env, &info) != JNI_OK) {
		_jc_destroy_loader(vm, &loader);
		_jc_post_exception_info(env);
		goto done;
	}

done:
	/* Unlock VM */
	if (vm_locked)
		_JC_MUTEX_UNLOCK(env, vm->mutex);

	/* Done */
	return loader;
}
Exemple #8
0
/*
 * Search for a class file node in the VM class file tree. If not found,
 * actively retrieve it by trying to load it with the supplied class loader.
 *
 * Because user class loaders control finding and loading their classes,
 * the only way for us to force the acquisition of a classfile is to try to
 * load the type. In general this may cause ClassCircularityErrors, but we
 * don't care about them because by the time one is thrown, the class file
 * has already been seen by us and its node stored in the class file tree.
 *
 * If successful, the node is returned with an extra reference.
 *
 * This function is used only if vm->without_classfiles is false.
 */
_jc_class_node *
_jc_get_class_node(_jc_env *env, _jc_class_loader *loader, const char *name)
{
	_jc_jvm *const vm = env->vm;
	_jc_class_save class_save;
	_jc_class_node *node;
	_jc_class_node key;
	_jc_type *type;

	/* Sanity check */
	_JC_ASSERT(name[0] != '[');
	_JC_ASSERT(!vm->without_classfiles);

	/* Lock VM */
	_JC_MUTEX_LOCK(env, vm->mutex);

	/* Search for existing class file node */
	key.name = name;
	if ((node = _jc_splay_find(&vm->classfiles, &key)) != NULL
	    && node->bytes != NULL) {
		node->refs++;
		_JC_MUTEX_UNLOCK(env, vm->mutex);
		return node;
	}
	node = NULL;

	/* Unlock VM */
	_JC_MUTEX_UNLOCK(env, vm->mutex);

	/* If loader is the boot loader, we can get the class file directly */
	if (loader == vm->boot.loader) {
		_jc_classbytes *cbytes;

		/* Find the class file bytes in the filesystem */
		if ((cbytes = _jc_bootcl_find_classbytes(env,
		    name, NULL)) == NULL) {
			_jc_post_exception_info(env);
			goto done;
		}

		/* Try to add class file to class file tree */
		_JC_MUTEX_LOCK(env, vm->mutex);
		node = _jc_ref_class_node(env, name, cbytes->hash, cbytes);
		_JC_MUTEX_UNLOCK(env, vm->mutex);

		/* Free class file bytes */
		_jc_free_classbytes(&cbytes);

		/* Post stored exception if failed */
		if (node == NULL)
			_jc_post_exception_info(env);

		/* Done */
		goto done;
	}

	/* Initialize our class file save structure */
	class_save.name = name;
	class_save.bytes = NULL;
	class_save.next = env->class_save;
	env->class_save = &class_save;

	/*
	 * Attempt to load the type in order to acquire the class file.
	 * If we succeeded, then the class file node must have been added.
	 */
	if ((type = _jc_load_type(env, loader, name)) != NULL) {

		/* Lock VM */
		_JC_MUTEX_LOCK(env, vm->mutex);

		/* Find node and add reference */
		node = _jc_splay_find(&vm->classfiles, &key);
		_JC_ASSERT(node != NULL);
		node->refs++;

		/* Unlock VM */
		_JC_MUTEX_UNLOCK(env, vm->mutex);

		/* Done */
		goto done;
	}

	/* Ignore LinkageError's but bail out if any other exception */
	if (!_jc_unpost_exception(env, _JC_LinkageError))
		goto done;

	/* Lock VM */
	_JC_MUTEX_LOCK(env, vm->mutex);

	/*
	 * Look for class file in our class file save structure; if found,
	 * copy its info to VM tree and grab a reference to the new node.
	 */
	if (class_save.bytes != NULL) {

		/* Add node */
		node = _jc_ref_class_node(env, name,
		    class_save.bytes->hash, class_save.bytes);
		_JC_MUTEX_UNLOCK(env, vm->mutex);

		/* Post exception if failed */
		if (node == NULL)
			_jc_post_exception_info(env);

		/* Done */
		goto done;
	}

	/* Unlock VM */
	_JC_MUTEX_UNLOCK(env, vm->mutex);

done:
	/* Destroy class save structure if we added one */
	if (env->class_save == &class_save) {
		_jc_free_classbytes(&class_save.bytes);
		env->class_save = class_save.next;
	}

	/* Done */
	return node;
}