lib: launch: implement alternate argument handling to support interpreters
This commit is contained in:
@@ -45,7 +45,9 @@ struct launch_ctx {
|
||||
struct launch_parameters {
|
||||
kern_handle_t p_parent_task;
|
||||
kern_handle_t p_local_address_space;
|
||||
kern_handle_t p_executable;
|
||||
|
||||
const char *p_exec_path;
|
||||
kern_handle_t p_exec_image;
|
||||
|
||||
const char *p_task_name;
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ static kern_handle_t get_library(
|
||||
|
||||
static virt_addr_t write_bootstrap_data(
|
||||
struct stack_writer *stack,
|
||||
const char *interpreter,
|
||||
const struct launch_parameters *params)
|
||||
{
|
||||
virt_addr_t bs_remote;
|
||||
@@ -51,9 +52,15 @@ static virt_addr_t write_bootstrap_data(
|
||||
bs->bs_handles_count = params->p_handle_count;
|
||||
bs->bs_channels_count = params->p_channel_count;
|
||||
|
||||
if (interpreter) {
|
||||
/* two extra args: interpreter path and path to executable */
|
||||
bs->bs_argc += 2;
|
||||
}
|
||||
|
||||
const char **argv, **envp;
|
||||
|
||||
if (bs->bs_argc > 0) {
|
||||
int argc = bs->bs_argc;
|
||||
virt_addr_t remote_argv;
|
||||
argv = stack_writer_put(
|
||||
stack,
|
||||
@@ -73,13 +80,22 @@ static virt_addr_t write_bootstrap_data(
|
||||
bs->bs_envp = (const char **)remote_envp;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < params->p_argc; i++) {
|
||||
size_t i = 0, j = 0;
|
||||
if (interpreter) {
|
||||
virt_addr_t arg_ptr;
|
||||
stack_writer_put_string(stack, params->p_argv[i], &arg_ptr);
|
||||
stack_writer_put_string(stack, interpreter, &arg_ptr);
|
||||
argv[i++] = (const char *)arg_ptr;
|
||||
stack_writer_put_string(stack, params->p_exec_path, &arg_ptr);
|
||||
argv[i++] = (const char *)arg_ptr;
|
||||
}
|
||||
|
||||
for (; i < bs->bs_argc; i++, j++) {
|
||||
virt_addr_t arg_ptr;
|
||||
stack_writer_put_string(stack, params->p_argv[j], &arg_ptr);
|
||||
argv[i] = (const char *)arg_ptr;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < params->p_envc; i++) {
|
||||
for (size_t i = 0; i < bs->bs_envc; i++) {
|
||||
virt_addr_t env_ptr;
|
||||
stack_writer_put_string(stack, params->p_envp[i], &env_ptr);
|
||||
envp[i] = (const char *)env_ptr;
|
||||
@@ -118,16 +134,20 @@ enum launch_status launch_ctx_execute(
|
||||
return LAUNCH_ERR_TASK_CREATION_FAILED;
|
||||
}
|
||||
|
||||
char interp_path[4096];
|
||||
interp_path[0] = 0;
|
||||
|
||||
struct elf_image image;
|
||||
elf_image_init(&image);
|
||||
|
||||
enum launch_status status = elf_image_load(
|
||||
&image,
|
||||
params->p_executable,
|
||||
params->p_exec_image,
|
||||
params->p_local_address_space,
|
||||
remote_address_space);
|
||||
|
||||
if (status == LAUNCH_ERR_INTERPRETER_REQUIRED) {
|
||||
snprintf(interp_path, sizeof interp_path, "%s", image.e_interp);
|
||||
kern_handle_t interp = get_library(
|
||||
ctx,
|
||||
image.e_interp,
|
||||
@@ -187,7 +207,7 @@ enum launch_status launch_ctx_execute(
|
||||
&stack,
|
||||
local_stack_buf + STACK_SIZE,
|
||||
remote_stack_buf + STACK_SIZE);
|
||||
virt_addr_t bsdata = write_bootstrap_data(&stack, params);
|
||||
virt_addr_t bsdata = write_bootstrap_data(&stack, interp_path, params);
|
||||
|
||||
virt_addr_t ip = image.e_hdr.e_entry + image.e_remote_base;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user