diff --git a/lib/std/c.zig b/lib/std/c.zig index 6d904c8b9846bd880c95cd3e9408cc194d50dd85..396a6f6702a4ee9571a900b41a8a7047b4faf09d 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -123,6 +123,7 @@ pub extern "c" fn write(fd: c.fd_t, buf: [*]const u8, nbyte: usize) isize; pub extern "c" fn pwrite(fd: c.fd_t, buf: [*]const u8, nbyte: usize, offset: c.off_t) isize; pub extern "c" fn mmap(addr: ?*align(page_size) anyopaque, len: usize, prot: c_uint, flags: c_uint, fd: c.fd_t, offset: c.off_t) *anyopaque; pub extern "c" fn munmap(addr: *align(page_size) const anyopaque, len: usize) c_int; +pub extern "c" fn msync(addr: *align(page_size) const anyopaque, len: usize, flags: c_int) c_int; pub extern "c" fn mprotect(addr: *align(page_size) anyopaque, len: usize, prot: c_uint) c_int; pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: c_int) c_int; pub extern "c" fn linkat(oldfd: c.fd_t, oldpath: [*:0]const u8, newfd: c.fd_t, newpath: [*:0]const u8, flags: c_int) c_int; diff --git a/lib/std/c/linux.zig b/lib/std/c/linux.zig index db55b5d850275880e227337e899a3da919754a03..be136bcbea3d14a10b99e74349748a635c28d87c 100644 --- a/lib/std/c/linux.zig +++ b/lib/std/c/linux.zig @@ -30,6 +30,7 @@ pub const MAP = struct { /// Only used by libc to communicate failure. pub const FAILED = @intToPtr(*anyopaque, maxInt(usize)); }; +pub const MSF = linux.MSF; pub const MMAP2_UNIT = linux.MMAP2_UNIT; pub const MSG = linux.MSG; pub const NAME_MAX = linux.NAME_MAX; diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 69a68faad60894aaf10bc3c6ce75b60087829d6e..be4798504193528b93553337bd126bb2b58830a1 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -424,6 +424,28 @@ pub const StackIterator = struct { return address; } + fn isValidMemory(address: u64) bool { + if (native_os != .windows) { + var res = true; + const length = 2 * mem.page_size; + const aligned_address = address & ~@intCast(u64, (mem.page_size - 1)); + const aligned_memory = @intToPtr([*]align(mem.page_size) u8, aligned_address)[0..length]; + + os.msync(aligned_memory, os.MSF.ASYNC) catch |err| { + switch (err) { + os.MSyncError.UnmappedMemory => { + res = false; + }, + else => unreachable, + } + }; + return res; + } else { + // TODO: Using windows memory API check if a page is mapped + return true; + } + } + fn next_internal(self: *StackIterator) ?usize { const fp = if (comptime native_arch.isSPARC()) // On SPARC the offset is positive. (!) @@ -432,7 +454,7 @@ pub const StackIterator = struct { math.sub(usize, self.fp, fp_offset) catch return null; // Sanity check. - if (fp == 0 or !mem.isAligned(fp, @alignOf(usize))) + if (fp == 0 or !mem.isAligned(fp, @alignOf(usize)) or !isValidMemory(fp)) return null; const new_fp = math.add(usize, @intToPtr(*const usize, fp).*, fp_bias) catch return null; diff --git a/lib/std/os.zig b/lib/std/os.zig index a935cfd8c02ab7af269c82b2e77a669290dc85ed..16a32766dc8fd0bc71881a65f98a270740aac2dd 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -88,6 +88,7 @@ pub const Kevent = system.Kevent; pub const LOCK = system.LOCK; pub const MADV = system.MADV; pub const MAP = system.MAP; +pub const MSF = system.MSF; pub const MAX_ADDR_LEN = system.MAX_ADDR_LEN; pub const MMAP2_UNIT = system.MMAP2_UNIT; pub const MSG = system.MSG; @@ -4016,6 +4017,19 @@ pub fn munmap(memory: []align(mem.page_size) const u8) void { } } +pub const MSyncError = error{ + UnmappedMemory, +} || UnexpectedError; + +pub fn msync(memory: []align(mem.page_size) u8, flags: i32) MSyncError!void { + switch (errno(system.msync(memory.ptr, memory.len, flags))) { + .SUCCESS => return, + .NOMEM => return error.UnmappedMemory, // Unsuccessful, provided pointer does not point mapped memory + .INVAL => unreachable, // Invalid parameters. + else => unreachable, + } +} + pub const AccessError = error{ PermissionDenied, FileNotFound, diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index c1591f7ea14152961134a4cfc9c0836179a0572b..608db08a9c901a8279ebba37e4c29c5ba4ce3891 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -406,6 +406,16 @@ pub fn mprotect(address: [*]const u8, length: usize, protection: usize) usize { return syscall3(.mprotect, @ptrToInt(address), length, protection); } +pub const MSF = struct { + pub const ASYNC = 1; + pub const INVALIDATE = 2; + pub const SYNC = 4; +}; + +pub fn msync(address: [*]const u8, length: usize, flags: u32) usize { + return syscall3(.msync, @ptrToInt(address), length, flags); +} + pub fn munmap(address: [*]const u8, length: usize) usize { return syscall2(.munmap, @ptrToInt(address), length); }