about summary refs log tree commit diff
path: root/src/libstd/sys/windows
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2018-08-19 18:34:46 +0200
committerGitHub <noreply@github.com>2018-08-19 18:34:46 +0200
commit08b1d83a46848dd7bd778aeae67a1e529e95d8cd (patch)
tree9153a34f91860b175afb24f904fd50ac09e77c4e /src/libstd/sys/windows
parentac64ef33756d05557153e00211cdf8fcf65d4be3 (diff)
parentb355906919927ab3c879becd14392f023af883a1 (diff)
downloadrust-08b1d83a46848dd7bd778aeae67a1e529e95d8cd.tar.gz
rust-08b1d83a46848dd7bd778aeae67a1e529e95d8cd.zip
Merge branch 'master' into feature/core_convert_id
Diffstat (limited to 'src/libstd/sys/windows')
-rw-r--r--src/libstd/sys/windows/backtrace/mod.rs298
-rw-r--r--src/libstd/sys/windows/backtrace/printing/mod.rs14
-rw-r--r--src/libstd/sys/windows/backtrace/printing/msvc.rs198
-rw-r--r--src/libstd/sys/windows/c.rs84
-rw-r--r--src/libstd/sys/windows/ext/ffi.rs11
-rw-r--r--src/libstd/sys/windows/ext/fs.rs128
-rw-r--r--src/libstd/sys/windows/ext/mod.rs1
-rw-r--r--src/libstd/sys/windows/ext/process.rs8
-rw-r--r--src/libstd/sys/windows/fs.rs47
-rw-r--r--src/libstd/sys/windows/mod.rs10
-rw-r--r--src/libstd/sys/windows/mutex.rs2
-rw-r--r--src/libstd/sys/windows/os_str.rs5
-rw-r--r--src/libstd/sys/windows/pipe.rs2
-rw-r--r--src/libstd/sys/windows/process.rs26
-rw-r--r--src/libstd/sys/windows/stdio.rs4
-rw-r--r--src/libstd/sys/windows/thread.rs13
16 files changed, 655 insertions, 196 deletions
diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs
index 176891fff23..f64cae810b9 100644
--- a/src/libstd/sys/windows/backtrace/mod.rs
+++ b/src/libstd/sys/windows/backtrace/mod.rs
@@ -46,111 +46,281 @@ mod printing;
 #[path = "backtrace_gnu.rs"]
 pub mod gnu;
 
-pub use self::printing::{resolve_symname, foreach_symbol_fileline};
+pub use self::printing::{foreach_symbol_fileline, resolve_symname};
+use self::printing::{load_printing_fns_64, load_printing_fns_ex};
 
-pub fn unwind_backtrace(frames: &mut [Frame])
-    -> io::Result<(usize, BacktraceContext)>
-{
+pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> {
     let dbghelp = DynamicLibrary::open("dbghelp.dll")?;
 
     // Fetch the symbols necessary from dbghelp.dll
     let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn)?;
     let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn)?;
-    let StackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn)?;
+
+    // StackWalkEx might not be present and we'll fall back to StackWalk64
+    let sw_var = match sym!(dbghelp, "StackWalkEx", StackWalkExFn) {
+        Ok(StackWalkEx) => {
+            StackWalkVariant::StackWalkEx(StackWalkEx, load_printing_fns_ex(&dbghelp)?)
+        }
+        Err(e) => match sym!(dbghelp, "StackWalk64", StackWalk64Fn) {
+            Ok(StackWalk64) => {
+                StackWalkVariant::StackWalk64(StackWalk64, load_printing_fns_64(&dbghelp)?)
+            }
+            Err(..) => return Err(e),
+        },
+    };
 
     // Allocate necessary structures for doing the stack walk
     let process = unsafe { c::GetCurrentProcess() };
-    let thread = unsafe { c::GetCurrentThread() };
-    let mut context: c::CONTEXT = unsafe { mem::zeroed() };
-    unsafe { c::RtlCaptureContext(&mut context) };
-    let mut frame: c::STACKFRAME64 = unsafe { mem::zeroed() };
-    let image = init_frame(&mut frame, &context);
 
     let backtrace_context = BacktraceContext {
         handle: process,
         SymCleanup,
+        StackWalkVariant: sw_var,
         dbghelp,
     };
 
     // Initialize this process's symbols
     let ret = unsafe { SymInitialize(process, ptr::null_mut(), c::TRUE) };
     if ret != c::TRUE {
-        return Ok((0, backtrace_context))
+        return Ok((0, backtrace_context));
     }
 
     // And now that we're done with all the setup, do the stack walking!
