summaryrefslogtreecommitdiffhomepage
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/nt64/atomic.h7
-rw-r--r--arch/nt64/psxglue.h63
-rw-r--r--arch/nt64/pthread_arch.h74
-rw-r--r--arch/nt64/reloc.h6
-rw-r--r--arch/nt64/src/crt_glue.c87
-rw-r--r--arch/nt64/src/crt_pe.c7
-rw-r--r--arch/nt64/src/crt_tls.c27
-rw-r--r--arch/nt64/src/libc_entry_point.c10
-rw-r--r--arch/nt64/src/syscall_disp.c22
-rw-r--r--arch/nt64/src/vtbl.c12
-rw-r--r--arch/nt64/syscall_arch.h63
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"