コード例 #1
0
ファイル: stack_dump_os.cpp プロジェクト: dacut/juliet
void sd_cleanup_crash_handler()
{
    if (g_curdir)
        STD_FREE(g_curdir);
    if (g_cmdline)
        STD_FREE(g_cmdline);
}
コード例 #2
0
void gc_verifier_metadata_destruct(Heap_Verifier* heap_verifier)
{
  Heap_Verifier_Metadata* metadata = heap_verifier->heap_verifier_metadata;
  
  sync_pool_destruct(metadata->free_task_pool);
  sync_pool_destruct(metadata->free_set_pool);

  sync_pool_destruct(metadata->mark_task_pool);
  sync_pool_destruct(metadata->root_set_pool); 
  sync_pool_destruct(metadata->objects_pool_before_gc);
  sync_pool_destruct(metadata->objects_pool_after_gc);
  sync_pool_destruct(metadata->resurrect_objects_pool_before_gc);
  sync_pool_destruct(metadata->resurrect_objects_pool_after_gc);
  sync_pool_destruct(metadata->new_objects_pool);  
  sync_pool_destruct(metadata->hashcode_pool_before_gc);
  sync_pool_destruct(metadata->hashcode_pool_after_gc);
  
  sync_pool_destruct(metadata->obj_with_fin_pool);
  sync_pool_destruct(metadata->finalizable_obj_pool);

  for(unsigned int i=0; i<metadata->num_alloc_segs; i++){
    assert(metadata->segments[i]);
    STD_FREE(metadata->segments[i]);
  }
  STD_FREE( heap_verifier->heap_verifier_metadata);
  heap_verifier->heap_verifier_metadata = NULL;
}
コード例 #3
0
ファイル: compile.cpp プロジェクト: dacut/juliet
void compile_clear_dynamic_code_list(DynamicCode* list)
{
    while (list)
    {
        DynamicCode* next = list->next;
        if (list->free_name)
            STD_FREE((void *)list->name);
        STD_FREE(list);
        list = next;
    }
}
コード例 #4
0
ファイル: io.c プロジェクト: rod-lin/ivm
ivm_char_t *
ivm_file_readAll(ivm_file_t *file,
				 ivm_size_t *size)
{
	ivm_file_raw_t fp = file->fp;
	ivm_size_t len = ivm_file_length(file), tmp_len;
	ivm_size_t orig = IVM_FTELL(fp);
	ivm_char_t *ret, *cur;

	if (len == -1) {
		// read from non-static file
		len = IVM_DEFAULT_FILE_READ_BUFFER_SIZE;
		cur = ret = STD_ALLOC(sizeof(*ret) * (len + 1));

		// read and check if the buffer is full
		while ((tmp_len = IVM_FREAD(cur, sizeof(*cur), IVM_DEFAULT_FILE_READ_BUFFER_SIZE, fp))
			   == IVM_DEFAULT_FILE_READ_BUFFER_SIZE) {
			len += IVM_DEFAULT_FILE_READ_BUFFER_SIZE;
			ret = STD_REALLOC(ret, sizeof(*ret) * (len + 1));
			cur = ret + len - IVM_DEFAULT_FILE_READ_BUFFER_SIZE; // next write point
		}

		if (!feof(fp)) {
			STD_FREE(ret);
			return IVM_NULL;
		}

		// trim the empty buffer
		len -= IVM_DEFAULT_FILE_READ_BUFFER_SIZE - tmp_len;
		ret = STD_REALLOC(ret, sizeof(*ret) * (len + 1));
	} else {
		len -= IVM_FTELL(fp); // remove the length we've already read
		ret = STD_ALLOC(sizeof(*ret) * (len + 1));
		// FGOTO(fp, HEAD);
		if (len != IVM_FREAD(ret, sizeof(*ret), len, fp)) {
			/* unexpected read len */
			// unwind to the original position
			IVM_FSEEK(fp, IVM_FSEEK_HEAD, orig);
			STD_FREE(ret);
			return IVM_NULL;
		}
	}

	ret[len] = '\0';
	if (size) *size = len; // return size

	return ret;
}
コード例 #5
0
int port_thread_detach()
{
    port_tls_data_t* tlsdata;
    int res;

    if (!port_shared_data && (res = init_port_shared_data()) != 0)
        return res;

    tlsdata = get_private_tls_data();

    if (!tlsdata)
        return 0;

    if (port_thread_detach_temporary() == 0)
        return 0;

    res = set_guard_page(tlsdata, FALSE);

    if (res != 0)
        return res;

    size_t mapping_addr = (size_t)tlsdata->stack_addr - tlsdata->stack_size;
    size_t mapping_size =
        (tlsdata->guard_stack_size + tlsdata->mem_protect_size + 2*PSD->guard_page_size - 1) &
            ~(PSD->guard_page_size - 1);
    munmap((void*)mapping_addr, mapping_size);

    if (tlsdata->foreign)
        STD_FREE(tlsdata);

    return set_private_tls_data(NULL);
}
コード例 #6
0
static void c_handler(Registers* pregs,
                        void* fault_addr, size_t code, size_t flags)
{ // this exception handler is executed *after* VEH handler returned
    int result;
    Boolean iscrash = (DWORD)flags == EXCEPTION_NONCONTINUABLE;

    switch ((DWORD)code)
    {
    case STATUS_STACK_OVERFLOW:
        result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, pregs, fault_addr, iscrash);
        break;
    case STATUS_ACCESS_VIOLATION:
        result = port_process_signal(PORT_SIGNAL_GPF, pregs, fault_addr, iscrash);
        break;
    case STATUS_INTEGER_DIVIDE_BY_ZERO:
    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
    case EXCEPTION_FLT_OVERFLOW:
    case EXCEPTION_FLT_UNDERFLOW:
    case EXCEPTION_INT_OVERFLOW:
        result = port_process_signal(PORT_SIGNAL_ARITHMETIC, pregs, fault_addr, iscrash);
        break;
    case JVMTI_EXCEPTION_STATUS:
        result = port_process_signal(PORT_SIGNAL_BREAKPOINT, pregs, fault_addr, iscrash);
        break;
    default:
        result = port_process_signal(PORT_SIGNAL_UNKNOWN, pregs, fault_addr, TRUE);
    }

    port_tls_data_t* tlsdata = get_private_tls_data();

    if (result == 0)
    {
        // Restore guard page if needed
        if (tlsdata->restore_guard_page)
        {
            port_thread_restore_guard_page();
            tlsdata->restore_guard_page = FALSE;
        }

        if (port_thread_detach_temporary() == 0)
            STD_FREE(tlsdata);
        return;
    }

    if (result > 0 /*Assert dialog*/|| FLAG_CORE)
    {
        // Prepare second catch of this exception to produce minidump (because
        // we've lost LPEXCEPTION_POINTERS structure) and/or show assert dialog
        if (FLAG_CORE)
            tlsdata->produce_core = TRUE;
        if (result > 0)
            tlsdata->debugger = TRUE;
        // To catch STACK_OVERFLOW
        port_thread_restore_guard_page();

        return; // To produce exception again
    }

    _exit(-1); // We need neither dump nor assert dialog
}
コード例 #7
0
ファイル: io.c プロジェクト: rod-lin/ivm
IVM_PRIVATE
void
_ivm_buffer_stream_destruct(ivm_stream_t *stream)
{
	ivm_buffer_stream_t *bufs = (ivm_buffer_stream_t *)stream;
	STD_FREE(bufs->buf);
	return;
}
コード例 #8
0
ファイル: io.c プロジェクト: rod-lin/ivm
void
ivm_file_free_n(ivm_file_t *file)
{
	if (file) {
		STD_FREE(file);
	}

	return;
}
コード例 #9
0
ファイル: io.c プロジェクト: rod-lin/ivm
void
ivm_file_free(ivm_file_t *file)
{
	if (file) {
		IVM_FCLOSE(file->fp);
		STD_FREE(file);
	}

	return;
}
コード例 #10
0
void mutator_destruct(GC* gc, void *unused_gc_information)
{

  Mutator *mutator = (Mutator *)gc_get_tls();

  alloc_context_reset((Allocator*)mutator);


  lock(gc->mutator_list_lock);     // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

#ifdef USE_UNIQUE_MARK_SWEEP_GC
  allocactor_destruct_local_chunks((Allocator*)mutator);
#endif
  mutator_register_new_obj_size(mutator);

  volatile Mutator *temp = gc->mutator_list;
  if (temp == mutator) {  /* it is at the head of the list */
    gc->mutator_list = temp->next;
  } else {
    while (temp->next != mutator) {
      temp = temp->next;
      assert(temp);
    }
    temp->next = mutator->next;
  }
  gc->num_mutators--;

  unlock(gc->mutator_list_lock); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  
  if(gc_is_gen_mode()){ /* put back the remset when a mutator exits */
    pool_put_entry(gc->metadata->mutator_remset_pool, mutator->rem_set);
    mutator->rem_set = NULL;
  }
  
  if(mutator->obj_with_fin){
    pool_put_entry(gc->finref_metadata->obj_with_fin_pool, mutator->obj_with_fin);
    mutator->obj_with_fin = NULL;
  }

  lock(mutator->dirty_set_lock);
  if( mutator->dirty_set != NULL){
    if(vector_block_is_empty(mutator->dirty_set))
      pool_put_entry(gc->metadata->free_set_pool, mutator->dirty_set);
    else{ /* FIXME:: this condition may be released. */
      pool_put_entry(gc->metadata->gc_dirty_set_pool, mutator->dirty_set);
      mutator->dirty_set = NULL;
    }
  }
  unlock(mutator->dirty_set_lock);
  STD_FREE(mutator);
  gc_set_tls(NULL);
  
  return;
}
コード例 #11
0
ファイル: io.c プロジェクト: rod-lin/ivm
void
ivm_stream_free(ivm_stream_t *stream)
{
	if (stream) {
		if (stream->des) {
			stream->des(stream);
		}

		STD_FREE(stream);
	}

	return;
}
コード例 #12
0
APR_DECLARE(apr_status_t) port_dso_load_ex(apr_dso_handle_t** handle,
                                           const char* path,
                                           U_32 mode,
                                           apr_pool_t* pool){
    /*
    * FIXME Windows does not support lazy dll resolution a la Linux's RTLD_LAZY.
    * Proper support for it requires hacking of APR DSO functions. 
    * Just ignore the <code>mode<code> param for now.
    */

    /*if (mode == PORT_DSO_DEFAULT || !path) {*/
        char *self_path;
        apr_status_t res;

        if (!path) {
            port_executable_name(&self_path);
            res = apr_dso_load(handle, (const char*)self_path, pool);
            STD_FREE(self_path);
            return res;
        }

        return apr_dso_load(handle, path, pool);

    /*} else {
        HINSTANCE native_handle = NULL;
        DWORD flag = (mode & PORT_DSO_BIND_DEFER) ? 
            (DONT_RESOLVE_DLL_REFERENCES) : (0);
        char *cp = apr_pstrdup(pool, path);
        char *p = cp;
        while ((p = strchr(p, '/')) != NULL) {
            *p = '\\';
        }

        native_handle = LoadLibraryEx(cp, NULL, flag);
        *handle = apr_palloc(pool, sizeof(apr_dso_handle_t));
        if (native_handle == 0) {
            native_handle = LoadLibraryEx(cp, NULL, flag | LOAD_WITH_ALTERED_SEARCH_PATH);
            if (native_handle == 0) {
                DWORD sys_err = apr_get_os_error();
                (*handle)->error = sys_err;
                return sys_err;
            }
        }
        (*handle)->handle = native_handle;
        (*handle)->pool = pool;
        (*handle)->error = APR_SUCCESS;
        return APR_SUCCESS;
    }*/
}
コード例 #13
0
void Method::unregister_jit_recompiled_method_callbacks(const Method* caller) {
    TRACE2("cu.debug", "unregister jit callback, caller=" << caller << " callee=" << this);
    Method_Change_Notification_Record *nr,*prev = NULL;
    for (nr = _notify_recompiled_records;  nr != NULL;  ) {
        if (nr->caller == caller) {
            if (prev) {
                prev->next = nr->next;
            } else {
                _notify_recompiled_records = nr->next;
            }
            Method_Change_Notification_Record *next = nr->next;
            STD_FREE(nr);
            nr = next;
        } else {
            prev = nr;
            nr = nr->next;
        }
    }
}
コード例 #14
0
// This function is for native library support
// It takes a class name with .s not /s. 
// FIXME: caller could convert it itself
Class_Handle class_find_loaded(Class_Loader_Handle loader, const char* name)
{
    char* name3 = strdup(name);
    char* p = name3;
    while (*p) {
        if (*p=='.') *p='/';
        p++;
    }
    Global_Env* env = VM_Global_State::loader_env;
    String* name2 = env->string_pool.lookup(name3);
    Class* ch;
    if (loader) {
        ch = loader->LookupClass(name2);
    } else {
        ch = env->bootstrap_class_loader->LookupClass(name2);
    }
    STD_FREE(name3);
    if(ch && (!ch->verify(env) || !ch->prepare(env))) return NULL;
    return ch;
}
コード例 #15
0
ファイル: io.c プロジェクト: rod-lin/ivm
ivm_char_t *
ivm_file_read_n(ivm_file_t *file,
				ivm_size_t len)
{
	ivm_file_raw_t fp = file->fp;
	ivm_size_t orig = IVM_FTELL(fp);
	ivm_char_t *ret;

	ret = STD_ALLOC(sizeof(*ret) * (len + 1));
	// IVM_TRACE("%ld\n", len);
	
	if (len != IVM_FREAD(ret, sizeof(*ret), len, fp)) {
		/* unexpected read len */
		IVM_FSEEK(fp, IVM_FSEEK_HEAD, orig);
		STD_FREE(ret);
		return IVM_NULL;
	}
	
	ret[len] = '\0';

	return ret;
}
コード例 #16
0
/*Copy the fake blocks into real blocks, reconnect these new block into main list of mspace.
  *Free the fake blocks. The infomation of mspace is not updated yet.
 */
