diff --git a/executer/include/uprotocol.h b/executer/include/uprotocol.h index ff5c0653..34247103 100644 --- a/executer/include/uprotocol.h +++ b/executer/include/uprotocol.h @@ -80,6 +80,7 @@ struct program_load_desc { unsigned long envs_len; unsigned long rlimit_stack_cur; unsigned long rlimit_stack_max; + unsigned long interp_align; struct program_image_section sections[0]; }; diff --git a/executer/user/mcexec.c b/executer/user/mcexec.c index 437cb0fa..edba2c80 100644 --- a/executer/user/mcexec.c +++ b/executer/user/mcexec.c @@ -248,6 +248,7 @@ struct program_load_desc *load_interp(struct program_load_desc *desc0, FILE *fp) int i, j, nhdrs = 0; struct program_load_desc *desc = desc0; size_t newsize; + unsigned long align; if (fread(&hdr, sizeof(hdr), 1, fp) < 1) { __eprint("Cannot read Ehdr.\n"); @@ -278,6 +279,7 @@ struct program_load_desc *load_interp(struct program_load_desc *desc0, FILE *fp) } fseek(fp, hdr.e_phoff, SEEK_SET); + align = 1; j = desc->num_sections; for (i = 0; i < hdr.e_phnum; i++) { if (fread(&phdr, sizeof(phdr), 1, fp) < 1) { @@ -301,6 +303,10 @@ struct program_load_desc *load_interp(struct program_load_desc *desc0, FILE *fp) desc->sections[j].prot |= (phdr.p_flags & PF_W)? PROT_WRITE: 0; desc->sections[j].prot |= (phdr.p_flags & PF_X)? PROT_EXEC: 0; + if (phdr.p_align > align) { + align = phdr.p_align; + } + __dprintf("%d: (%s) %lx, %lx, %lx, %lx, %x\n", j, (phdr.p_type == PT_LOAD ? "PT_LOAD" : "PT_TLS"), desc->sections[j].vaddr, @@ -314,6 +320,7 @@ struct program_load_desc *load_interp(struct program_load_desc *desc0, FILE *fp) desc->num_sections = j; desc->entry = hdr.e_entry; + desc->interp_align = align; return desc; } diff --git a/kernel/host.c b/kernel/host.c index 937f84b2..a130e17b 100644 --- a/kernel/host.c +++ b/kernel/host.c @@ -67,6 +67,8 @@ static int process_msg_prepare_process(unsigned long rphys) int range_npages; void *up_v; unsigned long flags; + uintptr_t interp_obase = -1; + uintptr_t interp_nbase = -1; sz = sizeof(struct program_load_desc) + sizeof(struct program_image_section) * 16; @@ -100,6 +102,8 @@ static int process_msg_prepare_process(unsigned long rphys) proc->tid = pn->pid; proc->vm->region.user_start = pn->user_start; proc->vm->region.user_end = pn->user_end; + proc->vm->region.map_start = (USER_END / 3) & LARGE_PAGE_MASK; + proc->vm->region.map_end = proc->vm->region.map_start; proc->rlimit_stack.rlim_cur = pn->rlimit_stack_cur; proc->rlimit_stack.rlim_max = pn->rlimit_stack_max; @@ -107,6 +111,18 @@ static int process_msg_prepare_process(unsigned long rphys) cpu_local_var(scp).post_idx = 0; for (i = 0; i < n; i++) { + if (pn->sections[i].interp && (interp_nbase == (uintptr_t)-1)) { + interp_obase = pn->sections[i].vaddr; + interp_obase -= (interp_obase % pn->interp_align); + interp_nbase = proc->vm->region.map_start; + interp_nbase = (interp_nbase + pn->interp_align - 1) + & ~(pn->interp_align - 1); + } + if (pn->sections[i].interp) { + pn->sections[i].vaddr -= interp_obase; + pn->sections[i].vaddr += interp_nbase; + p->sections[i].vaddr = pn->sections[i].vaddr; + } s = (pn->sections[i].vaddr) & PAGE_MASK; e = (pn->sections[i].vaddr + pn->sections[i].len + PAGE_SIZE - 1) & PAGE_MASK; @@ -153,7 +169,7 @@ static int process_msg_prepare_process(unsigned long rphys) /* TODO: Maybe we need flag */ if (pn->sections[i].interp) { - /* nothing to do */ + proc->vm->region.map_end = e; } else if (i == 0) { proc->vm->region.text_start = s; @@ -171,6 +187,13 @@ static int process_msg_prepare_process(unsigned long rphys) } } + if (interp_nbase != (uintptr_t)-1) { + pn->entry -= interp_obase; + pn->entry += interp_nbase; + p->entry = pn->entry; + ihk_mc_modify_user_context(proc->uctx, IHK_UCR_PROGRAM_COUNTER, pn->entry); + } + #if 1 /* Fix for the problem where brk grows to hit .bss section @@ -188,8 +211,6 @@ static int process_msg_prepare_process(unsigned long rphys) proc->vm->region.brk_start = proc->vm->region.brk_end = proc->vm->region.data_end; #endif - proc->vm->region.map_start = proc->vm->region.map_end = - (USER_END / 3) & LARGE_PAGE_MASK; /* Map system call stuffs */ flags = VR_RESERVED | VR_PROT_READ | VR_PROT_WRITE; diff --git a/kernel/include/syscall.h b/kernel/include/syscall.h index 1671af8f..f1335f10 100644 --- a/kernel/include/syscall.h +++ b/kernel/include/syscall.h @@ -122,6 +122,7 @@ struct program_load_desc { unsigned long envs_len; unsigned long rlimit_stack_cur; unsigned long rlimit_stack_max; + unsigned long interp_align; struct program_image_section sections[0]; };