-    // Start from -1 to avoid printing this stack frame, which will
-    // always be exactly the same.
+    match backtrace_context.StackWalkVariant {
+        StackWalkVariant::StackWalkEx(StackWalkEx, _) => {
+            set_frames(StackWalkEx, frames).map(|i| (i, backtrace_context))
+        }
+
+        StackWalkVariant::StackWalk64(StackWalk64, _) => {
+            set_frames(StackWalk64, frames).map(|i| (i, backtrace_context))
+        }
+    }
+}
+
+fn set_frames<W: StackWalker>(StackWalk: W, frames: &mut [Frame]) -> io::Result<usize> {
+    let process = unsafe { c::GetCurrentProcess() };
+    let thread = unsafe { c::GetCurrentProcess() };
+    let mut context: c::CONTEXT = unsafe { mem::zeroed() };
+    unsafe { c::RtlCaptureContext(&mut context) };
+    let mut frame = W::Item::new();
+    let image = frame.init(&context);
+
     let mut i = 0;
-    unsafe {
-        while i < frames.len() &&
-              StackWalk64(image, process, thread, &mut frame, &mut context,
-                          ptr::null_mut(),
-                          ptr::null_mut(),
-                          ptr::null_mut(),
-                          ptr::null_mut()) == c::TRUE
-        {
-            let addr = frame.AddrPC.Offset;
-            if addr == frame.AddrReturn.Offset || addr == 0 ||
-               frame.AddrReturn.Offset == 0 { break }
-
-            frames[i] = Frame {
-                symbol_addr: (addr - 1) as *const u8,
-                exact_position: (addr - 1) as *const u8,
-            };
-            i += 1;
+    while i < frames.len()
+        && StackWalk.walk(image, process, thread, &mut frame, &mut context) == c::TRUE
+    {
+        let addr = frame.get_addr();
+        frames[i] = Frame {
+            symbol_addr: addr,
+            exact_position: addr,
+            inline_context: 0,
+        };
+
+        i += 1
+    }
+    Ok(i)
+}
+
+type SymInitializeFn = unsafe extern "system" fn(c::HANDLE, *mut c_void, c::BOOL) -> c::BOOL;
+type SymCleanupFn = unsafe extern "system" fn(c::HANDLE) -> c::BOOL;
+
+type StackWalkExFn = unsafe extern "system" fn(
+    c::DWORD,
+    c::HANDLE,
+    c::HANDLE,
+    *mut c::STACKFRAME_EX,
+    *mut c::CONTEXT,
+    *mut c_void,
+    *mut c_void,
+    *mut c_void,
+    *mut c_void,
+    c::DWORD,
+) -> c::BOOL;
+
+type StackWalk64Fn = unsafe extern "system" fn(
+    c::DWORD,
+    c::HANDLE,
+    c::HANDLE,
+    *mut c::STACKFRAME64,
+    *mut c::CONTEXT,
+    *mut c_void,
+    *mut c_void,
+    *mut c_void,
+    *mut c_void,
+) -> c::BOOL;
+
+trait StackWalker {
+    type Item: StackFrame;
+
+    fn walk(&self, c::DWORD, c::HANDLE, c::HANDLE, &mut Self::Item, &mut c::CONTEXT) -> c::BOOL;
+}
+
+impl StackWalker for StackWalkExFn {
+    type Item = c::STACKFRAME_EX;
+    fn walk(
+        &self,
+        image: c::DWORD,
+        process: c::HANDLE,
+        thread: c::HANDLE,
+        frame: &mut Self::Item,
+        context: &mut c::CONTEXT,
+    ) -> c::BOOL {
+        unsafe {
+            self(
+                image,
+                process,
+                thread,
+                frame,
+                context,
+                ptr::null_mut(),
+                ptr::null_mut(),
+                ptr::null_mut(),
+                ptr::null_mut(),
+                0,
+            )
+        }
+    }
+}
+
+impl StackWalker for StackWalk64Fn {
+    type Item = c::STACKFRAME64;
+    fn walk(
+        &self,
+        image: c::DWORD,
+        process: c::HANDLE,
+        thread: c::HANDLE,
+        frame: &mut Self::Item,
+        context: &mut c::CONTEXT,
+    ) -> c::BOOL {
+        unsafe {
+            self(
+                image,
+                process,
+                thread,
+                frame,
+                context,
+                ptr::null_mut(),
+                ptr::null_mut(),
+                ptr::null_mut(),
+                ptr::null_mut(),
+            )
         }
     }
+}
+
+trait StackFrame {
+    fn new() -> Self;
+    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD;
+    fn get_addr(&self) -> *const u8;
+}
+
+impl StackFrame for c::STACKFRAME_EX {
+    fn new() -> c::STACKFRAME_EX {
+        unsafe { mem::zeroed() }
+    }
+
+    #[cfg(target_arch = "x86")]
+    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
+        self.AddrPC.Offset = ctx.Eip as u64;
+        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrStack.Offset = ctx.Esp as u64;
+        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrFrame.Offset = ctx.Ebp as u64;
+        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        c::IMAGE_FILE_MACHINE_I386
+    }
+
+    #[cfg(target_arch = "x86_64")]
+    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
+        self.AddrPC.Offset = ctx.Rip as u64;
+        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrStack.Offset = ctx.Rsp as u64;
+        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrFrame.Offset = ctx.Rbp as u64;
+        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        c::IMAGE_FILE_MACHINE_AMD64
+    }
+
+    #[cfg(target_arch = "aarch64")]
+    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
+        self.AddrPC.Offset = ctx.Pc as u64;
+        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrStack.Offset = ctx.Sp as u64;
+        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrFrame.Offset = ctx.Fp as u64;
+        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        c::IMAGE_FILE_MACHINE_ARM64
+    }
 
-    Ok((i, backtrace_context))
+    fn get_addr(&self) -> *const u8 {
+        (self.AddrPC.Offset - 1) as *const u8
+    }
 }
 
-type SymInitializeFn =
-    unsafe extern "system" fn(c::HANDLE, *mut c_void,
-                              c::BOOL) -> c::BOOL;
-type SymCleanupFn =
-    unsafe extern "system" fn(c::HANDLE) -> c::BOOL;
-
-type StackWalk64Fn =
-    unsafe extern "system" fn(c::DWORD, c::HANDLE, c::HANDLE,
-                              *mut c::STACKFRAME64, *mut c::CONTEXT,
-                              *mut c_void, *mut c_void,
-                              *mut c_void, *mut c_void) -> c::BOOL;
-
-#[cfg(target_arch = "x86")]
-fn init_frame(frame: &mut c::STACKFRAME64,
-              ctx: &c::CONTEXT) -> c::DWORD {
-    frame.AddrPC.Offset = ctx.Eip as u64;
-    frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
-    frame.AddrStack.Offset = ctx.Esp as u64;
-    frame.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
-    frame.AddrFrame.Offset = ctx.Ebp as u64;
-    frame.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
-    c::IMAGE_FILE_MACHINE_I386
+impl StackFrame for c::STACKFRAME64 {
+    fn new() -> c::STACKFRAME64 {
+        unsafe { mem::zeroed() }
+    }
+
+    #[cfg(target_arch = "x86")]
+    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
+        self.AddrPC.Offset = ctx.Eip as u64;
+        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrStack.Offset = ctx.Esp as u64;
+        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrFrame.Offset = ctx.Ebp as u64;
+        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        c::IMAGE_FILE_MACHINE_I386
+    }
+
+    #[cfg(target_arch = "x86_64")]
+    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
+        self.AddrPC.Offset = ctx.Rip as u64;
+        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrStack.Offset = ctx.Rsp as u64;
+        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrFrame.Offset = ctx.Rbp as u64;
+        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        c::IMAGE_FILE_MACHINE_AMD64
+    }
+
+    #[cfg(target_arch = "aarch64")]
+    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
+        self.AddrPC.Offset = ctx.Pc as u64;
+        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrStack.Offset = ctx.Sp as u64;
+        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrFrame.Offset = ctx.Fp as u64;
+        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        c::IMAGE_FILE_MACHINE_ARM64
+    }
+
+    fn get_addr(&self) -> *const u8 {
+        (self.AddrPC.Offset - 1) as *const u8
+    }
 }
 
