diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/nt64/atomic.h | 7 | ||||
-rw-r--r-- | arch/nt64/psxglue.h | 63 | ||||
-rw-r--r-- | arch/nt64/pthread_arch.h | 74 | ||||
-rw-r--r-- | arch/nt64/reloc.h | 6 | ||||
-rw-r--r-- | arch/nt64/src/crt_glue.c | 87 | ||||
-rw-r--r-- | arch/nt64/src/crt_pe.c | 7 | ||||
-rw-r--r-- | arch/nt64/src/crt_tls.c | 27 | ||||
-rw-r--r-- | arch/nt64/src/libc_entry_point.c | 10 | ||||
-rw-r--r-- | arch/nt64/src/syscall_disp.c | 22 | ||||
-rw-r--r-- | arch/nt64/src/vtbl.c | 12 | ||||
-rw-r--r-- | arch/nt64/syscall_arch.h | 63 |
11 files changed, 378 insertions, 0 deletions
diff --git a/arch/nt64/atomic.h b/arch/nt64/atomic.h new file mode 100644 index 0000000..a2b141a --- /dev/null +++ b/arch/nt64/atomic.h @@ -0,0 +1,7 @@ +#ifndef _INTERNAL_ATOMIC_NT64_H +#define _INTERNAL_ATOMIC_NT64_H + +#include "../x86_64/atomic.h" + +#endif + diff --git a/arch/nt64/psxglue.h b/arch/nt64/psxglue.h new file mode 100644 index 0000000..73ad2b0 --- /dev/null +++ b/arch/nt64/psxglue.h @@ -0,0 +1,63 @@ +#ifndef _PSXGLUE_H_ +#define _PSXGLUE_H_ + +#define __PSXOPT_NATIVE 0x0 +#define __PSXOPT_POSIX 0x1 +#define __PSXOPT_TTYDBG 0x2 +#define __PSXOPT_LDSO 0x4 + +typedef int __ldso_dladdr(const void * addr, void * info); +typedef int __ldso_dlinfo(void * dso, int req, void * res); +typedef void * __ldso_dlsym(void * p, const char * s, void * ra); +typedef void * __ldso_dlopen(const char * file, int mode); +typedef int __ldso_dlclose(void *p); +typedef char * __ldso_dlerror(void); +typedef void __ldso_reset_tls(void); + +typedef void __psx_convert_thread(void); +typedef void __psx_unmapself(void *, void *); +typedef void * __psx_get_osfhandle(int fd); + +struct __ldso_vtbl { + __ldso_dladdr * dladdr; + __ldso_dlinfo * dlinfo; + __ldso_dlsym * dlsym; + __ldso_dlopen * dlopen; + __ldso_dlclose * dlclose; + __ldso_dlerror * dlerror; + __ldso_reset_tls * reset_tls; +}; + +struct __psx_vtbl { + __psx_convert_thread * convert_thread; + __psx_unmapself * unmapself; + __psx_get_osfhandle * get_osfhandle; +}; + +struct __psx_context { + int size; + int options; + void *** sys_vtbl; + struct __ldso_vtbl * ldso_vtbl; + struct __psx_vtbl * psx_vtbl; + unsigned int teb_sys_idx; + unsigned int teb_libc_idx; + void * pthread_surrogate_fn; + void * pthread_create_fn; +}; + +struct __tlca { + void * pthread_self; + int * pthread_set_child_tid; + int * pthread_clear_child_tid; + char * pthread_tls; + char ***pthread_dtls; +}; + +typedef int __psx_init_routine( + int * argc, + char *** argv, + char *** envp, + struct __psx_context * ctx); + +#endif diff --git a/arch/nt64/pthread_arch.h b/arch/nt64/pthread_arch.h new file mode 100644 index 0000000..98babcd --- /dev/null +++ b/arch/nt64/pthread_arch.h @@ -0,0 +1,74 @@ +#include <stddef.h> + +#define TP_ADJ(p) (p) +#define CANCEL_REG_IP 16 + +extern uintptr_t __teb_sys_idx; +extern uintptr_t __teb_libc_idx; + +struct __os_tib { + void * exception_list; + void * stack_base; + void * stack_limit; +}; + +static __inline__ void * __os_get_teb_address(void) +{ + void * ptrRet; + __asm__ __volatile__ ( + "mov %%gs:0x30, %0\n\t" + : "=r" (ptrRet) : : + ); + return ptrRet; +} + + +static inline void __pthread_convert(void) +{ + /* (third-party thread support) */ + __asm__ __volatile__ ( + "push %rax\n\t" + "movq __psx_vtbl,%rax\n\t" + "call *(%rax)\n\t" + "pop %rax\n\t" + ); +} + + +static inline struct pthread ** __psx_tlca(void) +{ + struct pthread ** ptlca; + struct __os_tib * tib; + void ** slots; + void *** xslots; + uintptr_t sys_idx; + + tib = __os_get_teb_address(); + sys_idx = __teb_sys_idx; + + if (sys_idx < 64) { + slots = (void **)((uintptr_t)tib + 0x1480); + ptlca = (struct pthread **)(slots[sys_idx]); + } else { + xslots = (void ***)((uintptr_t)tib + 0x1780); + slots = *xslots; + ptlca = (struct pthread **)(slots[sys_idx - 64]); + } + + return ptlca; +} + + +static inline struct pthread * __pthread_self(void) +{ + struct pthread ** ptlca; + + ptlca = __psx_tlca(); + if (ptlca) return *ptlca; + + /* (third-party thread) */ + __pthread_convert(); + ptlca = __psx_tlca(); + return *ptlca; +} + diff --git a/arch/nt64/reloc.h b/arch/nt64/reloc.h new file mode 100644 index 0000000..20abf44 --- /dev/null +++ b/arch/nt64/reloc.h @@ -0,0 +1,6 @@ +#define LDSO_ARCH "PE32+" + +static int remap_rel(int type) +{ + return 0; +} diff --git a/arch/nt64/src/crt_glue.c b/arch/nt64/src/crt_glue.c new file mode 100644 index 0000000..e8a07de --- /dev/null +++ b/arch/nt64/src/crt_glue.c @@ -0,0 +1,87 @@ +#include <unistd.h> +#include <pthread.h> +#include "atomic.h" +#include "syscall.h" +#include "psxglue.h" +#include "pthread_impl.h" + +extern struct __ldso_vtbl * __ldso_vtbl; +extern struct __psx_vtbl * __psx_vtbl; + +typedef int __app_main(); +typedef int __pthread_surrogate_routine(struct pthread *); + +extern int _init(void); +static int __pthread_surrogate_init(struct pthread * self); + +extern int __libc_start_main( + void * main, + int argc, + char ** argv); + +void __libc_entry_routine( + __app_main * __main, + __psx_init_routine * __psx_init_routine, + int options) +{ + int argc; + char ** argv; + char ** envp; + struct __psx_context ctx; + + /* ctx init */ + ctx.size = sizeof(ctx); + ctx.options = options; + ctx.pthread_create_fn = pthread_create; + ctx.pthread_surrogate_fn= __pthread_surrogate_init; + + /* __psx_init must succeed... */ + if (__psx_init_routine(&argc,&argv,&envp,&ctx)) + a_crash(); + + /* ...and conform */ + else if (envp != argv + (argc + 1)) + a_crash(); + + /* dso init routines */ + _init(); + + /* write once */ + __syscall_vtbl = (unsigned long **)ctx.sys_vtbl; + __ldso_vtbl = ctx.ldso_vtbl; + __psx_vtbl = ctx.psx_vtbl; + __teb_sys_idx = ctx.teb_sys_idx; + __teb_libc_idx = ctx.teb_libc_idx; + + /* enter libc */ + __libc_start_main(__main,argc,argv); + + /* guard */ + a_crash(); +} + +static int __pthread_surrogate_init(struct pthread * self) +{ + /** + * invoked by psxscl upon creation of a surrogate libc + * thread, which in turn may only call pthread_create(); + * + * the purpose of this mecahnism is to support a scenario + * where a third-party library creates a non-posix thread + * which then calls, be it directly or via a callback + * function, a libc api that depends on a valid + * pthread_self. + * + * self: a pointer to an already zero'ed memory page + * + * struct pthread relevant members: + * -------------------------------- + * cancel (already zero) + * canary (already zero) + * + * pthread_create() reference: + * 1a47ed15eebf96d0c8d5de4aea54108bc8cc3f53 + **/ + + return 0; +} diff --git a/arch/nt64/src/crt_pe.c b/arch/nt64/src/crt_pe.c new file mode 100644 index 0000000..0dc75a4 --- /dev/null +++ b/arch/nt64/src/crt_pe.c @@ -0,0 +1,7 @@ +#include "pthread_impl.h" +#include <threads.h> + +void * __pthread_getspecific_impl(pthread_key_t k) +{ + return (__pthread_self())->tsd[k]; +} diff --git a/arch/nt64/src/crt_tls.c b/arch/nt64/src/crt_tls.c new file mode 100644 index 0000000..15183d3 --- /dev/null +++ b/arch/nt64/src/crt_tls.c @@ -0,0 +1,27 @@ +#include <stdint.h> +#include <stddef.h> +#include "psxglue.h" +#include "pthread_arch.h" + +typedef unsigned int __tls_word __attribute__((mode(word))); +typedef unsigned int __tls_ptr __attribute__((mode(pointer))); + +struct __emutls_object +{ + __tls_word size; + __tls_word align; + ptrdiff_t offset; + void * defval; +}; + +void * __emutls_get_address (struct __emutls_object * obj) +{ + int dsoidx = obj->align & 0xFFFF0000; + struct __tlca * tlca = (struct __tlca *)__psx_tlca(); + + if (dsoidx) + return (*tlca->pthread_dtls)[dsoidx >> 16] + obj->offset; + else + return tlca->pthread_tls + obj->offset; +} + diff --git a/arch/nt64/src/libc_entry_point.c b/arch/nt64/src/libc_entry_point.c new file mode 100644 index 0000000..0929cc4 --- /dev/null +++ b/arch/nt64/src/libc_entry_point.c @@ -0,0 +1,10 @@ +typedef unsigned int uint32_t; + +int __libc_entry_point( + void * hinstance, + uint32_t reason, + void * reserved) +{ + return 1; +} + diff --git a/arch/nt64/src/syscall_disp.c b/arch/nt64/src/syscall_disp.c new file mode 100644 index 0000000..cb9655d --- /dev/null +++ b/arch/nt64/src/syscall_disp.c @@ -0,0 +1,22 @@ +#include <stdint.h> +#include <stddef.h> +#include "syscall.h" +#include "psxglue.h" + +extern struct __psx_vtbl * __psx_vtbl; + +void __unmapself(void * base, size_t size) +{ + __psx_vtbl->unmapself(base,size); +} + +uintptr_t __syscall_disp(long n, + uintptr_t a1, + uintptr_t a2, + uintptr_t a3, + uintptr_t a4, + uintptr_t a5, + uintptr_t a6) +{ + return __syscall(n,a1,a2,a3,a4,a5,a6); +} diff --git a/arch/nt64/src/vtbl.c b/arch/nt64/src/vtbl.c new file mode 100644 index 0000000..028f153 --- /dev/null +++ b/arch/nt64/src/vtbl.c @@ -0,0 +1,12 @@ +#include "psxglue.h" + +unsigned long ** __syscall_vtbl = 0; +struct __ldso_vtbl * __ldso_vtbl = 0; +struct __psx_vtbl * __psx_vtbl = 0; +unsigned long __teb_sys_idx = 0; +unsigned long __teb_libc_idx = 0; + +void ___chkstk_ms(void) +{ +} + diff --git a/arch/nt64/syscall_arch.h b/arch/nt64/syscall_arch.h new file mode 100644 index 0000000..9c8fea4 --- /dev/null +++ b/arch/nt64/syscall_arch.h @@ -0,0 +1,63 @@ +extern unsigned long ** __syscall_vtbl; + +typedef long __syscall0_fn(void); +typedef long __syscall1_fn(long a1); +typedef long __syscall2_fn(long a1, long a2); +typedef long __syscall3_fn(long a1, long a2, long a3); +typedef long __syscall4_fn(long a1, long a2, long a3, long a4); +typedef long __syscall5_fn(long a1, long a2, long a3, long a4, long a5); +typedef long __syscall6_fn(long a1, long a2, long a3, long a4, long a5, long a6); + +#define sysfn_from_fn(x) \ + x * sysfn = (x *)__syscall_vtbl[n] + +static __inline long __syscall0(long n) +{ + sysfn_from_fn(__syscall0_fn); + return sysfn(); +} + +static __inline long __syscall1(long n, long a1) +{ + sysfn_from_fn(__syscall1_fn); + return sysfn(a1); +} + +static __inline long __syscall2(long n, long a1, long a2) +{ + sysfn_from_fn(__syscall2_fn); + return sysfn(a1, a2); +} + +static __inline long __syscall3(long n, long a1, long a2, long a3) +{ + sysfn_from_fn(__syscall3_fn); + return sysfn(a1, a2, a3); +} + +static __inline long __syscall4(long n, long a1, long a2, long a3, long a4) +{ + sysfn_from_fn(__syscall4_fn); + return sysfn(a1, a2, a3, a4); +} + +static __inline long __syscall5(long n, long a1, long a2, long a3, long a4, long a5) +{ + sysfn_from_fn(__syscall5_fn); + return sysfn(a1, a2, a3, a4, a5); +} + +static __inline long __syscall6(long n, long a1, long a2, long a3, long a4, long a5, long a6) +{ + sysfn_from_fn(__syscall6_fn); + return sysfn(a1, a2, a3, a4, a5, a6); +} + + +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + + +#define VDSO_USEFUL +#define VDSO_CGT_SYM "__clock_gettime" +#define VDSO_CGT_VER "LINUX_2.6" |