void gc_space_tuner_release_fake_blocks_for_los_shrink(GC* gc)
{
  Space_Tuner *tuner = gc->tuner;
  Blocked_Space* mspace = (Blocked_Space*)gc_get_mos((GC_Gen*)gc);
  
  POINTER_SIZE_INT tune_size = tuner->tuning_size;
  unsigned int tune_blocks = (unsigned int)(tune_size >> GC_BLOCK_SHIFT_COUNT);

  Block* blocks = (Block*)((POINTER_SIZE_INT)mspace->blocks - tune_size);
  Block_Header* last_real_block = (Block_Header*)blocks;
  unsigned int i;
  for(i=0; i < tune_blocks; i++){
    Block_Header* real_block = (Block_Header*)&(blocks[i]);
    Block_Header* fake_block = &tuner->interim_blocks[i];
    memcpy((void*)real_block, (void*)fake_block, sizeof(Block_Header));
    last_real_block->next = real_block;
    last_real_block = real_block;
  }
  last_real_block->next = (Block_Header*)mspace->blocks;
  STD_FREE(tuner->interim_blocks);
  return;
}
コード例 #17
0
ファイル: compile.cpp プロジェクト: dacut/juliet
// Create an exception from a given type and a message.
// Set cause to the current thread exception.
static void compile_raise_exception(const char* name, const char* message, Method* method)
{
    assert(hythread_is_suspend_enabled());
    jthrowable old_exc = exn_get();
    exn_clear();

    const char* c = method->get_class()->get_name()->bytes;
    const char* m = method->get_name()->bytes;
    const char* d = method->get_descriptor()->bytes;
    size_t sz = 3 + // a space, a dot, and a terminator
        strlen(message) +
        method->get_class()->get_name()->len +
        method->get_name()->len +
        method->get_descriptor()->len;
    char* msg_raw = (char*)STD_MALLOC(sz);
    assert(msg_raw);
    sprintf(msg_raw, "%s%s.%s%s", message, c, m, d);
    assert(strlen(msg_raw) < sz);

    jthrowable new_exc = exn_create(name, msg_raw, old_exc);
    exn_raise_object(new_exc);
    STD_FREE(msg_raw);
}
コード例 #18
0
int port_thread_attach()
{
    int res;
    port_tls_data_t* tlsdata;

    if (!port_shared_data && (res = init_port_shared_data()) != 0)
        return res;

    if (get_private_tls_data())
        return 0;

    tlsdata = (port_tls_data_t*)STD_MALLOC(sizeof(port_tls_data_t));

    if (!tlsdata)
        return ENOMEM;

    res = port_thread_attach_local(tlsdata, FALSE, TRUE, 0);

    if (res != 0)
        STD_FREE(tlsdata);

    return res;
}
コード例 #19
0
Class_Handle class_find_class_from_loader(Class_Loader_Handle loader, const char* n, Boolean init)
{
    ASSERT_RAISE_AREA;
    assert(hythread_is_suspend_enabled()); // -salikh
    char *new_name = strdup(n);
    char *p = new_name;
    while (*p) {
        if (*p == '.') *p = '/';
        p++;
    }
    String* name = VM_Global_State::loader_env->string_pool.lookup(new_name);
    STD_FREE(new_name);
    Class* ch;
    if (loader) {
        ch = class_load_verify_prepare_by_loader_jni(
            VM_Global_State::loader_env, name, loader);
    } else {
        assert(hythread_is_suspend_enabled());
        ch = class_load_verify_prepare_from_jni(VM_Global_State::loader_env, name);
    }
    if (!ch) return NULL;
    // All initialization from jni should not propagate exceptions and
    // should return to calling native method.
    if(init) {
        class_initialize_from_jni(ch);

        if (exn_raised()) {
            return NULL;
        }
    }

    if(exn_raised()) {
        return 0;
    }

    return ch;
}
コード例 #20
0
Class* resolve_class_array_of_class(Global_Env* env, Class* cc)
{
    // If the element type is primitive, return one of the preloaded
    // classes of arrays of primitive types.
    if (cc->is_primitive()) {
        if (cc == env->Boolean_Class) {
            return env->ArrayOfBoolean_Class;
        } else if (cc == env->Byte_Class) {
            return env->ArrayOfByte_Class;
        } else if (cc == env->Char_Class) {
            return env->ArrayOfChar_Class;
        } else if (cc == env->Short_Class) {
            return env->ArrayOfShort_Class;
        } else if (cc == env->Int_Class) {
            return env->ArrayOfInt_Class;
        } else if (cc == env->Long_Class) {
            return env->ArrayOfLong_Class;
        } else if (cc == env->Float_Class) {
            return env->ArrayOfFloat_Class;
        } else if (cc == env->Double_Class) {
            return env->ArrayOfDouble_Class;
        }
    }

    char *array_name = (char *)STD_MALLOC(cc->get_name()->len + 5);
    if(cc->get_name()->bytes[0] == '[') {
        sprintf(array_name, "[%s", cc->get_name()->bytes);
    } else {
        sprintf(array_name, "[L%s;", cc->get_name()->bytes);
    }
    String *arr_str = env->string_pool.lookup(array_name);
    STD_FREE(array_name);

    Class* arr_clss = cc->get_class_loader()->LoadVerifyAndPrepareClass(env, arr_str);

    return arr_clss;
} // resolve_class_array_of_class
コード例 #21
0
static PORT_CDECL int thread_start_func(void* arg)
{
    int err, result;
    port_tls_data_t* tlsdata = NULL;
    thread_start_struct_t* ptr = (thread_start_struct_t*)arg;
    port_threadfunc_t fun = ptr->fun;
    size_t stack_size = ptr->stack_size;
    arg = ptr->arg;
    STD_FREE(ptr);

    if (port_shared_data)
    {
        tlsdata = (port_tls_data_t*)STD_ALLOCA(sizeof(port_tls_data_t));
        err = port_thread_attach_local(tlsdata, FALSE, FALSE, stack_size);
        assert(err == 0);
    }

    result = fun(arg);

    if (tlsdata)
        port_thread_detach();

    return result;
}
コード例 #22
0
void gc_gen_collector_stats_destruct(Collector* collector)
{
  STD_FREE(collector->stats);
}
コード例 #23
0
static void c_handler(Registers* pregs, size_t signum, void* fault_addr)
{   // this exception handler is executed *after* OS signal handler returned
    int result;
    port_tls_data_t* tlsdata = get_private_tls_data();

    switch ((int)signum)
    {
    case SIGSEGV:
        if (tlsdata->restore_guard_page)
        {
            // Now it's safe to disable alternative stack
            set_alt_stack(tlsdata, FALSE);
            result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, pregs, fault_addr, FALSE);
        }
        else
            result = port_process_signal(PORT_SIGNAL_GPF, pregs, fault_addr, FALSE);
        break;
    case SIGFPE:
        result = port_process_signal(PORT_SIGNAL_ARITHMETIC, pregs, fault_addr, FALSE);
        break;
    case SIGTRAP:
        // Correct return address
        pregs->set_ip((void*)((POINTER_SIZE_INT)pregs->get_ip() - 1));
        result = port_process_signal(PORT_SIGNAL_BREAKPOINT, pregs, fault_addr, FALSE);
        break;
    case SIGINT:
        result = port_process_signal(PORT_SIGNAL_CTRL_C, pregs, fault_addr, FALSE);
        break;
    case SIGQUIT:
        result = port_process_signal(PORT_SIGNAL_QUIT, pregs, fault_addr, FALSE);
        break;
    case SIGABRT:
        result = port_process_signal(PORT_SIGNAL_ABORT, NULL, fault_addr, FALSE);
        break;
    default:
        result = port_process_signal(PORT_SIGNAL_UNKNOWN, pregs, fault_addr, TRUE);
    }

    if (result == 0)
    {
        // Restore guard page if needed
        if (tlsdata->restore_guard_page)
        {
            port_thread_restore_guard_page();
            tlsdata->restore_guard_page = FALSE;

            if (port_thread_detach_temporary() == 0)
                STD_FREE(tlsdata);
        }
        return;
    }

    // We've got a crash
    if (signum == SIGSEGV)
    {
        port_thread_restore_guard_page(); // To catch SO again
        tlsdata->restore_guard_page = FALSE;
    }

    if (result > 0) // invoke debugger
    {   // Prepare second catch of signal to attach GDB from signal handler
        //assert(tlsdata); // Should be attached - provided by general_signal_handler
        tlsdata->debugger = TRUE;
        return; // To produce signal again
    }

    // result < 0 - exit process
    if (FLAG_CORE)
    {   // Return to the same place to produce the same crash and generate core
        signal(signum, SIG_DFL); // setup default handler
        return;
    }

    // No core needed - simply terminate
    _exit(-1);
}
コード例 #24
0
ncaiError JNICALL ncaiWriteMemory(ncaiEnv* env,
        void* addr, size_t size, void* buf)
{
    TRACE2("ncai.memory", "WriteMemory called");

    if (!env)
        return NCAI_ERROR_INVALID_ENVIRONMENT;

    VMBreakPoints* vm_breaks = VM_Global_State::loader_env->TI->vm_brpt;
    LMAutoUnlock lock(vm_breaks->get_lock());

    jbyte* end_addr = (jbyte*)addr + size;
    VMBreakPoint* cur;
    size_t rewrite_count = 0;

    // Count addresses in given range
    for (cur = vm_breaks->get_first_breakpoint(); cur;
         cur = vm_breaks->get_next_breakpoint(cur))
    {
        if (cur->addr >= addr && cur->addr < end_addr)
            ++rewrite_count;
    }

    // Simple case: there are no breakpoints in specified address range
    if (rewrite_count == 0)
    {
        if (port_write_memory(addr, size, buf) == 0)
            return NCAI_ERROR_NONE;
        else
            return NCAI_ERROR_ACCESS_DENIED;
    }

    // Allocate array for address sorting
    RewriteArray rwa;
    rwa.array = (BreakListItem*)STD_MALLOC(rewrite_count*sizeof(BreakListItem));

    if (!rwa.array)
        return NCAI_ERROR_OUT_OF_MEMORY;

    memset(rwa.array, 0, rewrite_count*sizeof(BreakListItem));
    rwa.list = NULL;
    rwa.size = rewrite_count;
    rwa.count = 0;

    // Add matching addresses to sorted list
    for (cur = vm_breaks->get_first_breakpoint(); cur;
         cur = vm_breaks->get_next_breakpoint(cur))
    {
        if (cur->addr >= addr && cur->addr < end_addr)
            add_rewrite_address(&rwa, cur);
    }

    // Write memory
    size_t remain = size;
    BreakListItem* cur_bla = rwa.list;
    assert(cur_bla);
    jbyte* cbuf = (jbyte*)buf;
    jbyte* cur_addr = (jbyte*)addr;
    int err = 0;

    while (remain)
    {
        if (!cur_bla || cur_bla->bp->addr > cur_addr)
        { // Write buffer to memory
            size_t offset = (size_t)cur_addr - (size_t)addr;
            size_t chunk_size = cur_bla ? ((jbyte*)cur_bla->bp->addr - cur_addr)
                                        : (end_addr - cur_addr);
            err = port_write_memory(cur_addr, chunk_size, cbuf + offset);

            if (err != 0)
                break;

            cur_addr += chunk_size;
            remain -= chunk_size;
        }

        if (cur_bla)
        { // Write byte from buffer to 'saved_byte' field in breakpoint
            assert(cur_addr == cur_bla->bp->addr);

            size_t offset = (size_t)cur_addr - (size_t)addr;
            cur_bla->bp->saved_byte = cbuf[offset];
            cur_bla = cur_bla->next;
            ++cur_addr;
            --remain;
        }
    }

    STD_FREE(rwa.array);
    return (err == 0) ? NCAI_ERROR_NONE : NCAI_ERROR_ACCESS_DENIED;
}
コード例 #25
0
ファイル: parse_arguments.cpp プロジェクト: dacut/juliet
void parse_vm_arguments2(Global_Env *p_env)
{
    bool version_printed = false;
#ifdef _DEBUG
    TRACE("p_env->vm_arguments.nOptions  = " << p_env->vm_arguments.nOptions);
    for (int _i = 0; _i < p_env->vm_arguments.nOptions; _i++)
        TRACE("p_env->vm_arguments.options[ " << _i << "] = " << p_env->vm_arguments.options[_i].optionString);
#endif //_DEBUG

    apr_pool_t *pool;
    apr_pool_create(&pool, 0);

    for (int i = 0; i < p_env->vm_arguments.nOptions; i++) {
        const char* option = p_env->vm_arguments.options[i].optionString;

        if (begins_with(option, XBOOTCLASSPATH)) {
            /*
             *  Override for bootclasspath - 
             *  set in the environment- the boot classloader will be responsible for 
             *  processing and setting up "vm.boot.class.path" and "sun.boot.class.path"
             *  Note that in the case of multiple arguments, the last one will be used
             */
            p_env->VmProperties()->set(XBOOTCLASSPATH, option + strlen(XBOOTCLASSPATH));
        }
        else if (begins_with(option, XBOOTCLASSPATH_A)) {
            /*
             *  addition to append to boot classpath
             *  set in environment - responsibility of boot classloader to process
             *  Note that we accumulate if multiple, appending each time
             */

            char *bcp_old = p_env->VmProperties()->get(XBOOTCLASSPATH_A);
            const char *value = option + strlen(XBOOTCLASSPATH_A);
            char *bcp_new = NULL;
            
            if (bcp_old) { 
                 char *tmp = (char *) STD_MALLOC(strlen(bcp_old) + strlen(PORT_PATH_SEPARATOR_STR)
                                                        + strlen(value) + 1);
            
                 strcpy(tmp, bcp_old);
                 strcat(tmp, PORT_PATH_SEPARATOR_STR);
                 strcat(tmp, value);
                 
                 bcp_new = tmp;
            }
            
            p_env->VmProperties()->set(XBOOTCLASSPATH_A, bcp_old ? bcp_new : value);                       
            p_env->VmProperties()->destroy(bcp_old);
            STD_FREE((void*)bcp_new);
        }
        else if (begins_with(option, XBOOTCLASSPATH_P)) {
            /*
             *  addition to prepend to boot classpath
             *  set in environment - responsibility of boot classloader to process
             *  Note that we accumulate if multiple, prepending each time
             */
             
            char *bcp_old = p_env->VmProperties()->get(XBOOTCLASSPATH_P);
            const char *value = option + strlen(XBOOTCLASSPATH_P);
            
            char *bcp_new = NULL;
            
            if (bcp_old) { 
                 char *tmp = (char *) STD_MALLOC(strlen(bcp_old) + strlen(PORT_PATH_SEPARATOR_STR)
                                                        + strlen(value) + 1);
            
                 strcpy(tmp, value);
                 strcat(tmp, PORT_PATH_SEPARATOR_STR);
                 strcat(tmp, bcp_old);
                 
                 bcp_new = tmp;
            }
            
            p_env->VmProperties()->set(XBOOTCLASSPATH_P, bcp_old ? bcp_new : value);
            p_env->VmProperties()->destroy(bcp_old);
            STD_FREE((void*)bcp_new);
        } else if (begins_with(option, "-Xjit:")) {
            // Do nothing here, just skip this option for later parsing
        } else if (strcmp(option, "-Xint") == 0) {
            p_env->VmProperties()->set("vm.use_interpreter", "true");
#ifdef VM_STATS
        } else if (begins_with(option, "-Xstats:")) {
            vm_print_total_stats = true;
            const char* arg = option + strlen("-Xstats:");
            vm_print_total_stats_level = atoi(arg);
#endif
        } else if (strcmp(option, "-version") == 0) {
            // Print the version number and exit
            LECHO_VERSION;
            log_exit(0);
        } else if (strcmp(option, "-showversion") == 0) {
            if (!version_printed) {
                // Print the version number and continue
                LECHO_VERSION;
                version_printed = true;
            }
        } else if (strcmp(option, "-fullversion") == 0) {
            // Print the version number and exit
            LECHO_VM_VERSION;
            log_exit(0);

        } else if (begins_with(option, "-Xgc:")) {
            // make prop_key to be "gc.<something>"
            char* prop_key = strdup(option + strlen("-X"));
            prop_key[2] = '.';
            TRACE(prop_key << " = 1");
            p_env->VmProperties()->set(prop_key, "1");
            free(prop_key);

        } else if (begins_with(option, "-Xem:")) {
            const char* arg = option + strlen("-Xem:");
            p_env->VmProperties()->set("em.properties", arg);

        } else if (strcmp(option, "-client") == 0 || strcmp(option, "-server") == 0) {
            p_env->VmProperties()->set("em.properties", option + 1);

        } else if (begins_with(option, "-Xms") || begins_with(option, "-ms")) {
            // cut -Xms || -ms
            const char* arg = option + (begins_with(option, "-ms") ? 3 : 4);
            TRACE("gc.ms = " << arg);
            if (atoi(arg) <= 0) {
                LECHO(34, "Negative or invalid heap size. Default value will be used!");
            }
            p_env->VmProperties()->set("gc.ms", arg);

        } else if (begins_with(option, "-Xmx") || begins_with(option, "-mx")) {
            // cut -Xmx
            const char* arg = option + (begins_with(option, "-mx") ? 3 : 4);
            TRACE("gc.mx = " << arg);
            if (atoi(arg) <= 0) {
                LECHO(34, "Negative or invalid heap size. Default value will be used!");
            }
            p_env->VmProperties()->set("gc.mx", arg);
        } else if (begins_with(option, "-Xss")) {
            const char* arg = option + 4;
            TRACE("thread.stacksize = " << arg);
            if (atoi(arg) <= 0) {
                LECHO(34, "Negative or invalid stack size. Default value will be used!");
            }
            p_env->VmProperties()->set("thread.stacksize", arg);
    	}	  
        else if (begins_with(option, STRING_POOL_SIZE_OPTION)) {
            // the pool is already created
        }
        else if (begins_with(option, "-agentlib:")) {
            p_env->TI->addAgent(option);
        }
        else if (begins_with(option, "-agentpath:")) {
            p_env->TI->addAgent(option);
        }
        else if (begins_with(option, "-javaagent:")) {
            char* dest = (char*) STD_MALLOC(strlen("-agentlib:hyinstrument=") + strlen(option + 11) + 1);
            strcpy(dest, "-agentlib:hyinstrument=");
            strcat(dest, option + 11);
            p_env->TI->addAgent(dest);
            STD_FREE((void*) dest);
        }
        else if (begins_with(option, "-Xrun")) {
            // Compatibility with JNDI
            p_env->TI->addAgent(option);
        }
        else if (strcmp(option, "-Xnoagent") == 0) {
            // Do nothing, this option is only for compatibility with old JREs
        }
        else if (strcmp(option, "-Xdebug") == 0) {
            // Do nothing, this option is only for compatibility with old JREs
        }
        else if (strcmp(option, "-Xfuture") == 0) {
            // Do nothing, this option is only for compatibility with old JREs
        }
        else if (strcmp(option, "-Xinvisible") == 0) {
            p_env->retain_invisible_annotations = true;
        }
        else if (strcmp(option, "-Xverify") == 0) {
            p_env->verify_all = true;
        }
        else if (strcmp(option, "-Xverify:none") == 0 || strcmp(option, "-noverify") == 0) {
            p_env->VmProperties()->set("vm.use_verifier", "false");
        }
        else if (strcmp(option, "-Xverify:all") == 0) {
            p_env->verify_all = true;
            p_env->verify_strict = true;
        }
        else if (strcmp(option, "-Xverify:strict") == 0) {
            p_env->verify_all = true;
            p_env->verify_strict = true;
        }
        else if (strcmp(option, "-verify") == 0) {
            p_env->verify_all = true;
        }
        else if (begins_with(option, "-verbose")) {
            // Moved to set_log_levels_from_cmd
        } else if (begins_with(option, "-Xfileline")) {
            // Moved to set_log_levels_from_cmd
        } else if (begins_with(option, "-Xthread")) {
            // Moved to set_log_levels_from_cmd
        } else if (begins_with(option, "-Xcategory")) {
            // Moved to set_log_levels_from_cmd
        } else if (begins_with(option, "-Xtimestamp")) {
            // Moved to set_log_levels_from_cmd
        } else if (begins_with(option, "-Xverbose")) {
            // Moved to set_log_levels_from_cmd
        } else if (begins_with(option, "-Xwarn")) {
            // Moved to set_log_levels_from_cmd
        } else if (begins_with(option, "-Xfunction")) {
            // Moved to set_log_levels_from_cmd
#ifdef _DEBUG
        } else if (begins_with(option, "-Xlog")) {
            // Moved to set_log_levels_from_cmd
        } else if (begins_with(option, "-Xtrace")) {
            // Moved to set_log_levels_from_cmd
#endif //_DEBUG
        }
        else if (strncmp(option, "-D", 2) == 0) {
        }
        else if (strncmp(option, "-XD", 3) == 0 || strncmp(option, "-XX:", 4) == 0) {
        }
        else if (strcmp(option, "-Xdumpstubs") == 0) {
            dump_stubs = true;
        }
        else if (strcmp(option, "-Xparallel_jit") == 0) {
            parallel_jit = true;
        }
        else if (strcmp(option, "-Xno_parallel_jit") == 0) {
            parallel_jit = false;
        }
        else if (begins_with(option, "-Xdumpfile:")) {
            const char* arg = option + strlen("-Xdumpfile:");
            dump_file_name = arg;
        }
        else if (strcmp(option, "_org.apache.harmony.vmi.portlib") == 0) {
            // Store a pointer to the portlib
            p_env->portLib = p_env->vm_arguments.options[i].extraInfo;
        }
        else if (strcmp(option, "-help") == 0 
              || strcmp(option, "-h") == 0
              || strcmp(option, "-?") == 0) {
            print_generic_help();
            log_exit(0);
        }
        else if (strcmp(option,"-X") == 0) {
                print_help_on_nonstandard_options();
                log_exit(0);
        }
        else if (begins_with(option, "-enableassertions")) {
            add_assert_rec(p_env, option, "-enableassertions", true);
        }
        else if (begins_with(option, "-ea")) { 
            add_assert_rec(p_env, option, "-ea", true);
        }
        else if (begins_with(option, "-disableassertions")) { 
            add_assert_rec(p_env, option, "-disableassertions", false);
        }
        else if (begins_with(option, "-da")) { 
            add_assert_rec(p_env, option, "-da", false);
        }
        else if (strcmp(option, "-esa") == 0 
            || strcmp(option, "-enablesystemassertions") == 0) {
            get_assert_reg(p_env)->enable_system = true;
        }
        else if (strcmp(option, "-dsa") == 0 
            || strcmp(option, "-disablesystemassertions") == 0) {
                if (p_env->assert_reg) {
                    p_env->assert_reg->enable_system = false;
                }
        }
        else {
            LECHO(30, "Unknown option {0}" << option);
            USE_JAVA_HELP;
            log_exit(1);
       }
    } // for

    apr_pool_destroy(pool);
} //parse_vm_arguments2
コード例 #26
0
LONG NTAPI vectored_exception_handler_internal(LPEXCEPTION_POINTERS nt_exception)
{
    DWORD code = nt_exception->ExceptionRecord->ExceptionCode;
    void* fault_addr = nt_exception->ExceptionRecord->ExceptionAddress;

    Registers regs;
    // Convert NT context to Registers
    port_thread_context_to_regs(&regs, nt_exception->ContextRecord);

    // Check if TLS structure is set - probably we should produce minidump
    port_tls_data_t* tlsdata = get_private_tls_data();

    if (!tlsdata) // Tread is not attached - attach thread temporarily
    {
        int res;
        tlsdata = (port_tls_data_t*)STD_MALLOC(sizeof(port_tls_data_t));

        if (tlsdata) // Try to attach the thread
            res = port_thread_attach_local(tlsdata, TRUE, TRUE, 0);

        if (!tlsdata || res != 0)
        { // Can't process correctly; perform default actions
            if (FLAG_CORE)
                create_minidump(nt_exception);

            if (FLAG_DBG)
            {
                show_debugger_dialog(); // Workaround; EXCEPTION_CONTINUE_SEARCH does not work
                _exit(-1);
                return EXCEPTION_CONTINUE_SEARCH; // Assert dialog
            }

            _exit(-1);
        }

        // SO for alien thread can't be processed out of VEH
        if (code == STATUS_STACK_OVERFLOW &&
            sd_is_handler_registered(PORT_SIGNAL_STACK_OVERFLOW))
        {
            int result;
            size_t alt_stack_size = ALT_PAGES_COUNT*tlsdata->guard_page_size;
            void* alt_stack = map_alt_stack(alt_stack_size);
            void* stack_bottom = (void*)((POINTER_SIZE_INT)alt_stack + alt_stack_size);

            if (alt_stack)
                result = (int)(POINTER_SIZE_INT)port_call_alt_stack(
                                            port_process_signal, stack_bottom, 4,
                                            PORT_SIGNAL_STACK_OVERFLOW, &regs, fault_addr, FALSE);
            else
                result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, &regs, fault_addr, FALSE);

            if (result == 0)
            {
                if (port_thread_detach_temporary() == 0)
                    STD_FREE(tlsdata);
                if (alt_stack)
                    unmap_alt_stack(alt_stack, alt_stack_size);
                return EXCEPTION_CONTINUE_EXECUTION;
            }

            if (FLAG_CORE)
            {
                if (alt_stack)
                    port_call_alt_stack(create_minidump, stack_bottom, 1, nt_exception);
                else
                    create_minidump(nt_exception);
            }

            if (alt_stack)
                unmap_alt_stack(alt_stack, alt_stack_size);

            if (result > 0)
            {
                show_debugger_dialog(); // Workaround; EXCEPTION_CONTINUE_SEARCH does not work
                _exit(-1);
                shutdown_signals();
                return EXCEPTION_CONTINUE_SEARCH; // Assert dialog
            }

            _exit(-1);
        }
    }

    if (tlsdata->produce_core)
    {
        create_minidump(nt_exception);
        if (!tlsdata->debugger)
            _exit(-1);
    }

    if (tlsdata->debugger)
    {
        show_debugger_dialog(); // Workaround
        _exit(-1);
        // Go to handler to restore CRT/VEH settings and crash once again
//        port_set_longjump_regs(&prepare_assert_dialog, &regs, 1, &regs);
//        port_thread_regs_to_context(nt_exception->ContextRecord, &regs);
//        return EXCEPTION_CONTINUE_EXECUTION;
    }

    switch (code)
    {
    case STATUS_STACK_OVERFLOW:
        if (!sd_is_handler_registered(PORT_SIGNAL_STACK_OVERFLOW))
            return EXCEPTION_CONTINUE_SEARCH;
        break;
    case STATUS_ACCESS_VIOLATION:
        if (!sd_is_handler_registered(PORT_SIGNAL_GPF))
            return EXCEPTION_CONTINUE_SEARCH;
        break;
    case JVMTI_EXCEPTION_STATUS:
        if (!sd_is_handler_registered(PORT_SIGNAL_BREAKPOINT))
            return EXCEPTION_CONTINUE_SEARCH;
        break;
    case STATUS_INTEGER_DIVIDE_BY_ZERO:
    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
    case EXCEPTION_FLT_OVERFLOW:
    case EXCEPTION_FLT_UNDERFLOW:
    case EXCEPTION_INT_OVERFLOW:
        if (!sd_is_handler_registered(PORT_SIGNAL_ARITHMETIC))
            return EXCEPTION_CONTINUE_SEARCH;
        break;
    default:
        return EXCEPTION_CONTINUE_SEARCH;
    }

    if (code == STATUS_STACK_OVERFLOW)
    {
        tlsdata->guard_page_set = FALSE; // GUARD_PAGE was cleared by OS

        if (!tlsdata->restore_guard_page)
            tlsdata->restore_guard_page = TRUE;
    }

    // Prepare to transfering control out of VEH handler
    port_set_longjump_regs(&c_handler, &regs, 4, &regs,
        nt_exception->ExceptionRecord->ExceptionAddress,
        (void*)(size_t)nt_exception->ExceptionRecord->ExceptionCode,
        (void*)(size_t)nt_exception->ExceptionRecord->ExceptionFlags);
    // Convert prepared Registers back to NT context
    port_thread_regs_to_context(nt_exception->ContextRecord, &regs);
    // Return from VEH - presumably continue execution
    return EXCEPTION_CONTINUE_EXECUTION;
}
コード例 #27
0
int port_thread_create(/* out */osthread_t* phandle, size_t stacksize, int priority,
        port_threadfunc_t func, void *data)
{
    pthread_t thread;
    pthread_attr_t attr;
    pthread_attr_t attr_nosched;
    struct sched_param param;
    thread_start_struct_t* startstr;
    int res;

    if (!port_shared_data)
    {
        res = init_port_shared_data();
        /* assert(res); */
        /* It's OK to have an error here when Port shared library
           is not available yet; only signals/crash handling will
           not be available for the thread */
        /* return res; */
    }

    if (!func)
        return EINVAL;

    startstr =
        (thread_start_struct_t*)STD_MALLOC(sizeof(thread_start_struct_t));

    if (!startstr)
        return ENOMEM;

    pthread_attr_init(&attr);
    pthread_attr_init(&attr_nosched);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    pthread_attr_setdetachstate(&attr_nosched, PTHREAD_CREATE_DETACHED);

    if (stacksize != 0)
    {
        if (stacksize < MINSIGSTKSZ)
            stacksize = MINSIGSTKSZ;

        if (port_shared_data)
        {
            size_t min_stacksize =
                /* Let's get alt stack size for normal stack and add guard page size */
                ((2*port_shared_data->guard_stack_size + port_shared_data->guard_page_size)
                /* Roung up to alt stack size */
                    + port_shared_data->guard_stack_size - 1) & ~(port_shared_data->guard_stack_size - 1);

            if (stacksize < min_stacksize)
                stacksize = min_stacksize;
        }

        res = pthread_attr_setstacksize(&attr, stacksize);
        if (res == 0)
            res = pthread_attr_setstacksize(&attr_nosched, stacksize);
        if (res)
        {
            pthread_attr_destroy(&attr);
            pthread_attr_destroy(&attr_nosched);
            STD_FREE(startstr);
            return res;
        }
    }

    if (priority)
    {
        res = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
        if (res == 0)
        {
            param.sched_priority = priority;
            res = pthread_attr_setschedparam(&attr, &param);
        }
        /* This does not work anyway on some Linuses
        if (res != 0)
        {
            pthread_attr_destroy(&attr);
            pthread_attr_destroy(&attr_nosched);
            STD_FREE(startstr);
            return res;
        }*/
    }

    startstr->fun = func;
    startstr->arg = data;
    startstr->stack_size = stacksize;

    res = pthread_create(&thread, &attr, (pthread_func_t)thread_start_func, startstr);

    if (res == EPERM) // EPERM relates to scheduling only
        res = pthread_create(&thread, &attr_nosched, (pthread_func_t)thread_start_func, startstr);

    pthread_attr_destroy(&attr);
    pthread_attr_destroy(&attr_nosched);

    if (res == 0)
    {
        *phandle = thread;
        return 0;
    }

    STD_FREE(startstr);
    return res;
}
コード例 #28
0
static void general_signal_handler(int signum, siginfo_t* info, void* context)
{
    Registers regs;

    if (!context)
        return;

    // Convert OS context to Registers
    port_thread_context_to_regs(&regs, (ucontext_t*)context);
    void* fault_addr = info ? info->si_addr : NULL;

    // Check if SIGSEGV is produced by port_read/write_memory
    port_tls_data_t* tlsdata = get_private_tls_data();
    if (tlsdata && tlsdata->violation_flag)
    {
        tlsdata->violation_flag = 0;
        regs.set_ip(tlsdata->restart_address);
        return;
    }

    if (!tlsdata) // Tread is not attached - attach thread temporarily
    {
        int res;
        tlsdata = (port_tls_data_t*)STD_MALLOC(sizeof(port_tls_data_t));

        if (tlsdata) // Try to attach the thread
            res = port_thread_attach_local(tlsdata, TRUE, TRUE, 0);

        if (!tlsdata || res != 0)
        {   // Can't process correctly; perform default actions
            if (FLAG_DBG)
            {
                bool result = gdb_crash_handler(&regs);
                _exit(-1); // Exit process if not sucessful...
            }

            if (FLAG_CORE &&
                    signum != SIGABRT) // SIGABRT can't be rethrown
            {
                signal(signum, SIG_DFL); // setup default handler
                return;
            }

            _exit(-1);
        }

        // SIGSEGV can represent SO which can't be processed out of signal handler
        if (signum == SIGSEGV && // This can occur only when a user set an alternative stack
                is_stack_overflow(tlsdata, fault_addr))
        {
            int result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, &regs, fault_addr, FALSE);

            if (result == 0)
            {
                if (port_thread_detach_temporary() == 0)
                    STD_FREE(tlsdata);
                return;
            }

            if (result > 0)
                tlsdata->debugger = TRUE;
            else
            {
                if (FLAG_CORE)
                {   // Rethrow crash to generate core
                    signal(signum, SIG_DFL); // setup default handler
                    return;
                }
                _exit(-1);
            }
        }
    }

    if (tlsdata->debugger)
    {
        bool result = gdb_crash_handler(&regs);
        _exit(-1); // Exit process if not sucessful...
    }

    if (signum == SIGABRT && // SIGABRT can't be trown again from c_handler
            FLAG_DBG)
    {   // So attaching GDB right here
        bool result = gdb_crash_handler(&regs);
        _exit(-1); // Exit process if not sucessful...
    }

    if (signum == SIGSEGV &&
            is_stack_overflow(tlsdata, fault_addr))
    {
        // Second SO while previous SO is not processed yet - is GPF
        if (tlsdata->restore_guard_page)
            tlsdata->restore_guard_page = FALSE;
        else
        {   // To process signal on protected stack area
            port_thread_clear_guard_page();
            // Note: the call above does not disable alternative stack
            // It can't be made while we are on alternative stack
            // Alt stack will be disabled explicitly in c_handler()
            tlsdata->restore_guard_page = TRUE;
        }
    }

    // Prepare registers for transfering control out of signal handler
    void* callback = (void*)&c_handler;

    port_set_longjump_regs(callback, &regs, 3,
                           &regs, (void*)(size_t)signum, fault_addr);

    // Convert prepared Registers back to OS context
    port_thread_regs_to_context((ucontext_t*)context, &regs);
    // Return from signal handler to go to C handler
}
コード例 #29
0
void gc_gen_stats_destruct(GC_Gen* gc)
{
  STD_FREE(gc->stats);
}
コード例 #30
0
/*
 * Class:     java_lang_VMClassRegistry
 * Method:    getSystemPackages
 * Signature: (I)[[Ljava/lang/String;
 */