-#[cfg(target_arch = "x86_64")]
-fn init_frame(frame: &mut c::STACKFRAME64,
-              ctx: &c::CONTEXT) -> c::DWORD {
-    frame.AddrPC.Offset = ctx.Rip as u64;
-    frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
-    frame.AddrStack.Offset = ctx.Rsp as u64;
-    frame.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
-    frame.AddrFrame.Offset = ctx.Rbp as u64;
-    frame.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
-    c::IMAGE_FILE_MACHINE_AMD64
+enum StackWalkVariant {
+    StackWalkEx(StackWalkExFn, printing::PrintingFnsEx),
+    StackWalk64(StackWalk64Fn, printing::PrintingFns64),
 }
 
 pub struct BacktraceContext {
     handle: c::HANDLE,
     SymCleanup: SymCleanupFn,
     // Only used in printing for msvc and not gnu
+    // The gnu version is effectively a ZST dummy.
+    #[allow(dead_code)]
+    StackWalkVariant: StackWalkVariant,
+    // keeping DynamycLibrary loaded until its functions no longer needed
     #[allow(dead_code)]
     dbghelp: DynamicLibrary,
 }
 
 impl Drop for BacktraceContext {
     fn drop(&mut self) {
-        unsafe { (self.SymCleanup)(self.handle); }
+        unsafe {
+            (self.SymCleanup)(self.handle);
+        }
     }
 }
diff --git a/src/libstd/sys/windows/backtrace/printing/mod.rs b/src/libstd/sys/windows/backtrace/printing/mod.rs
index 3e566f6e2bd..251d5028aea 100644
--- a/src/libstd/sys/windows/backtrace/printing/mod.rs
+++ b/src/libstd/sys/windows/backtrace/printing/mod.rs
@@ -15,6 +15,20 @@ mod printing;
 #[cfg(target_env = "gnu")]
 mod printing {
     pub use sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname};
+
+    // dummy functions to mirror those present in msvc version.
+    use sys::dynamic_lib::DynamicLibrary;
+    use io;
+    pub struct PrintingFnsEx {}
+    pub struct PrintingFns64 {}
+    pub fn load_printing_fns_ex(_: &DynamicLibrary) -> io::Result<PrintingFnsEx> {
+        Ok(PrintingFnsEx{})
+    }
+    pub fn load_printing_fns_64(_: &DynamicLibrary) -> io::Result<PrintingFns64> {
+        Ok(PrintingFns64{})
+    }
 }
 
 pub use self::printing::{foreach_symbol_fileline, resolve_symname};
+pub use self::printing::{load_printing_fns_ex, load_printing_fns_64,
+                         PrintingFnsEx, PrintingFns64};
diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs
index 5a49b77af8e..c8b946bf13a 100644
--- a/src/libstd/sys/windows/backtrace/printing/msvc.rs
+++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs
@@ -10,27 +10,108 @@
 
 use ffi::CStr;
 use io;
-use libc::{c_ulong, c_char};
+use libc::{c_char, c_ulong};
 use mem;
-use sys::c;
 use sys::backtrace::BacktraceContext;
+use sys::backtrace::StackWalkVariant;
+use sys::c;
+use sys::dynamic_lib::DynamicLibrary;
 use sys_common::backtrace::Frame;
 
+// Structs holding printing functions and loaders for them
+// Two versions depending on whether dbghelp.dll has StackWalkEx or not
+// (the former being in newer Windows versions, the older being in Win7 and before)
+pub struct PrintingFnsEx {
+    resolve_symname: SymFromInlineContextFn,
+    sym_get_line: SymGetLineFromInlineContextFn,
+}
+pub struct PrintingFns64 {
+    resolve_symname: SymFromAddrFn,
+    sym_get_line: SymGetLineFromAddr64Fn,
+}
+
+pub fn load_printing_fns_ex(dbghelp: &DynamicLibrary) -> io::Result<PrintingFnsEx> {
+    Ok(PrintingFnsEx {
+        resolve_symname: sym!(dbghelp, "SymFromInlineContext", SymFromInlineContextFn)?,
+        sym_get_line: sym!(
+            dbghelp,
+            "SymGetLineFromInlineContext",
+            SymGetLineFromInlineContextFn
+        )?,
+    })
+}
+pub fn load_printing_fns_64(dbghelp: &DynamicLibrary) -> io::Result<PrintingFns64> {
+    Ok(PrintingFns64 {
+        resolve_symname: sym!(dbghelp, "SymFromAddr", SymFromAddrFn)?,
+        sym_get_line: sym!(dbghelp, "SymGetLineFromAddr64", SymGetLineFromAddr64Fn)?,
+    })
+}
+
 type SymFromAddrFn =
