mirror of
https://github.com/clearlinux/graphene.git
synced 2026-10-03 15:39:36 +00:00
apply multiple patches
This commit is contained in:
+2
-1
@@ -86,7 +86,7 @@ try:
|
||||
|
||||
os.chdir(buildDir)
|
||||
|
||||
cflags= '{0} -O2 -U_FORTIFY_SOURCE -fno-stack-protector'.format(debug_flags)
|
||||
cflags = '{0} -O2 -U_FORTIFY_SOURCE -fno-stack-protector'.format(debug_flags)
|
||||
disabled_features = { 'nscd' }
|
||||
extra_flags = '--with-tls --enable-add-ons=nptl --without-selinux {0}'.format(' '.join(['--disable-' + f for f in disabled_features]))
|
||||
|
||||
@@ -108,6 +108,7 @@ try:
|
||||
( 'nptl', 'libpthread.so.0' ),
|
||||
( 'nptl_db','libthread_db.so.1' ),
|
||||
( 'dlfcn', 'libdl.so.2' ),
|
||||
( 'math', 'libm.so.6' ),
|
||||
( 'csu', 'crt1.o' ),
|
||||
( 'csu', 'crti.o' ),
|
||||
( 'csu', 'crtn.o' ),
|
||||
|
||||
+14
-48
@@ -926,10 +926,10 @@ index dc95421..a772f66 100644
|
||||
cmpl $0, (%rdi)
|
||||
jne 1f
|
||||
diff --git a/LibOS/glibc-2.17/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/LibOS/glibc-2.17/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
|
||||
index 5a80ddd..bcc8d57 100644
|
||||
index 5a80ddd..f7319ca 100644
|
||||
--- a/LibOS/glibc-2.17/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
|
||||
+++ b/LibOS/glibc-2.17/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
|
||||
@@ -214,12 +214,12 @@ LLL_STUB_UNWIND_INFO_END
|
||||
@@ -214,7 +214,7 @@ LLL_STUB_UNWIND_INFO_END
|
||||
register const struct timespec *__to __asm ("r10") = timeout; \
|
||||
int __status; \
|
||||
register __typeof (val) _val __asm ("edx") = (val); \
|
||||
@@ -938,13 +938,7 @@ index 5a80ddd..bcc8d57 100644
|
||||
: "=a" (__status) \
|
||||
: "0" (SYS_futex), "D" (futex), \
|
||||
"S" (__lll_private_flag (FUTEX_WAIT, private)), \
|
||||
"d" (_val), "r" (__to) \
|
||||
- : "memory", "cc", "r11", "cx"); \
|
||||
+ : "memory", "cc", "r11", "cx", "bx"); \
|
||||
__status; \
|
||||
})
|
||||
|
||||
@@ -229,12 +229,12 @@ LLL_STUB_UNWIND_INFO_END
|
||||
@@ -229,7 +229,7 @@ LLL_STUB_UNWIND_INFO_END
|
||||
int __ignore; \
|
||||
register __typeof (nr) _nr __asm ("edx") = (nr); \
|
||||
LIBC_PROBE (lll_futex_wake, 3, futex, nr, private); \
|
||||
@@ -953,13 +947,7 @@ index 5a80ddd..bcc8d57 100644
|
||||
: "=a" (__ignore) \
|
||||
: "0" (SYS_futex), "D" (futex), \
|
||||
"S" (__lll_private_flag (FUTEX_WAKE, private)), \
|
||||
"d" (_nr) \
|
||||
- : "memory", "cc", "r10", "r11", "cx"); \
|
||||
+ : "memory", "cc", "r10", "r11", "cx", "bx"); \
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -532,12 +532,12 @@ LLL_STUB_UNWIND_INFO_END
|
||||
@@ -532,7 +532,7 @@ LLL_STUB_UNWIND_INFO_END
|
||||
{ \
|
||||
int ignore; \
|
||||
__asm __volatile (LOCK_INSTR "orl %3, (%2)\n\t" \
|
||||
@@ -968,13 +956,7 @@ index 5a80ddd..bcc8d57 100644
|
||||
: "=m" (futex), "=a" (ignore) \
|
||||
: "D" (&(futex)), "i" (FUTEX_OWNER_DIED), \
|
||||
"S" (__lll_private_flag (FUTEX_WAKE, private)), \
|
||||
"1" (__NR_futex), "d" (1) \
|
||||
- : "cx", "r11", "cc", "memory"); \
|
||||
+ : "cx", "bx", "r11", "cc", "memory"); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
@@ -547,13 +547,13 @@ LLL_STUB_UNWIND_INFO_END
|
||||
@@ -547,7 +547,7 @@ LLL_STUB_UNWIND_INFO_END
|
||||
register int __nr_move __asm ("r10") = nr_move; \
|
||||
register void *__mutex __asm ("r8") = mutex; \
|
||||
register int __val __asm ("r9") = val; \
|
||||
@@ -983,14 +965,7 @@ index 5a80ddd..bcc8d57 100644
|
||||
: "=a" (__res) \
|
||||
: "0" (__NR_futex), "D" ((void *) ftx), \
|
||||
"S" (__lll_private_flag (FUTEX_CMP_REQUEUE, \
|
||||
private)), "d" (nr_wake), \
|
||||
"r" (__nr_move), "r" (__mutex), "r" (__val) \
|
||||
- : "cx", "r11", "cc", "memory"); \
|
||||
+ : "cx", "bx", "r11", "cc", "memory"); \
|
||||
__res < 0; })
|
||||
|
||||
#define lll_islocked(futex) \
|
||||
@@ -573,13 +573,13 @@ LLL_STUB_UNWIND_INFO_END
|
||||
@@ -573,7 +573,7 @@ LLL_STUB_UNWIND_INFO_END
|
||||
if (_tid != 0) \
|
||||
__asm __volatile ("xorq %%r10, %%r10\n\t" \
|
||||
"1:\tmovq %2, %%rax\n\t" \
|
||||
@@ -999,13 +974,6 @@ index 5a80ddd..bcc8d57 100644
|
||||
"cmpl $0, (%%rdi)\n\t" \
|
||||
"jne 1b" \
|
||||
: "=&a" (__ignore) \
|
||||
: "S" (FUTEX_WAIT), "i" (SYS_futex), "D" (&tid), \
|
||||
"d" (_tid) \
|
||||
- : "memory", "cc", "r10", "r11", "cx"); \
|
||||
+ : "memory", "cc", "r10", "r11", "cx", "bx"); \
|
||||
} while (0)
|
||||
|
||||
extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime)
|
||||
diff --git a/LibOS/glibc-2.17/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S b/LibOS/glibc-2.17/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S
|
||||
index 0b4ef71..36c5572 100644
|
||||
--- a/LibOS/glibc-2.17/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S
|
||||
@@ -1401,7 +1369,7 @@ index 50587b8..374b553 100644
|
||||
+ asm volatile ("pushq %%rbx\n\tmovq syscalldb@GOTPCREL(%%rip), %%rbx\n\t" \
|
||||
+ "call %%rbx\n\t" :: "a" (__NR_exit), "D" (val) : "bx" )
|
||||
diff --git a/LibOS/glibc-2.17/nptl/sysdeps/x86_64/tls.h b/LibOS/glibc-2.17/nptl/sysdeps/x86_64/tls.h
|
||||
index f3b7649..b466cb1 100644
|
||||
index f3b7649..433b8c9 100644
|
||||
--- a/LibOS/glibc-2.17/nptl/sysdeps/x86_64/tls.h
|
||||
+++ b/LibOS/glibc-2.17/nptl/sysdeps/x86_64/tls.h
|
||||
@@ -28,6 +28,7 @@
|
||||
@@ -1423,16 +1391,20 @@ index f3b7649..b466cb1 100644
|
||||
int rtld_must_xmm_save;
|
||||
/* Reservation of some values for the TM ABI. */
|
||||
void *__private_tm[5];
|
||||
@@ -135,6 +140,8 @@ typedef struct
|
||||
@@ -135,6 +140,12 @@ typedef struct
|
||||
# define GET_DTV(descr) \
|
||||
(((tcbhead_t *) (descr))->dtv)
|
||||
|
||||
+/* For Graphene */
|
||||
+#define SYSCALLDB "movq syscalldb@GOTPCREL(%%rip), %%rbx\n\tcall %%rbx\n\t"
|
||||
+#define SYSCALLDB \
|
||||
+ "pushq %%rbx\n\t" \
|
||||
+ "movq syscalldb@GOTPCREL(%%rip), %%rbx\n\t" \
|
||||
+ "callq *%%rbx\n\t" \
|
||||
+ "popq %%rbx\n\t"
|
||||
|
||||
/* Code to initially initialize the thread pointer. This might need
|
||||
special attention since 'errno' is not yet available and if the
|
||||
@@ -152,12 +159,12 @@ typedef struct
|
||||
@@ -152,7 +163,7 @@ typedef struct
|
||||
_head->self = _thrdescr; \
|
||||
\
|
||||
/* It is a simple syscall to set the %fs value for the thread. */ \
|
||||
@@ -1441,12 +1413,6 @@ index f3b7649..b466cb1 100644
|
||||
: "=a" (_result) \
|
||||
: "0" ((unsigned long int) __NR_arch_prctl), \
|
||||
"D" ((unsigned long int) ARCH_SET_FS), \
|
||||
"S" (_thrdescr) \
|
||||
- : "memory", "cc", "r11", "cx"); \
|
||||
+ : "memory", "cc", "r11", "cx", "bx"); \
|
||||
\
|
||||
_result ? "cannot set %fs base address for thread-local storage" : 0; \
|
||||
})
|
||||
diff --git a/LibOS/glibc-2.17/scripts/mkinstalldirs b/LibOS/glibc-2.17/scripts/mkinstalldirs
|
||||
index f945dbf..3c0e48c 100755
|
||||
--- a/LibOS/glibc-2.17/scripts/mkinstalldirs
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
#include <syscalldb.h>
|
||||
|
||||
#ifdef WEAK_SYSCALLDB
|
||||
.weak syscalldb
|
||||
#else
|
||||
.global syscalldb
|
||||
#endif
|
||||
.type syscalldb,@function
|
||||
|
||||
syscalldb:
|
||||
.cfi_startproc
|
||||
syscall
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size syscalldb,.-syscalldb
|
||||
retq
|
||||
.cfi_endproc
|
||||
.size syscalldb,.-syscalldb
|
||||
|
||||
@@ -1,23 +1,13 @@
|
||||
#ifndef _SYSCALLDB_H_
|
||||
#define _SYSCALLDB_H_
|
||||
|
||||
#define WEAK_SYSCALLDB 1
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
# ifdef WEAK_SYSCALLDB
|
||||
.weak syscalldb
|
||||
# else
|
||||
.global syscalldb
|
||||
# endif
|
||||
.type syscalldb, @function
|
||||
|
||||
#else /* !__ASSEMBLER__ */
|
||||
asm (
|
||||
# ifdef WEAK_SYSCALLDB
|
||||
".weak syscalldb\r\n"
|
||||
# else
|
||||
".global syscalldb\r\n"
|
||||
# endif
|
||||
".type syscalldb, @function\r\n");
|
||||
|
||||
#endif /* Assembler */
|
||||
|
||||
@@ -742,6 +742,8 @@ extern const char ** initial_envp;
|
||||
_stack; \
|
||||
})
|
||||
|
||||
void get_brk_region (void ** start, void ** end, void ** current);
|
||||
|
||||
int init_randgen (void);
|
||||
int init_brk (void);
|
||||
int init_heap (void);
|
||||
|
||||
@@ -265,21 +265,7 @@ void set_handle_map (struct shim_thread * thread,
|
||||
int thread_exit (struct shim_thread * self, bool send_ipc);
|
||||
int try_process_exit (int error_code);
|
||||
|
||||
/* thread cloning helpers */
|
||||
struct clone_args {
|
||||
PAL_HANDLE create_event;
|
||||
PAL_HANDLE initialize_event;
|
||||
struct shim_thread * thread;
|
||||
void * stack;
|
||||
void * return_pc;
|
||||
};
|
||||
|
||||
int clone_implementation_wrapper(struct clone_args * arg);
|
||||
|
||||
int clean_held_locks (struct shim_thread * self);
|
||||
|
||||
void * allocate_stack (size_t size, size_t protect_size, bool user);
|
||||
|
||||
int populate_user_stack (void * stack, size_t stack_size,
|
||||
int nauxv, elf_auxv_t ** auxpp,
|
||||
const char *** argvp, const char *** envpp);
|
||||
|
||||
@@ -32,13 +32,13 @@ struct shim_regs {
|
||||
unsigned long r15;
|
||||
unsigned long r14;
|
||||
unsigned long r13;
|
||||
unsigned long r12;
|
||||
unsigned long r9;
|
||||
unsigned long r8;
|
||||
unsigned long rcx;
|
||||
unsigned long rdx;
|
||||
unsigned long rsi;
|
||||
unsigned long rdi;
|
||||
unsigned long r12;
|
||||
unsigned long rbx;
|
||||
unsigned long rbp;
|
||||
};
|
||||
|
||||
@@ -87,6 +87,8 @@ struct shim_vma * next_vma (struct shim_vma * vma);
|
||||
|
||||
void * get_unmapped_vma (size_t len, int flags);
|
||||
|
||||
int dump_all_vmas (struct shim_thread * thread, char * buf, size_t size);
|
||||
|
||||
void unmap_all_vmas (void);
|
||||
|
||||
/* Debugging */
|
||||
|
||||
@@ -64,7 +64,7 @@ libsysdb.so: $(addsuffix .o,$(objs)) $(filter %.map %.lds,$(LDFLAGS)) \
|
||||
$(LD) $(LDFLAGS) -o $@ $(filter-out %.map %.lds,$^) -soname $@ \
|
||||
-e shim_start
|
||||
|
||||
libsysdb_debug.so: $(addsuffix .o,$(objs)) \
|
||||
libsysdb_debug.so: $(addsuffix .o,$(filter-out syscallas,$(objs))) \
|
||||
$(filter %.map %.lds,$($LDFLAGS-debug)) \
|
||||
$(graphene_lib) $(pal_lib)
|
||||
@echo [ $@ ]
|
||||
|
||||
@@ -231,6 +231,7 @@ struct shim_thread * get_new_thread (IDTYPE new_tid)
|
||||
thread->parent = cur_thread;
|
||||
thread->stack = cur_thread->stack;
|
||||
thread->stack_top = cur_thread->stack_top;
|
||||
thread->stack_red = cur_thread->stack_red;
|
||||
thread->cwd = cur_thread->cwd;
|
||||
thread->root = cur_thread->root;
|
||||
thread->umask = cur_thread->umask;
|
||||
|
||||
@@ -282,6 +282,7 @@ static int __bkeep_mmap (void * addr, size_t length,
|
||||
prev->length = addr - prev->addr;
|
||||
}
|
||||
|
||||
assert(prev->addr + prev->length <= addr);
|
||||
cont = prev;
|
||||
pos = &prev->list;
|
||||
} else { /* has no precendent vma */
|
||||
@@ -584,9 +585,12 @@ static int __bkeep_mprotect (void * addr, size_t length, int prot,
|
||||
/* no more vmas, protect the whole area */
|
||||
ret = __bkeep_mmap((void *) addr, length, prot,
|
||||
VMA_UNMAPPED|(flags ? *flags : 0),
|
||||
NULL, 0, "bkeep");
|
||||
NULL, 0, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
candidate = __lookup_vma((void *) addr, length);
|
||||
assert(candidate);
|
||||
}
|
||||
|
||||
length -= candidate->addr - addr;
|
||||
@@ -801,6 +805,73 @@ struct shim_vma * next_vma (struct shim_vma * vma)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
int dump_all_vmas (struct shim_thread * thread, char * buf, size_t size)
|
||||
{
|
||||
lock(vma_list_lock);
|
||||
|
||||
struct shim_vma * vma;
|
||||
int cnt = 0;
|
||||
|
||||
list_for_each_entry(vma, &vma_list, list) {
|
||||
void * start = vma->addr, * end = vma->addr + vma->length;
|
||||
|
||||
if ((vma->flags & (VMA_INTERNAL|VMA_UNMAPPED)) && !vma->comment[0])
|
||||
continue;
|
||||
|
||||
char prot[3] = {'-', '-', '-'};
|
||||
if (vma->prot & PROT_READ)
|
||||
prot[0] = 'r';
|
||||
if (vma->prot & PROT_WRITE)
|
||||
prot[1] = 'w';
|
||||
if (vma->prot & PROT_EXEC)
|
||||
prot[2] = 'x';
|
||||
|
||||
if (vma->file) {
|
||||
int dev_major = 0, dev_minor = 0;
|
||||
unsigned long ino = vma->file->dentry ? vma->file->dentry->ino : 0;
|
||||
const char * name = "[unknown]";
|
||||
|
||||
if (!qstrempty(&vma->file->path))
|
||||
name = qstrgetstr(&vma->file->path);
|
||||
|
||||
cnt += snprintf(buf + cnt, size - cnt,
|
||||
start > (void *) 0xffffffff ? "%lx" : "%08x", start);
|
||||
|
||||
cnt += snprintf(buf + cnt, size - cnt,
|
||||
end > (void *) 0xffffffff ? "-%lx" : "-%08x", end);
|
||||
|
||||
cnt += snprintf(buf + cnt, size - cnt,
|
||||
" %c%c%cp %08x %02d:%02d %u %s\n",
|
||||
prot[0], prot[1], prot[2],
|
||||
vma->offset, dev_major, dev_minor, ino,
|
||||
name);
|
||||
} else {
|
||||
cnt += snprintf(buf + cnt, size - cnt,
|
||||
start > (void *) 0xffffffff ? "%lx" : "%08x", start);
|
||||
|
||||
cnt += snprintf(buf + cnt, size - cnt,
|
||||
end > (void *) 0xffffffff ? "-%lx" : "-%08x", end);
|
||||
|
||||
if (vma->comment[0])
|
||||
cnt += snprintf(buf + cnt, size - cnt,
|
||||
" %c%c%cp 00000000 00:00 0 [%s]\n",
|
||||
prot[0], prot[1], prot[2], vma->comment[0]);
|
||||
else
|
||||
cnt += snprintf(buf + cnt, size - cnt,
|
||||
" %c%c%cp 00000000 00:00 0\n",
|
||||
prot[0], prot[1], prot[2]);
|
||||
}
|
||||
|
||||
if (cnt >= size) {
|
||||
cnt = -EOVERFLOW;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unlock(vma_list_lock);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
void unmap_all_vmas (void)
|
||||
{
|
||||
struct shim_thread * cur_thread = get_cur_thread();
|
||||
@@ -1085,12 +1156,10 @@ RESUME_FUNC_BODY(all_vmas)
|
||||
}
|
||||
END_RESUME_FUNC
|
||||
|
||||
void debug_print_vma_list ()
|
||||
void debug_print_vma_list (void)
|
||||
{
|
||||
sys_printf("vma bookkeeping:\n");
|
||||
|
||||
lock(vma_list_lock);
|
||||
|
||||
struct shim_vma * vma;
|
||||
list_for_each_entry(vma, &vma_list, list) {
|
||||
const char * type = "", * name = "";
|
||||
@@ -1116,8 +1185,6 @@ void debug_print_vma_list ()
|
||||
vma->comment[0] ? " comment=" : "",
|
||||
vma->comment[0] ? vma->comment : "");
|
||||
}
|
||||
|
||||
unlock(vma_list_lock);
|
||||
}
|
||||
|
||||
void print_vma_hash (struct shim_vma * vma, void * addr, int len,
|
||||
|
||||
@@ -339,23 +339,6 @@ void setup_elf_hash (struct link_map * map)
|
||||
map->l_chain = hash;
|
||||
}
|
||||
|
||||
static const char * __obj_type_str (int type, struct link_map * remap)
|
||||
{
|
||||
switch (type) {
|
||||
case OBJECT_INTERNAL:
|
||||
return "elf-internal";
|
||||
case OBJECT_LOAD:
|
||||
return "elf-load";
|
||||
case OBJECT_MAPPED:
|
||||
return "elf-mapped";
|
||||
case OBJECT_REMAP:
|
||||
return __obj_type_str(remap->l_type, NULL);
|
||||
case OBJECT_USER:
|
||||
return "elf-user";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Map in the shared object NAME, actually located in REALNAME, and already
|
||||
opened on FD */
|
||||
static struct link_map *
|
||||
@@ -376,7 +359,6 @@ __map_elf_object (struct shim_handle * file,
|
||||
if (file && (!read || !mmap || !seek))
|
||||
return NULL;
|
||||
|
||||
const char * obj_type = __obj_type_str(type, remap);
|
||||
struct link_map * l = remap ? :
|
||||
new_elf_object(file ? (!qstrempty(&file->path) ?
|
||||
qstrgetstr(&file->path) :
|
||||
@@ -404,6 +386,7 @@ call_lose:
|
||||
|
||||
/* Extract the remaining details we need from the ELF header
|
||||
and then read in the program header table. */
|
||||
l->l_addr = (ElfW(Addr)) addr;
|
||||
l->l_entry = header->e_entry;
|
||||
int e_type = header->e_type;
|
||||
l->l_phnum = header->e_phnum;
|
||||
@@ -438,7 +421,7 @@ call_lose:
|
||||
break;
|
||||
|
||||
case PT_INTERP:
|
||||
l->l_interp_libname = ((const char *) l->l_addr + ph->p_vaddr);
|
||||
l->l_interp_libname = (const char *) ph->p_vaddr;
|
||||
break;
|
||||
|
||||
case PT_PHDR:
|
||||
@@ -559,7 +542,7 @@ map_error:
|
||||
bkeep_mmap((void *) mappref, ALIGN_UP(maplength), c->prot,
|
||||
c->flags|MAP_PRIVATE|
|
||||
(type == OBJECT_INTERNAL ? VMA_INTERNAL : 0),
|
||||
file, c->mapoff, obj_type);
|
||||
file, c->mapoff, NULL);
|
||||
|
||||
l->l_addr = l->l_map_start - c->mapstart;
|
||||
|
||||
@@ -593,6 +576,7 @@ map_error:
|
||||
}
|
||||
|
||||
/* Remember which part of the address space this object uses. */
|
||||
l->l_addr = 0;
|
||||
l->l_map_start = c->mapstart;
|
||||
l->l_map_end = l->l_map_start + maplength;
|
||||
|
||||
@@ -615,7 +599,7 @@ do_remap:
|
||||
bkeep_mmap(mapaddr, c->mapend - c->mapstart, c->prot,
|
||||
c->flags|MAP_FIXED|MAP_PRIVATE|
|
||||
(type == OBJECT_INTERNAL ? VMA_INTERNAL : 0),
|
||||
file, c->mapoff, obj_type);
|
||||
file, c->mapoff, NULL);
|
||||
}
|
||||
|
||||
postmap:
|
||||
@@ -1143,12 +1127,12 @@ static int __load_elf_object (struct shim_handle * file, void * addr,
|
||||
add_link_map(map);
|
||||
}
|
||||
|
||||
if ((type == OBJECT_LOAD || type == OBJECT_REMAP) &&
|
||||
if ((type == OBJECT_LOAD || type == OBJECT_REMAP || type == OBJECT_USER) &&
|
||||
map->l_file && !qstrempty(&map->l_file->uri)) {
|
||||
if (type == OBJECT_REMAP)
|
||||
remove_r_debug((void *) map->l_addr);
|
||||
|
||||
append_r_debug(qstrgetstr(&map->l_file->uri), (void *) map->l_addr,
|
||||
append_r_debug(qstrgetstr(&map->l_file->uri), (void *) map->l_map_start,
|
||||
(void *) map->l_real_ld);
|
||||
}
|
||||
|
||||
@@ -1440,7 +1424,8 @@ int free_elf_interp (void)
|
||||
|
||||
static int __load_interp_object (struct link_map * exec_map)
|
||||
{
|
||||
const char * interp_name = exec_map->l_interp_libname;
|
||||
const char * interp_name = (const char *) exec_map->l_interp_libname +
|
||||
(long) exec_map->l_addr;
|
||||
int len = strlen(interp_name);
|
||||
const char * filename = interp_name + len - 1;
|
||||
while (filename > interp_name && *filename != '/')
|
||||
|
||||
@@ -595,7 +595,7 @@ static inline int __map_buffer (struct shim_handle * hdl, int size)
|
||||
return -PAL_ERRNO;
|
||||
|
||||
bkeep_mmap(mapbuf, maplen, prot, MAP_FILE|MAP_SHARED|VMA_INTERNAL,
|
||||
hdl, mapoff, "chroot-buffer");
|
||||
hdl, mapoff, NULL);
|
||||
|
||||
file->mapbuf = mapbuf;
|
||||
file->mapoffset = mapoff;
|
||||
@@ -706,14 +706,26 @@ static int chroot_read (struct shim_handle * hdl, void * buf,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (hdl->info.file.buf_type == FILEBUF_MAP) {
|
||||
struct shim_file_handle * file = &hdl->info.file;
|
||||
|
||||
if (file->buf_type == FILEBUF_MAP) {
|
||||
ret = map_read(hdl, buf, count);
|
||||
goto out;
|
||||
if (ret != -EACCES)
|
||||
goto out;
|
||||
|
||||
lock(hdl->lock);
|
||||
file->buf_type = FILEBUF_NONE;
|
||||
} else {
|
||||
lock(hdl->lock);
|
||||
}
|
||||
|
||||
ret = DkStreamRead(hdl->pal_handle, 0, count, buf, NULL, 0) ? :
|
||||
ret = DkStreamRead(hdl->pal_handle, file->marker, count, buf, NULL, 0) ? :
|
||||
(PAL_NATIVE_ERRNO == PAL_ERROR_ENDOFSTREAM ? 0 : -PAL_ERRNO);
|
||||
|
||||
if (ret > 0)
|
||||
file->marker += ret;
|
||||
|
||||
unlock(hdl->lock);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@@ -730,13 +742,26 @@ static int chroot_write (struct shim_handle * hdl, const void * buf,
|
||||
goto out;
|
||||
}
|
||||
|
||||
struct shim_file_handle * file = &hdl->info.file;
|
||||
|
||||
if (hdl->info.file.buf_type == FILEBUF_MAP) {
|
||||
ret = map_write(hdl, buf, count);
|
||||
if (ret != -EACCES)
|
||||
goto out;
|
||||
|
||||
lock(hdl->lock);
|
||||
file->buf_type = FILEBUF_NONE;
|
||||
} else {
|
||||
ret = DkStreamWrite(hdl->pal_handle, 0, count, buf, NULL) ? :
|
||||
-PAL_ERRNO;
|
||||
lock(hdl->lock);
|
||||
}
|
||||
|
||||
ret = DkStreamWrite(hdl->pal_handle, file->marker, count, buf, NULL) ? :
|
||||
-PAL_ERRNO;
|
||||
|
||||
if (ret > 0)
|
||||
file->marker += ret;
|
||||
|
||||
unlock(hdl->lock);
|
||||
out:
|
||||
return ret;
|
||||
|
||||
@@ -804,9 +829,7 @@ static int chroot_seek (struct shim_handle * hdl, off_t offset, int wence)
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
if (offset < 0)
|
||||
goto out;
|
||||
marker = size - offset;
|
||||
marker = size + offset;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,11 +11,14 @@
|
||||
#include <pal.h>
|
||||
#include <pal_error.h>
|
||||
|
||||
#include <asm/fcntl.h>
|
||||
#include <asm/mman.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/prctl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define DEFAULT_BUFFER_SIZE 256
|
||||
|
||||
static int parse_thread_name (const char * name,
|
||||
const char ** next, int * next_len,
|
||||
const char ** nextnext)
|
||||
@@ -461,6 +464,100 @@ static const struct proc_dir dir_fd = { .size = 1, .ent = { {
|
||||
.nm_ops = &nm_thread_each_fd, .fs_ops = &fs_thread_each_fd,
|
||||
}, }, };
|
||||
|
||||
static int proc_thread_maps_open (struct shim_handle * hdl,
|
||||
const char * name, int flags)
|
||||
{
|
||||
if (flags & (O_WRONLY|O_RDWR))
|
||||
return -EACCES;
|
||||
|
||||
const char * next;
|
||||
int next_len;
|
||||
int pid = parse_thread_name(name, &next, &next_len, NULL);
|
||||
|
||||
if (pid < 0)
|
||||
return pid;
|
||||
|
||||
struct shim_thread * thread = lookup_thread(pid);
|
||||
|
||||
if (!thread)
|
||||
return -ENOENT;
|
||||
|
||||
int size = DEFAULT_BUFFER_SIZE;
|
||||
char * strbuf = malloc(size);
|
||||
int ret = 0, len = 0;
|
||||
|
||||
if (!strbuf) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
retry:
|
||||
ret = dump_all_vmas(thread, strbuf, size);
|
||||
|
||||
if (ret == -EOVERFLOW) {
|
||||
char * newbuf = malloc(size * 2);
|
||||
if (!newbuf) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
free(strbuf);
|
||||
strbuf = newbuf;
|
||||
size *= 2;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
len = ret;
|
||||
|
||||
struct shim_str_data * data = malloc(sizeof(struct shim_str_data));
|
||||
if (!data) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
memset(data, 0, sizeof(struct shim_str_data));
|
||||
data->str = strbuf;
|
||||
data->len = len;
|
||||
hdl->type = TYPE_STR;
|
||||
hdl->flags = flags & ~O_RDONLY;
|
||||
hdl->acc_mode = MAY_READ;
|
||||
hdl->info.str.data = data;
|
||||
ret = 0;
|
||||
out:
|
||||
put_thread(thread);
|
||||
return ret;
|
||||
err:
|
||||
free(strbuf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int proc_thread_maps_mode (const char * name, mode_t * mode)
|
||||
{
|
||||
*mode = 0400;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int proc_thread_maps_stat (const char * name, struct stat * buf)
|
||||
{
|
||||
memset(buf, 0, sizeof(struct stat));
|
||||
|
||||
buf->st_dev = buf->st_ino = 1;
|
||||
buf->st_mode = 0400|S_IFREG;
|
||||
buf->st_uid = 0;
|
||||
buf->st_gid = 0;
|
||||
buf->st_size = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct proc_fs_ops fs_thread_maps = {
|
||||
.open = &proc_thread_maps_open,
|
||||
.mode = &proc_thread_maps_mode,
|
||||
.stat = &proc_thread_maps_stat,
|
||||
};
|
||||
|
||||
static int proc_thread_dir_mode (const char * name, mode_t * mode)
|
||||
{
|
||||
const char * next;
|
||||
@@ -570,4 +667,5 @@ const struct proc_dir dir_thread = { .size = 5, .ent = {
|
||||
{ .name = "exe", .fs_ops = &fs_thread_link, },
|
||||
{ .name = "root", .fs_ops = &fs_thread_link, },
|
||||
{ .name = "fd", .dir = &dir_fd, .fs_ops = &fs_thread_fd, },
|
||||
{ .name = "maps", .fs_ops = &fs_thread_maps, },
|
||||
}, };
|
||||
|
||||
@@ -639,7 +639,7 @@ IDTYPE CONCAT2(allocate, NS) (IDTYPE min, IDTYPE max)
|
||||
for ( ; j < BITS ; f <<= 1, j++)
|
||||
if (!(map & f)) {
|
||||
(*m) |= f;
|
||||
idx = base + i * RANGE_SIZE + j;
|
||||
idx = base + i * BITS + j;
|
||||
debug("allocated " NS_STR ": %u\n", idx);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
SHIM {
|
||||
global:
|
||||
syscalldb;
|
||||
__libc_r_debug; __libc_dl_debug_state;
|
||||
glibc_vers_2_17;
|
||||
register_library;
|
||||
syscalldb; register_library;
|
||||
glibc_vers_*;
|
||||
local: *;
|
||||
};
|
||||
|
||||
@@ -875,7 +875,7 @@ int init_checkpoint (struct newproc_cp_header * hdr, void ** cpptr)
|
||||
|
||||
bkeep_mmap(cpaddr, ALIGN_UP(cpsize), PROT_READ|PROT_WRITE,
|
||||
MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL,
|
||||
NULL, 0, "migrated");
|
||||
NULL, 0, NULL);
|
||||
|
||||
SAVE_PROFILE_INTERVAL(child_load_checkpoint_by_gipc);
|
||||
|
||||
@@ -897,7 +897,7 @@ int init_checkpoint (struct newproc_cp_header * hdr, void ** cpptr)
|
||||
|
||||
bkeep_mmap(cpaddr, cpsize_pgalign, PROT_READ|PROT_WRITE,
|
||||
MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL,
|
||||
NULL, 0, "migrated");
|
||||
NULL, 0, NULL);
|
||||
|
||||
cpaddr -= cpaddr_pgalign;
|
||||
|
||||
@@ -944,8 +944,8 @@ int init_checkpoint (struct newproc_cp_header * hdr, void ** cpptr)
|
||||
|
||||
void restore_context (struct shim_context * context)
|
||||
{
|
||||
int nregs = sizeof(struct shim_regs) / sizeof(unsigned long);
|
||||
unsigned long regs[nregs + 1];
|
||||
int nregs = sizeof(struct shim_regs) / sizeof(void *);
|
||||
void * regs[nregs + 1];
|
||||
|
||||
if (context->regs)
|
||||
memcpy(regs, context->regs, sizeof(struct shim_regs));
|
||||
@@ -954,7 +954,8 @@ void restore_context (struct shim_context * context)
|
||||
|
||||
debug("restore context: SP = %p, IP = %p\n", context->sp, context->ret_ip);
|
||||
|
||||
regs[nregs] = (unsigned long) context->sp;
|
||||
regs[nregs] = (void *) context->sp - 8;
|
||||
*(void **) (context->sp - 8) = context->ret_ip;
|
||||
|
||||
memset(context, 0, sizeof(struct shim_context));
|
||||
|
||||
@@ -962,13 +963,13 @@ void restore_context (struct shim_context * context)
|
||||
"popq %%r15\r\n"
|
||||
"popq %%r14\r\n"
|
||||
"popq %%r13\r\n"
|
||||
"popq %%r12\r\n"
|
||||
"popq %%r9\r\n"
|
||||
"popq %%r8\r\n"
|
||||
"popq %%rcx\r\n"
|
||||
"popq %%rdx\r\n"
|
||||
"popq %%rsi\r\n"
|
||||
"popq %%rdi\r\n"
|
||||
"popq %%r12\r\n"
|
||||
"popq %%rbx\r\n"
|
||||
"popq %%rbp\r\n"
|
||||
"popq %%rsp\r\n"
|
||||
|
||||
+13
-160
@@ -44,171 +44,44 @@ struct gdb_link_map
|
||||
struct gdb_link_map *l_next, *l_prev;
|
||||
};
|
||||
|
||||
struct gdb_r_debug
|
||||
{
|
||||
int r_version;
|
||||
struct gdb_link_map *r_map;
|
||||
uintptr_t r_brk;
|
||||
enum
|
||||
{
|
||||
RT_CONSISTENT,
|
||||
RT_ADD,
|
||||
RT_DELETE,
|
||||
} r_state;
|
||||
uintptr_t r_ldbase;
|
||||
};
|
||||
|
||||
struct gdb_r_debug __libc_r_debug;
|
||||
|
||||
extern struct gdb_r_debug _r_debug;
|
||||
extern void _dl_debug_state_trigger (void);
|
||||
|
||||
static struct gdb_link_map * link_map_list = NULL;
|
||||
|
||||
static inline char * translate_file_path (const char * path)
|
||||
{
|
||||
struct shim_dentry * dent = NULL;
|
||||
|
||||
int ret = path_lookupat(NULL, path, 0, &dent);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
|
||||
struct shim_mount * fs = dent->fs;
|
||||
|
||||
if (!fs->d_ops->open)
|
||||
return NULL;
|
||||
|
||||
char * new_uri = NULL;
|
||||
struct shim_handle * hdl = get_new_handle();
|
||||
if (!hdl)
|
||||
return NULL;
|
||||
|
||||
set_handle_fs(hdl, fs);
|
||||
hdl->dentry = dent;
|
||||
|
||||
ret = fs->d_ops->open(hdl, dent, O_RDONLY);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
new_uri = qstrtostr(&hdl->uri, false);
|
||||
out:
|
||||
put_handle(hdl);
|
||||
return new_uri;
|
||||
}
|
||||
|
||||
void __libc_dl_debug_state (void)
|
||||
{
|
||||
/* first make sure libc map list matches the shadow map list */
|
||||
if (link_map_list) {
|
||||
struct gdb_link_map *m = link_map_list, *n;
|
||||
for ( ; m ; m = m->l_next) {
|
||||
for (n = __libc_r_debug.r_map ; n ; n = n->l_next)
|
||||
if (m->l_addr == n->l_addr)
|
||||
break;
|
||||
if (!n) {
|
||||
if (m->l_prev)
|
||||
m->l_prev->l_next = m->l_next;
|
||||
if (m->l_next)
|
||||
m->l_next->l_prev = m->l_prev;
|
||||
if (m == link_map_list)
|
||||
link_map_list = m->l_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* now find the end of the shadow map list, where we are adding to */
|
||||
struct gdb_link_map *prev = NULL;
|
||||
struct gdb_link_map **tail = &_r_debug.r_map;
|
||||
|
||||
while (*tail) {
|
||||
prev = *tail;
|
||||
tail = &(*tail)->l_next;
|
||||
}
|
||||
|
||||
/* add new maps to the shadow map list */
|
||||
struct gdb_link_map **t = tail;
|
||||
struct gdb_link_map *m = __libc_r_debug.r_map;
|
||||
|
||||
for ( ; m ; m = m->l_next) {
|
||||
struct gdb_link_map *re = _r_debug.r_map;
|
||||
while (re && re->l_addr != m->l_addr)
|
||||
re = re->l_next;
|
||||
|
||||
if (re)
|
||||
continue;
|
||||
|
||||
char * uri = translate_file_path(m->l_name);
|
||||
if (!uri)
|
||||
continue;
|
||||
debug("add a library for gdb: %s\n", uri);
|
||||
|
||||
struct gdb_link_map * new = malloc(sizeof(struct gdb_link_map));
|
||||
|
||||
new->l_addr = m->l_addr;
|
||||
new->l_ld = m->l_ld;
|
||||
new->l_name = uri;
|
||||
new->l_prev = prev;
|
||||
prev = *t = new;
|
||||
new->l_next = NULL;
|
||||
t = &new->l_next;
|
||||
}
|
||||
|
||||
if (!link_map_list)
|
||||
link_map_list = *tail;
|
||||
|
||||
_r_debug.r_state = __libc_r_debug.r_state;
|
||||
_dl_debug_state_trigger();
|
||||
}
|
||||
|
||||
void clean_link_map_list (void)
|
||||
{
|
||||
if (!link_map_list)
|
||||
return;
|
||||
|
||||
_r_debug.r_state = RT_DELETE;
|
||||
_dl_debug_state_trigger();
|
||||
|
||||
if (link_map_list->l_prev)
|
||||
link_map_list->l_prev->l_next = NULL;
|
||||
if (_r_debug.r_map == link_map_list)
|
||||
_r_debug.r_map = NULL;
|
||||
|
||||
struct gdb_link_map * m = link_map_list;
|
||||
for ( ; m ; m = m->l_next)
|
||||
for ( ; m ; m = m->l_next) {
|
||||
DkDebugDetachBinary(m->l_addr);
|
||||
free(m);
|
||||
}
|
||||
|
||||
link_map_list = NULL;
|
||||
|
||||
_r_debug.r_state = RT_CONSISTENT;
|
||||
_dl_debug_state_trigger();
|
||||
|
||||
}
|
||||
|
||||
void remove_r_debug (void * addr)
|
||||
{
|
||||
struct gdb_link_map * m = _r_debug.r_map;
|
||||
struct gdb_link_map * m = link_map_list;
|
||||
|
||||
for ( ; m && m != link_map_list ; m = m->l_next)
|
||||
for ( ; m ; m = m->l_next)
|
||||
if (m->l_addr == addr)
|
||||
break;
|
||||
|
||||
if (!m || m == link_map_list)
|
||||
if (!m)
|
||||
return;
|
||||
|
||||
_r_debug.r_state = RT_DELETE;
|
||||
_dl_debug_state_trigger();
|
||||
|
||||
debug("remove a library for gdb: %s\n", m->l_name);
|
||||
|
||||
if (m->l_prev)
|
||||
m->l_prev->l_next = m->l_next;
|
||||
if (m->l_next)
|
||||
m->l_next->l_prev = m->l_prev;
|
||||
if (_r_debug.r_map == m)
|
||||
_r_debug.r_map = m->l_next;
|
||||
|
||||
_r_debug.r_state = RT_CONSISTENT;
|
||||
_dl_debug_state_trigger();
|
||||
DkDebugDetachBinary(addr);
|
||||
}
|
||||
|
||||
void append_r_debug (const char * uri, void * addr, void * dyn_addr)
|
||||
@@ -224,26 +97,20 @@ void append_r_debug (const char * uri, void * addr, void * dyn_addr)
|
||||
new->l_name = new_uri;
|
||||
|
||||
struct gdb_link_map *prev = NULL;
|
||||
struct gdb_link_map **tail = &_r_debug.r_map;
|
||||
struct gdb_link_map **tail = &link_map_list;
|
||||
|
||||
while (*tail && *tail != link_map_list) {
|
||||
while (*tail) {
|
||||
prev = *tail;
|
||||
tail = &(*tail)->l_next;
|
||||
}
|
||||
|
||||
_r_debug.r_state = RT_ADD;
|
||||
_dl_debug_state_trigger();
|
||||
|
||||
debug("add a library for gdb: %s\n", new->l_name);
|
||||
debug("add a library for gdb: %s\n", uri);
|
||||
|
||||
new->l_prev = prev;
|
||||
new->l_next = link_map_list;
|
||||
new->l_next = NULL;
|
||||
*tail = new;
|
||||
if (link_map_list)
|
||||
link_map_list->l_prev = new;
|
||||
|
||||
_r_debug.r_state = RT_CONSISTENT;
|
||||
_dl_debug_state_trigger();
|
||||
DkDebugAttachBinary(uri, addr);
|
||||
}
|
||||
|
||||
DEFINE_MIGRATE_FUNC(gdb_map)
|
||||
@@ -278,10 +145,6 @@ END_MIGRATE_FUNC
|
||||
RESUME_FUNC_BODY(gdb_map)
|
||||
{
|
||||
uint64_t off = GET_FUNC_ENTRY();
|
||||
|
||||
_r_debug.r_state = RT_ADD;
|
||||
_dl_debug_state_trigger ();
|
||||
|
||||
struct gdb_link_map *map = (struct gdb_link_map *) (base + off);
|
||||
|
||||
RESUME_REBASE(map->l_name);
|
||||
@@ -299,20 +162,10 @@ RESUME_FUNC_BODY(gdb_map)
|
||||
map->l_prev = prev;
|
||||
*tail = map;
|
||||
|
||||
tail = &_r_debug.r_map;
|
||||
while (*tail && *tail != link_map_list) {
|
||||
prev = *tail;
|
||||
tail = &(*tail)->l_next;
|
||||
}
|
||||
|
||||
*tail = link_map_list;
|
||||
link_map_list->l_prev = prev;
|
||||
|
||||
#ifdef DEBUG_RESUME
|
||||
debug("gdb: %s loaded at %p\n", map->l_name, map->l_addr);
|
||||
#endif
|
||||
|
||||
_r_debug.r_state = RT_CONSISTENT;
|
||||
_dl_debug_state_trigger ();
|
||||
DkDebugAttachBinary(map->l_name, map->l_addr);
|
||||
}
|
||||
END_RESUME_FUNC
|
||||
|
||||
@@ -148,6 +148,9 @@ void allocate_tls (void * tcb_location, struct shim_thread * thread)
|
||||
thread->tcb = tcb;
|
||||
tcb->shim_tcb.tp = thread;
|
||||
tcb->shim_tcb.tid = thread->tid;
|
||||
} else {
|
||||
tcb->shim_tcb.tp = NULL;
|
||||
tcb->shim_tcb.tid = 0;
|
||||
}
|
||||
|
||||
DkThreadPrivate(tcb);
|
||||
@@ -210,7 +213,7 @@ void * allocate_stack (size_t size, size_t protect_size, bool user)
|
||||
|
||||
if (protect_size &&
|
||||
bkeep_mmap(stack - protect_size, protect_size, 0,
|
||||
STACK_FLAGS, NULL, 0, "stack-red") < 0)
|
||||
STACK_FLAGS, NULL, 0, NULL) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -394,7 +397,8 @@ int init_manifest (PAL_HANDLE manifest_handle)
|
||||
|
||||
size_t cfg_size = attr.size;
|
||||
void * cfg_addr = DkStreamMap(manifest_handle, NULL,
|
||||
PAL_PROT_READ, 0, ALIGN_UP(cfg_size));
|
||||
PAL_PROT_READ|PAL_PROT_WRITECOPY, 0,
|
||||
ALIGN_UP(cfg_size));
|
||||
|
||||
if (!cfg_addr)
|
||||
return -PAL_ERRNO;
|
||||
@@ -583,6 +587,7 @@ int shim_init (int argc, void * args, void ** return_stack)
|
||||
|
||||
/* create the initial TCB, shim can not be run without a tcb */
|
||||
__libc_tcb_t tcb;
|
||||
memset(&tcb, 0, sizeof(__libc_tcb_t));
|
||||
allocate_tls(&tcb, NULL);
|
||||
debug_setbuf(&tcb.shim_tcb, true);
|
||||
|
||||
@@ -920,6 +925,23 @@ int create_handle (const char * prefix, char * uri, size_t size,
|
||||
id ? : &suffix, hdl, NULL);
|
||||
}
|
||||
|
||||
void check_stack_hook (void)
|
||||
{
|
||||
struct shim_thread * cur_thread = get_cur_thread();
|
||||
|
||||
void * rsp;
|
||||
asm volatile ("movq %%rsp, %0" : "=r"(rsp) :: "memory");
|
||||
|
||||
if (rsp <= cur_thread->stack_top && rsp > cur_thread->stack) {
|
||||
if (rsp - cur_thread->stack < PAL_CB(pagesize))
|
||||
sys_printf("*** stack is almost drained (RSP = %p, stack = %p-%p) ***\n",
|
||||
rsp, cur_thread->stack, cur_thread->stack_top);
|
||||
} else {
|
||||
sys_printf("*** context dismateched with thread stack (RSP = %p, stack = %p-%p) ***\n",
|
||||
rsp, cur_thread->stack, cur_thread->stack_top);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PROFILE
|
||||
static void print_profile_result (PAL_HANDLE hdl, struct shim_profile * root,
|
||||
int level)
|
||||
|
||||
@@ -111,9 +111,7 @@ static struct shim_heap * __alloc_enough_heap (size_t size)
|
||||
|
||||
unlock(shim_heap_lock);
|
||||
bkeep_mmap(start, heap_size, PROT_READ|PROT_WRITE,
|
||||
MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL, NULL, 0,
|
||||
"shim-heap");
|
||||
|
||||
MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL, NULL, 0, NULL);
|
||||
lock(shim_heap_lock);
|
||||
}
|
||||
|
||||
@@ -175,8 +173,7 @@ int bkeep_shim_heap (void)
|
||||
bkeep_mmap(shim_heap_areas[i].start,
|
||||
shim_heap_areas[i].end - shim_heap_areas[i].start,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL, NULL, 0,
|
||||
"shim-heap");
|
||||
MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL, NULL, 0, NULL);
|
||||
|
||||
unlock(shim_heap_lock);
|
||||
return 0;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <asm/prctl.h>
|
||||
#include <asm/mman.h>
|
||||
#include <asm/ioctls.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/futex.h>
|
||||
#include <linux/wait.h>
|
||||
#include <errno.h>
|
||||
@@ -45,6 +46,7 @@
|
||||
static void parse_open_flags (const char *, va_list);
|
||||
static void parse_open_mode (const char *, va_list);
|
||||
static void parse_access_mode (const char *, va_list);
|
||||
static void parse_clone_flags (const char *, va_list);
|
||||
static void parse_mmap_prot (const char *, va_list);
|
||||
static void parse_mmap_flags (const char *, va_list);
|
||||
static void parse_exec_args (const char *, va_list);
|
||||
@@ -130,7 +132,7 @@ struct parser_table {
|
||||
.parser = { NULL, NULL, NULL, &parse_pipe_fds } },
|
||||
{ .slow = 0, .parser = { NULL } }, /* setsockopt */
|
||||
{ .slow = 0, .parser = { NULL } }, /* getsockopt */
|
||||
{ .slow = 1, .parser = { NULL } }, /* clone */
|
||||
{ .slow = 1, .parser = { &parse_clone_flags } }, /* clone */
|
||||
{ .slow = 1, .parser = { NULL } }, /* fork */
|
||||
{ .slow = 1, .parser = { NULL } }, /* vfork */
|
||||
{ .slow = 1, /* execve */
|
||||
@@ -612,6 +614,37 @@ static void parse_access_mode (const char * type, va_list ap)
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_clone_flags (const char * type, va_list ap)
|
||||
{
|
||||
int flags = va_arg (ap, int);
|
||||
|
||||
#define FLG(n) { "CLONE_" #n, CLONE_##n, }
|
||||
const struct {
|
||||
const char * name; int flag;
|
||||
} all_flags[] = {
|
||||
FLG(VM), FLG(FS), FLG(FILES), FLG(SIGHAND), FLG(PTRACE), FLG(VFORK),
|
||||
FLG(PARENT), FLG(THREAD), FLG(NEWNS), FLG(SYSVSEM), FLG(SETTLS),
|
||||
FLG(PARENT_SETTID), FLG(CHILD_CLEARTID), FLG(DETACHED), FLG(UNTRACED),
|
||||
FLG(CHILD_SETTID), FLG(NEWUTS), FLG(NEWIPC), FLG(NEWUSER),
|
||||
FLG(NEWPID), FLG(NEWNET), FLG(IO),
|
||||
};
|
||||
#undef FLG
|
||||
|
||||
bool printed = false;
|
||||
for (int i = 0 ; i < sizeof(all_flags) / sizeof(all_flags[0]) ; i++)
|
||||
if (flags & all_flags[i].flag) {
|
||||
if (printed)
|
||||
PUTCH('|');
|
||||
else
|
||||
printed = true;
|
||||
PUTS(all_flags[i].name);
|
||||
flags &= ~all_flags[i].flag;
|
||||
}
|
||||
|
||||
if (flags)
|
||||
PRINTF("|0x%x", flags);
|
||||
}
|
||||
|
||||
static void parse_mmap_prot (const char * type, va_list ap)
|
||||
{
|
||||
int prot = va_arg (ap, int);
|
||||
@@ -650,23 +683,36 @@ static void parse_mmap_flags (const char * type, va_list ap)
|
||||
PUTS("MAP_SHARED");
|
||||
flags &= ~MAP_SHARED;
|
||||
}
|
||||
else
|
||||
|
||||
if (flags & MAP_PRIVATE) {
|
||||
PUTS("MAP_PRIVATE");
|
||||
flags &= ~MAP_PRIVATE;
|
||||
}
|
||||
|
||||
if (flags & MAP_ANONYMOUS) {
|
||||
PUTS("|MAP_ANON");
|
||||
flags &= ~MAP_ANONYMOUS;
|
||||
}
|
||||
else
|
||||
|
||||
if (flags & MAP_FILE) {
|
||||
PUTS("|MAP_FILE");
|
||||
flags &= ~MAP_FILE;
|
||||
}
|
||||
|
||||
if (flags & MAP_FIXED) {
|
||||
PUTS("|MAP_FIXED");
|
||||
flags &= ~MAP_FIXED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
|
||||
if (flags & MAP_UNINITIALIZED) {
|
||||
PUTS("|MAP_UNINITIALIZED");
|
||||
flags &= ~MAP_UNINITIALIZED;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (flags)
|
||||
PRINTF("|%o", flags);
|
||||
PRINTF("|0x%x", flags);
|
||||
}
|
||||
|
||||
static void parse_exec_args (const char * type, va_list ap)
|
||||
@@ -884,7 +930,7 @@ static void parse_futexop (const char * type, va_list ap)
|
||||
PUTS("FUTEX_CMP_REQUEUE");
|
||||
break;
|
||||
case FUTEX_WAKE_OP:
|
||||
PUTS("FUTEX_WAKE");
|
||||
PUTS("FUTEX_WAKE_OP");
|
||||
break;
|
||||
default:
|
||||
PRINTF("OP %d", op);
|
||||
|
||||
@@ -50,6 +50,15 @@ DEFINE_PROFILE_OCCURENCE(brk, memory);
|
||||
DEFINE_PROFILE_OCCURENCE(brk_count, memory);
|
||||
DEFINE_PROFILE_OCCURENCE(brk_migrate_count, memory);
|
||||
|
||||
void get_brk_region (void ** start, void ** end, void ** current)
|
||||
{
|
||||
master_lock();
|
||||
*start = region.brk_start;
|
||||
*end = region.brk_end;
|
||||
*current = region.brk_current;
|
||||
master_unlock();
|
||||
}
|
||||
|
||||
int init_brk_region (void)
|
||||
{
|
||||
if (region.brk_start)
|
||||
@@ -88,11 +97,11 @@ int init_brk_region (void)
|
||||
brk_region + brk_max_size);
|
||||
|
||||
bkeep_mmap(brk_region, BRK_SIZE, PROT_READ|PROT_WRITE,
|
||||
MAP_ANONYMOUS|MAP_PRIVATE, NULL, 0, "brk");
|
||||
MAP_ANONYMOUS|MAP_PRIVATE, NULL, 0, "[heap]");
|
||||
bkeep_mmap(end_brk_region, brk_max_size - BRK_SIZE,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_ANONYMOUS|MAP_PRIVATE|VMA_UNMAPPED,
|
||||
NULL, 0, "brk-reserved");
|
||||
NULL, 0, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -148,7 +157,7 @@ unchanged:
|
||||
|
||||
bkeep_mmap(region.brk_start, brk_end - region.brk_start,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_ANONYMOUS|MAP_PRIVATE, NULL, 0, "brk");
|
||||
MAP_ANONYMOUS|MAP_PRIVATE, NULL, 0, "heap");
|
||||
|
||||
region.brk_current = brk;
|
||||
region.brk_end = brk_end;
|
||||
@@ -203,7 +212,7 @@ RESUME_FUNC_BODY(brk)
|
||||
bkeep_mmap(region.brk_end, brk_max_size - brk_size,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_ANONYMOUS|MAP_PRIVATE|VMA_UNMAPPED, NULL, 0,
|
||||
"brk-reserved");
|
||||
NULL);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_RESUME
|
||||
|
||||
+148
-71
@@ -29,6 +29,7 @@
|
||||
#include <shim_table.h>
|
||||
#include <shim_thread.h>
|
||||
#include <shim_utils.h>
|
||||
#include <shim_checkpoint.h>
|
||||
#include <shim_profile.h>
|
||||
|
||||
#include <pal.h>
|
||||
@@ -40,6 +41,14 @@
|
||||
#include <linux/sched.h>
|
||||
#include <asm/prctl.h>
|
||||
|
||||
struct clone_args {
|
||||
PAL_HANDLE create_event;
|
||||
PAL_HANDLE initialize_event;
|
||||
struct shim_thread * thread, * parent;
|
||||
void * stack;
|
||||
void * return_pc;
|
||||
};
|
||||
|
||||
/* from **sysdeps/unix/sysv/linux/x86_64/clone.S:
|
||||
The userland implementation is:
|
||||
int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg),
|
||||
@@ -96,10 +105,17 @@ int clone_implementation_wrapper(struct clone_args * arg)
|
||||
assert(my_thread);
|
||||
get_thread(my_thread);
|
||||
|
||||
if (my_thread->set_child_tid) {
|
||||
if (!my_thread->tcb)
|
||||
my_thread->tcb = __alloca(sizeof(__libc_tcb_t));
|
||||
allocate_tls(my_thread->tcb, my_thread);
|
||||
shim_tcb_t * tcb = &((__libc_tcb_t *) my_thread->tcb)->shim_tcb;
|
||||
debug_setbuf(tcb, true);
|
||||
|
||||
struct shim_regs * regs = __alloca(sizeof(struct shim_regs));
|
||||
*regs = *((__libc_tcb_t *) arg->parent->tcb)->shim_tcb.context.regs;
|
||||
|
||||
if (my_thread->set_child_tid)
|
||||
*(my_thread->set_child_tid) = my_thread->tid;
|
||||
debug("clone: tid set at %p\n", my_thread->set_child_tid);
|
||||
}
|
||||
|
||||
void * stack = pcargs->stack;
|
||||
void * return_pc = pcargs->return_pc;
|
||||
@@ -107,12 +123,9 @@ int clone_implementation_wrapper(struct clone_args * arg)
|
||||
struct shim_vma * vma = NULL;
|
||||
lookup_supervma(ALIGN_DOWN(stack), allocsize, &vma);
|
||||
assert(vma);
|
||||
my_thread->stack_top = stack;
|
||||
my_thread->stack_top = vma->addr + vma->length;
|
||||
my_thread->stack_red = my_thread->stack = vma->addr;
|
||||
|
||||
__libc_tcb_t tcb;
|
||||
allocate_tls(&tcb, my_thread);
|
||||
debug_setbuf(&tcb.shim_tcb, true);
|
||||
snprintf(vma->comment, VMA_COMMENT_LEN, "stack:%d", my_thread->tid);
|
||||
|
||||
/* Don't signal the initialize event until we are actually init-ed */
|
||||
DkEventSet(pcargs->initialize_event);
|
||||
@@ -125,13 +138,18 @@ int clone_implementation_wrapper(struct clone_args * arg)
|
||||
debug("child swapping stack to %p return %p: %d\n",
|
||||
stack, return_pc, my_thread->tid);
|
||||
|
||||
asm volatile("movq %0, %%rsp\r\n"
|
||||
"pushq %1\r\n"
|
||||
"retq\r\n"
|
||||
: : "r"(stack), "r"(return_pc), "a"(0));
|
||||
tcb->context.regs = regs;
|
||||
tcb->context.sp = stack;
|
||||
tcb->context.ret_ip = return_pc;
|
||||
|
||||
restore_context(&tcb->context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int migrate_fork (struct shim_cp_store * cpstore,
|
||||
struct shim_process * process,
|
||||
struct shim_thread * thread, va_list ap);
|
||||
|
||||
/* long int __arg0 - flags
|
||||
* long int __arg1 - 16 bytes ( 2 words ) offset into the child stack allocated
|
||||
* by the parent */
|
||||
@@ -144,8 +162,7 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr,
|
||||
INC_PROFILE_OCCURENCE(syscall_use_ipc);
|
||||
struct shim_thread * self = get_cur_thread();
|
||||
assert(self);
|
||||
struct clone_args * new_args = __alloca(sizeof(struct clone_args));
|
||||
memset(new_args, 0, sizeof(struct clone_args));
|
||||
int * set_parent_tid = NULL;
|
||||
int ret = 0;
|
||||
|
||||
assert((flags & ~(CLONE_PARENT_SETTID|CLONE_CHILD_SETTID|
|
||||
@@ -158,67 +175,58 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr,
|
||||
#endif
|
||||
CLONE_SYSVSEM|CSIGNAL)) == 0);
|
||||
|
||||
new_args->create_event = DkNotificationEventCreate(0);
|
||||
if (!new_args->create_event) {
|
||||
ret = -PAL_ERRNO;
|
||||
goto failed;
|
||||
if (!(flags & CLONE_FS))
|
||||
debug("clone without CLONE_FS is not yet implemented\n");
|
||||
|
||||
if (!(flags & CLONE_SIGHAND))
|
||||
debug("clone without CLONE_SIGHAND is not yet implemented\n");
|
||||
|
||||
if (!(flags & CLONE_SYSVSEM))
|
||||
debug("clone without CLONE_SYSVSEM is not yet implemented\n");
|
||||
|
||||
if (flags & CLONE_PARENT_SETTID) {
|
||||
if (!parent_tidptr)
|
||||
return -EINVAL;
|
||||
set_parent_tid = parent_tidptr;
|
||||
}
|
||||
|
||||
new_args->initialize_event = DkNotificationEventCreate(0);
|
||||
if (!new_args->initialize_event) {
|
||||
ret = -PAL_ERRNO;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
new_args->thread = get_new_thread(0);
|
||||
if (!new_args->thread) {
|
||||
struct shim_thread * thread = get_new_thread(0);
|
||||
if (!thread) {
|
||||
ret = -ENOMEM;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
new_args->stack = user_stack_addr;
|
||||
new_args->return_pc = *(void **) user_stack_addr;
|
||||
IDTYPE tid = thread->tid;
|
||||
|
||||
if (flags & CLONE_PARENT_SETTID)
|
||||
new_args->thread->set_child_tid = parent_tidptr;
|
||||
|
||||
if ((flags & CLONE_CHILD_SETTID) && (flags & CLONE_CHILD_CLEARTID)) {
|
||||
ret = -EINVAL;
|
||||
goto failed;
|
||||
if (flags & CLONE_CHILD_SETTID) {
|
||||
if (!child_tidptr) {
|
||||
ret = -EINVAL;
|
||||
goto failed;
|
||||
}
|
||||
thread->set_child_tid = child_tidptr;
|
||||
}
|
||||
|
||||
if (flags & CLONE_CHILD_SETTID)
|
||||
new_args->thread->set_child_tid = child_tidptr;
|
||||
|
||||
if (flags & CLONE_CHILD_CLEARTID)
|
||||
/* Implemented in shim_futex.c: release_clear_child_id */
|
||||
new_args->thread->clear_child_tid = parent_tidptr;
|
||||
thread->clear_child_tid = parent_tidptr;
|
||||
|
||||
if (flags & CLONE_SETTLS) {
|
||||
new_args->thread->tcb = tls;
|
||||
if (!tls) {
|
||||
ret = -EINVAL;
|
||||
goto failed;
|
||||
}
|
||||
thread->tcb = tls;
|
||||
} else {
|
||||
new_args->thread->tcb = NULL;
|
||||
thread->tcb = NULL;
|
||||
}
|
||||
|
||||
if ((flags & CLONE_VM) != CLONE_VM)
|
||||
debug("Fork-like behavior is not yet implemented in clone\n");
|
||||
|
||||
if ((flags & CLONE_FS) != CLONE_FS)
|
||||
debug("clone without CLONE_FS is not yet implemented\n");
|
||||
|
||||
if ((flags & CLONE_SIGHAND) != CLONE_SIGHAND)
|
||||
debug("clone without CLONE_SIGHAND is not yet implemented\n");
|
||||
|
||||
if ((flags & CLONE_SYSVSEM) != CLONE_SYSVSEM)
|
||||
debug("clone without CLONE_SYSVSEM is not yet implemented\n");
|
||||
|
||||
if ((flags & CLONE_THREAD) != CLONE_THREAD)
|
||||
new_args->thread->tgid = new_args->thread->tid;
|
||||
if (!(flags & CLONE_THREAD))
|
||||
thread->tgid = thread->tid;
|
||||
|
||||
struct shim_handle_map * handle_map = get_cur_handle_map(self);
|
||||
|
||||
if (flags & CLONE_FILES) {
|
||||
set_handle_map(new_args->thread, handle_map);
|
||||
set_handle_map(thread, handle_map);
|
||||
} else {
|
||||
/* if CLONE_FILES is not given, the new thread should receive
|
||||
a copy of current descriptor table */
|
||||
@@ -226,10 +234,81 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr,
|
||||
|
||||
get_handle_map(handle_map);
|
||||
dup_handle_map(&new_map, handle_map);
|
||||
set_handle_map(new_args->thread, new_map);
|
||||
set_handle_map(thread, new_map);
|
||||
put_handle_map(handle_map);
|
||||
}
|
||||
|
||||
if (!(flags & CLONE_VM)) {
|
||||
__libc_tcb_t * tcb;
|
||||
shim_tcb_t * old_shim_tcb = NULL;
|
||||
|
||||
if (thread->tcb) {
|
||||
tcb = (__libc_tcb_t *) thread->tcb;
|
||||
} else {
|
||||
thread->tcb = tcb = (__libc_tcb_t *) self->tcb;
|
||||
old_shim_tcb = __alloca(sizeof(shim_tcb_t));
|
||||
memcpy(old_shim_tcb, &tcb->shim_tcb, sizeof(shim_tcb_t));
|
||||
}
|
||||
|
||||
if (user_stack_addr) {
|
||||
struct shim_vma * vma = NULL;
|
||||
lookup_supervma(ALIGN_DOWN(user_stack_addr), allocsize, &vma);
|
||||
assert(vma);
|
||||
thread->stack_top = vma->addr + vma->length;
|
||||
thread->stack_red = thread->stack = vma->addr;
|
||||
tcb->shim_tcb.context.sp = user_stack_addr;
|
||||
tcb->shim_tcb.context.ret_ip = *(void **) user_stack_addr;
|
||||
} else {
|
||||
tcb->shim_tcb.context.ret_ip = *(void **) tcb->shim_tcb.context.sp;
|
||||
}
|
||||
|
||||
thread->is_alive = true;
|
||||
thread->in_vm = false;
|
||||
add_thread(thread);
|
||||
set_as_child(self, thread);
|
||||
|
||||
if ((ret = do_migrate_process(&migrate_fork, NULL, NULL, thread)) < 0)
|
||||
goto failed;
|
||||
|
||||
if (old_shim_tcb)
|
||||
memcpy(&tcb->shim_tcb, old_shim_tcb, sizeof(shim_tcb_t));
|
||||
|
||||
lock(thread->lock);
|
||||
handle_map = thread->handle_map;
|
||||
thread->handle_map = NULL;
|
||||
unlock(thread->lock);
|
||||
if (handle_map)
|
||||
put_handle_map(handle_map);
|
||||
|
||||
if (set_parent_tid)
|
||||
*set_parent_tid = tid;
|
||||
|
||||
put_thread(thread);
|
||||
return tid;
|
||||
}
|
||||
|
||||
enable_locking();
|
||||
|
||||
struct clone_args * new_args = __alloca(sizeof(struct clone_args));
|
||||
memset(new_args, 0, sizeof(struct clone_args));
|
||||
|
||||
new_args->create_event = DkNotificationEventCreate(0);
|
||||
if (!new_args->create_event) {
|
||||
ret = -PAL_ERRNO;
|
||||
goto clone_thread_failed;
|
||||
}
|
||||
|
||||
new_args->initialize_event = DkNotificationEventCreate(0);
|
||||
if (!new_args->initialize_event) {
|
||||
ret = -PAL_ERRNO;
|
||||
goto clone_thread_failed;
|
||||
}
|
||||
|
||||
new_args->thread = thread;
|
||||
new_args->parent = self;
|
||||
new_args->stack = user_stack_addr;
|
||||
new_args->return_pc = *(void **) user_stack_addr;
|
||||
|
||||
// Invoke DkThreadCreate to spawn off a child process using the actual
|
||||
// "clone" system call. DkThreadCreate allocates a stack for the child
|
||||
// and then runs the given function on that stack However, we want our
|
||||
@@ -240,32 +319,30 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr,
|
||||
new_args, flags);
|
||||
if (!pal_handle) {
|
||||
ret = -PAL_ERRNO;
|
||||
goto failed;
|
||||
goto clone_thread_failed;
|
||||
}
|
||||
|
||||
new_args->thread->pal_handle = pal_handle;
|
||||
thread->pal_handle = pal_handle;
|
||||
thread->in_vm = thread->is_alive = true;
|
||||
add_thread(thread);
|
||||
set_as_child(self, thread);
|
||||
|
||||
new_args->thread->in_vm = new_args->thread->is_alive = true;
|
||||
add_thread(new_args->thread);
|
||||
set_as_child(NULL, new_args->thread);
|
||||
put_thread(new_args->thread);
|
||||
|
||||
if (new_args->thread->set_child_tid)
|
||||
*new_args->thread->set_child_tid = new_args->thread->tid;
|
||||
if (set_parent_tid)
|
||||
*set_parent_tid = tid;
|
||||
|
||||
DkEventSet(new_args->create_event);
|
||||
|
||||
DkObjectsWaitAny(1, &new_args->initialize_event, NO_TIMEOUT);
|
||||
DkObjectClose(new_args->initialize_event);
|
||||
put_thread(thread);
|
||||
return tid;
|
||||
|
||||
return new_args->thread->tid;
|
||||
|
||||
failed:
|
||||
clone_thread_failed:
|
||||
if (new_args->create_event)
|
||||
DkObjectClose(new_args->create_event);
|
||||
if (new_args->initialize_event)
|
||||
DkObjectClose(new_args->initialize_event);
|
||||
if (new_args->thread)
|
||||
put_thread(new_args->thread);
|
||||
failed:
|
||||
if (thread)
|
||||
put_thread(thread);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -154,8 +154,7 @@ static void * __malloc (size_t size)
|
||||
addr = DkVirtualMemoryAlloc(addr, size, 0, PAL_PROT_READ|PAL_PROT_WRITE);
|
||||
|
||||
if (addr)
|
||||
bkeep_mmap(addr, size, PROT_READ|PROT_WRITE, flags, NULL, 0,
|
||||
"checkpoint");
|
||||
bkeep_mmap(addr, size, PROT_READ|PROT_WRITE, flags, NULL, 0, NULL);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -47,8 +47,7 @@ static void * __malloc (size_t size)
|
||||
addr = DkVirtualMemoryAlloc(addr, size, 0, PAL_PROT_READ|PAL_PROT_WRITE);
|
||||
|
||||
if (addr)
|
||||
bkeep_mmap(addr, size, PROT_READ|PROT_WRITE, flags, NULL, 0,
|
||||
"checkpoint");
|
||||
bkeep_mmap(addr, size, PROT_READ|PROT_WRITE, flags, NULL, 0, NULL);
|
||||
|
||||
return addr;
|
||||
}
|
||||
@@ -56,9 +55,9 @@ static void * __malloc (size_t size)
|
||||
#define malloc_method __malloc
|
||||
#include <shim_checkpoint.h>
|
||||
|
||||
static int migrate_fork (struct shim_cp_store * cpstore,
|
||||
struct shim_process * process,
|
||||
struct shim_thread * thread, va_list ap)
|
||||
int migrate_fork (struct shim_cp_store * cpstore,
|
||||
struct shim_process * process,
|
||||
struct shim_thread * thread, va_list ap)
|
||||
{
|
||||
BEGIN_MIGRATION_DEF(fork, struct shim_process * proc,
|
||||
struct shim_thread * thread)
|
||||
@@ -104,7 +103,6 @@ int shim_do_fork (void)
|
||||
if (!new_thread)
|
||||
return -ENOMEM;
|
||||
|
||||
new_thread->stack = cur_thread->stack;
|
||||
new_thread->tcb = cur_thread->tcb;
|
||||
new_thread->tgid = new_thread->tid;
|
||||
new_thread->in_vm = false;
|
||||
|
||||
+126
-20
@@ -43,6 +43,11 @@
|
||||
#define FUTEX_MIN_VALUE 0
|
||||
#define FUTEX_MAX_VALUE 255
|
||||
|
||||
struct futex_waiter {
|
||||
struct shim_thread * thread;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
static LIST_HEAD(futex_list);
|
||||
static LOCKTYPE futex_list_lock;
|
||||
|
||||
@@ -66,11 +71,9 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
|
||||
}
|
||||
|
||||
if (futex) {
|
||||
hdl = container_of(tmp, struct shim_handle, info.futex);
|
||||
hdl = container_of(futex, struct shim_handle, info.futex);
|
||||
get_handle(hdl);
|
||||
} else {
|
||||
struct shim_vma * vma_addr = NULL;
|
||||
|
||||
if (!(hdl = get_new_handle())) {
|
||||
unlock(futex_list_lock);
|
||||
return -ENOMEM;
|
||||
@@ -79,15 +82,6 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
|
||||
hdl->type = TYPE_FUTEX;
|
||||
futex = &hdl->info.futex;
|
||||
futex->uaddr = uaddr;
|
||||
futex->vma = vma_addr;
|
||||
|
||||
futex->event = DkSynchronizationEventCreate(0);
|
||||
if (futex->event == NULL) {
|
||||
ret = -PAL_ERRNO;
|
||||
unlock(futex_list_lock);
|
||||
goto out;
|
||||
}
|
||||
|
||||
get_handle(hdl);
|
||||
INIT_LIST_HEAD(&futex->waiters);
|
||||
INIT_LIST_HEAD(&futex->list);
|
||||
@@ -97,13 +91,9 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
|
||||
unlock(futex_list_lock);
|
||||
lock(hdl->lock);
|
||||
|
||||
struct futex_waiter {
|
||||
struct shim_thread * thread;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
switch (op & FUTEX_CMD_MASK) {
|
||||
case FUTEX_WAIT:
|
||||
debug("FUTEX_WAIT: %p (val = %d) vs %d\n", uaddr, *uaddr, val);
|
||||
if (*uaddr != val)
|
||||
break;
|
||||
|
||||
@@ -118,7 +108,76 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
|
||||
break;
|
||||
|
||||
case FUTEX_WAKE: {
|
||||
for (int cnt = 0 ; cnt < val ; cnt++) {
|
||||
debug("FUTEX_WAKE: %p (val = %d)\n", uaddr, *uaddr);
|
||||
int cnt;
|
||||
for (cnt = 0 ; cnt < val ; cnt++) {
|
||||
if (list_empty(&futex->waiters))
|
||||
break;
|
||||
|
||||
struct futex_waiter * waiter = list_entry(futex->waiters.next,
|
||||
struct futex_waiter,
|
||||
list);
|
||||
|
||||
debug("FUTEX_WAKE wake thread %d: %p (val = %d)\n",
|
||||
waiter->thread->tid, uaddr, *uaddr);
|
||||
list_del(&waiter->list);
|
||||
thread_wakeup(waiter->thread);
|
||||
}
|
||||
ret = cnt;
|
||||
debug("FUTEX_WAKE done: %p (val = %d)\n", uaddr, *uaddr);
|
||||
break;
|
||||
}
|
||||
|
||||
case FUTEX_CMP_REQUEUE:
|
||||
if (*uaddr != val3) {
|
||||
ret = -EAGAIN;
|
||||
break;
|
||||
}
|
||||
|
||||
case FUTEX_REQUEUE: {
|
||||
struct shim_futex_handle * futex2 = NULL;
|
||||
struct shim_handle * hdl2;
|
||||
|
||||
lock(futex_list_lock);
|
||||
|
||||
list_for_each_entry(tmp, &futex_list, list)
|
||||
if (tmp->uaddr == uaddr2) {
|
||||
futex2 = tmp;
|
||||
break;
|
||||
}
|
||||
|
||||
if (futex2) {
|
||||
hdl2 = container_of(futex2, struct shim_handle, info.futex);
|
||||
get_handle(hdl2);
|
||||
} else {
|
||||
if (!(hdl2 = get_new_handle())) {
|
||||
unlock(futex_list_lock);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdl2->type = TYPE_FUTEX;
|
||||
futex2 = &hdl2->info.futex;
|
||||
futex2->uaddr = uaddr2;
|
||||
#if 0
|
||||
futex2->event = DkSynchronizationEventCreate(0);
|
||||
if (futex2->event == NULL) {
|
||||
ret = -PAL_ERRNO;
|
||||
unlock(futex_list_lock);
|
||||
put_handle(hdl2);
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
get_handle(hdl2);
|
||||
INIT_LIST_HEAD(&futex2->waiters);
|
||||
INIT_LIST_HEAD(&futex2->list);
|
||||
list_add_tail(&futex2->list, &futex_list);
|
||||
}
|
||||
|
||||
unlock(futex_list_lock);
|
||||
|
||||
int cnt;
|
||||
for (cnt = 0 ; cnt < val ; cnt++) {
|
||||
if (list_empty(&futex->waiters))
|
||||
break;
|
||||
|
||||
@@ -129,6 +188,19 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
|
||||
list_del(&waiter->list);
|
||||
thread_wakeup(waiter->thread);
|
||||
}
|
||||
|
||||
lock(hdl2->lock);
|
||||
while (!list_empty(&futex->waiters)) {
|
||||
struct futex_waiter * waiter = list_entry(futex->waiters.next,
|
||||
struct futex_waiter,
|
||||
list);
|
||||
|
||||
list_del(&waiter->list);
|
||||
list_add_tail(&waiter->list, &futex2->waiters);
|
||||
}
|
||||
unlock(hdl2->lock);
|
||||
put_handle(hdl2);
|
||||
ret = cnt;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -137,6 +209,7 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("unsupported futex op: 0x%x\n", op);
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
@@ -205,7 +278,24 @@ void release_robust_list (struct robust_list_head * head)
|
||||
if (!futex)
|
||||
continue;
|
||||
|
||||
DkEventSet(futex->event);
|
||||
struct shim_handle * hdl =
|
||||
container_of(futex, struct shim_handle, info.futex);
|
||||
get_handle(hdl);
|
||||
lock(hdl->lock);
|
||||
|
||||
debug("release robust list: %p\n", futex_addr);
|
||||
*(int *) futex_addr = 0;
|
||||
while (!list_empty(&futex->waiters)) {
|
||||
struct futex_waiter * waiter = list_entry(futex->waiters.next,
|
||||
struct futex_waiter,
|
||||
list);
|
||||
|
||||
list_del(&waiter->list);
|
||||
thread_wakeup(waiter->thread);
|
||||
}
|
||||
|
||||
unlock(hdl->lock);
|
||||
put_handle(hdl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +320,22 @@ void release_clear_child_id (int * clear_child_tid)
|
||||
if (!futex)
|
||||
return;
|
||||
|
||||
struct shim_handle * hdl =
|
||||
container_of(futex, struct shim_handle, info.futex);
|
||||
get_handle(hdl);
|
||||
lock(hdl->lock);
|
||||
|
||||
debug("release futex at %p\n", clear_child_tid);
|
||||
DkEventSet(futex->event);
|
||||
*clear_child_tid = 0;
|
||||
while (!list_empty(&futex->waiters)) {
|
||||
struct futex_waiter * waiter = list_entry(futex->waiters.next,
|
||||
struct futex_waiter,
|
||||
list);
|
||||
|
||||
list_del(&waiter->list);
|
||||
thread_wakeup(waiter->thread);
|
||||
}
|
||||
|
||||
unlock(hdl->lock);
|
||||
put_handle(hdl);
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ void * shim_do_mmap (void * addr, size_t length, int prot, int flags, int fd,
|
||||
}
|
||||
|
||||
ret = bkeep_mmap((void *) mapped, mapped_end - mapped, prot,
|
||||
flags, hdl, offset, "user");
|
||||
flags, hdl, offset, NULL);
|
||||
assert(!ret);
|
||||
if (hdl)
|
||||
put_handle(hdl);
|
||||
|
||||
@@ -165,8 +165,7 @@ static int __kill_proc (struct shim_thread * thread, void * arg,
|
||||
if (!warg->use_ipc && !thread->in_vm)
|
||||
return 0;
|
||||
|
||||
/* only signal thread leader */
|
||||
if (thread->tgid != warg->id || thread->tid != thread->tgid)
|
||||
if (thread->tgid != warg->id)
|
||||
return 0;
|
||||
|
||||
if (warg->current == thread)
|
||||
@@ -185,7 +184,6 @@ static int __kill_proc (struct shim_thread * thread, void * arg,
|
||||
return (!ipc_pid_kill_send(warg->sender, warg->id, KILL_PROCESS,
|
||||
warg->sig)) ? 1 : 0;
|
||||
} else {
|
||||
|
||||
lock(thread->lock);
|
||||
|
||||
if (!thread->is_alive)
|
||||
@@ -216,7 +214,7 @@ static int __kill_proc_simple (struct shim_simple_thread * sthread,
|
||||
struct walk_arg * warg = (struct walk_arg *) arg;
|
||||
int srched = 0;
|
||||
|
||||
if (sthread->tgid != warg->id || sthread->tgid != sthread->tid)
|
||||
if (sthread->tgid != warg->id)
|
||||
return 0;
|
||||
|
||||
lock(sthread->lock);
|
||||
@@ -276,8 +274,7 @@ static int __kill_pgroup (struct shim_thread * thread, void * arg,
|
||||
if (!warg->use_ipc && !thread->in_vm)
|
||||
return 0;
|
||||
|
||||
/* only signal thread leader */
|
||||
if (thread->pgid != warg->id || thread->tgid != thread->tid)
|
||||
if (thread->pgid != warg->id)
|
||||
return 0;
|
||||
|
||||
if (warg->current == thread)
|
||||
@@ -312,7 +309,7 @@ static int __kill_pgroup_simple (struct shim_simple_thread * sthread,
|
||||
struct walk_arg * warg = (struct walk_arg *) arg;
|
||||
int srched = 0;
|
||||
|
||||
if (sthread->pgid != warg->id || sthread->tgid != sthread->tid)
|
||||
if (sthread->pgid != warg->id)
|
||||
return 0;
|
||||
|
||||
lock(sthread->lock);
|
||||
|
||||
+19
-22
@@ -22,8 +22,8 @@
|
||||
|
||||
#include <shim_tls.h>
|
||||
|
||||
.text
|
||||
.globl syscalldb
|
||||
.text
|
||||
.global syscalldb
|
||||
.type syscalldb, @function
|
||||
.extern shim_table
|
||||
|
||||
@@ -42,18 +42,10 @@ syscalldb:
|
||||
.cfi_def_cfa_register 6
|
||||
|
||||
pushq %rbx
|
||||
pushq %r12
|
||||
|
||||
movq %rax, %fs:(SHIM_TCB_OFFSET + 24)
|
||||
movq %rsp, %rbx
|
||||
addq $152, %rbx
|
||||
movq %rbx, %fs:(SHIM_TCB_OFFSET + 32)
|
||||
movq (%rbx), %rbx
|
||||
movq %rbx, %fs:(SHIM_TCB_OFFSET + 40)
|
||||
|
||||
movq shim_table@GOTPCREL(%rip), %rbx
|
||||
movq (%rbx,%rax,8), %r12
|
||||
cmp $0, (%r12)
|
||||
leaq shim_table(%rip), %rbx
|
||||
movq (%rbx,%rax,8), %rbx
|
||||
cmp $0, (%rbx)
|
||||
je isundef
|
||||
|
||||
isdef:
|
||||
@@ -63,16 +55,29 @@ isdef:
|
||||
pushq %rcx
|
||||
pushq %r8
|
||||
pushq %r9
|
||||
pushq %r12
|
||||
pushq %r13
|
||||
pushq %r14
|
||||
pushq %r15
|
||||
|
||||
movq %rax, %fs:(SHIM_TCB_OFFSET + 24)
|
||||
leaq 224(%rsp), %rax
|
||||
movq %rax, %fs:(SHIM_TCB_OFFSET + 32)
|
||||
movq (%rax), %rax
|
||||
movq %rax, %fs:(SHIM_TCB_OFFSET + 40)
|
||||
movq %rsp, %fs:(SHIM_TCB_OFFSET + 48)
|
||||
|
||||
call *(%rbx,%rax,8)
|
||||
call *%rbx
|
||||
|
||||
movq $0, %fs:(SHIM_TCB_OFFSET + 24)
|
||||
movq $0, %fs:(SHIM_TCB_OFFSET + 32)
|
||||
movq $0, %fs:(SHIM_TCB_OFFSET + 40)
|
||||
movq $0, %fs:(SHIM_TCB_OFFSET + 48)
|
||||
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
popq %r12
|
||||
popq %r9
|
||||
popq %r8
|
||||
popq %rcx
|
||||
@@ -86,17 +91,9 @@ isundef:
|
||||
movq $-38, %rax
|
||||
|
||||
ret:
|
||||
popq %r12
|
||||
popq %rbx
|
||||
popq %rbp
|
||||
|
||||
movq $0, %fs:(SHIM_TCB_OFFSET + 24)
|
||||
movq $0, %fs:(SHIM_TCB_OFFSET + 32)
|
||||
movq $0, %fs:(SHIM_TCB_OFFSET + 40)
|
||||
movq $0, %fs:(SHIM_TCB_OFFSET + 48)
|
||||
|
||||
addq $128, %rsp
|
||||
|
||||
retq
|
||||
|
||||
.cfi_endproc
|
||||
|
||||
@@ -26,12 +26,11 @@ manifest: manifest.template
|
||||
rm -rf $@
|
||||
cp $@.template $@
|
||||
|
||||
.PHONY: pal palsec
|
||||
|
||||
pal:
|
||||
ln -sf $(level)../../../Pal/src/libpal.so
|
||||
palsec:
|
||||
ln -sf $(level)../../../Pal/src/libpal_sec.so libpal.so
|
||||
[ ! -f $(level)../../../Pal/src/pal ] || ln -sf $(level)../../../Pal/src/pal pal
|
||||
|
||||
pal_sec:
|
||||
[ ! -f $(level)../../../Pal/src/pal_sec ] || ln -sf $(level)../../../Pal/src/pal_sec pal_sec
|
||||
|
||||
# Regression Test
|
||||
rtest: $(rtarget)
|
||||
|
||||
@@ -1,26 +1,24 @@
|
||||
apps = lmbench gcc busybox lighttpd bash apache make
|
||||
|
||||
targets = pal
|
||||
targets = pal pal_sec
|
||||
clean-extra = clean-all
|
||||
|
||||
level = ../
|
||||
include ../Makefile
|
||||
|
||||
manifest_rules = \
|
||||
-e 's:\$$(PAL):$(shell pwd)/pal_loader:g' \
|
||||
-e 's:\$$(PWD):$(shell pwd)/$(appdir):g' \
|
||||
-e 's:\$$(BIN):$(subst .manifest,,$(notdir $@)):g' \
|
||||
-e 's:\$$(SHIMPATH):$(shell readlink -f ../../src/libsysdb.so):g' \
|
||||
-e 's:\$$(GLIBCDIR):$(shell readlink -f $(glibc_dir)):g' \
|
||||
$(extra_rules)
|
||||
|
||||
%.manifest: %.manifest.template libpal.so
|
||||
%.manifest: %.manifest.template
|
||||
rm -f $@ $@.backup
|
||||
sed $(manifest_rules) $< >$@
|
||||
chmod +x $@
|
||||
|
||||
libpal.so:
|
||||
make pal
|
||||
|
||||
build-all:
|
||||
for f in $(apps); do (cd $$f; make $(DEBUG) || true; cd ..); done
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.exec = file:obj/bin/httpd
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.exec = file:bash-local
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.exec = file:/bin/bash
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.exec = file:busybox
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.exec = file:busybox_nofork
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.exec = file:/usr/bin/g++
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.interp = file:$(SHIM)build/elf/ld.so
|
||||
loader.preload = file:$(SHIM)build/libsysdb.so
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.exec = file:/usr/bin/g++
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.exec = file:/usr/bin/gcc
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.interp = file:$(SHIMROOT)build/elf/ld.so
|
||||
loader.preload = file:$(SHIMROOT)build/libsysdb.so
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.exec = file:/usr/bin/gcc
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.exec = file:$(PWD)build/sbin/lighttpd-angel
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.exec = file:$(PWD)build/sbin/lighttpd
|
||||
|
||||
@@ -12,23 +12,23 @@ char *id = "$Id$\n";
|
||||
#define FNAME "/usr/include/x86_64-linux-gnu/sys/types.h"
|
||||
|
||||
void
|
||||
do_write(int fd)
|
||||
do_write(int fd, char *s)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (write(fd, &c, 1) != 1) {
|
||||
perror("/dev/null");
|
||||
perror(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
do_read(int fd)
|
||||
do_read(int fd, char *s)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (read(fd, &c, 1) != 1) {
|
||||
perror("/dev/zero");
|
||||
perror(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -81,17 +81,23 @@ main(int ac, char **av)
|
||||
BENCH(getppid(), 0);
|
||||
micro("Simple syscall", get_n());
|
||||
} else if (!strcmp("write", av[1])) {
|
||||
fd = open("/dev/null", 1);
|
||||
BENCH(do_write(fd), 0);;
|
||||
file = av[2] ? av[2] : "/dev/null";
|
||||
fd = open(file, 1);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "Write from %s: %s\n", file, strerror(errno));
|
||||
return(1);
|
||||
}
|
||||
BENCH(do_write(fd, file), 0);;
|
||||
micro("Simple write", get_n());
|
||||
close(fd);
|
||||
} else if (!strcmp("read", av[1])) {
|
||||
fd = open("/dev/zero", 0);
|
||||
file = av[2] ? av[2] : "/dev/null";
|
||||
fd = open(file, 0);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "Read from /dev/zero: -1");
|
||||
fprintf(stderr, "Read from %s: %s\n", file, strerror(errno));
|
||||
return(1);
|
||||
}
|
||||
BENCH(do_read(fd), 0);
|
||||
BENCH(do_read(fd, file), 0);
|
||||
micro("Simple read", get_n());
|
||||
close(fd);
|
||||
} else if (!strcmp("stat", av[1])) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.exec = file:$(PWD)lmbench-2.5/bin/linux/$(BIN)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.exec = file:/usr/bin/make
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.exec = file:make-local
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.exec = file:/usr/bin/make
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!$(PWD)../libpal.so
|
||||
#!$(PAL)
|
||||
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.exec = file:/usr/bin/python
|
||||
|
||||
@@ -2,7 +2,7 @@ INLINE_TESTS_CPP = $(patsubst %.cpp,%,$(wildcard *.cpp))
|
||||
INLINE_TESTS = $(patsubst %.c,%,$(wildcard *.c))
|
||||
|
||||
rtarget = helloworld fork vfork
|
||||
targets = $(rtarget) manifest pal
|
||||
targets = $(rtarget) manifest pal pal_sec
|
||||
clean-extra = clean-exec
|
||||
|
||||
level = ../
|
||||
@@ -23,4 +23,4 @@ test-vfork = grep -q "Hello, Dad" OUTPUT && grep -q "Hello, Kid" OUTPUT
|
||||
|
||||
clean-exec:
|
||||
find -type f -executable -exec rm {} \;
|
||||
rm -rf manifest libpal.so
|
||||
rm -rf manifest pal pal_sec
|
||||
|
||||
@@ -5,7 +5,7 @@ NATIVE_TESTS_STATIC = static
|
||||
NATIVE_TESTS = $(filter-out $(NATIVE_TESTS_STATIC),$(patsubst %.c,%,$(wildcard *.c)))
|
||||
|
||||
targets = $(NATIVE_TESTS) $(NATIVE_TESTS_CPP) $(NATIVE_TESTS_STATIC) \
|
||||
manifest static.manifest pal
|
||||
manifest static.manifest pal pal_sec
|
||||
rtarget = helloworld clone vfork fork exec vfork_exec errno dup time \
|
||||
helloworld.pthread udp tcp unix file dev
|
||||
clean-extra = clean-exec
|
||||
@@ -47,4 +47,4 @@ test-helloworld = grep -q "Hello world" OUTPUT
|
||||
|
||||
clean-exec:
|
||||
find -type f -executable -exec rm {} \;
|
||||
rm -rf manifest static.manifest libpal.so
|
||||
rm -rf manifest static.manifest pal pal_sec
|
||||
|
||||
@@ -10,6 +10,10 @@ fs.mount.other.lib.type = chroot
|
||||
fs.mount.other.lib.path = /lib
|
||||
fs.mount.other.lib.uri = file:../../../build
|
||||
|
||||
fs.mount.other.bin.type = chroot
|
||||
fs.mount.other.bin.path = /bin
|
||||
fs.mount.other.bin.uri = file:/bin
|
||||
|
||||
# allow to bind on port 8000
|
||||
net.rules.1 = 127.0.0.1:8000:0.0.0.0:0-65535
|
||||
# allow to connect to port 8000
|
||||
|
||||
@@ -28,6 +28,5 @@ int main (int argc, char ** argv, char ** envp)
|
||||
unsigned long long overhead = (msec4 - msec3) / OVERHEAD_TIMES;
|
||||
|
||||
printf("%llu\n", msec2 - msec1 - overhead);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
|
||||
/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
|
||||
|
||||
/* a simple helloworld test */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
system("./helloworld");
|
||||
return 0;
|
||||
}
|
||||
@@ -895,7 +895,7 @@ out:
|
||||
mutex_unlock(&pending->receiver_lock);
|
||||
up_write(¤t_tsk->mm->mmap_sem);
|
||||
|
||||
rv = copy_to_user(((struct gipc_recv *)arg)->addr, addrs,
|
||||
rv = copy_to_user(gr.addr, addrs,
|
||||
sizeof(unsigned long) * gr.entries);
|
||||
if (rv) {
|
||||
printk(KERN_ERR "Graphene error: bad buffer %p\n",
|
||||
|
||||
+26
-11
@@ -9,18 +9,21 @@ LD = ld
|
||||
CFLAGS = -Wall -fPIC -O2 -std=gnu99 -fgnu89-inline -U_FORTIFY_SOURCE \
|
||||
-fno-omit-frame-pointer \
|
||||
-fno-stack-protector -fno-builtin
|
||||
LDFLAGS = -shared -nostdlib --version-script pal.map -z combreloc -z defs \
|
||||
-T pal.lds
|
||||
LDFLAGS = -shared -nostdlib -z combreloc -z defs
|
||||
ARFLAGS =
|
||||
|
||||
pal_loader = libpal.so
|
||||
pal_lib = libpal.a
|
||||
pal_sec =
|
||||
pal_lib = libpal.so
|
||||
pal_lib_deps =
|
||||
pal_lib_post =
|
||||
pal_static = libpal.a
|
||||
|
||||
include host/$(OS)/Makefile.am
|
||||
|
||||
CFLAGS += -I. -I../include -Ihost/$(OS) -I../lib
|
||||
|
||||
pal_target = $(pal_loader) $(pal_lib)
|
||||
pal_target = $(pal_lib) $(pal_lib_post) $(pal_static) $(pal_loader) $(pal_sec) pal pal_sec
|
||||
defs = -DIN_PAL -DSRCDIR="$(PWD)/"
|
||||
objs = $(addprefix db_,streams memory threading semaphore events process \
|
||||
object main misc ipc exception rtld) slab printf
|
||||
@@ -28,14 +31,14 @@ graphene_lib = ../lib/graphene-lib.a
|
||||
host_lib = host/$(OS)/libpal-$(OS).a
|
||||
headers = $(wildcard *.h) $(wildcard ../lib/*.h)
|
||||
|
||||
all: $(pal_target) security
|
||||
all: $(pal_target)
|
||||
|
||||
debug: debug = debug
|
||||
debug: CC = gcc -gdwarf-2 -g3
|
||||
debug: CFLAGS += -DDEBUG
|
||||
debug: $(pal_target) security
|
||||
debug: $(pal_target)
|
||||
|
||||
.PHONY: security $(host_lib) $(graphene_lib)
|
||||
.PHONY: $(host_lib) $(graphene_lib)
|
||||
|
||||
$(graphene_lib):
|
||||
make -C ../lib $(debug)
|
||||
@@ -43,15 +46,27 @@ $(graphene_lib):
|
||||
$(host_lib):
|
||||
@[ ! -d host/$(OS) ] || make -C host/$(OS) $(debug)
|
||||
|
||||
security:
|
||||
ifneq ($(pal_sec),)
|
||||
$(pal_sec):
|
||||
@[ ! -d security/$(OS) ] || make -C security/$(OS) $(debug)
|
||||
|
||||
$(pal_loader): $(addsuffix .o,$(objs)) $(filter %.map %.lds,$(LDFLAGS)) \
|
||||
$(host_lib) $(graphene_lib)
|
||||
pal_sec: $(pal_sec)
|
||||
ln -sf $(pal_sec) pal_sec
|
||||
endif
|
||||
|
||||
$(pal_lib): $(addsuffix .o,$(objs)) $(host_lib) $(graphene_lib) $(pal_lib_deps)
|
||||
@echo [ libpal.exe ]
|
||||
$(LD) $(LDFLAGS) -o $@ $(filter-out %.map %.lds,$^) $(LDFLAGS-suffix)
|
||||
|
||||
$(pal_lib): $(addsuffix .o,$(objs)) $(host_lib) $(graphene_lib)
|
||||
pal: $(pal_loader)
|
||||
ln -sf $(pal_loader) pal
|
||||
|
||||
ifneq ($(pal_lib_post),)
|
||||
$(pal_lib_post): $(pal_lib)
|
||||
make -C host/$(OS) ../../$@
|
||||
endif
|
||||
|
||||
$(pal_static): $(addsuffix .o,$(objs)) $(host_lib) $(graphene_lib)
|
||||
@echo [ $@ ]
|
||||
$(AR) $(ARFLAGS) $@ $^ $(ARFLAGS-suffix)
|
||||
|
||||
|
||||
+78
-65
@@ -52,39 +52,6 @@ void __attribute__((noinline)) __assert (void)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This structure communicates dl state to the debugger. The debugger
|
||||
normally finds it via the DT_DEBUG entry in the dynamic section, but in
|
||||
a statically-linked program there is no dynamic section for the debugger
|
||||
to examine and it looks for this particular symbol name. */
|
||||
struct r_debug pal_r_debug =
|
||||
{ 1, NULL, (ElfW(Addr)) &pal_dl_debug_state, RT_CONSISTENT, 0 };
|
||||
|
||||
extern __typeof(pal_r_debug) _r_debug
|
||||
__attribute ((alias ("pal_r_debug")));
|
||||
|
||||
/* This function exists solely to have a breakpoint set on it by the
|
||||
debugger. The debugger is supposed to find this function's address by
|
||||
examining the r_brk member of struct r_debug, but GDB 4.15 in fact looks
|
||||
for this particular symbol name in the PT_INTERP file. */
|
||||
|
||||
/* The special symbol name is set as breakpoint in gdb */
|
||||
void __attribute__((noinline)) pal_dl_debug_state (void)
|
||||
{
|
||||
}
|
||||
|
||||
extern __typeof(pal_dl_debug_state) _dl_debug_state
|
||||
__attribute ((alias ("pal_dl_debug_state")));
|
||||
|
||||
void __attribute__((noinline)) _dl_debug_state_trigger (void)
|
||||
{
|
||||
struct link_map *l = pal_r_debug.r_map;
|
||||
for ( ; l ; l = l->l_next)
|
||||
if (!memcmp(l->l_name, "file:", 5))
|
||||
l->l_name += 5;
|
||||
|
||||
pal_dl_debug_state();
|
||||
}
|
||||
|
||||
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
|
||||
static ElfW(Addr) resolve_map (const char **strtab, ElfW(Sym) ** ref)
|
||||
{
|
||||
@@ -251,7 +218,7 @@ call_lose:
|
||||
/* Scan the program header table, collecting its load commands. */
|
||||
struct loadcmd {
|
||||
ElfW(Addr) mapstart, mapend, dataend, allocend;
|
||||
off_t mapoff;
|
||||
unsigned int mapoff;
|
||||
int prot;
|
||||
} loadcmds[l->l_phnum], *c;
|
||||
|
||||
@@ -309,18 +276,13 @@ call_lose:
|
||||
has_holes = true;
|
||||
|
||||
/* Optimize a common case. */
|
||||
#if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
|
||||
c->prot = (PF_TO_PROT
|
||||
>> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf;
|
||||
#else
|
||||
c->prot = 0;
|
||||
if (ph->p_flags & PF_R)
|
||||
c->prot |= PROT_READ;
|
||||
c->prot |= PAL_PROT_READ;
|
||||
if (ph->p_flags & PF_W)
|
||||
c->prot |= PROT_WRITE;
|
||||
c->prot |= PAL_PROT_WRITE;
|
||||
if (ph->p_flags & PF_X)
|
||||
c->prot |= PROT_EXEC;
|
||||
#endif
|
||||
c->prot |= PAL_PROT_EXEC;
|
||||
break;
|
||||
|
||||
case PT_TLS:
|
||||
@@ -390,7 +352,7 @@ map_error:
|
||||
unallocated. Then jump into the normal segment-mapping loop to
|
||||
handle the portion of the segment past the end of the file
|
||||
mapping. */
|
||||
_DkVirtualMemoryProtect((caddr_t) (l->l_addr + c->mapend),
|
||||
_DkVirtualMemoryProtect((void *) (l->l_addr + c->mapend),
|
||||
loadcmds[nloadcmds - 1].mapstart - c->mapend,
|
||||
PAL_PROT_NONE);
|
||||
|
||||
@@ -414,12 +376,12 @@ map_error:
|
||||
}
|
||||
|
||||
postmap:
|
||||
if (c->prot & PROT_EXEC) {
|
||||
if (c->prot & PAL_PROT_EXEC) {
|
||||
l->l_text_start = l->l_addr + c->mapstart;
|
||||
l->l_text_end = l->l_addr + c->mapend;
|
||||
}
|
||||
|
||||
if (c->prot & PROT_WRITE) {
|
||||
if (c->prot & PAL_PROT_WRITE) {
|
||||
l->l_data_start = l->l_addr + c->mapstart;
|
||||
l->l_data_end = l->l_addr + c->mapend;
|
||||
}
|
||||
@@ -447,7 +409,7 @@ postmap:
|
||||
|
||||
if (zerosec > zero) {
|
||||
/* Zero the final part of the last section of the segment. */
|
||||
if (__builtin_expect ((c->prot & PROT_WRITE) == 0, 0))
|
||||
if (__builtin_expect ((c->prot & PAL_PROT_WRITE) == 0, 0))
|
||||
{
|
||||
/* Dag nab it. */
|
||||
if (_DkVirtualMemoryProtect((void *) ALLOC_ALIGNDOWN(zero),
|
||||
@@ -458,7 +420,7 @@ postmap:
|
||||
}
|
||||
}
|
||||
memset ((void *) zero, '\0', zerosec - zero);
|
||||
if (__builtin_expect ((c->prot & PROT_WRITE) == 0, 0))
|
||||
if (__builtin_expect ((c->prot & PAL_PROT_WRITE) == 0, 0))
|
||||
_DkVirtualMemoryProtect((void *) ALLOC_ALIGNDOWN(zero),
|
||||
allocsize, c->prot);
|
||||
}
|
||||
@@ -563,16 +525,12 @@ void free_elf_object (struct link_map * map)
|
||||
_DkVirtualMemoryFree((void *) map->l_map_start,
|
||||
map->l_map_end - map->l_map_start);
|
||||
|
||||
pal_sec_info._r_debug->r_state = RT_DELETE;
|
||||
pal_sec_info._dl_debug_state();
|
||||
|
||||
if (map->l_prev)
|
||||
map->l_prev->l_next = map->l_next;
|
||||
if (map->l_next)
|
||||
map->l_next->l_prev = map->l_prev;
|
||||
|
||||
pal_sec_info._r_debug->r_state = RT_CONSISTENT;
|
||||
pal_sec_info._dl_debug_state();
|
||||
_DkDebugDelMap(map);
|
||||
|
||||
if (loaded_libraries == map)
|
||||
loaded_libraries = map->l_next;
|
||||
@@ -675,9 +633,6 @@ int load_elf_object_by_handle (PAL_HANDLE handle, enum object_type type)
|
||||
}
|
||||
}
|
||||
|
||||
pal_sec_info._r_debug->r_state = RT_ADD;
|
||||
pal_sec_info._dl_debug_state();
|
||||
|
||||
struct link_map * map;
|
||||
|
||||
if (!(map = map_elf_object_by_handle(handle, type, &fb, len, true))) {
|
||||
@@ -706,8 +661,7 @@ int load_elf_object_by_handle (PAL_HANDLE handle, enum object_type type)
|
||||
map->l_prev = prev;
|
||||
map->l_next = NULL;
|
||||
|
||||
pal_sec_info._r_debug->r_state = RT_CONSISTENT;
|
||||
pal_sec_info._dl_debug_state();
|
||||
_DkDebugAddMap(map);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -969,18 +923,13 @@ static int relocate_elf_object (struct link_map * l)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
#if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
|
||||
r->prot = (PF_TO_PROT
|
||||
>> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf;
|
||||
#else
|
||||
r->prot = 0;
|
||||
if (ph->p_flags & PF_R)
|
||||
r->prot |= PROT_READ;
|
||||
r->prot |= PAL_PROT_READ;
|
||||
if (ph->p_flags & PF_W)
|
||||
r->prot |= PROT_WRITE;
|
||||
r->prot |= PAL_PROT_WRITE;
|
||||
if (ph->p_flags & PF_X)
|
||||
r->prot |= PROT_EXEC;
|
||||
#endif
|
||||
r->prot |= PAL_PROT_EXEC;
|
||||
r->next = textrels;
|
||||
textrels = r;
|
||||
}
|
||||
@@ -1026,6 +975,70 @@ static int relocate_elf_object (struct link_map * l)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DkDebugAttachBinary (PAL_STR uri, PAL_PTR start_addr)
|
||||
{
|
||||
if (memcmp(uri, "file:", 5))
|
||||
return;
|
||||
|
||||
struct link_map * l = new_elf_object(uri + 5, OBJECT_EXTERNAL);
|
||||
|
||||
/* This is the ELF header. We read it in `open_verify'. */
|
||||
const ElfW(Ehdr) * header = start_addr;
|
||||
|
||||
l->l_entry = header->e_entry;
|
||||
l->l_phnum = header->e_phnum;
|
||||
l->l_addr = l->l_map_start = (ElfW(Addr)) start_addr;
|
||||
|
||||
ElfW(Phdr) * phdr = (void *) (start_addr + header->e_phoff);
|
||||
const ElfW(Phdr) * ph;
|
||||
|
||||
for (ph = phdr; ph < &phdr[l->l_phnum]; ++ph)
|
||||
switch (ph->p_type)
|
||||
{
|
||||
/* These entries tell us where to find things once the file's
|
||||
segments are mapped in. We record the addresses it says
|
||||
verbatim, and later correct for the run-time load address. */
|
||||
case PT_DYNAMIC:
|
||||
l->l_ld = l->l_real_ld = (void *) ph->p_vaddr;
|
||||
l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn));
|
||||
break;
|
||||
|
||||
case PT_PHDR:
|
||||
l->l_phdr = (void *) ph->p_vaddr;
|
||||
break;
|
||||
|
||||
case PT_LOAD: {
|
||||
ElfW(Addr) start = l->l_addr + ALLOC_ALIGNDOWN(ph->p_vaddr);
|
||||
ElfW(Addr) end = l->l_addr + ALLOC_ALIGNDOWN(ph->p_vaddr +
|
||||
ph->p_memsz);
|
||||
|
||||
if (ph->p_flags & PF_X) {
|
||||
l->l_text_start = start;
|
||||
l->l_text_end = end;
|
||||
}
|
||||
|
||||
if (ph->p_flags & PF_W) {
|
||||
l->l_data_start = start;
|
||||
l->l_data_end = end;
|
||||
}
|
||||
|
||||
l->l_map_end = end;
|
||||
break;
|
||||
}
|
||||
|
||||
case PT_GNU_RELRO:
|
||||
l->l_relro_addr = ph->p_vaddr;
|
||||
l->l_relro_size = ph->p_memsz;
|
||||
break;
|
||||
}
|
||||
|
||||
_DkDebugAddMap(l);
|
||||
}
|
||||
|
||||
void DkDebugDetachBinary (PAL_PTR start_addr)
|
||||
{
|
||||
}
|
||||
|
||||
void start_execution (int argc, const char ** argv)
|
||||
{
|
||||
/* First we will try to run all the preloaded libraries which come with
|
||||
|
||||
@@ -39,23 +39,23 @@
|
||||
copying memory, breaking the very code written to handle the
|
||||
unaligned cases. */
|
||||
#if ! ELF_MACHINE_NO_REL
|
||||
static void __attribute__((always_inline))
|
||||
static inline void __attribute__((always_inline))
|
||||
elf_machine_rel (ElfW(Dyn) ** l_info, ElfW(Addr) l_addr,
|
||||
ElfW(Rel) *reloc, ElfW(Sym) *sym, void *const reloc_addr,
|
||||
bool rel, bool rel_relative);
|
||||
|
||||
static void __attribute__((always_inline))
|
||||
static inline void __attribute__((always_inline))
|
||||
elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
|
||||
void *const reloc_addr);
|
||||
#endif
|
||||
|
||||
#if ! ELF_MACHINE_NO_RELA
|
||||
static void __attribute__((always_inline))
|
||||
static inline void __attribute__((always_inline))
|
||||
elf_machine_rela (ElfW(Dyn) ** l_info, ElfW(Addr) l_addr,
|
||||
ElfW(Rela) *reloc, ElfW(Sym) *sym, void *const reloc_addr,
|
||||
bool rel, bool rel_relative);
|
||||
|
||||
static void __attribute__((always_inline))
|
||||
static inline void __attribute__((always_inline))
|
||||
elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
|
||||
void *const reloc_addr);
|
||||
#endif
|
||||
|
||||
@@ -16,7 +16,8 @@ ARFLAGS =
|
||||
|
||||
host_target = libpal-Linux.a
|
||||
|
||||
defs = -DIN_PAL -DGDB_SCRIPT="$(CURDIR)/pal-gdb.py"
|
||||
defs = -DIN_PAL -DPAL_LOADER_PATH="$(shell readlink -f ../../pal)" \
|
||||
-DGDB_SCRIPT="$(CURDIR)/pal-gdb.py"
|
||||
objs = $(addprefix db_,files devices pipes sockets streams memory threading \
|
||||
semaphore mutex events process object main rtld misc ipc \
|
||||
exception) manifest clone-x86_64 gettimeofday-x86_64
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
# Add host-specific compilation rules here
|
||||
HOST_DIR = host/$(OS)
|
||||
SEC_DIR = security/$(OS)
|
||||
|
||||
pal_sec = $(SEC_DIR)/libpal_sec.so
|
||||
pal_lib_deps = $(HOST_DIR)/pal.map $(HOST_DIR)/pal.lds
|
||||
|
||||
LDFLAGS += --version-script $(HOST_DIR)/pal.map -T $(HOST_DIR)/pal.lds
|
||||
|
||||
@@ -70,7 +70,6 @@ static gid_t gid;
|
||||
static ElfW(Addr) sysinfo_ehdr;
|
||||
#endif
|
||||
|
||||
static const char * libname;
|
||||
static const char * child_args;
|
||||
|
||||
static void pal_init_bootstrap (void * args, int * pargc,
|
||||
@@ -124,9 +123,7 @@ static void pal_init_bootstrap (void * args, int * pargc,
|
||||
#endif
|
||||
}
|
||||
|
||||
if (memcmp(*argv + strlen(*argv) - LIBRARY_NAMELEN, LIBRARY_NAME,
|
||||
LIBRARY_NAMELEN) == 0) {
|
||||
libname = *argv;
|
||||
if (!memcmp(*argv + strlen(*argv) - 3, "pal", 3)) {
|
||||
argv++;
|
||||
argc--;
|
||||
|
||||
@@ -198,8 +195,6 @@ int read_shebang (const char ** argv)
|
||||
|
||||
if (IS_ERR(fd)) {
|
||||
bad_shebang:
|
||||
printf("The program is either not libpal.so or script with "
|
||||
"shebang. I can't recognize.\n");
|
||||
INLINE_SYSCALL(close, 1, fd);
|
||||
return -PAL_ERROR_INVAL;
|
||||
}
|
||||
@@ -215,14 +210,8 @@ bad_shebang:
|
||||
goto bad_shebang;
|
||||
|
||||
char * p = &buffer[2];
|
||||
while (*p && *p != ' ' && *p != '\r' && *p != '\n');
|
||||
p++;
|
||||
|
||||
if (!libname) {
|
||||
char * name = malloc(p - buffer - 1);
|
||||
memcpy(name, &buffer[2], p - buffer - 2);
|
||||
libname = name;
|
||||
}
|
||||
while (*p && *p != ' ' && *p != '\r' && *p != '\n')
|
||||
p++;
|
||||
|
||||
int len = strlen(*argv);
|
||||
PAL_HANDLE manifest = malloc(HANDLE_SIZE(file) + len + 1);
|
||||
@@ -265,7 +254,7 @@ void pal_linux_main (void * args)
|
||||
|
||||
init_slab_mgr();
|
||||
|
||||
setup_pal_map(XSTRINGIFY(SRCDIR) "/" LIBRARY_NAME, pal_dyn, pal_addr);
|
||||
setup_pal_map(XSTRINGIFY(SRCDIR) "/pal", pal_dyn, pal_addr);
|
||||
|
||||
/* jump to main function */
|
||||
pal_main(argc, argv, envp);
|
||||
@@ -345,9 +334,6 @@ int _DkInitHost (int * pargc, const char *** pargv)
|
||||
return -PAL_ERROR_INVAL;
|
||||
}
|
||||
|
||||
if (pal_sec_info.pal_name)
|
||||
libname = pal_sec_info.pal_name;
|
||||
|
||||
pal_linux_config.pid = INLINE_SYSCALL(getpid, 0);
|
||||
|
||||
signal_setup();
|
||||
@@ -359,12 +345,8 @@ int _DkInitHost (int * pargc, const char *** pargv)
|
||||
goto read_manifest;
|
||||
}
|
||||
|
||||
if (!libname) {
|
||||
if ((ret = read_shebang(argv)) < 0)
|
||||
return ret;
|
||||
|
||||
if (!(ret = read_shebang(argv)) < 0)
|
||||
goto read_manifest;
|
||||
}
|
||||
|
||||
PAL_HANDLE file = NULL;
|
||||
const char * file_uri = NULL;
|
||||
@@ -468,12 +450,6 @@ read_manifest:
|
||||
}
|
||||
|
||||
done_init:
|
||||
if (!child_args && pal_config.exec)
|
||||
printf("Program \"%s\" loaded in Graphene Library OS\n",
|
||||
pal_config.exec);
|
||||
|
||||
pal_config.lib_name = libname;
|
||||
|
||||
if (!child_args && !pal_sec_info.domain_id) {
|
||||
if ((ret = create_domain_dir()) < 0)
|
||||
return ret;
|
||||
@@ -490,9 +466,9 @@ done_init:
|
||||
#endif
|
||||
|
||||
if (!pal_sec_info.mcast_port) {
|
||||
do {
|
||||
getrand(&pal_sec_info.mcast_port, sizeof(unsigned short));
|
||||
} while (pal_sec_info.mcast_port < 1024);
|
||||
unsigned short mcast_port;
|
||||
getrand(&mcast_port, sizeof(unsigned short));
|
||||
pal_sec_info.mcast_port = mcast_port % 1024;
|
||||
}
|
||||
|
||||
__pal_control.broadcast_stream = pal_sec_info.mcast_handle ? :
|
||||
|
||||
@@ -55,10 +55,10 @@ unsigned long _DkSystemTimeQuery (void)
|
||||
|
||||
#if USE_VDSO_GETTIME == 1
|
||||
if (__vdso_clock_gettime) {
|
||||
ret = __vdso_clock_gettime(CLOCK_MONOTONIC, &time);
|
||||
ret = __vdso_clock_gettime(CLOCK_REALTIME, &time);
|
||||
} else {
|
||||
#endif
|
||||
ret = INLINE_SYSCALL(clock_gettime, 2, CLOCK_MONOTONIC, &time);
|
||||
ret = INLINE_SYSCALL(clock_gettime, 2, CLOCK_REALTIME, &time);
|
||||
#if USE_VDSO_GETTIME == 1
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -165,7 +165,7 @@ static int pipe_waitforclient (PAL_HANDLE handle, PAL_HANDLE * client)
|
||||
*client = clnt;
|
||||
#else
|
||||
PAL_IDX connid;
|
||||
getrand(&connid, sizeof(PAL_IDX));
|
||||
system_getrand(&connid, sizeof(PAL_IDX));
|
||||
PAL_HANDLE clnt = malloc(HANDLE_SIZE(pipe));
|
||||
SET_HANDLE_TYPE(clnt, pipecli);
|
||||
clnt->__in.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
|
||||
|
||||
@@ -106,7 +106,7 @@ int _DkProcessCreate (PAL_HANDLE * handle, const char * uri,
|
||||
const char ** new_args = __alloca(sizeof(const char *) * (nargs + 3));
|
||||
int bufsize = STRARG_SIZE;
|
||||
char * argbuf = __alloca(STRARG_SIZE);
|
||||
new_args[0] = pal_config.lib_name;
|
||||
new_args[0] = PAL_LOADER;
|
||||
new_args[1] = argbuf;
|
||||
if (args)
|
||||
memcpy(new_args + 2, args, sizeof(const char *) * nargs);
|
||||
@@ -170,7 +170,7 @@ int _DkProcessCreate (PAL_HANDLE * handle, const char * uri,
|
||||
if (manifest_fd >= 0)
|
||||
INLINE_SYSCALL(fcntl, 3, manifest_fd, F_SETFD, 0);
|
||||
|
||||
rete = INLINE_SYSCALL(execve, 3, pal_config.lib_name, new_args,
|
||||
rete = INLINE_SYSCALL(execve, 3, PAL_LOADER, new_args,
|
||||
pal_config.environments);
|
||||
|
||||
/* shouldn't get to here */
|
||||
|
||||
+106
-23
@@ -43,7 +43,111 @@
|
||||
|
||||
#include "elf-x86_64.h"
|
||||
|
||||
struct link_map * rtld_map = NULL;
|
||||
/* This structure communicates dl state to the debugger. The debugger
|
||||
normally finds it via the DT_DEBUG entry in the dynamic section, but in
|
||||
a statically-linked program there is no dynamic section for the debugger
|
||||
to examine and it looks for this particular symbol name. */
|
||||
struct r_debug pal_r_debug =
|
||||
{ 1, NULL, (ElfW(Addr)) &pal_dl_debug_state, RT_CONSISTENT, 0 };
|
||||
|
||||
extern __typeof(pal_r_debug) _r_debug
|
||||
__attribute ((alias ("pal_r_debug")));
|
||||
|
||||
/* This function exists solely to have a breakpoint set on it by the
|
||||
debugger. The debugger is supposed to find this function's address by
|
||||
examining the r_brk member of struct r_debug, but GDB 4.15 in fact looks
|
||||
for this particular symbol name in the PT_INTERP file. */
|
||||
|
||||
/* The special symbol name is set as breakpoint in gdb */
|
||||
void __attribute__((noinline)) pal_dl_debug_state (void)
|
||||
{
|
||||
if (pal_sec_info._dl_debug_state)
|
||||
pal_sec_info._dl_debug_state();
|
||||
}
|
||||
|
||||
extern __typeof(pal_dl_debug_state) _dl_debug_state
|
||||
__attribute ((alias ("pal_dl_debug_state")));
|
||||
|
||||
void _DkDebugAddMap (struct link_map * map)
|
||||
{
|
||||
struct r_debug * dbg = pal_sec_info._r_debug ? : &pal_r_debug;
|
||||
int len = map->l_name ? strlen(map->l_name) + 1 : 0;
|
||||
|
||||
struct link_map ** prev = &dbg->r_map, * last = NULL,
|
||||
* tmp = *prev;
|
||||
while (tmp) {
|
||||
if (tmp->l_addr == map->l_addr &&
|
||||
tmp->l_ld == map->l_ld &&
|
||||
!memcmp(tmp->l_name, map->l_name, len))
|
||||
return;
|
||||
|
||||
last = tmp;
|
||||
tmp = *(prev = &last->l_next);
|
||||
}
|
||||
|
||||
struct link_gdb_map * m = malloc(sizeof(struct link_gdb_map) + len);
|
||||
if (!m)
|
||||
return;
|
||||
|
||||
if (len) {
|
||||
m->l_name = (char *) m + sizeof(struct link_gdb_map);
|
||||
memcpy((void *) m->l_name, map->l_name, len);
|
||||
} else {
|
||||
m->l_name = NULL;
|
||||
}
|
||||
|
||||
m->l_addr = map->l_addr;
|
||||
m->l_ld = map->l_real_ld;
|
||||
|
||||
dbg->r_state = RT_ADD;
|
||||
pal_dl_debug_state();
|
||||
|
||||
*prev = (struct link_map *) m;
|
||||
m->l_prev = last;
|
||||
m->l_next = NULL;
|
||||
|
||||
dbg->r_state = RT_CONSISTENT;
|
||||
pal_dl_debug_state();
|
||||
}
|
||||
|
||||
void _DkDebugDelMap (struct link_map * map)
|
||||
{
|
||||
struct r_debug * dbg = pal_sec_info._r_debug ? : &pal_r_debug;
|
||||
int len = map->l_name ? strlen(map->l_name) + 1 : 0;
|
||||
|
||||
struct link_map ** prev = &dbg->r_map, * last = NULL,
|
||||
* tmp = *prev, * found = NULL;
|
||||
while (tmp) {
|
||||
if (tmp->l_addr == map->l_addr &&
|
||||
tmp->l_ld == map->l_ld &&
|
||||
!memcmp(tmp->l_name, map->l_name, len)) {
|
||||
found = tmp;
|
||||
break;
|
||||
}
|
||||
|
||||
last = tmp;
|
||||
tmp = *(prev = &last->l_next);
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return;
|
||||
|
||||
dbg->r_state = RT_DELETE;
|
||||
pal_dl_debug_state();
|
||||
|
||||
if (last)
|
||||
last->l_next = tmp->l_next;
|
||||
else
|
||||
dbg->r_map = tmp->l_next;
|
||||
|
||||
if (tmp->l_next)
|
||||
tmp->l_next->l_prev = last;
|
||||
|
||||
free(tmp);
|
||||
|
||||
dbg->r_state = RT_CONSISTENT;
|
||||
pal_dl_debug_state();
|
||||
}
|
||||
|
||||
extern void setup_elf_hash (struct link_map *map);
|
||||
|
||||
@@ -84,30 +188,9 @@ void setup_pal_map (const char * realname, ElfW(Dyn) ** dyn, ElfW(Addr) addr)
|
||||
l->l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) &pal_r_debug;
|
||||
|
||||
l->l_prev = l->l_next = NULL;
|
||||
rtld_map = l;
|
||||
loaded_libraries = l;
|
||||
|
||||
if (!pal_sec_info._r_debug) {
|
||||
pal_r_debug.r_version = 1;
|
||||
pal_r_debug.r_brk = (ElfW(Addr)) &pal_dl_debug_state;
|
||||
pal_r_debug.r_ldbase = addr;
|
||||
pal_r_debug.r_map = loaded_libraries;
|
||||
pal_sec_info._r_debug = &pal_r_debug;
|
||||
pal_sec_info._dl_debug_state = &pal_dl_debug_state;
|
||||
} else {
|
||||
pal_sec_info._r_debug->r_state = RT_ADD;
|
||||
pal_sec_info._dl_debug_state();
|
||||
|
||||
if (pal_sec_info._r_debug->r_map) {
|
||||
l->l_prev = pal_sec_info._r_debug->r_map;
|
||||
pal_sec_info._r_debug->r_map->l_next = l;
|
||||
} else {
|
||||
pal_sec_info._r_debug->r_map = loaded_libraries;
|
||||
}
|
||||
|
||||
pal_sec_info._r_debug->r_state = RT_CONSISTENT;
|
||||
pal_sec_info._dl_debug_state();
|
||||
}
|
||||
_DkDebugAddMap(l);
|
||||
}
|
||||
|
||||
#if USE_VDSO_GETTIME == 1
|
||||
|
||||
@@ -44,11 +44,10 @@ PAL {
|
||||
DkStreamAttributesSetbyHandle;
|
||||
|
||||
# Debugging ABIs
|
||||
pal_printf; pal_snprintf;
|
||||
pal_printf; pal_snprintf; DkDebugAttachBinary; DkDebugDetachBinary;
|
||||
|
||||
# Control block
|
||||
pal_control; pal_control_addr; pal_sec_info;
|
||||
|
||||
|
||||
local: *;
|
||||
};
|
||||
@@ -23,6 +23,9 @@
|
||||
#include "pal_defs.h"
|
||||
#include "pal_linux_defs.h"
|
||||
#include "pal.h"
|
||||
#include "pal_internal.h"
|
||||
|
||||
#define PAL_LOADER XSTRINGIFY(PAL_LOADER_PATH)
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
|
||||
@@ -59,6 +59,9 @@ int pal_snprintf (char *buf, size_t n, const char *fmt, ...);
|
||||
int pal_atoi (const char *nptr);
|
||||
long int pal_atol (const char *nptr);
|
||||
|
||||
void DkDebugAttachBinary (PAL_STR uri, PAL_PTR start_addr);
|
||||
void DkDebugDetachBinary (PAL_PTR start_addr);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,9 +35,6 @@
|
||||
# error "pal_internal.h can only be included in PAL"
|
||||
#endif
|
||||
|
||||
#define LIBRARY_NAME "libpal.so"
|
||||
#define LIBRARY_NAMELEN 9
|
||||
|
||||
/* handle_ops is the operators provided for each handler type. They are
|
||||
mostly used by Stream-related PAL calls, but can also be used by
|
||||
some others in special ways. */
|
||||
@@ -286,7 +283,6 @@ extern struct pal_config {
|
||||
PAL_HANDLE manifest_handle;
|
||||
PAL_HANDLE exec_handle;
|
||||
struct config_store * root_config;
|
||||
const char * lib_name;
|
||||
const char ** environments;
|
||||
unsigned long pagesize;
|
||||
unsigned long alloc_align;
|
||||
@@ -430,7 +426,7 @@ int unblock_signals (int * sigs, int nsig);
|
||||
void * find_address (void * addr);
|
||||
|
||||
/* function and definition for loading binaries */
|
||||
enum object_type { OBJECT_RTLD, OBJECT_EXEC, OBJECT_PRELOAD };
|
||||
enum object_type { OBJECT_RTLD, OBJECT_EXEC, OBJECT_PRELOAD, OBJECT_EXTERNAL };
|
||||
|
||||
int check_elf_object (PAL_HANDLE handle);
|
||||
int load_elf_object (const char * uri, enum object_type type);
|
||||
|
||||
@@ -102,6 +102,16 @@ struct link_map {
|
||||
const Elf32_Word * l_gnu_chain_zero;
|
||||
};
|
||||
|
||||
struct link_gdb_map {
|
||||
/* These first few members are part of the protocol with the debugger.
|
||||
This is the same format used in SVR4. */
|
||||
|
||||
ElfW(Addr) l_addr; /* Base address shared object is loaded at. */
|
||||
const char * l_name; /* Absolute file name object was found in. */
|
||||
ElfW(Dyn) * l_ld; /* Dynamic section of the shared object. */
|
||||
struct link_map * l_next, * l_prev; /* Chain of loaded objects. */
|
||||
};
|
||||
|
||||
extern struct link_map * loaded_libraries;
|
||||
extern struct link_map * rtld_map;
|
||||
extern struct link_map * exec_map;
|
||||
@@ -207,4 +217,9 @@ do_lookup_map (ElfW(Sym) * ref, const char * undef_name,
|
||||
const uint_fast32_t hash, unsigned long int elf_hash,
|
||||
const struct link_map * map);
|
||||
|
||||
/* for GDB debugging */
|
||||
void _DkDebugAddMap (struct link_map * map);
|
||||
void _DkDebugDelMap (struct link_map * map);
|
||||
|
||||
|
||||
#endif /* PAL_RTLD_H */
|
||||
|
||||
@@ -27,7 +27,6 @@ libpal_sec.so: $(addsuffix .o,$(objs)) $(graphene_lib)
|
||||
@echo [ security/Linux/$@ ]
|
||||
@[ ! -f $@ ] || mv -f $@ $@.backup
|
||||
@$(LD) $(LDFLAGS) -o $@ $^ -soname=libpal_sec.so
|
||||
@cd ../.. && ln -sf security/Linux/libpal_sec.so
|
||||
|
||||
%.o: %.c
|
||||
@echo [ security/Linux/$@ ]
|
||||
|
||||
Reference in New Issue
Block a user