JNIEXPORT jobjectArray JNICALL Java_java_lang_VMClassRegistry_getSystemPackages
  (JNIEnv *jenv, jclass, jint len)
{
    Global_Env* genv = VM_Global_State::loader_env;
    ClassLoader* cl = static_cast<ClassLoader*>
        (genv->bootstrap_class_loader);
    Package_Table* ptab = cl->getPackageTable();
    cl->Lock();
    unsigned p_num = (unsigned)ptab->size();
    if (p_num == (unsigned)len) 
    {
        cl->Unlock();
        return NULL;
    }
    const char ** pkgs = (const char **)STD_MALLOC(p_num * 2 * sizeof(char*));
    size_t buf_len = 0;
    unsigned index = 0;
    for (Package_Table::const_iterator it = ptab->begin(), end = ptab->end(); 
        it != end; ++it)
    {
        const char* name = pkgs[index++] = (*it).first->bytes;
        pkgs[index++] = (*it).second->get_jar();
        size_t name_len = (*it).first->len;
        if (name_len > buf_len) {
            buf_len = name_len;
        }
    }
    cl->Unlock();

    jclass string_class = struct_Class_to_java_lang_Class_Handle(genv->JavaLangString_Class);
    static Class* aos = genv->LoadCoreClass("[Ljava/lang/String;");
    jclass string_array_class = struct_Class_to_java_lang_Class_Handle(aos);
    assert(string_class);
    assert(string_array_class);
        
    jobjectArray result = NewObjectArray(jenv, p_num, string_array_class, NULL);
    if (result) 
    {
        char* buf = (char*)STD_MALLOC(buf_len + 1);
        p_num *= 2;
        for (index = 0; index < p_num; )
        {
            jobjectArray pair = NewObjectArray(jenv, 2, string_class, NULL);
            if (!pair) {
                break;
            }
            SetObjectArrayElement(jenv, result, index/2, pair);

            char* name = strcpy(buf, pkgs[index++]);
            for (char* c = name; *c != '\0'; ++c) {
                if (*c == '/') {
                    *c = '.';
                }
            }
            jstring jname = NewStringUTF(jenv, name);
            if (!jname) {
                break;
            }
            SetObjectArrayElement(jenv, pair, 0, jname);

            const char * jar = pkgs[index++];
            if (jar) {
                jstring js = NewStringUTF(jenv, jar);
                if (!js) break;
                SetObjectArrayElement(jenv, pair, 1, js);
            }
        }
        STD_FREE(buf);
    }

    STD_FREE(pkgs);
    
    assert(result || exn_raised());
    return result;
}