142 lines
3.1 KiB
C
142 lines
3.1 KiB
C
|
|
#include "elf.h"
|
||
|
|
|
||
|
|
#include <launch.h>
|
||
|
|
#include <mango/handle.h>
|
||
|
|
#include <mango/log.h>
|
||
|
|
#include <mango/task.h>
|
||
|
|
#include <mango/vm.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
#define STACK_SIZE 0x10000
|
||
|
|
|
||
|
|
enum launch_status launch_ctx_init(struct launch_ctx *ctx)
|
||
|
|
{
|
||
|
|
memset(ctx, 0x0, sizeof *ctx);
|
||
|
|
return LAUNCH_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
void launch_ctx_cleanup(struct launch_ctx *ctx)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
static kern_handle_t get_library(
|
||
|
|
struct launch_ctx *ctx,
|
||
|
|
const char *name,
|
||
|
|
void *arg)
|
||
|
|
{
|
||
|
|
enum launch_status status = LAUNCH_ERR_CANNOT_RESOLVE_DEPENDENCY;
|
||
|
|
kern_handle_t result = KERN_HANDLE_INVALID;
|
||
|
|
if (ctx->ctx_resolve_library) {
|
||
|
|
status = ctx->ctx_resolve_library(ctx, name, &result, arg);
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
enum launch_status launch_ctx_execute(
|
||
|
|
struct launch_ctx *ctx,
|
||
|
|
const struct launch_parameters *params,
|
||
|
|
enum launch_flags flags,
|
||
|
|
struct launch_result *result)
|
||
|
|
{
|
||
|
|
kern_status_t kstatus;
|
||
|
|
kern_handle_t stack_vmo;
|
||
|
|
|
||
|
|
kstatus = vm_object_create(
|
||
|
|
"stack",
|
||
|
|
5,
|
||
|
|
STACK_SIZE,
|
||
|
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||
|
|
&stack_vmo);
|
||
|
|
|
||
|
|
size_t name_len = params->p_task_name ? strlen(params->p_task_name) : 0;
|
||
|
|
kern_handle_t remote_task = KERN_HANDLE_INVALID,
|
||
|
|
remote_address_space = KERN_HANDLE_INVALID;
|
||
|
|
kstatus = task_create(
|
||
|
|
params->p_parent_task,
|
||
|
|
params->p_task_name,
|
||
|
|
name_len,
|
||
|
|
&remote_task,
|
||
|
|
&remote_address_space);
|
||
|
|
if (kstatus != KERN_OK) {
|
||
|
|
kern_handle_close(stack_vmo);
|
||
|
|
return LAUNCH_ERR_TASK_CREATION_FAILED;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct elf_image image;
|
||
|
|
elf_image_init(&image);
|
||
|
|
|
||
|
|
enum launch_status status = elf_image_load(
|
||
|
|
&image,
|
||
|
|
params->p_executable,
|
||
|
|
params->p_local_address_space,
|
||
|
|
remote_address_space);
|
||
|
|
|
||
|
|
if (status == LAUNCH_ERR_INTERPRETER_REQUIRED) {
|
||
|
|
kern_handle_t interp = get_library(
|
||
|
|
ctx,
|
||
|
|
image.e_interp,
|
||
|
|
params->p_resolver_arg);
|
||
|
|
if (interp == KERN_HANDLE_INVALID) {
|
||
|
|
elf_image_cleanup(&image);
|
||
|
|
kern_handle_close(stack_vmo);
|
||
|
|
kern_handle_close(remote_address_space);
|
||
|
|
kern_handle_close(remote_task);
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
elf_image_init(&image);
|
||
|
|
status = elf_image_load(
|
||
|
|
&image,
|
||
|
|
interp,
|
||
|
|
params->p_local_address_space,
|
||
|
|
remote_address_space);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (status != LAUNCH_OK) {
|
||
|
|
elf_image_cleanup(&image);
|
||
|
|
kern_handle_close(stack_vmo);
|
||
|
|
kern_handle_close(remote_address_space);
|
||
|
|
kern_handle_close(remote_task);
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
virt_addr_t stack_buf;
|
||
|
|
kstatus = vm_region_map_relative(
|
||
|
|
remote_address_space,
|
||
|
|
VM_REGION_ANY_OFFSET,
|
||
|
|
stack_vmo,
|
||
|
|
0,
|
||
|
|
STACK_SIZE,
|
||
|
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||
|
|
&stack_buf);
|
||
|
|
kern_handle_close(stack_vmo);
|
||
|
|
|
||
|
|
if (kstatus != KERN_OK) {
|
||
|
|
elf_image_cleanup(&image);
|
||
|
|
kern_handle_close(remote_address_space);
|
||
|
|
kern_handle_close(remote_task);
|
||
|
|
return LAUNCH_ERR_MEMORY_MAP_FAILED;
|
||
|
|
}
|
||
|
|
|
||
|
|
virt_addr_t ip = image.e_hdr.e_entry + image.e_remote_base;
|
||
|
|
virt_addr_t sp = stack_buf + STACK_SIZE;
|
||
|
|
|
||
|
|
kern_handle_t thread;
|
||
|
|
kstatus = task_create_thread(remote_task, ip, sp, NULL, 0, &thread);
|
||
|
|
if (kstatus != KERN_OK) {
|
||
|
|
elf_image_cleanup(&image);
|
||
|
|
kern_handle_close(remote_address_space);
|
||
|
|
kern_handle_close(remote_task);
|
||
|
|
return LAUNCH_ERR_THREAD_CREATION_FAILED;
|
||
|
|
}
|
||
|
|
|
||
|
|
thread_start(thread);
|
||
|
|
|
||
|
|
kern_handle_close(thread);
|
||
|
|
elf_image_cleanup(&image);
|
||
|
|
|
||
|
|
return LAUNCH_OK;
|
||
|
|
}
|