lib: launch: implement passing args and environment variables to new tasks
This commit is contained in:
@@ -18,4 +18,4 @@ sysroot_add_library(
|
|||||||
HEADER_DIR /usr/include
|
HEADER_DIR /usr/include
|
||||||
LIB_DIR /usr/lib)
|
LIB_DIR /usr/lib)
|
||||||
|
|
||||||
target_link_libraries(liblaunch libmango ulibc)
|
target_link_libraries(liblaunch librosetta libmango libc-core)
|
||||||
|
|||||||
@@ -300,8 +300,14 @@ static enum launch_status map_executable(struct elf_image *image)
|
|||||||
|
|
||||||
static elf_sym_t *get_dynsym(struct elf_image *image, size_t index)
|
static elf_sym_t *get_dynsym(struct elf_image *image, size_t index)
|
||||||
{
|
{
|
||||||
return (elf_sym_t *)(image->e_local_base + image->e_dynsym
|
elf_sym_t *sym = (elf_sym_t *)(image->e_local_base + image->e_dynsym
|
||||||
+ (index * image->e_dynsym_entsize));
|
+ (index * image->e_dynsym_entsize));
|
||||||
|
|
||||||
|
if (!sym->st_value) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum launch_status do_rela(struct elf_image *image, elf_rela_t *rela)
|
static enum launch_status do_rela(struct elf_image *image, elf_rela_t *rela)
|
||||||
@@ -312,6 +318,10 @@ static enum launch_status do_rela(struct elf_image *image, elf_rela_t *rela)
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case R_X86_64_JUMP_SLOT:
|
case R_X86_64_JUMP_SLOT:
|
||||||
sym = get_dynsym(image, ELF64_R_SYM(rela->r_info));
|
sym = get_dynsym(image, ELF64_R_SYM(rela->r_info));
|
||||||
|
if (!sym) {
|
||||||
|
return LAUNCH_ERR_MISSING_SYMBOL;
|
||||||
|
}
|
||||||
|
|
||||||
*(uint64_t *)(image->e_local_base + rela->r_offset)
|
*(uint64_t *)(image->e_local_base + rela->r_offset)
|
||||||
= image->e_remote_base + sym->st_value + rela->r_addend;
|
= image->e_remote_base + sym->st_value + rela->r_addend;
|
||||||
kern_tracef(
|
kern_tracef(
|
||||||
@@ -354,7 +364,7 @@ static enum launch_status do_rela_list(
|
|||||||
rela = (elf_rela_t *)((char *)rela + entsize);
|
rela = (elf_rela_t *)((char *)rela + entsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
return LAUNCH_OK;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum launch_status do_rel(
|
static enum launch_status do_rel(
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ enum launch_status {
|
|||||||
* version, etc).
|
* version, etc).
|
||||||
*/
|
*/
|
||||||
LAUNCH_ERR_UNSUPPORTED_EXECUTABLE,
|
LAUNCH_ERR_UNSUPPORTED_EXECUTABLE,
|
||||||
|
LAUNCH_ERR_MISSING_SYMBOL,
|
||||||
/* a particular dependency of the executable could not be resolved. */
|
/* a particular dependency of the executable could not be resolved. */
|
||||||
LAUNCH_ERR_CANNOT_RESOLVE_DEPENDENCY,
|
LAUNCH_ERR_CANNOT_RESOLVE_DEPENDENCY,
|
||||||
LAUNCH_ERR_MEMORY_MAP_FAILED,
|
LAUNCH_ERR_MEMORY_MAP_FAILED,
|
||||||
@@ -28,6 +29,8 @@ enum launch_flags {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct launch_ctx;
|
struct launch_ctx;
|
||||||
|
struct rosetta_bootstrap_handle;
|
||||||
|
struct rosetta_bootstrap_channel;
|
||||||
|
|
||||||
typedef enum launch_status (*launch_resolve_library_function)(
|
typedef enum launch_status (*launch_resolve_library_function)(
|
||||||
struct launch_ctx *,
|
struct launch_ctx *,
|
||||||
@@ -52,6 +55,12 @@ struct launch_parameters {
|
|||||||
int p_envc;
|
int p_envc;
|
||||||
const char **p_envp;
|
const char **p_envp;
|
||||||
|
|
||||||
|
const struct rosetta_bootstrap_handle *p_handles;
|
||||||
|
size_t p_handle_count;
|
||||||
|
|
||||||
|
const struct rosetta_bootstrap_channel *p_channels;
|
||||||
|
size_t p_channel_count;
|
||||||
|
|
||||||
void *p_resolver_arg;
|
void *p_resolver_arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
|
#include "stack.h"
|
||||||
|
|
||||||
#include <launch.h>
|
#include <launch.h>
|
||||||
#include <mango/handle.h>
|
#include <mango/handle.h>
|
||||||
#include <mango/log.h>
|
#include <mango/log.h>
|
||||||
#include <mango/task.h>
|
#include <mango/task.h>
|
||||||
#include <mango/vm.h>
|
#include <mango/vm.h>
|
||||||
|
#include <rosetta/bootstrap.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -34,6 +36,58 @@ static kern_handle_t get_library(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static virt_addr_t write_bootstrap_data(
|
||||||
|
struct stack_writer *stack,
|
||||||
|
const struct launch_parameters *params)
|
||||||
|
{
|
||||||
|
virt_addr_t bs_remote;
|
||||||
|
struct rosetta_bootstrap *bs
|
||||||
|
= stack_writer_put(stack, NULL, sizeof *bs, &bs_remote);
|
||||||
|
|
||||||
|
memset(bs, 0x0, sizeof *bs);
|
||||||
|
|
||||||
|
bs->bs_argc = params->p_argc;
|
||||||
|
bs->bs_envc = params->p_envc;
|
||||||
|
bs->bs_handles_count = params->p_handle_count;
|
||||||
|
bs->bs_channels_count = params->p_channel_count;
|
||||||
|
|
||||||
|
const char **argv, **envp;
|
||||||
|
|
||||||
|
if (bs->bs_argc > 0) {
|
||||||
|
virt_addr_t remote_argv;
|
||||||
|
argv = stack_writer_put(
|
||||||
|
stack,
|
||||||
|
NULL,
|
||||||
|
bs->bs_argc * sizeof(char *),
|
||||||
|
&remote_argv);
|
||||||
|
bs->bs_argv = (const char **)remote_argv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bs->bs_envc > 0) {
|
||||||
|
virt_addr_t remote_envp;
|
||||||
|
envp = stack_writer_put(
|
||||||
|
stack,
|
||||||
|
NULL,
|
||||||
|
bs->bs_envc * sizeof(char *),
|
||||||
|
&remote_envp);
|
||||||
|
bs->bs_envp = (const char **)remote_envp;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < params->p_argc; i++) {
|
||||||
|
virt_addr_t arg_ptr;
|
||||||
|
stack_writer_put_string(stack, params->p_argv[i], &arg_ptr);
|
||||||
|
argv[i] = (const char *)arg_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < params->p_envc; i++) {
|
||||||
|
virt_addr_t env_ptr;
|
||||||
|
stack_writer_put_string(stack, params->p_envp[i], &env_ptr);
|
||||||
|
envp[i] = (const char *)env_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bs_remote;
|
||||||
|
}
|
||||||
|
|
||||||
enum launch_status launch_ctx_execute(
|
enum launch_status launch_ctx_execute(
|
||||||
struct launch_ctx *ctx,
|
struct launch_ctx *ctx,
|
||||||
const struct launch_parameters *params,
|
const struct launch_parameters *params,
|
||||||
@@ -102,7 +156,7 @@ enum launch_status launch_ctx_execute(
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
virt_addr_t stack_buf;
|
virt_addr_t remote_stack_buf, local_stack_buf;
|
||||||
kstatus = vm_region_map_relative(
|
kstatus = vm_region_map_relative(
|
||||||
remote_address_space,
|
remote_address_space,
|
||||||
VM_REGION_ANY_OFFSET,
|
VM_REGION_ANY_OFFSET,
|
||||||
@@ -110,7 +164,15 @@ enum launch_status launch_ctx_execute(
|
|||||||
0,
|
0,
|
||||||
STACK_SIZE,
|
STACK_SIZE,
|
||||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||||||
&stack_buf);
|
&remote_stack_buf);
|
||||||
|
kstatus = vm_region_map_relative(
|
||||||
|
params->p_local_address_space,
|
||||||
|
VM_REGION_ANY_OFFSET,
|
||||||
|
stack_vmo,
|
||||||
|
0,
|
||||||
|
STACK_SIZE,
|
||||||
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||||||
|
&local_stack_buf);
|
||||||
kern_handle_close(stack_vmo);
|
kern_handle_close(stack_vmo);
|
||||||
|
|
||||||
if (kstatus != KERN_OK) {
|
if (kstatus != KERN_OK) {
|
||||||
@@ -120,11 +182,23 @@ enum launch_status launch_ctx_execute(
|
|||||||
return LAUNCH_ERR_MEMORY_MAP_FAILED;
|
return LAUNCH_ERR_MEMORY_MAP_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct stack_writer stack;
|
||||||
|
stack_writer_init(
|
||||||
|
&stack,
|
||||||
|
local_stack_buf + STACK_SIZE,
|
||||||
|
remote_stack_buf + STACK_SIZE);
|
||||||
|
virt_addr_t bsdata = write_bootstrap_data(&stack, params);
|
||||||
|
|
||||||
virt_addr_t ip = image.e_hdr.e_entry + image.e_remote_base;
|
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;
|
kern_handle_t thread;
|
||||||
kstatus = task_create_thread(remote_task, ip, sp, NULL, 0, &thread);
|
kstatus = task_create_thread(
|
||||||
|
remote_task,
|
||||||
|
ip,
|
||||||
|
stack.w_remote_sp,
|
||||||
|
&bsdata,
|
||||||
|
1,
|
||||||
|
&thread);
|
||||||
if (kstatus != KERN_OK) {
|
if (kstatus != KERN_OK) {
|
||||||
elf_image_cleanup(&image);
|
elf_image_cleanup(&image);
|
||||||
kern_handle_close(remote_address_space);
|
kern_handle_close(remote_address_space);
|
||||||
|
|||||||
59
lib/liblaunch/stack.c
Normal file
59
lib/liblaunch/stack.c
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#include "stack.h"
|
||||||
|
|
||||||
|
#include <mango/log.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void stack_writer_init(
|
||||||
|
struct stack_writer *w,
|
||||||
|
virt_addr_t local_sp,
|
||||||
|
virt_addr_t remote_sp)
|
||||||
|
{
|
||||||
|
memset(w, 0x0, sizeof *w);
|
||||||
|
|
||||||
|
w->w_local_sp = local_sp;
|
||||||
|
w->w_remote_sp = remote_sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *stack_writer_put_string(
|
||||||
|
struct stack_writer *w,
|
||||||
|
const char *s,
|
||||||
|
virt_addr_t *out_remote)
|
||||||
|
{
|
||||||
|
size_t len = strlen(s);
|
||||||
|
|
||||||
|
w->w_local_sp -= (len + 1);
|
||||||
|
w->w_remote_sp -= (len + 1);
|
||||||
|
|
||||||
|
char *local_ptr = (char *)w->w_local_sp;
|
||||||
|
virt_addr_t remote_ptr = w->w_remote_sp;
|
||||||
|
|
||||||
|
memcpy(local_ptr, s, len);
|
||||||
|
local_ptr[len] = '\0';
|
||||||
|
|
||||||
|
if (out_remote) {
|
||||||
|
*out_remote = remote_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return local_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *stack_writer_put(
|
||||||
|
struct stack_writer *w,
|
||||||
|
const void *p,
|
||||||
|
size_t len,
|
||||||
|
virt_addr_t *out_remote)
|
||||||
|
{
|
||||||
|
w->w_local_sp -= len;
|
||||||
|
w->w_remote_sp -= len;
|
||||||
|
|
||||||
|
void *local_ptr = (char *)w->w_local_sp;
|
||||||
|
virt_addr_t remote_ptr = w->w_remote_sp;
|
||||||
|
|
||||||
|
memset(local_ptr, 0x0, len);
|
||||||
|
|
||||||
|
if (out_remote) {
|
||||||
|
*out_remote = remote_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return local_ptr;
|
||||||
|
}
|
||||||
26
lib/liblaunch/stack.h
Normal file
26
lib/liblaunch/stack.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef LIBLAUNCH_STACK_H_
|
||||||
|
#define LIBLAUNCH_STACK_H_
|
||||||
|
|
||||||
|
#include <mango/types.h>
|
||||||
|
|
||||||
|
struct stack_writer {
|
||||||
|
virt_addr_t w_local_sp;
|
||||||
|
virt_addr_t w_remote_sp;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void stack_writer_init(
|
||||||
|
struct stack_writer *w,
|
||||||
|
virt_addr_t local_sp,
|
||||||
|
virt_addr_t remote_sp);
|
||||||
|
|
||||||
|
extern void *stack_writer_put_string(
|
||||||
|
struct stack_writer *w,
|
||||||
|
const char *s,
|
||||||
|
virt_addr_t *out_remote);
|
||||||
|
extern void *stack_writer_put(
|
||||||
|
struct stack_writer *w,
|
||||||
|
const void *p,
|
||||||
|
size_t len,
|
||||||
|
virt_addr_t *out_remote);
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user