Merge branch 'master' of postpeta.pccluster.org:mckernel
This commit is contained in:
@@ -189,6 +189,8 @@ do_setpgid(int pid, int pgid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void coredump(struct process *proc, void *regs);
|
||||||
|
|
||||||
void
|
void
|
||||||
do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pending *pending)
|
do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pending *pending)
|
||||||
{
|
{
|
||||||
@@ -260,11 +262,26 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin
|
|||||||
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
int coredumped = 0;
|
||||||
kfree(pending);
|
kfree(pending);
|
||||||
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate);
|
||||||
if(sig == SIGCHLD || sig == SIGURG)
|
switch(sig){
|
||||||
|
case SIGCHLD:
|
||||||
|
case SIGURG:
|
||||||
return;
|
return;
|
||||||
terminate(0, sig, (ihk_mc_user_context_t *)regs->rsp);
|
case SIGQUIT:
|
||||||
|
case SIGILL:
|
||||||
|
case SIGTRAP:
|
||||||
|
case SIGABRT:
|
||||||
|
case SIGBUS:
|
||||||
|
case SIGFPE:
|
||||||
|
case SIGUSR1:
|
||||||
|
case SIGSEGV:
|
||||||
|
case SIGUSR2:
|
||||||
|
coredump(proc, regs);
|
||||||
|
coredumped = 0x80;
|
||||||
|
}
|
||||||
|
terminate(0, sig | coredumped, (ihk_mc_user_context_t *)regs->rsp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,8 +578,10 @@ set_signal(int sig, void *regs0)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if((__sigmask(sig) & proc->sigmask.__val[0]) ||
|
if((__sigmask(sig) & proc->sigmask.__val[0]) ||
|
||||||
(regs->rsp & 0x8000000000000000))
|
(regs->rsp & 0x8000000000000000)){
|
||||||
terminate(0, sig, (ihk_mc_user_context_t *)regs->rsp);
|
coredump(proc, regs0);
|
||||||
|
terminate(0, sig | 0x80, (ihk_mc_user_context_t *)regs->rsp);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
do_kill(proc->pid, proc->tid, sig);
|
do_kill(proc->pid, proc->tid, sig);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ struct program_image_section {
|
|||||||
void *fp;
|
void *fp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SHELL_PATH_MAX_LEN 1024
|
||||||
|
|
||||||
struct program_load_desc {
|
struct program_load_desc {
|
||||||
int num_sections;
|
int num_sections;
|
||||||
int status;
|
int status;
|
||||||
@@ -88,6 +90,7 @@ struct program_load_desc {
|
|||||||
unsigned long rlimit_stack_cur;
|
unsigned long rlimit_stack_cur;
|
||||||
unsigned long rlimit_stack_max;
|
unsigned long rlimit_stack_max;
|
||||||
unsigned long interp_align;
|
unsigned long interp_align;
|
||||||
|
char shell_path[SHELL_PATH_MAX_LEN];
|
||||||
struct program_image_section sections[0];
|
struct program_image_section sections[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ static long mcexec_send_signal(ihk_os_t os, struct signal_desc *sigparam)
|
|||||||
isp.pid = sig.pid;
|
isp.pid = sig.pid;
|
||||||
isp.arg = (long)sig.tid << 32 | (sig.sig & 0x00000000ffffffffL);
|
isp.arg = (long)sig.tid << 32 | (sig.sig & 0x00000000ffffffffL);
|
||||||
|
|
||||||
mcctrl_ikc_send(os, 0, &isp);
|
mcctrl_ikc_send(os, sig.cpu, &isp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -405,6 +405,25 @@ static int rus_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|||||||
pfn = phys >> PAGE_SHIFT;
|
pfn = phys >> PAGE_SHIFT;
|
||||||
#if USE_VM_INSERT_PFN
|
#if USE_VM_INSERT_PFN
|
||||||
for (pix = 0; pix < (pgsize / PAGE_SIZE); ++pix) {
|
for (pix = 0; pix < (pgsize / PAGE_SIZE); ++pix) {
|
||||||
|
struct page *page;
|
||||||
|
|
||||||
|
if (pfn_valid(pfn+pix)) {
|
||||||
|
page = pfn_to_page(pfn+pix);
|
||||||
|
if (!page_count(page)) {
|
||||||
|
get_page(page);
|
||||||
|
/*
|
||||||
|
* TODO:
|
||||||
|
* The pages which get_page() has been called with
|
||||||
|
* should be recorded. Because these pages have to
|
||||||
|
* be passed to put_page() before they are freed.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
error = vm_insert_page(vma, rva+(pix*PAGE_SIZE), page);
|
||||||
|
if (error) {
|
||||||
|
printk("vm_insert_page: %d\n", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
error = vm_insert_pfn(vma, rva+(pix*PAGE_SIZE), pfn+pix);
|
error = vm_insert_pfn(vma, rva+(pix*PAGE_SIZE), pfn+pix);
|
||||||
if (error) {
|
if (error) {
|
||||||
break;
|
break;
|
||||||
@@ -429,7 +448,7 @@ static struct vm_operations_struct rus_vmops = {
|
|||||||
|
|
||||||
static int rus_mmap(struct file *file, struct vm_area_struct *vma)
|
static int rus_mmap(struct file *file, struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
vma->vm_flags |= VM_IO | VM_RESERVED | VM_DONTEXPAND | VM_PFNMAP;
|
vma->vm_flags |= VM_RESERVED | VM_DONTEXPAND | VM_MIXEDMAP;
|
||||||
vma->vm_ops = &rus_vmops;
|
vma->vm_ops = &rus_vmops;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1125,13 +1144,16 @@ out:
|
|||||||
return (IS_ERR_VALUE(map))? (int)map: 0;
|
return (IS_ERR_VALUE(map))? (int)map: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_pte_range(uintptr_t start, uintptr_t len)
|
static int clear_pte_range(uintptr_t start, uintptr_t len)
|
||||||
{
|
{
|
||||||
struct mm_struct *mm = current->mm;
|
struct mm_struct *mm = current->mm;
|
||||||
struct vm_area_struct *vma;
|
struct vm_area_struct *vma;
|
||||||
uintptr_t addr;
|
uintptr_t addr;
|
||||||
uintptr_t end;
|
uintptr_t end;
|
||||||
|
int error;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
down_read(&mm->mmap_sem);
|
down_read(&mm->mmap_sem);
|
||||||
addr = start;
|
addr = start;
|
||||||
while (addr < (start + len)) {
|
while (addr < (start + len)) {
|
||||||
@@ -1148,14 +1170,15 @@ static void clear_pte_range(uintptr_t start, uintptr_t len)
|
|||||||
end = vma->vm_end;
|
end = vma->vm_end;
|
||||||
}
|
}
|
||||||
if (addr < end) {
|
if (addr < end) {
|
||||||
zap_vma_ptes(vma, addr, end-addr);
|
error = zap_vma_ptes(vma, addr, end-addr);
|
||||||
dprintk("clear_pte_range() 0x%lx - 0x%lx OK\n",
|
if (ret == 0) {
|
||||||
vma->vm_start, vma->vm_end);
|
ret = error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
addr = end;
|
addr = end;
|
||||||
}
|
}
|
||||||
up_read(&mm->mmap_sem);
|
up_read(&mm->mmap_sem);
|
||||||
return;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1293,7 +1316,11 @@ int __do_in_kernel_syscall(ihk_os_t os, struct mcctrl_channel *c, struct syscall
|
|||||||
ppd->pid, ppd->rpgtable);
|
ppd->pid, ppd->rpgtable);
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_pte_range(sc->args[0], sc->args[1]);
|
error = clear_pte_range(sc->args[0], sc->args[1]);
|
||||||
|
if (error) {
|
||||||
|
error = -ENOSYS;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -338,14 +338,144 @@ struct program_load_desc *load_interp(struct program_load_desc *desc0, FILE *fp)
|
|||||||
|
|
||||||
unsigned char *dma_buf;
|
unsigned char *dma_buf;
|
||||||
|
|
||||||
int load_elf_desc(char *filename, struct program_load_desc **desc_p)
|
int lookup_exec_path(char *filename, char *path, int max_len)
|
||||||
|
{
|
||||||
|
int found;
|
||||||
|
int error;
|
||||||
|
struct stat sb;
|
||||||
|
char *link_path = NULL;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
found = 0;
|
||||||
|
|
||||||
|
/* Is file not absolute path? */
|
||||||
|
if (strncmp(filename, "/", 1)) {
|
||||||
|
|
||||||
|
/* Is filename a single component without path? */
|
||||||
|
if (strncmp(filename, ".", 1) && !strchr(filename, '/')) {
|
||||||
|
|
||||||
|
char *token, *string, *tofree;
|
||||||
|
char *PATH = getenv("COKERNEL_PATH");
|
||||||
|
if (!PATH) {
|
||||||
|
PATH = getenv("PATH");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(filename) >= 255) {
|
||||||
|
return ENAMETOOLONG;
|
||||||
|
}
|
||||||
|
|
||||||
|
__dprintf("PATH: %s\n", PATH);
|
||||||
|
|
||||||
|
/* strsep() modifies string! */
|
||||||
|
tofree = string = strdup(PATH);
|
||||||
|
if (string == NULL) {
|
||||||
|
printf("lookup_exec_path(): copying PATH, not enough memory?\n");
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((token = strsep(&string, ":")) != NULL) {
|
||||||
|
|
||||||
|
error = snprintf(path, max_len,
|
||||||
|
"%s/%s", token, filename);
|
||||||
|
if (error < 0 || error >= max_len) {
|
||||||
|
fprintf(stderr, "lookup_exec_path(): array too small?\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = access(path, X_OK);
|
||||||
|
if (error == 0) {
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(tofree);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not in path, file to be open from the working directory */
|
||||||
|
if (!found) {
|
||||||
|
error = snprintf(path, max_len, "%s", filename);
|
||||||
|
|
||||||
|
if (error < 0 || error >= max_len) {
|
||||||
|
fprintf(stderr, "lookup_exec_path(): array too small?\n");
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Absolute path */
|
||||||
|
else if (!strncmp(filename, "/", 1)) {
|
||||||
|
char *root = getenv("COKERNEL_EXEC_ROOT");
|
||||||
|
|
||||||
|
if (root) {
|
||||||
|
error = snprintf(path, max_len, "%s/%s", root, filename);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
error = snprintf(path, max_len, "%s", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error < 0 || error >= max_len) {
|
||||||
|
fprintf(stderr, "lookup_exec_path(): array too small?\n");
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (link_path) {
|
||||||
|
free(link_path);
|
||||||
|
link_path = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check whether the resolved path is a symlink */
|
||||||
|
if (lstat(path, &sb) == -1) {
|
||||||
|
fprintf(stderr, "lookup_exec_path(): error stat\n");
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sb.st_mode & S_IFMT) == S_IFLNK) {
|
||||||
|
char *link_path = malloc(max_len);
|
||||||
|
if (!link_path) {
|
||||||
|
fprintf(stderr, "lookup_exec_path(): error allocating\n");
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = readlink(path, link_path, max_len);
|
||||||
|
if (error == -1 || error == max_len) {
|
||||||
|
fprintf(stderr, "lookup_exec_path(): error readlink\n");
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
__dprintf("lookup_exec_path(): %s is link -> %s\n", path, link_path);
|
||||||
|
|
||||||
|
filename = link_path;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"lookup_exec_path(): error finding file %s\n", filename);
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
__dprintf("lookup_exec_path(): %s\n", path);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int load_elf_desc(char *filename, struct program_load_desc **desc_p,
|
||||||
|
char **shell_p)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
FILE *interp = NULL;
|
FILE *interp = NULL;
|
||||||
char *interp_path;
|
char *interp_path;
|
||||||
|
char *shell = NULL;
|
||||||
|
size_t shell_len = 0;
|
||||||
struct program_load_desc *desc;
|
struct program_load_desc *desc;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
|
char header[1024];
|
||||||
|
|
||||||
if ((ret = access(filename, X_OK)) != 0) {
|
if ((ret = access(filename, X_OK)) != 0) {
|
||||||
fprintf(stderr, "Error: %s is not an executable?, errno: %d\n",
|
fprintf(stderr, "Error: %s is not an executable?, errno: %d\n",
|
||||||
@@ -369,6 +499,27 @@ int load_elf_desc(char *filename, struct program_load_desc **desc_p)
|
|||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fread(&header, 1, 2, fp) != 2) {
|
||||||
|
fprintf(stderr, "Error: Failed to read header from %s\n", filename);
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strncmp(header, "#!", 2)) {
|
||||||
|
|
||||||
|
if (getline(&shell, &shell_len, fp) == -1) {
|
||||||
|
fprintf(stderr, "Error: reading shell path %s\n", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
/* Delete new line character */
|
||||||
|
shell[strlen(shell) - 1] = 0;
|
||||||
|
*shell_p = shell;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind(fp);
|
||||||
|
|
||||||
desc = load_elf(fp, &interp_path);
|
desc = load_elf(fp, &interp_path);
|
||||||
if (!desc) {
|
if (!desc) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -519,7 +670,7 @@ void print_flat(char *flat)
|
|||||||
* returns the total length of the flat string and updates flat to
|
* returns the total length of the flat string and updates flat to
|
||||||
* point to the beginning.
|
* point to the beginning.
|
||||||
*/
|
*/
|
||||||
int flatten_strings(int nr_strings, char **strings, char **flat)
|
int flatten_strings(int nr_strings, char *first, char **strings, char **flat)
|
||||||
{
|
{
|
||||||
int full_len, string_i;
|
int full_len, string_i;
|
||||||
unsigned long flat_offset;
|
unsigned long flat_offset;
|
||||||
@@ -532,6 +683,10 @@ int flatten_strings(int nr_strings, char **strings, char **flat)
|
|||||||
|
|
||||||
/* Count full length */
|
/* Count full length */
|
||||||
full_len = sizeof(int) + sizeof(char *); // Counter and terminating NULL
|
full_len = sizeof(int) + sizeof(char *); // Counter and terminating NULL
|
||||||
|
if (first) {
|
||||||
|
full_len += sizeof(char *) + strlen(first) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (string_i = 0; string_i < nr_strings; ++string_i) {
|
for (string_i = 0; string_i < nr_strings; ++string_i) {
|
||||||
// Pointer + actual value
|
// Pointer + actual value
|
||||||
full_len += sizeof(char *) + strlen(strings[string_i]) + 1;
|
full_len += sizeof(char *) + strlen(strings[string_i]) + 1;
|
||||||
@@ -545,18 +700,25 @@ int flatten_strings(int nr_strings, char **strings, char **flat)
|
|||||||
memset(_flat, 0, full_len);
|
memset(_flat, 0, full_len);
|
||||||
|
|
||||||
/* Number of strings */
|
/* Number of strings */
|
||||||
*((int*)_flat) = nr_strings;
|
*((int*)_flat) = nr_strings + (first ? 1 : 0);
|
||||||
|
|
||||||
// Actual offset
|
// Actual offset
|
||||||
flat_offset = sizeof(int) + sizeof(char *) * (nr_strings + 1);
|
flat_offset = sizeof(int) + sizeof(char *) * (nr_strings + 1 +
|
||||||
|
(first ? 1 : 0));
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
*((char **)(_flat + sizeof(int))) = (void *)flat_offset;
|
||||||
|
memcpy(_flat + flat_offset, first, strlen(first) + 1);
|
||||||
|
flat_offset += strlen(first) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (string_i = 0; string_i < nr_strings; ++string_i) {
|
for (string_i = 0; string_i < nr_strings; ++string_i) {
|
||||||
|
|
||||||
/* Fabricate the string */
|
/* Fabricate the string */
|
||||||
*((char **)(_flat + sizeof(int) + string_i * sizeof(char *))) = (void *)flat_offset;
|
*((char **)(_flat + sizeof(int) + (string_i + (first ? 1 : 0))
|
||||||
|
* sizeof(char *))) = (void *)flat_offset;
|
||||||
memcpy(_flat + flat_offset, strings[string_i], strlen(strings[string_i]) + 1);
|
memcpy(_flat + flat_offset, strings[string_i], strlen(strings[string_i]) + 1);
|
||||||
flat_offset += strlen(strings[string_i]) + 1;
|
flat_offset += strlen(strings[string_i]) + 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*flat = _flat;
|
*flat = _flat;
|
||||||
@@ -609,33 +771,27 @@ sendsig(int sig, siginfo_t *siginfo, void *context)
|
|||||||
siginfo->si_signo == SIGINT)
|
siginfo->si_signo == SIGINT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(tid == master_tid){
|
for(i = 0; i < ncpu; i++){
|
||||||
cpu = 0;
|
if(siginfo->si_pid == pid &&
|
||||||
remote_tid = -1;
|
thread_data[i].tid == tid){
|
||||||
|
if(thread_data[i].terminate)
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(siginfo->si_pid != pid &&
|
||||||
|
thread_data[i].remote_tid == tid){
|
||||||
|
if(thread_data[i].terminate)
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(i != ncpu){
|
||||||
|
remote_tid = thread_data[i].remote_tid;
|
||||||
|
cpu = thread_data[i].cpu;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
for(i = 1; i < ncpu; i++){
|
cpu = 0;
|
||||||
if(siginfo->si_pid == pid &&
|
remote_tid = -1;
|
||||||
thread_data[i].tid == tid){
|
|
||||||
if(thread_data[i].terminate)
|
|
||||||
return;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(siginfo->si_pid != pid &&
|
|
||||||
thread_data[i].remote_tid == tid){
|
|
||||||
if(thread_data[i].terminate)
|
|
||||||
return;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(i != ncpu){
|
|
||||||
remote_tid = thread_data[i].remote_tid;
|
|
||||||
cpu = thread_data[i].cpu;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
cpu = 0;
|
|
||||||
remote_tid = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sigdesc.cpu = cpu;
|
sigdesc.cpu = cpu;
|
||||||
@@ -764,6 +920,9 @@ int main(int argc, char **argv)
|
|||||||
int target_core = 0;
|
int target_core = 0;
|
||||||
int mcosid = 0;
|
int mcosid = 0;
|
||||||
int opt;
|
int opt;
|
||||||
|
char path[1024];
|
||||||
|
char *shell = NULL;
|
||||||
|
char shell_path[1024];
|
||||||
|
|
||||||
#ifdef USE_SYSCALL_MOD_CALL
|
#ifdef USE_SYSCALL_MOD_CALL
|
||||||
__glob_argc = argc;
|
__glob_argc = argc;
|
||||||
@@ -776,7 +935,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Collect environment variables */
|
/* Collect environment variables */
|
||||||
envs_len = flatten_strings(-1, environ, &envs);
|
envs_len = flatten_strings(-1, NULL, environ, &envs);
|
||||||
envs = envs;
|
envs = envs;
|
||||||
|
|
||||||
error = getrlimit(RLIMIT_STACK, &rlim_stack);
|
error = getrlimit(RLIMIT_STACK, &rlim_stack);
|
||||||
@@ -828,18 +987,40 @@ int main(int argc, char **argv)
|
|||||||
for (i = optind; i < argc; ++i) {
|
for (i = optind; i < argc; ++i) {
|
||||||
__dprintf("%s ", argv[i]);
|
__dprintf("%s ", argv[i]);
|
||||||
}
|
}
|
||||||
__dprintf("\n");
|
__dprintf("%s", "\n");
|
||||||
|
|
||||||
if (load_elf_desc(argv[optind], &desc) != 0) {
|
if (lookup_exec_path(argv[optind], path, sizeof(path)) != 0) {
|
||||||
|
fprintf(stderr, "error: finding file: %s\n", argv[optind]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (load_elf_desc(path, &desc, &shell) != 0) {
|
||||||
fprintf(stderr, "error: loading file: %s\n", argv[optind]);
|
fprintf(stderr, "error: loading file: %s\n", argv[optind]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check whether shell script */
|
||||||
|
if (shell) {
|
||||||
|
if (lookup_exec_path(shell, shell_path, sizeof(shell_path)) != 0) {
|
||||||
|
fprintf(stderr, "error: finding file: %s\n", shell);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (load_elf_desc(shell_path, &desc, &shell) != 0) {
|
||||||
|
fprintf(stderr, "error: loading file: %s\n", shell);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shell) {
|
||||||
|
argv[optind] = path;
|
||||||
|
}
|
||||||
|
|
||||||
desc->envs_len = envs_len;
|
desc->envs_len = envs_len;
|
||||||
desc->envs = envs;
|
desc->envs = envs;
|
||||||
//print_flat(envs);
|
//print_flat(envs);
|
||||||
|
|
||||||
desc->args_len = flatten_strings(-1, argv + optind, &args);
|
desc->args_len = flatten_strings(-1, shell, argv + optind, &args);
|
||||||
desc->args = args;
|
desc->args = args;
|
||||||
//print_flat(args);
|
//print_flat(args);
|
||||||
|
|
||||||
@@ -1168,12 +1349,17 @@ int main_loop(int fd, int cpu, pthread_mutex_t *lock, int mcosid)
|
|||||||
return w.sr.args[0];
|
return w.sr.args[0];
|
||||||
|
|
||||||
case __NR_mmap:
|
case __NR_mmap:
|
||||||
case __NR_munmap:
|
|
||||||
case __NR_mprotect:
|
case __NR_mprotect:
|
||||||
/* reserved for internal use */
|
/* reserved for internal use */
|
||||||
do_syscall_return(fd, cpu, -ENOSYS, 0, 0, 0, 0);
|
do_syscall_return(fd, cpu, -ENOSYS, 0, 0, 0, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case __NR_munmap:
|
||||||
|
ret = madvise((void *)w.sr.args[0], w.sr.args[1], MADV_DONTNEED);
|
||||||
|
SET_ERR(ret);
|
||||||
|
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
#ifdef USE_SYSCALL_MOD_CALL
|
#ifdef USE_SYSCALL_MOD_CALL
|
||||||
case 303:{
|
case 303:{
|
||||||
__dprintf("mcexec.c,mod_cal,mod=%ld,cmd=%ld\n", w.sr.args[0], w.sr.args[1]);
|
__dprintf("mcexec.c,mod_cal,mod=%ld,cmd=%ld\n", w.sr.args[0], w.sr.args[1]);
|
||||||
@@ -1271,93 +1457,51 @@ int main_loop(int fd, int cpu, pthread_mutex_t *lock, int mcosid)
|
|||||||
switch (w.sr.args[0]) {
|
switch (w.sr.args[0]) {
|
||||||
struct program_load_desc *desc;
|
struct program_load_desc *desc;
|
||||||
struct remote_transfer trans;
|
struct remote_transfer trans;
|
||||||
int error;
|
char path[1024];
|
||||||
int found;
|
|
||||||
char path[2048];
|
|
||||||
char *filename;
|
char *filename;
|
||||||
int ret;
|
int ret;
|
||||||
|
char *shell = NULL;
|
||||||
|
char shell_path[1024];
|
||||||
|
|
||||||
/* Load descriptor phase */
|
/* Load descriptor phase */
|
||||||
case 1:
|
case 1:
|
||||||
|
|
||||||
ret = -1;
|
|
||||||
found = 0;
|
|
||||||
filename = (char *)w.sr.args[1];
|
filename = (char *)w.sr.args[1];
|
||||||
|
|
||||||
/* Is filename a single component without path? */
|
|
||||||
if (strncmp(filename, "/", 1)
|
|
||||||
&& !strchr(filename, '/')) {
|
|
||||||
|
|
||||||
char *token, *string, *tofree;
|
|
||||||
char *PATH = getenv("COKERNEL_PATH");
|
|
||||||
if (!PATH) {
|
|
||||||
PATH = getenv("PATH");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen(filename) >= 255) {
|
|
||||||
ret = ENAMETOOLONG;
|
|
||||||
goto return_execve1;
|
|
||||||
}
|
|
||||||
|
|
||||||
__dprintf("PATH: %s\n", PATH);
|
|
||||||
|
|
||||||
/* strsep() modifies string! */
|
|
||||||
tofree = string = strdup(PATH);
|
|
||||||
if (string == NULL) {
|
|
||||||
printf("error: copying PATH, not enough memory?\n");
|
|
||||||
goto return_execve1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((token = strsep(&string, ":")) != NULL) {
|
|
||||||
|
|
||||||
error = snprintf(path, sizeof(path),
|
|
||||||
"%s/%s", token, filename);
|
|
||||||
if (error < 0 || error >= sizeof(path)) {
|
|
||||||
fprintf(stderr, "execve(): array too small?\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
error = access(path, X_OK);
|
|
||||||
if (error == 0) {
|
|
||||||
found = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(tofree);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
char *root = getenv("COKERNEL_EXEC_ROOT");
|
|
||||||
|
|
||||||
if (root) {
|
|
||||||
error = snprintf(path, sizeof(path), "%s/%s", root, filename);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
error = snprintf(path, sizeof(path), "%s", filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error < 0 || error >= sizeof(path)) {
|
|
||||||
fprintf(stderr, "execve(): array too small?\n");
|
|
||||||
goto return_execve1;
|
|
||||||
}
|
|
||||||
|
|
||||||
found = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
if ((ret = lookup_exec_path(filename, path, sizeof(path)))
|
||||||
fprintf(stderr,
|
!= 0) {
|
||||||
"execve(): error finding file %s\n", filename);
|
|
||||||
ret = ENOENT;
|
|
||||||
goto return_execve1;
|
goto return_execve1;
|
||||||
}
|
}
|
||||||
|
|
||||||
__dprintf("execve(): path to binary: %s\n", path);
|
if ((ret = load_elf_desc(path, &desc, &shell)) != 0) {
|
||||||
|
|
||||||
if ((ret = load_elf_desc(path, &desc)) != 0) {
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"execve(): error loading ELF for file %s\n", path);
|
"execve(): error loading ELF for file %s\n", path);
|
||||||
goto return_execve1;
|
goto return_execve1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check whether shell script */
|
||||||
|
if (shell) {
|
||||||
|
if ((ret = lookup_exec_path(shell, shell_path,
|
||||||
|
sizeof(shell_path))) != 0) {
|
||||||
|
fprintf(stderr, "execve(): error: finding file: %s\n", shell);
|
||||||
|
goto return_execve1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = load_elf_desc(shell_path, &desc, &shell))
|
||||||
|
!= 0) {
|
||||||
|
fprintf(stderr, "execve(): error: loading file: %s\n", shell);
|
||||||
|
goto return_execve1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(shell_path) >= SHELL_PATH_MAX_LEN) {
|
||||||
|
fprintf(stderr, "execve(): error: shell path too long: %s\n", shell_path);
|
||||||
|
ret = ENAMETOOLONG;
|
||||||
|
goto return_execve1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let the LWK know the shell interpreter */
|
||||||
|
strcpy(desc->shell_path, shell_path);
|
||||||
|
}
|
||||||
|
|
||||||
__dprintf("execve(): load_elf_desc() for %s OK, num sections: %d\n",
|
__dprintf("execve(): load_elf_desc() for %s OK, num sections: %d\n",
|
||||||
path, desc->num_sections);
|
path, desc->num_sections);
|
||||||
@@ -1412,10 +1556,10 @@ return_execve1:
|
|||||||
goto return_execve1;
|
goto return_execve1;
|
||||||
}
|
}
|
||||||
|
|
||||||
__dprintf("execve(): transfer ELF desc OK\n");
|
__dprintf("%s", "execve(): transfer ELF desc OK\n");
|
||||||
|
|
||||||
transfer_image(fd, desc);
|
transfer_image(fd, desc);
|
||||||
__dprintf("execve(): image transferred\n");
|
__dprintf("%s", "execve(): image transferred\n");
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
return_execve2:
|
return_execve2:
|
||||||
|
|||||||
@@ -109,6 +109,8 @@ struct program_image_section {
|
|||||||
void *fp;
|
void *fp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SHELL_PATH_MAX_LEN 1024
|
||||||
|
|
||||||
struct program_load_desc {
|
struct program_load_desc {
|
||||||
int num_sections;
|
int num_sections;
|
||||||
int status;
|
int status;
|
||||||
@@ -134,6 +136,7 @@ struct program_load_desc {
|
|||||||
unsigned long rlimit_stack_cur;
|
unsigned long rlimit_stack_cur;
|
||||||
unsigned long rlimit_stack_max;
|
unsigned long rlimit_stack_max;
|
||||||
unsigned long interp_align;
|
unsigned long interp_align;
|
||||||
|
char shell_path[SHELL_PATH_MAX_LEN];
|
||||||
struct program_image_section sections[0];
|
struct program_image_section sections[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
14
kernel/mem.c
14
kernel/mem.c
@@ -180,7 +180,7 @@ void freecore(struct coretable **);
|
|||||||
* \param regs A pointer to a x86_regs structure.
|
* \param regs A pointer to a x86_regs structure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void coredump(struct process *proc, void *regs)
|
void coredump(struct process *proc, void *regs)
|
||||||
{
|
{
|
||||||
struct syscall_request request IHK_DMA_ALIGN;
|
struct syscall_request request IHK_DMA_ALIGN;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -216,9 +216,9 @@ static void unhandled_page_fault(struct process *proc, void *fault_addr, void *r
|
|||||||
unsigned long error = ((struct x86_regs *)regs)->error;
|
unsigned long error = ((struct x86_regs *)regs)->error;
|
||||||
|
|
||||||
irqflags = kprintf_lock();
|
irqflags = kprintf_lock();
|
||||||
__kprintf("[%d] Page fault for 0x%lX\n",
|
dkprintf("[%d] Page fault for 0x%lX\n",
|
||||||
ihk_mc_get_processor_id(), address);
|
ihk_mc_get_processor_id(), address);
|
||||||
__kprintf("%s for %s access in %s mode (reserved bit %s set), "
|
dkprintf("%s for %s access in %s mode (reserved bit %s set), "
|
||||||
"it %s an instruction fetch\n",
|
"it %s an instruction fetch\n",
|
||||||
(error & PF_PROT ? "protection fault" : "no page found"),
|
(error & PF_PROT ? "protection fault" : "no page found"),
|
||||||
(error & PF_WRITE ? "write" : "read"),
|
(error & PF_WRITE ? "write" : "read"),
|
||||||
@@ -230,14 +230,14 @@ static void unhandled_page_fault(struct process *proc, void *fault_addr, void *r
|
|||||||
list_for_each_entry(range, &vm->vm_range_list, list) {
|
list_for_each_entry(range, &vm->vm_range_list, list) {
|
||||||
if (range->start <= address && range->end > address) {
|
if (range->start <= address && range->end > address) {
|
||||||
found = 1;
|
found = 1;
|
||||||
__kprintf("address is in range, flag: 0x%X! \n",
|
dkprintf("address is in range, flag: 0x%X! \n",
|
||||||
range->flag);
|
range->flag);
|
||||||
ihk_mc_pt_print_pte(vm->page_table, (void*)address);
|
ihk_mc_pt_print_pte(vm->page_table, (void*)address);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
__kprintf("address is out of range! \n");
|
dkprintf("address is out of range! \n");
|
||||||
}
|
}
|
||||||
|
|
||||||
kprintf_unlock(irqflags);
|
kprintf_unlock(irqflags);
|
||||||
@@ -246,8 +246,8 @@ static void unhandled_page_fault(struct process *proc, void *fault_addr, void *r
|
|||||||
ihk_mc_debug_show_interrupt_context(regs);
|
ihk_mc_debug_show_interrupt_context(regs);
|
||||||
|
|
||||||
|
|
||||||
dkprintf("now dump a core file\n");
|
//dkprintf("now dump a core file\n");
|
||||||
coredump(proc, regs);
|
//coredump(proc, regs);
|
||||||
|
|
||||||
#ifdef DEBUG_PRINT_MEM
|
#ifdef DEBUG_PRINT_MEM
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -311,6 +311,9 @@ SYSCALL_DECLARE(wait4)
|
|||||||
struct waitq_entry waitpid_wqe;
|
struct waitq_entry waitpid_wqe;
|
||||||
int empty = 1;
|
int empty = 1;
|
||||||
|
|
||||||
|
if (options & ~(WNOHANG | WUNTRACED | WCONTINUED)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
rescan:
|
rescan:
|
||||||
child = NULL;
|
child = NULL;
|
||||||
pid = (int)ihk_mc_syscall_arg0(ctx);
|
pid = (int)ihk_mc_syscall_arg0(ctx);
|
||||||
@@ -333,7 +336,7 @@ rescan:
|
|||||||
ihk_mc_spinlock_unlock_noirq(&child_iter->lock);
|
ihk_mc_spinlock_unlock_noirq(&child_iter->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty) {
|
if (empty || (!child && pid != -1)) {
|
||||||
ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock);
|
ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock);
|
||||||
return -ECHILD;
|
return -ECHILD;
|
||||||
}
|
}
|
||||||
@@ -400,7 +403,7 @@ terminate(int rc, int sig, ihk_mc_user_context_t *ctx)
|
|||||||
struct fork_tree_node *child, *next;
|
struct fork_tree_node *child, *next;
|
||||||
|
|
||||||
request.number = __NR_exit_group;
|
request.number = __NR_exit_group;
|
||||||
request.args[0] = ((rc & 0x00ff) << 8) | (sig & 0x7f);
|
request.args[0] = ((rc & 0x00ff) << 8) | (sig & 0xff);
|
||||||
|
|
||||||
#ifdef DCFA_KMOD
|
#ifdef DCFA_KMOD
|
||||||
do_mod_exit(rc);
|
do_mod_exit(rc);
|
||||||
@@ -430,7 +433,7 @@ terminate(int rc, int sig, ihk_mc_user_context_t *ctx)
|
|||||||
|
|
||||||
ihk_mc_spinlock_lock_noirq(&ftn->lock);
|
ihk_mc_spinlock_lock_noirq(&ftn->lock);
|
||||||
ftn->pid = proc->pid;
|
ftn->pid = proc->pid;
|
||||||
ftn->exit_status = ((rc & 0x00ff) << 8) | (sig & 0x7f);
|
ftn->exit_status = ((rc & 0x00ff) << 8) | (sig & 0xff);
|
||||||
ftn->status = PS_ZOMBIE;
|
ftn->status = PS_ZOMBIE;
|
||||||
ihk_mc_spinlock_unlock_noirq(&ftn->lock);
|
ihk_mc_spinlock_unlock_noirq(&ftn->lock);
|
||||||
|
|
||||||
@@ -1245,15 +1248,20 @@ SYSCALL_DECLARE(execve)
|
|||||||
|
|
||||||
dkprintf("execve(): ELF desc received, num sections: %d\n",
|
dkprintf("execve(): ELF desc received, num sections: %d\n",
|
||||||
desc->num_sections);
|
desc->num_sections);
|
||||||
|
|
||||||
|
if (desc->shell_path[0]) {
|
||||||
|
dkprintf("execve(): shell interpreter: %s\n", desc->shell_path);
|
||||||
|
}
|
||||||
|
|
||||||
/* Flatten argv and envp into kernel-space buffers */
|
/* Flatten argv and envp into kernel-space buffers */
|
||||||
argv_flat_len = flatten_strings(-1, argv, &argv_flat);
|
argv_flat_len = flatten_strings(-1, (desc->shell_path[0] ?
|
||||||
|
desc->shell_path : NULL), argv, &argv_flat);
|
||||||
if (argv_flat_len == 0) {
|
if (argv_flat_len == 0) {
|
||||||
kprintf("ERROR: no argv for executable: %s?\n", filename);
|
kprintf("ERROR: no argv for executable: %s?\n", filename);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
envp_flat_len = flatten_strings(-1, envp, &envp_flat);
|
envp_flat_len = flatten_strings(-1, NULL, envp, &envp_flat);
|
||||||
if (envp_flat_len == 0) {
|
if (envp_flat_len == 0) {
|
||||||
kprintf("ERROR: no envp for executable: %s?\n", filename);
|
kprintf("ERROR: no envp for executable: %s?\n", filename);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -2009,6 +2017,7 @@ SYSCALL_DECLARE(sched_setaffinity)
|
|||||||
struct process *thread;
|
struct process *thread;
|
||||||
int cpu_id;
|
int cpu_id;
|
||||||
unsigned long irqstate;
|
unsigned long irqstate;
|
||||||
|
extern int num_processors;
|
||||||
|
|
||||||
if (sizeof(k_cpu_set) > len) {
|
if (sizeof(k_cpu_set) > len) {
|
||||||
kprintf("%s:%d\n Too small buffer.", __FILE__, __LINE__);
|
kprintf("%s:%d\n Too small buffer.", __FILE__, __LINE__);
|
||||||
@@ -2023,11 +2032,13 @@ SYSCALL_DECLARE(sched_setaffinity)
|
|||||||
|
|
||||||
// XXX: We should build something like cpu_available_mask in advance
|
// XXX: We should build something like cpu_available_mask in advance
|
||||||
CPU_ZERO(&cpu_set);
|
CPU_ZERO(&cpu_set);
|
||||||
extern int num_processors;
|
|
||||||
for (cpu_id = 0; cpu_id < num_processors; cpu_id++)
|
for (cpu_id = 0; cpu_id < num_processors; cpu_id++)
|
||||||
if (CPU_ISSET(cpu_id, &k_cpu_set))
|
if (CPU_ISSET(cpu_id, &k_cpu_set))
|
||||||
CPU_SET(cpu_id, &cpu_set);
|
CPU_SET(cpu_id, &cpu_set);
|
||||||
|
|
||||||
|
if(tid == 0)
|
||||||
|
tid = cpu_local_var(current)->tid;
|
||||||
|
|
||||||
for (cpu_id = 0; cpu_id < num_processors; cpu_id++) {
|
for (cpu_id = 0; cpu_id < num_processors; cpu_id++) {
|
||||||
irqstate = ihk_mc_spinlock_lock(&get_cpu_local_var(cpu_id)->runq_lock);
|
irqstate = ihk_mc_spinlock_lock(&get_cpu_local_var(cpu_id)->runq_lock);
|
||||||
list_for_each_entry(thread, &get_cpu_local_var(cpu_id)->runq, sched_list)
|
list_for_each_entry(thread, &get_cpu_local_var(cpu_id)->runq, sched_list)
|
||||||
@@ -2064,6 +2075,7 @@ SYSCALL_DECLARE(sched_getaffinity)
|
|||||||
int found = 0;
|
int found = 0;
|
||||||
int i;
|
int i;
|
||||||
unsigned long irqstate;
|
unsigned long irqstate;
|
||||||
|
extern int num_processors;
|
||||||
|
|
||||||
if (sizeof(k_cpu_set) > len) {
|
if (sizeof(k_cpu_set) > len) {
|
||||||
kprintf("%s:%d Too small buffer.\n", __FILE__, __LINE__);
|
kprintf("%s:%d Too small buffer.\n", __FILE__, __LINE__);
|
||||||
@@ -2071,7 +2083,9 @@ SYSCALL_DECLARE(sched_getaffinity)
|
|||||||
}
|
}
|
||||||
len = MIN2(len, sizeof(k_cpu_set));
|
len = MIN2(len, sizeof(k_cpu_set));
|
||||||
|
|
||||||
extern int num_processors;
|
if(tid == 0)
|
||||||
|
tid = cpu_local_var(current)->tid;
|
||||||
|
|
||||||
for (i = 0; i < num_processors && !found; i++) {
|
for (i = 0; i < num_processors && !found; i++) {
|
||||||
struct process *thread;
|
struct process *thread;
|
||||||
irqstate = ihk_mc_spinlock_lock(&get_cpu_local_var(i)->runq_lock);
|
irqstate = ihk_mc_spinlock_lock(&get_cpu_local_var(i)->runq_lock);
|
||||||
|
|||||||
@@ -29,6 +29,6 @@ int memcmp(const void *s1, const void *s2, size_t n);
|
|||||||
void *memset(void *s, int n, size_t l);
|
void *memset(void *s, int n, size_t l);
|
||||||
|
|
||||||
unsigned long strtol(const char *cp, char **endp, unsigned int base);
|
unsigned long strtol(const char *cp, char **endp, unsigned int base);
|
||||||
int flatten_strings(int nr_strings, char **strings, char **flat);
|
int flatten_strings(int nr_strings, char *first, char **strings, char **flat);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
21
lib/string.c
21
lib/string.c
@@ -196,7 +196,7 @@ int memcmp(const void *s1, const void *s2, size_t n)
|
|||||||
* returns the total length of the flat string and updates flat to
|
* returns the total length of the flat string and updates flat to
|
||||||
* point to the beginning.
|
* point to the beginning.
|
||||||
*/
|
*/
|
||||||
int flatten_strings(int nr_strings, char **strings, char **flat)
|
int flatten_strings(int nr_strings, char *first, char **strings, char **flat)
|
||||||
{
|
{
|
||||||
int full_len, string_i;
|
int full_len, string_i;
|
||||||
unsigned long flat_offset;
|
unsigned long flat_offset;
|
||||||
@@ -209,6 +209,10 @@ int flatten_strings(int nr_strings, char **strings, char **flat)
|
|||||||
|
|
||||||
/* Count full length */
|
/* Count full length */
|
||||||
full_len = sizeof(int) + sizeof(char *); // Counter and terminating NULL
|
full_len = sizeof(int) + sizeof(char *); // Counter and terminating NULL
|
||||||
|
if (first) {
|
||||||
|
full_len += sizeof(char *) + strlen(first) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (string_i = 0; string_i < nr_strings; ++string_i) {
|
for (string_i = 0; string_i < nr_strings; ++string_i) {
|
||||||
// Pointer + actual value
|
// Pointer + actual value
|
||||||
full_len += sizeof(char *) + strlen(strings[string_i]) + 1;
|
full_len += sizeof(char *) + strlen(strings[string_i]) + 1;
|
||||||
@@ -222,18 +226,25 @@ int flatten_strings(int nr_strings, char **strings, char **flat)
|
|||||||
memset(_flat, 0, full_len);
|
memset(_flat, 0, full_len);
|
||||||
|
|
||||||
/* Number of strings */
|
/* Number of strings */
|
||||||
*((int*)_flat) = nr_strings;
|
*((int*)_flat) = nr_strings + (first ? 1 : 0);
|
||||||
|
|
||||||
// Actual offset
|
// Actual offset
|
||||||
flat_offset = sizeof(int) + sizeof(char *) * (nr_strings + 1);
|
flat_offset = sizeof(int) + sizeof(char *) * (nr_strings + 1 +
|
||||||
|
(first ? 1 : 0));
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
*((char **)(_flat + sizeof(int))) = (void *)flat_offset;
|
||||||
|
memcpy(_flat + flat_offset, first, strlen(first) + 1);
|
||||||
|
flat_offset += strlen(first) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (string_i = 0; string_i < nr_strings; ++string_i) {
|
for (string_i = 0; string_i < nr_strings; ++string_i) {
|
||||||
|
|
||||||
/* Fabricate the string */
|
/* Fabricate the string */
|
||||||
*((char **)(_flat + sizeof(int) + string_i * sizeof(char *))) = (void *)flat_offset;
|
*((char **)(_flat + sizeof(int) + (string_i + (first ? 1 : 0))
|
||||||
|
* sizeof(char *))) = (void *)flat_offset;
|
||||||
memcpy(_flat + flat_offset, strings[string_i], strlen(strings[string_i]) + 1);
|
memcpy(_flat + flat_offset, strings[string_i], strlen(strings[string_i]) + 1);
|
||||||
flat_offset += strlen(strings[string_i]) + 1;
|
flat_offset += strlen(strings[string_i]) + 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*flat = _flat;
|
*flat = _flat;
|
||||||
|
|||||||
Reference in New Issue
Block a user