| author | |
| committer | |
| log | 0e7461d4a34272a94acba20b09aaee283e88a806 |
| tree | 72b45e0feb56452e8d3fb25c8bf68a401b19b656 |
| parent | eff50abce68ffc69d236fcc0b919bc63fcd0e89a |
| parent | a779450fefd623c54da37912995ffe7ad16b514e |
| signature |
handle SIGBUS, fix mmap on i386 linux3 files changed, 111 insertions(+), 4 deletions(-)
lib/std/debug.zig+3| ... | @@ -2256,6 +2256,7 @@ pub fn attachSegfaultHandler() void { | ... | @@ -2256,6 +2256,7 @@ pub fn attachSegfaultHandler() void { |
| 2256 | 2256 | ||
| 2257 | os.sigaction(os.SIGSEGV, &act, null); | 2257 | os.sigaction(os.SIGSEGV, &act, null); |
| 2258 | os.sigaction(os.SIGILL, &act, null); | 2258 | os.sigaction(os.SIGILL, &act, null); |
| 2259 | os.sigaction(os.SIGBUS, &act, null); | ||
| 2259 | } | 2260 | } |
| 2260 | 2261 | ||
| 2261 | fn resetSegfaultHandler() void { | 2262 | fn resetSegfaultHandler() void { |
| ... | @@ -2273,6 +2274,7 @@ fn resetSegfaultHandler() void { | ... | @@ -2273,6 +2274,7 @@ fn resetSegfaultHandler() void { |
| 2273 | }; | 2274 | }; |
| 2274 | os.sigaction(os.SIGSEGV, &act, null); | 2275 | os.sigaction(os.SIGSEGV, &act, null); |
| 2275 | os.sigaction(os.SIGILL, &act, null); | 2276 | os.sigaction(os.SIGILL, &act, null); |
| 2277 | os.sigaction(os.SIGBUS, &act, null); | ||
| 2276 | } | 2278 | } |
| 2277 | 2279 | ||
| 2278 | fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_void) callconv(.C) noreturn { | 2280 | fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_void) callconv(.C) noreturn { |
| ... | @@ -2285,6 +2287,7 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_vo | ... | @@ -2285,6 +2287,7 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_vo |
| 2285 | switch (sig) { | 2287 | switch (sig) { |
| 2286 | os.SIGSEGV => std.debug.warn("Segmentation fault at address 0x{x}\n", .{addr}), | 2288 | os.SIGSEGV => std.debug.warn("Segmentation fault at address 0x{x}\n", .{addr}), |
| 2287 | os.SIGILL => std.debug.warn("Illegal instruction at address 0x{x}\n", .{addr}), | 2289 | os.SIGILL => std.debug.warn("Illegal instruction at address 0x{x}\n", .{addr}), |
| 2290 | os.SIGBUS => std.debug.warn("Bus error at address 0x{x}\n", .{addr}), | ||
| 2288 | else => unreachable, | 2291 | else => unreachable, |
| 2289 | } | 2292 | } |
| 2290 | switch (builtin.arch) { | 2293 | switch (builtin.arch) { |
lib/std/os/linux/i386.zig+10-4| ... | @@ -72,11 +72,17 @@ pub fn syscall6( | ... | @@ -72,11 +72,17 @@ pub fn syscall6( |
| 72 | arg5: usize, | 72 | arg5: usize, |
| 73 | arg6: usize, | 73 | arg6: usize, |
| 74 | ) usize { | 74 | ) usize { |
| 75 | // The 6th argument is passed via memory as we're out of registers if ebp is | ||
| 76 | // used as frame pointer. We push arg6 value on the stack before changing | ||
| 77 | // ebp or esp as the compiler may reference it as an offset relative to one | ||
| 78 | // of those two registers. | ||
| 75 | return asm volatile ( | 79 | return asm volatile ( |
| 76 | \\ push %%ebp | 80 | \\ push %[arg6] |
| 77 | \\ mov %[arg6], %%ebp | 81 | \\ push %%ebp |
| 78 | \\ int $0x80 | 82 | \\ mov 4(%%esp), %%ebp |
| 79 | \\ pop %%ebp | 83 | \\ int $0x80 |
| 84 | \\ pop %%ebp | ||
| 85 | \\ add $4, %%esp | ||
| 80 | : [ret] "={eax}" (-> usize) | 86 | : [ret] "={eax}" (-> usize) |
| 81 | : [number] "{eax}" (number), | 87 | : [number] "{eax}" (number), |
| 82 | [arg1] "{ebx}" (arg1), | 88 | [arg1] "{ebx}" (arg1), |
lib/std/os/test.zig+98| ... | @@ -256,3 +256,101 @@ test "memfd_create" { | ... | @@ -256,3 +256,101 @@ test "memfd_create" { |
| 256 | expect(bytes_read == 4); | 256 | expect(bytes_read == 4); |
| 257 | expect(mem.eql(u8, buf[0..4], "test")); | 257 | expect(mem.eql(u8, buf[0..4], "test")); |
| 258 | } | 258 | } |
| 259 | |||
| 260 | test "mmap" { | ||
| 261 | if (builtin.os == .windows) | ||
| 262 | return error.SkipZigTest; | ||
| 263 | |||
| 264 | // Simple mmap() call with non page-aligned size | ||
| 265 | { | ||
| 266 | const data = try os.mmap( | ||
| 267 | null, | ||
| 268 | 1234, | ||
| 269 | os.PROT_READ | os.PROT_WRITE, | ||
| 270 | os.MAP_ANONYMOUS | os.MAP_PRIVATE, | ||
| 271 | -1, | ||
| 272 | 0, | ||
| 273 | ); | ||
| 274 | defer os.munmap(data); | ||
| 275 | |||
| 276 | testing.expectEqual(@as(usize, 1234), data.len); | ||
| 277 | |||
| 278 | // By definition the data returned by mmap is zero-filled | ||
| 279 | std.mem.set(u8, data[0 .. data.len - 1], 0x55); | ||
| 280 | testing.expect(mem.indexOfScalar(u8, data, 0).? == 1234 - 1); | ||
| 281 | } | ||
| 282 | |||
| 283 | const test_out_file = "os_tmp_test"; | ||
| 284 | // Must be a multiple of 4096 so that the test works with mmap2 | ||
| 285 | const alloc_size = 8 * 4096; | ||
| 286 | |||
| 287 | // Create a file used for testing mmap() calls with a file descriptor | ||
| 288 | { | ||
| 289 | const file = try fs.cwd().createFile(test_out_file, .{}); | ||
| 290 | defer file.close(); | ||
| 291 | |||
| 292 | var out_stream = file.outStream(); | ||
| 293 | const stream = &out_stream.stream; | ||
| 294 | |||
| 295 | var i: u32 = 0; | ||
| 296 | while (i < alloc_size / @sizeOf(u32)) : (i += 1) { | ||
| 297 | try stream.writeIntNative(u32, i); | ||
| 298 | } | ||
| 299 | } | ||
| 300 | |||
| 301 | // Map the whole file | ||
| 302 | { | ||
| 303 | const file = try fs.cwd().createFile(test_out_file, .{ | ||
| 304 | .read = true, | ||
| 305 | .truncate = false, | ||
| 306 | }); | ||
| 307 | defer file.close(); | ||
| 308 | |||
| 309 | const data = try os.mmap( | ||
| 310 | null, | ||
| 311 | alloc_size, | ||
| 312 | os.PROT_READ, | ||
| 313 | os.MAP_PRIVATE, | ||
| 314 | file.handle, | ||
| 315 | 0, | ||
| 316 | ); | ||
| 317 | defer os.munmap(data); | ||
| 318 | |||
| 319 | var mem_stream = io.SliceInStream.init(data); | ||
| 320 | const stream = &mem_stream.stream; | ||
| 321 | |||
| 322 | var i: u32 = 0; | ||
| 323 | while (i < alloc_size / @sizeOf(u32)) : (i += 1) { | ||
| 324 | testing.expectEqual(i, try stream.readIntNative(u32)); | ||
| 325 | } | ||
| 326 | } | ||
| 327 | |||
| 328 | // Map the upper half of the file | ||
| 329 | { | ||
| 330 | const file = try fs.cwd().createFile(test_out_file, .{ | ||
| 331 | .read = true, | ||
| 332 | .truncate = false, | ||
| 333 | }); | ||
| 334 | defer file.close(); | ||
| 335 | |||
| 336 | const data = try os.mmap( | ||
| 337 | null, | ||
| 338 | alloc_size, | ||
| 339 | os.PROT_READ, | ||
| 340 | os.MAP_PRIVATE, | ||
| 341 | file.handle, | ||
| 342 | alloc_size / 2, | ||
| 343 | ); | ||
| 344 | defer os.munmap(data); | ||
| 345 | |||
| 346 | var mem_stream = io.SliceInStream.init(data); | ||
| 347 | const stream = &mem_stream.stream; | ||
| 348 | |||
| 349 | var i: u32 = alloc_size / 2 / @sizeOf(u32); | ||
| 350 | while (i < alloc_size / @sizeOf(u32)) : (i += 1) { | ||
| 351 | testing.expectEqual(i, try stream.readIntNative(u32)); | ||
| 352 | } | ||
| 353 | } | ||
| 354 | |||
| 355 | try fs.cwd().deleteFile(test_out_file); | ||
| 356 | } |