diff --git a/lib/emscripten/src/emscripten_target.rs b/lib/emscripten/src/emscripten_target.rs
index 329136e11..f12d681f9 100644
--- a/lib/emscripten/src/emscripten_target.rs
+++ b/lib/emscripten/src/emscripten_target.rs
@@ -135,7 +135,8 @@ pub fn _pthread_condattr_setclock(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
 }
 pub fn _pthread_create(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32, _d: i32) -> i32 {
     trace!("emscripten::_pthread_create");
-    0
+    // 11 seems to mean "no"
+    11
 }
 pub fn _pthread_detach(_ctx: &mut Ctx, _a: i32) -> i32 {
     trace!("emscripten::_pthread_detach");
diff --git a/lib/emscripten/src/env/unix/mod.rs b/lib/emscripten/src/env/unix/mod.rs
index 35c2b1852..cd7613ca2 100644
--- a/lib/emscripten/src/env/unix/mod.rs
+++ b/lib/emscripten/src/env/unix/mod.rs
@@ -220,10 +220,10 @@ pub fn _getaddrinfo(
                 .deref(memory)
                 .map(|m| m as *const Cell<c_char> as *const c_char))
             .unwrap_or(std::ptr::null()),
-            (service_str_ptr
+            service_str_ptr
                 .deref(memory)
-                .map(|m| m as *const Cell<c_char> as *const c_char))
-            .unwrap_or(std::ptr::null()),
+                .map(|m| m as *const Cell<c_char> as *const c_char)
+                .unwrap_or(std::ptr::null()),
             hints
                 .as_ref()
                 .map(|h| h as *const addrinfo)
diff --git a/lib/emscripten/src/memory.rs b/lib/emscripten/src/memory.rs
index 0f1cb1f19..e3ff2e4c8 100644
--- a/lib/emscripten/src/memory.rs
+++ b/lib/emscripten/src/memory.rs
@@ -21,9 +21,9 @@ pub fn _emscripten_memcpy_big(ctx: &mut Ctx, dest: u32, src: u32, len: u32) -> u
 
 /// emscripten: _emscripten_get_heap_size
 pub fn _emscripten_get_heap_size(ctx: &mut Ctx) -> u32 {
-    debug!("emscripten::_emscripten_get_heap_size");
+    trace!("emscripten::_emscripten_get_heap_size");
     let result = ctx.memory(0).size().bytes().0 as u32;
-    debug!("=> {}", result);
+    trace!("=> {}", result);
 
     result
 }
diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs
index 34ba90818..2e9b39fd3 100644
--- a/lib/emscripten/src/syscalls/mod.rs
+++ b/lib/emscripten/src/syscalls/mod.rs
@@ -276,34 +276,6 @@ pub fn ___syscall75(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
     -1
 }
 
-// readlink
-pub fn ___syscall85(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
-    debug!("emscripten::___syscall85 (readlink)");
-    let _path = varargs.get_str(ctx);
-    let buf = varargs.get_str(ctx);
-    // let buf_addr: i32 = varargs.get(ctx);
-    let buf_size: i32 = varargs.get(ctx);
-    let fd = 3;
-    let ret = unsafe { read(fd, buf as _, buf_size as _) as i32 };
-    debug!(
-        "=> buf: {}, buf_size: {}, return: {} ",
-        unsafe { std::ffi::CStr::from_ptr(buf as _).to_str().unwrap() },
-        buf_size,
-        ret
-    );
-    // let ret = unsafe {
-    //     readlink(path, buf as _, buf_size as _) as i32
-    // };
-    // debug!("=> path: {}, buf: {}, buf_size: {}, return: {} ",
-    //     unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() },
-    //     unsafe { std::ffi::CStr::from_ptr(buf as _).to_str().unwrap() },
-    //     // std::ffi::CStr::from_ptr(buf).to_str().unwrap(),
-    //     // buf,
-    //     buf_size,
-    //     ret);
-    ret
-}
-
 pub fn ___syscall91(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
     debug!("emscripten::___syscall91 - stub");
     0
@@ -531,11 +503,6 @@ pub fn ___syscall146(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
     }
 }
 
-pub fn ___syscall168(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
-    debug!("emscripten::___syscall168 - stub");
-    -1
-}
-
 pub fn ___syscall191(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
     let _resource: i32 = varargs.get(ctx);
     debug!(
diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix.rs
index 1c041c434..6ce54ebb6 100644
--- a/lib/emscripten/src/syscalls/unix.rs
+++ b/lib/emscripten/src/syscalls/unix.rs
@@ -7,7 +7,6 @@ use libc::{
     accept,
     access,
     bind,
-    c_char,
     c_int,
     c_void,
     chown,
@@ -72,15 +71,15 @@ use libc::{
     F_GETFD,
     F_SETFD,
     SOL_SOCKET,
-    SO_REUSEADDR,
     TIOCGWINSZ,
 };
 
 #[allow(unused_imports)]
 use std::ffi::CStr;
-use wasmer_runtime_core::vm::Ctx;
+use wasmer_runtime_core::{memory::ptr::WasmPtr, vm::Ctx};
 
-use crate::utils;
+use crate::env::EmSockAddr;
+use crate::utils::{self, get_cstr_path};
 #[allow(unused_imports)]
 use std::io::Error;
 use std::mem;
@@ -92,7 +91,7 @@ extern "C" {
     pub fn wait4(pid: pid_t, status: *mut c_int, options: c_int, rusage: *mut rusage) -> pid_t;
     pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int;
     pub fn fdatasync(fd: c_int) -> c_int;
-    pub fn lstat64(path: *const c_char, buf: *mut c_void) -> c_int;
+    pub fn lstat64(path: *const libc::c_char, buf: *mut c_void) -> c_int;
 }
 
 #[cfg(not(target_os = "macos"))]
@@ -101,9 +100,9 @@ use libc::{fallocate, fdatasync, ftruncate64, lstat, madvise, wait4};
 // Another conditional constant for name resolution: Macos et iOS use
 // SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket.
 // Other platforms do otherwise.
-#[cfg(target_os = "darwin")]
+#[cfg(target_os = "macos")]
 use libc::SO_NOSIGPIPE;
-#[cfg(not(target_os = "darwin"))]
+#[cfg(not(target_os = "macos"))]
 const SO_NOSIGPIPE: c_int = 0;
 
 /// open
@@ -187,6 +186,35 @@ pub fn ___syscall83(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int
     result
 }
 
+/// readlink
+pub fn ___syscall85(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
+    debug!("emscripten::___syscall85 (readlink)");
+    let pathname_addr = varargs.get_str(ctx);
+    let buf = varargs.get_str(ctx);
+    // let buf_addr: i32 = varargs.get(ctx);
+    let buf_size: i32 = varargs.get(ctx);
+    let real_path_owned = get_cstr_path(ctx, pathname_addr);
+    let real_path = if let Some(ref rp) = real_path_owned {
+        rp.as_c_str().as_ptr()
+    } else {
+        pathname_addr
+    };
+
+    let ret = unsafe { libc::readlink(real_path, buf as _, buf_size as _) as i32 };
+    if ret == -1 {
+        debug!("readlink failed");
+        return ret;
+    }
+    debug!(
+        "=> path: {}, buf: {}, buf_size: {}, return: {} ",
+        unsafe { std::ffi::CStr::from_ptr(real_path).to_str().unwrap() },
+        unsafe { std::ffi::CStr::from_ptr(buf as _).to_str().unwrap() },
+        buf_size,
+        ret
+    );
+    ret
+}
+
 /// ftruncate64
 pub fn ___syscall194(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
     debug!("emscripten::___syscall194 (ftruncate64) {}", _which);
@@ -444,6 +472,7 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
     let call: u32 = varargs.get(ctx);
     let mut socket_varargs: VarArgs = varargs.get(ctx);
 
+    // migrating to EmSockAddr, port being separate here is nice, should update that too
     #[repr(C)]
     pub struct GuestSockaddrIn {
         pub sin_family: sa_family_t, // u16
@@ -458,13 +487,6 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
         pub s_addr: in_addr_t, // u32
     }
 
-    // debug!("GuestSockaddrIn = {}", size_of::<GuestSockaddrIn>());
-
-    pub struct LinuxSockAddr {
-        pub sa_family: u16,
-        pub sa_data: [c_char; 14],
-    }
-
     match call {
         1 => {
             debug!("socket: socket");
@@ -487,6 +509,7 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
                 unimplemented!("non blocking sockets");
             }
 
+            // why is this here?
             type T = u32;
             let payload = 1 as *const T as _;
             unsafe {
@@ -500,7 +523,7 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
             };
 
             debug!(
-                "=> domain: {} (AF_INET/2), type: {} (SOCK_STREAM/1), protocol: {} = fd: {}",
+                "=> domain: {}, type: {}, protocol: {} = fd: {}",
                 domain, ty, protocol, fd
             );
             fd as _
@@ -555,47 +578,75 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
         5 => {
             debug!("socket: accept");
             // accept (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int
-            let socket = socket_varargs.get(ctx);
-            let address_addr: u32 = socket_varargs.get(ctx);
-            let address_len: u32 = socket_varargs.get(ctx);
-            let address = emscripten_memory_pointer!(ctx.memory(0), address_addr) as *mut sockaddr;
+            let socket: i32 = socket_varargs.get(ctx);
+            let address: WasmPtr<EmSockAddr> = socket_varargs.get(ctx);
+            let address_len: WasmPtr<u32> = socket_varargs.get(ctx);
 
             debug!(
                 "=> socket: {}, address: {:?}, address_len: {}",
-                socket, address, address_len
+                socket,
+                address.deref(ctx.memory(0)).unwrap().get(),
+                address_len.deref(ctx.memory(0)).unwrap().get()
             );
             let address_len_addr =
-                emscripten_memory_pointer!(ctx.memory(0), address_len) as *mut socklen_t;
+                unsafe { address_len.deref_mut(ctx.memory(0)).unwrap().get_mut() };
             // let mut address_len_addr: socklen_t = 0;
 
-            let fd = unsafe { accept(socket, address, address_len_addr) };
+            let (fd, host_address) = unsafe {
+                let mut host_address: sockaddr = std::mem::uninitialized();
+                let fd = accept(socket, &mut host_address, address_len_addr);
 
-            unsafe {
-                let address_linux =
-                    emscripten_memory_pointer!(ctx.memory(0), address_addr) as *mut LinuxSockAddr;
-                (*address_linux).sa_family = (*address).sa_family as u16;
-                (*address_linux).sa_data = (*address).sa_data;
+                (fd, host_address)
             };
 
+            let address_addr = unsafe { address.deref_mut(ctx.memory(0)).unwrap().get_mut() };
+
+            address_addr.sa_family = host_address.sa_family as _;
+            address_addr.sa_data = host_address.sa_data.clone();
+
+            // why is this here?
             // set_cloexec
             unsafe {
                 ioctl(fd, FIOCLEX);
             };
 
-            debug!("fd: {}", fd);
+            debug!(
+                "address: {:?}, len: {}, result fd = {}",
+                address_addr, address_len_addr, fd
+            );
 
             fd as _
         }
         6 => {
             debug!("socket: getsockname");
             // getsockname (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int
-            let socket = socket_varargs.get(ctx);
-            let address: u32 = socket_varargs.get(ctx);
-            let address_len: u32 = socket_varargs.get(ctx);
-            let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut sockaddr;
+            let socket: i32 = socket_varargs.get(ctx);
+            let address: WasmPtr<EmSockAddr> = socket_varargs.get(ctx);
+            let address_len: WasmPtr<u32> = socket_varargs.get(ctx);
             let address_len_addr =
-                emscripten_memory_pointer!(ctx.memory(0), address_len) as *mut socklen_t;
-            unsafe { getsockname(socket, address, address_len_addr) }
+                unsafe { address_len.deref_mut(ctx.memory(0)).unwrap().get_mut() };
+
+            let (ret, sock_addr_host) = unsafe {
+                // read host data into new var
+                let mut address: sockaddr = std::mem::uninitialized();
+                let ret = getsockname(
+                    socket,
+                    &mut address as *mut sockaddr,
+                    address_len_addr as *mut u32,
+                );
+                (ret, address)
+            };
+            // translate from host data into emscripten data
+            let mut address_mut = unsafe { address.deref_mut(ctx.memory(0)).unwrap().get_mut() };
+            address_mut.sa_family = sock_addr_host.sa_family as _;
+            address_mut.sa_data = sock_addr_host.sa_data.clone();
+
+            debug!(
+                "=> socket: {}, address, {:?}, address_len: {}, result = {}",
+                socket, address_mut, address_len_addr, ret
+            );
+
+            ret
         }
         7 => {
             debug!("socket: getpeername");
@@ -647,25 +698,23 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
         }
         14 => {
             debug!("socket: setsockopt");
-            // NOTE: Emscripten seems to be passing the wrong values to this syscall
-            //      level: Em passes 1 as SOL_SOCKET; SOL_SOCKET is 0xffff in BSD
-            //      name: Em passes SO_ACCEPTCONN, but Nginx complains about REUSEADDR
+            // OSX and BSD have completely different values, be very careful here
             //      https://github.com/openbsd/src/blob/master/sys/sys/socket.h#L156
             // setsockopt (socket: c_int, level: c_int, name: c_int, value: *const c_void, option_len: socklen_t) -> c_int
 
             let socket = socket_varargs.get(ctx);
             let level: i32 = socket_varargs.get(ctx);
-            // SOL_SOCKET = 0xffff (BSD, OSX)
             let level = if level == 1 { SOL_SOCKET } else { level };
-            let name: i32 = socket_varargs.get(ctx);
-            // SO_REUSEADDR = 0x4 (BSD, OSX)
-            let name = if name == 2 { SO_REUSEADDR } else { name };
+            let untranslated_name: i32 = socket_varargs.get(ctx);
             let value: u32 = socket_varargs.get(ctx);
-            let option_len = socket_varargs.get(ctx);
-            let value_addr = emscripten_memory_pointer!(ctx.memory(0), value) as _; // Endian problem
+            let option_len: u32 = socket_varargs.get(ctx);
+            let value_addr =
+                emscripten_memory_pointer!(ctx.memory(0), value) as *const libc::c_void;
+            let name: i32 = translate_socket_name_flag(untranslated_name);
+
             let ret = unsafe { setsockopt(socket, level, name, value_addr, option_len) };
 
-            debug!("=> socketfd: {}, level: {}, name: {}, value_addr: {:?}, option_len: {} = status: {}", socket, level, name, value_addr, option_len, ret);
+            debug!("=> socketfd: {}, level: {}, name: {}, value_addr: {:?}, option_len: {} = status: {}", socket, level, untranslated_name, value_addr, option_len, ret);
             ret
         }
         15 => {
@@ -673,7 +722,9 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
             // getsockopt (sockfd: c_int, level: c_int, optname: c_int, optval: *mut c_void, optlen: *mut socklen_t) -> c_int
             let socket = socket_varargs.get(ctx);
             let level: i32 = socket_varargs.get(ctx);
-            let name: i32 = socket_varargs.get(ctx);
+            let level = if level == 1 { SOL_SOCKET } else { level };
+            let untranslated_name: i32 = socket_varargs.get(ctx);
+            let name: i32 = translate_socket_name_flag(untranslated_name);
             let value: u32 = socket_varargs.get(ctx);
             let option_len: u32 = socket_varargs.get(ctx);
             let value_addr = emscripten_memory_pointer!(ctx.memory(0), value) as _;
@@ -706,6 +757,60 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
     }
 }
 
+/// OSX and BSD have completely different values, we must translate from emscripten's Linuxy
+/// value into one that we can pass to native syscalls
+fn translate_socket_name_flag(name: i32) -> i32 {
+    match name {
+        2 => libc::SO_REUSEADDR,
+        3 => libc::SO_TYPE,
+        4 => libc::SO_ERROR,
+        5 => libc::SO_DONTROUTE,
+        6 => libc::SO_BROADCAST,
+        7 => libc::SO_SNDBUF,
+        8 => libc::SO_RCVBUF,
+        9 => libc::SO_KEEPALIVE,
+        10 => libc::SO_OOBINLINE,
+        13 => libc::SO_LINGER,
+        18 => libc::SO_RCVLOWAT,
+        19 => libc::SO_SNDLOWAT,
+        20 => libc::SO_RCVTIMEO,
+        21 => libc::SO_SNDTIMEO,
+        // SO_DEBUG missing
+        30 => libc::SO_ACCEPTCONN,
+        otherwise => otherwise,
+    }
+}
+
+#[derive(Debug, Copy, Clone)]
+#[repr(C)]
+pub struct EmPollFd {
+    pub fd: i32,
+    pub events: i16,
+    pub revents: i16,
+}
+
+unsafe impl wasmer_runtime_core::types::ValueType for EmPollFd {}
+
+/// poll
+pub fn ___syscall168(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
+    debug!("emscripten::___syscall168(poll)");
+    let fds: WasmPtr<EmPollFd> = varargs.get(ctx);
+    let nfds: u32 = varargs.get(ctx);
+    let timeout: i32 = varargs.get(ctx);
+
+    let fds_mut = unsafe { fds.deref_mut(ctx.memory(0)).unwrap().get_mut() };
+
+    let ret = unsafe {
+        libc::poll(
+            fds_mut as *mut EmPollFd as *mut libc::pollfd,
+            nfds as _,
+            timeout,
+        )
+    };
+
+    ret
+}
+
 // pread
 pub fn ___syscall180(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
     debug!("emscripten::___syscall180 (pread) {}", _which);
@@ -885,11 +990,11 @@ pub fn ___syscall220(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
 
     let dirp = emscripten_memory_pointer!(ctx.memory(0), dirp_addr) as *mut u8;
 
-    let mut opened_dirs = &mut get_emscripten_data(ctx).opened_dirs;
+    let opened_dirs = &mut get_emscripten_data(ctx).opened_dirs;
 
     // need to persist stream across calls?
     // let dir: *mut libc::DIR = unsafe { libc::fdopendir(fd) };
-    let mut dir = &*opened_dirs
+    let dir = &*opened_dirs
         .entry(fd)
         .or_insert_with(|| unsafe { Box::new(libc::fdopendir(fd)) });
 
diff --git a/lib/emscripten/src/syscalls/windows.rs b/lib/emscripten/src/syscalls/windows.rs
index 5551dd6e1..b48303358 100644
--- a/lib/emscripten/src/syscalls/windows.rs
+++ b/lib/emscripten/src/syscalls/windows.rs
@@ -128,6 +128,12 @@ pub fn ___syscall83(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
     unimplemented!()
 }
 
+/// readlink
+pub fn ___syscall85(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
+    debug!("emscripten::___syscall85 (readlink) {}", _which);
+    -1
+}
+
 /// lchown
 pub fn ___syscall198(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
     debug!("emscripten::___syscall198 (lchown) {}", _which);
@@ -255,6 +261,12 @@ pub fn ___syscall122(_ctx: &mut Ctx, which: c_int, mut _varargs: VarArgs) -> c_i
     -1
 }
 
+/// poll
+pub fn ___syscall168(_ctx: &mut Ctx, _which: i32, _varargs: VarArgs) -> i32 {
+    debug!("emscripten::___syscall168(poll) - stub");
+    -1
+}
+
 /// lstat64
 pub fn ___syscall196(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
     debug!("emscripten::___syscall196 (lstat64) - stub");
diff --git a/lib/runtime-core/src/memory/ptr.rs b/lib/runtime-core/src/memory/ptr.rs
index fd249b5e3..465474c13 100644
--- a/lib/runtime-core/src/memory/ptr.rs
+++ b/lib/runtime-core/src/memory/ptr.rs
@@ -46,7 +46,9 @@ fn align_pointer(ptr: usize, align: usize) -> usize {
 impl<T: Copy + ValueType> WasmPtr<T, Item> {
     #[inline]
     pub fn deref<'a>(self, memory: &'a Memory) -> Option<&'a Cell<T>> {
-        if (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0 {
+        if self.offset == 0
+            || (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0
+        {
             return None;
         }
         unsafe {
@@ -60,7 +62,9 @@ impl<T: Copy + ValueType> WasmPtr<T, Item> {
 
     #[inline]
     pub unsafe fn deref_mut<'a>(self, memory: &'a Memory) -> Option<&'a mut Cell<T>> {
-        if (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0 {
+        if self.offset == 0
+            || (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0
+        {
             return None;
         }
         let cell_ptr = align_pointer(
@@ -79,7 +83,9 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
         let item_size = mem::size_of::<T>() + (mem::size_of::<T>() % mem::align_of::<T>());
         let slice_full_len = index as usize + length as usize;
 
-        if (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0 {
+        if self.offset == 0
+            || (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0
+        {
             return None;
         }
 
@@ -106,7 +112,9 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
         let item_size = mem::size_of::<T>() + (mem::size_of::<T>() % mem::align_of::<T>());
         let slice_full_len = index as usize + length as usize;
 
-        if (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0 {
+        if self.offset == 0
+            || (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0
+        {
             return None;
         }