-    unsafe extern "system" fn(c::HANDLE, u64, *mut u64,
-                              *mut c::SYMBOL_INFO) -> c::BOOL;
+    unsafe extern "system" fn(c::HANDLE, u64, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
+type SymFromInlineContextFn =
+    unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
+
 type SymGetLineFromAddr64Fn =
-    unsafe extern "system" fn(c::HANDLE, u64, *mut u32,
-                              *mut c::IMAGEHLP_LINE64) -> c::BOOL;
+    unsafe extern "system" fn(c::HANDLE, u64, *mut u32, *mut c::IMAGEHLP_LINE64) -> c::BOOL;
+type SymGetLineFromInlineContextFn = unsafe extern "system" fn(
+    c::HANDLE,
+    u64,
+    c::ULONG,
+    u64,
+    *mut c::DWORD,
+    *mut c::IMAGEHLP_LINE64,
+) -> c::BOOL;
 
 /// Converts a pointer to symbol to its string value.
-pub fn resolve_symname<F>(frame: Frame,
-                          callback: F,
-                          context: &BacktraceContext) -> io::Result<()>
-    where F: FnOnce(Option<&str>) -> io::Result<()>
+pub fn resolve_symname<F>(frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()>
+where
+    F: FnOnce(Option<&str>) -> io::Result<()>,
 {
-    let SymFromAddr = sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn)?;
+    match context.StackWalkVariant {
+        StackWalkVariant::StackWalkEx(_, ref fns) => resolve_symname_internal(
+            |process: c::HANDLE,
+             symbol_address: u64,
+             inline_context: c::ULONG,
+             info: *mut c::SYMBOL_INFO| unsafe {
+                let mut displacement = 0u64;
+                (fns.resolve_symname)(
+                    process,
+                    symbol_address,
+                    inline_context,
+                    &mut displacement,
+                    info,
+                )
+            },
+            frame,
+            callback,
+            context,
+        ),
+        StackWalkVariant::StackWalk64(_, ref fns) => resolve_symname_internal(
+            |process: c::HANDLE,
+             symbol_address: u64,
+             _inline_context: c::ULONG,
+             info: *mut c::SYMBOL_INFO| unsafe {
+                let mut displacement = 0u64;
+                (fns.resolve_symname)(process, symbol_address, &mut displacement, info)
+            },
+            frame,
+            callback,
+            context,
+        ),
+    }
+}
 
+fn resolve_symname_internal<F, R>(
+    mut symbol_resolver: R,
+    frame: Frame,
+    callback: F,
+    context: &BacktraceContext,
+) -> io::Result<()>
+where
+    F: FnOnce(Option<&str>) -> io::Result<()>,
+    R: FnMut(c::HANDLE, u64, c::ULONG, *mut c::SYMBOL_INFO) -> c::BOOL,
+{
     unsafe {
         let mut info: c::SYMBOL_INFO = mem::zeroed();
         info.MaxNameLen = c::MAX_SYM_NAME as c_ulong;
@@ -39,13 +120,22 @@ pub fn resolve_symname<F>(frame: Frame,
         // due to struct alignment.
         info.SizeOfStruct = 88;
 
-        let mut displacement = 0u64;
-        let ret = SymFromAddr(context.handle,
-                              frame.symbol_addr as u64,
-                              &mut displacement,
-                              &mut info);
-
-        let symname = if ret == c::TRUE {
+        let ret = symbol_resolver(
+            context.handle,
+            frame.symbol_addr as u64,
+            frame.inline_context,
+            &mut info,
+        );
+        let valid_range = if ret == c::TRUE && frame.symbol_addr as usize >= info.Address as usize {
+            if info.Size != 0 {
+                (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize
+            } else {
+                true
+            }
+        } else {
+            false
+        };
+        let symname = if valid_range {
             let ptr = info.Name.as_ptr() as *const c_char;
             CStr::from_ptr(ptr).to_str().ok()
         } else {
@@ -55,28 +145,72 @@ pub fn resolve_symname<F>(frame: Frame,
     }
 }
 
-pub fn foreach_symbol_fileline<F>(frame: Frame,
-                                  mut f: F,
-                                  context: &BacktraceContext)
-    -> io::Result<bool>
-    where F: FnMut(&[u8], u32) -> io::Result<()>
+pub fn foreach_symbol_fileline<F>(
+    frame: Frame,
+    callback: F,
+    context: &BacktraceContext,
+) -> io::Result<bool>
+where
+    F: FnMut(&[u8], u32) -> io::Result<()>,
 {
-    let SymGetLineFromAddr64 = sym!(&context.dbghelp,
-                                    "SymGetLineFromAddr64",
-                                    SymGetLineFromAddr64Fn)?;
+    match context.StackWalkVariant {
+        StackWalkVariant::StackWalkEx(_, ref fns) => foreach_symbol_fileline_iternal(
+            |process: c::HANDLE,
+             frame_address: u64,
+             inline_context: c::ULONG,
+             line: *mut c::IMAGEHLP_LINE64| unsafe {
+                let mut displacement = 0u32;
+                (fns.sym_get_line)(
+                    process,
+                    frame_address,
+                    inline_context,
+                    0,
+                    &mut displacement,
+                    line,
+                )
+            },
+            frame,
+            callback,
+            context,
+        ),
+        StackWalkVariant::StackWalk64(_, ref fns) => foreach_symbol_fileline_iternal(
+            |process: c::HANDLE,
+             frame_address: u64,
+             _inline_context: c::ULONG,
+             line: *mut c::IMAGEHLP_LINE64| unsafe {
+                let mut displacement = 0u32;
+                (fns.sym_get_line)(process, frame_address, &mut displacement, line)
+            },
+            frame,
+            callback,
+            context,
+        ),
+    }
+}
 
+fn foreach_symbol_fileline_iternal<F, G>(
+    mut line_getter: G,
+    frame: Frame,
+    mut callback: F,
+    context: &BacktraceContext,
+) -> io::Result<bool>
+where
+    F: FnMut(&[u8], u32) -> io::Result<()>,
+    G: FnMut(c::HANDLE, u64, c::ULONG, *mut c::IMAGEHLP_LINE64) -> c::BOOL,
+{
     unsafe {
         let mut line: c::IMAGEHLP_LINE64 = mem::zeroed();
         line.SizeOfStruct = ::mem::size_of::<c::IMAGEHLP_LINE64>() as u32;
 
-        let mut displacement = 0u32;
-        let ret = SymGetLineFromAddr64(context.handle,
-                                       frame.exact_position as u64,
-                                       &mut displacement,
-                                       &mut line);
+        let ret = line_getter(
+            context.handle,
+            frame.exact_position as u64,
+            frame.inline_context,
+            &mut line,
+        );
         if ret == c::TRUE {
             let name = CStr::from_ptr(line.Filename).to_bytes();
-            f(name, line.LineNumber as u32)?;
+            callback(name, line.LineNumber as u32)?;
         }
         Ok(false)
     }
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index 66b44f1402f..e514a56dcc4 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -280,6 +280,9 @@ pub const IMAGE_FILE_MACHINE_I386: DWORD = 0x014c;
 #[cfg(target_arch = "x86_64")]
 #[cfg(feature = "backtrace")]
 pub const IMAGE_FILE_MACHINE_AMD64: DWORD = 0x8664;
+#[cfg(target_arch = "aarch64")]
+#[cfg(feature = "backtrace")]
+pub const IMAGE_FILE_MACHINE_ARM64: DWORD = 0xAA64;
 
 pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
 pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
@@ -296,6 +299,8 @@ pub const PIPE_READMODE_BYTE: DWORD = 0x00000000;
 
 pub const FD_SETSIZE: usize = 64;
 
+pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000;
+
 #[repr(C)]
 #[cfg(not(target_pointer_width = "64"))]
 pub struct WSADATA {
@@ -619,6 +624,24 @@ pub struct ADDRESS64 {
 
 #[repr(C)]
 #[cfg(feature = "backtrace")]
+pub struct STACKFRAME_EX {
+    pub AddrPC: ADDRESS64,
+    pub AddrReturn: ADDRESS64,
+    pub AddrFrame: ADDRESS64,
+    pub AddrStack: ADDRESS64,
+    pub AddrBStore: ADDRESS64,
+    pub FuncTableEntry: *mut c_void,
+    pub Params: [u64; 4],
+    pub Far: BOOL,
+    pub Virtual: BOOL,
+    pub Reserved: [u64; 3],
+    pub KdHelp: KDHELP64,
+    pub StackFrameSize: DWORD,
+    pub InlineFrameContext: DWORD,
+}
+
+#[repr(C)]
+#[cfg(feature = "backtrace")]
 pub struct STACKFRAME64 {
     pub AddrPC: ADDRESS64,
     pub AddrReturn: ADDRESS64,
@@ -771,9 +794,68 @@ pub struct FLOATING_SAVE_AREA {
 // will not appear in the final documentation. This should be also defined for
 // other architectures supported by Windows such as ARM, and for historical
 // interest, maybe MIPS and PowerPC as well.
-#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86"))))]
+#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))))]
 pub enum CONTEXT {}
 
+#[cfg(target_arch = "aarch64")]
+pub const ARM64_MAX_BREAKPOINTS: usize = 8;
+
+#[cfg(target_arch = "aarch64")]
+pub const ARM64_MAX_WATCHPOINTS: usize = 2;
+
+#[cfg(target_arch = "aarch64")]
+#[repr(C)]
+pub struct ARM64_NT_NEON128 {
+    pub D: [f64; 2],
+}
+
+#[cfg(target_arch = "aarch64")]
+#[repr(C, align(16))]
+pub struct CONTEXT {
+    pub ContextFlags: DWORD,
+    pub Cpsr: DWORD,
+    pub X0: u64,
+    pub X1: u64,
+    pub X2: u64,
+    pub X3: u64,
+    pub X4: u64,
+    pub X5: u64,
+    pub X6: u64,
+    pub X7: u64,
+    pub X8: u64,
+    pub X9: u64,
+    pub X10: u64,
+    pub X11: u64,
+    pub X12: u64,
+    pub X13: u64,
+    pub X14: u64,
+    pub X15: u64,
+    pub X16: u64,
+    pub X17: u64,
+    pub X18: u64,
+    pub X19: u64,
+    pub X20: u64,
+    pub X21: u64,
+    pub X22: u64,
+    pub X23: u64,
+    pub X24: u64,
+    pub X25: u64,
+    pub X26: u64,
+    pub X27: u64,
+    pub X28: u64,
+    pub Fp: u64,
+    pub Lr: u64,
+    pub Sp: u64,
+    pub Pc: u64,
+    pub V: [ARM64_NT_NEON128; 32],
+    pub Fpcr: DWORD,
+    pub Fpsr: DWORD,
+    pub Bcr: [DWORD; ARM64_MAX_BREAKPOINTS],
+    pub Bvr: [DWORD; ARM64_MAX_BREAKPOINTS],
+    pub Wcr: [DWORD; ARM64_MAX_WATCHPOINTS],
+    pub Wvr: [DWORD; ARM64_MAX_WATCHPOINTS],
+}
+
 #[repr(C)]
 pub struct SOCKADDR_STORAGE_LH {
     pub ss_family: ADDRESS_FAMILY,
diff --git a/src/libstd/sys/windows/ext/ffi.rs b/src/libstd/sys/windows/ext/ffi.rs
index d6b8896ac09..bae0d02786a 100644
--- a/src/libstd/sys/windows/ext/ffi.rs
+++ b/src/libstd/sys/windows/ext/ffi.rs
@@ -31,7 +31,7 @@
 //!
 //! If Rust code *does* need to look into those strings, it can
 //! convert them to valid UTF-8, possibly lossily, by substituting
-//! invalid sequences with U+FFFD REPLACEMENT CHARACTER, as is
+//! invalid sequences with [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], as is
 //! conventionally done in other Rust APIs that deal with string
 //! encodings.
 //!
@@ -65,6 +65,7 @@
 //! [`from_wide`]: trait.OsStringExt.html#tymethod.from_wide
 //! [`encode_wide`]: trait.OsStrExt.html#tymethod.encode_wide
 //! [`collect`]: ../../../iter/trait.Iterator.html#method.collect
+//! [U+FFFD]: ../../../char/constant.REPLACEMENT_CHARACTER.html
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -76,7 +77,9 @@ use sys_common::{FromInner, AsInner};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use sys_common::wtf8::EncodeWide;
 
-/// Windows-specific extensions to `OsString`.
+/// Windows-specific extensions to [`OsString`].
+///
+/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStringExt {
     /// Creates an `OsString` from a potentially ill-formed UTF-16 slice of
@@ -109,7 +112,9 @@ impl OsStringExt for OsString {
     }
 }
 
-/// Windows-specific extensions to `OsStr`.
+/// Windows-specific extensions to [`OsStr`].
+///
+/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStrExt {
     /// Re-encodes an `OsStr` as a wide character sequence, i.e. potentially
diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs
index 24c41046f26..78c9e95a055 100644
--- a/src/libstd/sys/windows/ext/fs.rs
+++ b/src/libstd/sys/windows/ext/fs.rs
@@ -45,15 +45,15 @@ pub trait FileExt {
     /// use std::fs::File;
     /// use std::os::windows::prelude::*;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let mut file = File::open("foo.txt")?;
-    /// let mut buffer = [0; 10];
-    ///
-    /// // Read 10 bytes, starting 72 bytes from the
-    /// // start of the file.
-    /// file.seek_read(&mut buffer[..], 72)?;
-    /// # Ok(())
-    /// # }
+    /// fn main() -> io::Result<()> {
+    ///     let mut file = File::open("foo.txt")?;
+    ///     let mut buffer = [0; 10];
+    ///
+    ///     // Read 10 bytes, starting 72 bytes from the
+    ///     // start of the file.
+    ///     file.seek_read(&mut buffer[..], 72)?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "file_offset", since = "1.15.0")]
     fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
@@ -79,14 +79,14 @@ pub trait FileExt {
     /// use std::fs::File;
     /// use std::os::windows::prelude::*;
     ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut buffer = File::create("foo.txt")?;
+    /// fn main() -> std::io::Result<()> {
+    ///     let mut buffer = File::create("foo.txt")?;
     ///
-    /// // Write a byte string starting 72 bytes from
-    /// // the start of the file.
-    /// buffer.seek_write(b"some bytes", 72)?;
-    /// # Ok(())
-    /// # }
+    ///     // Write a byte string starting 72 bytes from
+    ///     // the start of the file.
+    ///     buffer.seek_write(b"some bytes", 72)?;
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "file_offset", since = "1.15.0")]
     fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
@@ -103,9 +103,9 @@ impl FileExt for fs::File {
     }
 }
 
-/// Windows-specific extensions to [`OpenOptions`].
+/// Windows-specific extensions to [`fs::OpenOptions`].
 ///
-/// [`OpenOptions`]: ../../../fs/struct.OpenOptions.html
+/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
 #[stable(feature = "open_options_ext", since = "1.10.0")]
 pub trait OpenOptionsExt {
     /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`]
@@ -281,13 +281,12 @@ impl OpenOptionsExt for OpenOptions {
     }
 }
 
-/// Extension methods for [`fs::Metadata`] to access the raw fields contained
-/// within.
+/// Windows-specific extensions to [`fs::Metadata`].
 ///
 /// The data members that this trait exposes correspond to the members
 /// of the [`BY_HANDLE_FILE_INFORMATION`] structure.
 ///
-/// [`fs::Metadata`]: ../../../fs/struct.Metadata.html
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 /// [`BY_HANDLE_FILE_INFORMATION`]:
 ///     https://msdn.microsoft.com/en-us/library/windows/desktop/aa363788.aspx
 #[stable(feature = "metadata_ext", since = "1.1.0")]
@@ -305,11 +304,11 @@ pub trait MetadataExt {
     /// use std::fs;
     /// use std::os::windows::prelude::*;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let metadata = fs::metadata("foo.txt")?;
-    /// let attributes = metadata.file_attributes();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> io::Result<()> {
+    ///     let metadata = fs::metadata("foo.txt")?;
+    ///     let attributes = metadata.file_attributes();
+    ///     Ok(())
+    /// }
     /// ```
     ///
     /// [File Attribute Constants]:
@@ -335,11 +334,11 @@ pub trait MetadataExt {
     /// use std::fs;
     /// use std::os::windows::prelude::*;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let metadata = fs::metadata("foo.txt")?;
-    /// let creation_time = metadata.creation_time();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> io::Result<()> {
+    ///     let metadata = fs::metadata("foo.txt")?;
+    ///     let creation_time = metadata.creation_time();
+    ///     Ok(())
+    /// }
     /// ```
     ///
     /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx
@@ -370,11 +369,11 @@ pub trait MetadataExt {
     /// use std::fs;
     /// use std::os::windows::prelude::*;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let metadata = fs::metadata("foo.txt")?;
-    /// let last_access_time = metadata.last_access_time();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> io::Result<()> {
+    ///     let metadata = fs::metadata("foo.txt")?;
+    ///     let last_access_time = metadata.last_access_time();
+    ///     Ok(())
+    /// }
     /// ```
     ///
     /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx
@@ -403,11 +402,11 @@ pub trait MetadataExt {
     /// use std::fs;
     /// use std::os::windows::prelude::*;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let metadata = fs::metadata("foo.txt")?;
-    /// let last_write_time = metadata.last_write_time();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> io::Result<()> {
+    ///     let metadata = fs::metadata("foo.txt")?;
+    ///     let last_write_time = metadata.last_write_time();
+    ///     Ok(())
+    /// }
     /// ```
     ///
     /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx
@@ -426,11 +425,11 @@ pub trait MetadataExt {
     /// use std::fs;
     /// use std::os::windows::prelude::*;
     ///
-    /// # fn foo() -> io::Result<()> {
-    /// let metadata = fs::metadata("foo.txt")?;
-    /// let file_size = metadata.file_size();
-    /// # Ok(())
-    /// # }
+    /// fn main() -> io::Result<()> {
+    ///     let metadata = fs::metadata("foo.txt")?;
+    ///     let file_size = metadata.file_size();
+    ///     Ok(())
+    /// }
     /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn file_size(&self) -> u64;
@@ -445,6 +444,27 @@ impl MetadataExt for Metadata {
     fn file_size(&self) -> u64 { self.as_inner().size() }
 }
 
+/// Windows-specific extensions to [`FileType`].
+///
+/// On Windows, a symbolic link knows whether it is a file or directory.
+///
+/// [`FileType`]: ../../../../std/fs/struct.FileType.html
+#[unstable(feature = "windows_file_type_ext", issue = "0")]
+pub trait FileTypeExt {
+    /// Returns whether this file type is a symbolic link that is also a directory.
+    #[unstable(feature = "windows_file_type_ext", issue = "0")]
+    fn is_symlink_dir(&self) -> bool;
+    /// Returns whether this file type is a symbolic link that is also a file.
+    #[unstable(feature = "windows_file_type_ext", issue = "0")]
+    fn is_symlink_file(&self) -> bool;
+}
+
+#[unstable(feature = "windows_file_type_ext", issue = "0")]
+impl FileTypeExt for fs::FileType {
+    fn is_symlink_dir(&self) -> bool { self.as_inner().is_symlink_dir() }
+    fn is_symlink_file(&self) -> bool { self.as_inner().is_symlink_file() }
+}
+
 /// Creates a new file symbolic link on the filesystem.
 ///
 /// The `dst` path will be a file symbolic link pointing to the `src`
@@ -455,10 +475,10 @@ impl MetadataExt for Metadata {
 /// ```no_run
 /// use std::os::windows::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::symlink_file("a.txt", "b.txt")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     fs::symlink_file("a.txt", "b.txt")?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "symlink", since = "1.1.0")]
 pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
@@ -476,10 +496,10 @@ pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
 /// ```no_run
 /// use std::os::windows::fs;
 ///
-/// # fn foo() -> std::io::Result<()> {
-/// fs::symlink_dir("a", "b")?;
-/// # Ok(())
-/// # }
+/// fn main() -> std::io::Result<()> {
+///     fs::symlink_dir("a", "b")?;
+///     Ok(())
+/// }
 /// ```
 #[stable(feature = "symlink", since = "1.1.0")]
 pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
diff --git a/src/libstd/sys/windows/ext/mod.rs b/src/libstd/sys/windows/ext/mod.rs
index 4b458d293bc..1f10609f32c 100644
--- a/src/libstd/sys/windows/ext/mod.rs
+++ b/src/libstd/sys/windows/ext/mod.rs
@@ -18,6 +18,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(cfg(windows))]
+#![allow(missing_docs)]
 
 pub mod ffi;
 pub mod fs;
diff --git a/src/libstd/sys/windows/ext/process.rs b/src/libstd/sys/windows/ext/process.rs
index 759f055c4b1..a02bcbe0c87 100644
--- a/src/libstd/sys/windows/ext/process.rs
+++ b/src/libstd/sys/windows/ext/process.rs
@@ -82,7 +82,9 @@ impl IntoRawHandle for process::ChildStderr {
     }
 }
 
-/// Windows-specific extensions to `std::process::ExitStatus`
+/// Windows-specific extensions to [`process::ExitStatus`].
+///
+/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html
 #[stable(feature = "exit_status_from", since = "1.12.0")]
 pub trait ExitStatusExt {
     /// Creates a new `ExitStatus` from the raw underlying `u32` return value of
@@ -98,7 +100,9 @@ impl ExitStatusExt for process::ExitStatus {
     }
 }
 
-/// Windows-specific extensions to the `std::process::Command` builder
+/// Windows-specific extensions to the [`process::Command`] builder.
+///
+/// [`process::Command`]: ../../../../std/process/struct.Command.html
 #[stable(feature = "windows_process_extensions", since = "1.16.0")]
 pub trait CommandExt {
     /// Sets the [process creation flags][1] to be passed to `CreateProcess`.
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index 165e1b0609b..082d4689c7b 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -38,8 +38,9 @@ pub struct FileAttr {
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub enum FileType {
-    Dir, File, SymlinkFile, SymlinkDir, ReparsePoint, MountPoint,
+pub struct FileType {
+    attributes: c::DWORD,
+    reparse_tag: c::DWORD,
 }
 
 pub struct ReadDir {
@@ -516,30 +517,34 @@ impl FilePermissions {
 
 impl FileType {
     fn new(attrs: c::DWORD, reparse_tag: c::DWORD) -> FileType {
-        match (attrs & c::FILE_ATTRIBUTE_DIRECTORY != 0,
-               attrs & c::FILE_ATTRIBUTE_REPARSE_POINT != 0,
-               reparse_tag) {
-            (false, false, _) => FileType::File,
-            (true, false, _) => FileType::Dir,
-            (false, true, c::IO_REPARSE_TAG_SYMLINK) => FileType::SymlinkFile,
-            (true, true, c::IO_REPARSE_TAG_SYMLINK) => FileType::SymlinkDir,
-            (true, true, c::IO_REPARSE_TAG_MOUNT_POINT) => FileType::MountPoint,
-            (_, true, _) => FileType::ReparsePoint,
-            // Note: if a _file_ has a reparse tag of the type IO_REPARSE_TAG_MOUNT_POINT it is
-            // invalid, as junctions always have to be dirs. We set the filetype to ReparsePoint
-            // to indicate it is something symlink-like, but not something you can follow.
+        FileType {
+            attributes: attrs,
+            reparse_tag: reparse_tag,
         }
     }
-
-    pub fn is_dir(&self) -> bool { *self == FileType::Dir }
-    pub fn is_file(&self) -> bool { *self == FileType::File }
+    pub fn is_dir(&self) -> bool {
+        !self.is_symlink() && self.is_directory()
+    }
+    pub fn is_file(&self) -> bool {
+        !self.is_symlink() && !self.is_directory()
+    }
     pub fn is_symlink(&self) -> bool {
-        *self == FileType::SymlinkFile ||
-        *self == FileType::SymlinkDir ||
-        *self == FileType::MountPoint
+        self.is_reparse_point() && self.is_reparse_tag_name_surrogate()
     }
     pub fn is_symlink_dir(&self) -> bool {
-        *self == FileType::SymlinkDir || *self == FileType::MountPoint
+        self.is_symlink() && self.is_directory()
+    }
+    pub fn is_symlink_file(&self) -> bool {
+        self.is_symlink() && !self.is_directory()
+    }
+    fn is_directory(&self) -> bool {
+        self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0
+    }
+    fn is_reparse_point(&self) -> bool {
+        self.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0
+    }
+    fn is_reparse_tag_name_surrogate(&self) -> bool {
+        self.reparse_tag & 0x20000000 != 0
     }
 }
 
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index 0d12ecf8fe3..ccf79de909f 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -266,8 +266,12 @@ pub fn dur2timeout(dur: Duration) -> c::DWORD {
 // handlers.
 //
 // https://msdn.microsoft.com/en-us/library/dn774154.aspx
-#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+#[allow(unreachable_code)]
 pub unsafe fn abort_internal() -> ! {
-    asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
-    ::intrinsics::unreachable();
+    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+    {
+        asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
+        ::intrinsics::unreachable();
+    }
+    ::intrinsics::abort();
 }
diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs
index 85560368590..9bf9f749d4d 100644
--- a/src/libstd/sys/windows/mutex.rs
+++ b/src/libstd/sys/windows/mutex.rs
@@ -117,7 +117,7 @@ impl Mutex {
             0 => {}
             n => return n as *mut _,
         }
-        let mut re = Box::new(ReentrantMutex::uninitialized());
+        let mut re = box ReentrantMutex::uninitialized();
         re.init();
         let re = Box::into_raw(re);
         match self.lock.compare_and_swap(0, re as usize, Ordering::SeqCst) {
diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs
index 414c9c5418e..bcc66b9954b 100644
--- a/src/libstd/sys/windows/os_str.rs
+++ b/src/libstd/sys/windows/os_str.rs
@@ -114,6 +114,11 @@ impl Buf {
     }
 
     #[inline]
+    pub fn shrink_to(&mut self, min_capacity: usize) {
+        self.inner.shrink_to(min_capacity)
+    }
+
+    #[inline]
     pub fn into_box(self) -> Box<Slice> {
         unsafe { mem::transmute(self.inner.into_box()) }
     }
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index f3b1185c6ea..df1dd7401af 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -236,7 +236,7 @@ enum State {
 impl<'a> AsyncPipe<'a> {
     fn new(pipe: Handle, dst: &'a mut Vec<u8>) -> io::Result<AsyncPipe<'a>> {
         // Create an event which we'll use to coordinate our overlapped
-        // opreations, this event will be used in WaitForMultipleObjects
+        // operations, this event will be used in WaitForMultipleObjects
         // and passed as part of the OVERLAPPED handle.
         //
         // Note that we do a somewhat clever thing here by flagging the
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index c93179869a6..4974a8de89c 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -10,7 +10,6 @@
 
 #![unstable(feature = "process_internals", issue = "0")]
 
-use ascii::AsciiExt;
 use collections::BTreeMap;
 use env::split_paths;
 use env;
@@ -18,7 +17,7 @@ use ffi::{OsString, OsStr};
 use fmt;
 use fs;
 use io::{self, Error, ErrorKind};
-use libc::c_void;
+use libc::{c_void, EXIT_SUCCESS, EXIT_FAILURE};
 use mem;
 use os::windows::ffi::OsStrExt;
 use path::Path;
@@ -32,7 +31,7 @@ use sys::stdio;
 use sys::cvt;
 use sys_common::{AsInner, FromInner, IntoInner};
 use sys_common::process::{CommandEnv, EnvKey};
-use alloc::borrow::Borrow;
+use borrow::Borrow;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Command
@@ -408,6 +407,19 @@ impl fmt::Display for ExitStatus {
     }
 }
 
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitCode(c::DWORD);
+
+impl ExitCode {
+    pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _);
+    pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _);
+
+    #[inline]
+    pub fn as_i32(&self) -> i32 {
+        self.0 as i32
+    }
+}
+
 fn zeroed_startupinfo() -> c::STARTUPINFO {
     c::STARTUPINFO {
         cb: 0,
@@ -475,9 +487,7 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result<Vec<u16>> {
             } else {
                 if x == '"' as u16 {
                     // Add n+1 backslashes to total 2n+1 before internal '"'.
-                    for _ in 0..(backslashes+1) {
-                        cmd.push('\\' as u16);
-                    }
+                    cmd.extend((0..(backslashes + 1)).map(|_| '\\' as u16));
                 }
                 backslashes = 0;
             }
@@ -486,9 +496,7 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result<Vec<u16>> {
 
         if quote {
             // Add n backslashes to total 2n before ending '"'.
-            for _ in 0..backslashes {
-                cmd.push('\\' as u16);
-            }
+            cmd.extend((0..backslashes).map(|_| '\\' as u16));
             cmd.push('"' as u16);
         }
         Ok(())
diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs
index b43df20bddd..81b89da21d3 100644
--- a/src/libstd/sys/windows/stdio.rs
+++ b/src/libstd/sys/windows/stdio.rs
@@ -227,3 +227,7 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 // idea is that on windows we use a slightly smaller buffer that's
 // been seen to be acceptable.
 pub const STDIN_BUF_SIZE: usize = 8 * 1024;
+
+pub fn stderr_prints_nothing() -> bool {
+    false
+}
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
index 74786d09285..85588cc6c8e 100644
--- a/src/libstd/sys/windows/thread.rs
+++ b/src/libstd/sys/windows/thread.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::boxed::FnBox;
+use boxed::FnBox;
 use io;
 use ffi::CStr;
 use mem;
@@ -28,7 +28,7 @@ pub struct Thread {
 }
 
 impl Thread {
-    pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>)
+    pub unsafe fn new<'a>(stack: usize, p: Box<dyn FnBox() + 'a>)
                           -> io::Result<Thread> {
         let p = box p;
 
@@ -42,7 +42,8 @@ impl Thread {
         let stack_size = (stack + 0xfffe) & (!0xfffe);
         let ret = c::CreateThread(ptr::null_mut(), stack_size,
                                   thread_start, &*p as *const _ as *mut _,
-                                  0, ptr::null_mut());
+                                  c::STACK_SIZE_PARAM_IS_A_RESERVATION,
+                                  ptr::null_mut());
 
         return if ret as usize == 0 {
             Err(io::Error::last_os_error())
@@ -93,6 +94,8 @@ impl Thread {
 
 #[cfg_attr(test, allow(dead_code))]
 pub mod guard {
-    pub unsafe fn current() -> Option<usize> { None }
-    pub unsafe fn init() -> Option<usize> { None }
+    pub type Guard = !;
+    pub unsafe fn current() -> Option<Guard> { None }
+    pub unsafe fn init() -> Option<Guard> { None }
+    pub unsafe fn deinit() {}
 }