| author | |
| committer | |
| log | caa334712fc8f540349e54fa3008aa3fdef64e13 |
| tree | 5cc39b79cc97a305cfbc981d9e426cf1896947d4 |
| parent | 89ef004646896a145ec0607678882a395fabda3d |
debug: fixup ucontext_t check3 files changed, 118 insertions(+), 64 deletions(-)
lib/std/debug.zig+1-1| ... | ... | @@ -136,7 +136,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void { |
| 136 | 136 | pub const StackTraceContext = blk: { |
| 137 | 137 | if (native_os == .windows) { |
| 138 | 138 | break :blk std.os.windows.CONTEXT; |
| 139 | } else if (@hasDecl(os.system, "ucontext_t")) { | |
| 139 | } else if (StackIterator.supports_context) { | |
| 140 | 140 | break :blk os.ucontext_t; |
| 141 | 141 | } else { |
| 142 | 142 | break :blk void; |
lib/std/os/linux/x86.zig+57-28| ... | ... | @@ -394,28 +394,51 @@ fn gpRegisterOffset(comptime reg_index: comptime_int) usize { |
| 394 | 394 | return @offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "gregs") + @sizeOf(usize) * reg_index; |
| 395 | 395 | } |
| 396 | 396 | |
| 397 | pub inline fn getcontext(context: *ucontext_t) usize { | |
| 397 | noinline fn getContextReturnAddress() usize { | |
| 398 | return @returnAddress(); | |
| 399 | } | |
| 400 | ||
| 401 | pub fn getContextInternal() callconv(.Naked) void { | |
| 398 | 402 | asm volatile ( |
| 399 | \\ movl %%edi, (%[edi_offset])(%[context]) | |
| 400 | \\ movl %%esi, (%[esi_offset])(%[context]) | |
| 401 | \\ movl %%ebp, (%[ebp_offset])(%[context]) | |
| 402 | \\ movl %%esp, (%[esp_offset])(%[context]) | |
| 403 | \\ movl %%ebx, (%[ebx_offset])(%[context]) | |
| 404 | \\ movl %%edx, (%[edx_offset])(%[context]) | |
| 405 | \\ movl %%ecx, (%[ecx_offset])(%[context]) | |
| 406 | \\ movl %%eax, (%[eax_offset])(%[context]) | |
| 403 | \\ movl $0, (%[flags_offset])(%%edx) | |
| 404 | \\ movl $0, (%[link_offset])(%%edx) | |
| 405 | \\ movl %%edi, (%[edi_offset])(%%edx) | |
| 406 | \\ movl %%esi, (%[esi_offset])(%%edx) | |
| 407 | \\ movl %%ebp, (%[ebp_offset])(%%edx) | |
| 408 | \\ movl %%ebx, (%[ebx_offset])(%%edx) | |
| 409 | \\ movl %%edx, (%[edx_offset])(%%edx) | |
| 410 | \\ movl %%ecx, (%[ecx_offset])(%%edx) | |
| 411 | \\ movl %%eax, (%[eax_offset])(%%edx) | |
| 412 | \\ movl (%%esp), %%ecx | |
| 413 | \\ movl %%ecx, (%[eip_offset])(%%edx) | |
| 414 | \\ leal 4(%%esp), %%ecx | |
| 415 | \\ movl %%ecx, (%[esp_offset])(%%edx) | |
| 407 | 416 | \\ xorl %%ecx, %%ecx |
| 408 | 417 | \\ movw %%fs, %%cx |
| 409 | \\ movl %%ecx, (%[fs_offset])(%[context]) | |
| 410 | \\ leal (%[regspace_offset])(%[context]), %%ecx | |
| 411 | \\ movl %%ecx, (%[fpregs_offset])(%[context]) | |
| 418 | \\ movl %%ecx, (%[fs_offset])(%%edx) | |
| 419 | \\ leal (%[regspace_offset])(%%edx), %%ecx | |
| 420 | \\ movl %%ecx, (%[fpregs_offset])(%%edx) | |
| 412 | 421 | \\ fnstenv (%%ecx) |
| 413 | 422 | \\ fldenv (%%ecx) |
| 414 | \\ call getcontext_read_eip | |
| 415 | \\ getcontext_read_eip: pop %%ecx | |
| 416 | \\ movl %%ecx, (%[eip_offset])(%[context]) | |
| 423 | \\ pushl %%ebx | |
| 424 | \\ pushl %%esi | |
| 425 | \\ xorl %%ebx, %%ebx | |
| 426 | \\ movl %[sigaltstack], %%eax | |
| 427 | \\ leal (%[stack_offset])(%%edx), %%ecx | |
| 428 | \\ int $0x80 | |
| 429 | \\ cmpl $0, %%eax | |
| 430 | \\ jne return | |
| 431 | \\ movl %[sigprocmask], %%eax | |
| 432 | \\ xorl %%ecx, %%ecx | |
| 433 | \\ leal (%[sigmask_offset])(%%edx), %%edx | |
| 434 | \\ movl %[sigset_size], %%esi | |
| 435 | \\ int $0x80 | |
| 436 | \\ return: | |
| 437 | \\ popl %%esi | |
| 438 | \\ popl %%ebx | |
| 417 | 439 | : |
| 418 | : [context] "{edi}" (context), | |
| 440 | : [flags_offset] "p" (@offsetOf(ucontext_t, "flags")), | |
| 441 | [link_offset] "p" (@offsetOf(ucontext_t, "link")), | |
| 419 | 442 | [edi_offset] "p" (comptime gpRegisterOffset(REG.EDI)), |
| 420 | 443 | [esi_offset] "p" (comptime gpRegisterOffset(REG.ESI)), |
| 421 | 444 | [ebp_offset] "p" (comptime gpRegisterOffset(REG.EBP)), |
| ... | ... | @@ -428,18 +451,24 @@ pub inline fn getcontext(context: *ucontext_t) usize { |
| 428 | 451 | [fs_offset] "p" (comptime gpRegisterOffset(REG.FS)), |
| 429 | 452 | [fpregs_offset] "p" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")), |
| 430 | 453 | [regspace_offset] "p" (@offsetOf(ucontext_t, "regspace")), |
| 431 | : "memory", "ecx" | |
| 454 | [sigaltstack] "i" (@intFromEnum(linux.SYS.sigaltstack)), | |
| 455 | [stack_offset] "p" (@offsetOf(ucontext_t, "stack")), | |
| 456 | [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)), | |
| 457 | [sigmask_offset] "p" (@offsetOf(ucontext_t, "sigmask")), | |
| 458 | [sigset_size] "i" (linux.NSIG / 8), | |
| 459 | : "memory", "eax", "ecx", "edx" | |
| 432 | 460 | ); |
| 461 | } | |
| 433 | 462 | |
| 434 | // TODO: Read CS/SS registers? | |
| 435 | // TODO: Store mxcsr state, need an actual definition of fpstate for that | |
| 436 | ||
| 437 | // TODO: `flags` isn't present in the getcontext man page, figure out what to write here | |
| 438 | context.flags = 0; | |
| 439 | context.link = null; | |
| 440 | ||
| 441 | const altstack_result = linux.sigaltstack(null, &context.stack); | |
| 442 | if (altstack_result != 0) return altstack_result; | |
| 443 | ||
| 444 | return linux.sigprocmask(0, null, &context.sigmask); | |
| 463 | pub inline fn getcontext(context: *ucontext_t) usize { | |
| 464 | // This method is used so that getContextInternal can control | |
| 465 | // its prologue in order to read ESP from a constant offset. | |
| 466 | // The unused &getContextInternal input is required so the function is included in the binary. | |
| 467 | return asm volatile ( | |
| 468 | \\ call os.linux.x86.getContextInternal | |
| 469 | : [ret] "={eax}" (-> usize), | |
| 470 | : [context] "{edx}" (context), | |
| 471 | [getContextInternal] "X" (&getContextInternal), | |
| 472 | : "memory", "ecx" | |
| 473 | ); | |
| 445 | 474 | } |
lib/std/os/linux/x86_64.zig+60-35| ... | ... | @@ -400,35 +400,53 @@ fn gpRegisterOffset(comptime reg_index: comptime_int) usize { |
| 400 | 400 | return @offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "gregs") + @sizeOf(usize) * reg_index; |
| 401 | 401 | } |
| 402 | 402 | |
| 403 | pub inline fn getcontext(context: *ucontext_t) usize { | |
| 403 | fn getContextInternal() callconv(.Naked) void { | |
| 404 | // TODO: Read GS/FS registers? | |
| 404 | 405 | asm volatile ( |
| 405 | \\ movq %%r8, (%[r8_offset])(%[context]) | |
| 406 | \\ movq %%r9, (%[r9_offset])(%[context]) | |
| 407 | \\ movq %%r10, (%[r10_offset])(%[context]) | |
| 408 | \\ movq %%r11, (%[r11_offset])(%[context]) | |
| 409 | \\ movq %%r12, (%[r12_offset])(%[context]) | |
| 410 | \\ movq %%r13, (%[r13_offset])(%[context]) | |
| 411 | \\ movq %%r14, (%[r14_offset])(%[context]) | |
| 412 | \\ movq %%r15, (%[r15_offset])(%[context]) | |
| 413 | \\ movq %%rdi, (%[rdi_offset])(%[context]) | |
| 414 | \\ movq %%rsi, (%[rsi_offset])(%[context]) | |
| 415 | \\ movq %%rbp, (%[rbp_offset])(%[context]) | |
| 416 | \\ movq %%rbx, (%[rbx_offset])(%[context]) | |
| 417 | \\ movq %%rdx, (%[rdx_offset])(%[context]) | |
| 418 | \\ movq %%rax, (%[rax_offset])(%[context]) | |
| 419 | \\ movq %%rcx, (%[rcx_offset])(%[context]) | |
| 420 | \\ movq %%rsp, (%[rsp_offset])(%[context]) | |
| 421 | \\ leaq (%%rip), %%rcx | |
| 422 | \\ movq %%rcx, (%[rip_offset])(%[context]) | |
| 406 | \\ movq $0, (%[flags_offset])(%%rdi) | |
| 407 | \\ movq $0, (%[link_offset])(%%rdi) | |
| 408 | \\ movq %%r8, (%[r8_offset])(%%rdi) | |
| 409 | \\ movq %%r9, (%[r9_offset])(%%rdi) | |
| 410 | \\ movq %%r10, (%[r10_offset])(%%rdi) | |
| 411 | \\ movq %%r11, (%[r11_offset])(%%rdi) | |
| 412 | \\ movq %%r12, (%[r12_offset])(%%rdi) | |
| 413 | \\ movq %%r13, (%[r13_offset])(%%rdi) | |
| 414 | \\ movq %%r14, (%[r14_offset])(%%rdi) | |
| 415 | \\ movq %%r15, (%[r15_offset])(%%rdi) | |
| 416 | \\ movq %%rdi, (%[rdi_offset])(%%rdi) | |
| 417 | \\ movq %%rsi, (%[rsi_offset])(%%rdi) | |
| 418 | \\ movq %%rbp, (%[rbp_offset])(%%rdi) | |
| 419 | \\ movq %%rbx, (%[rbx_offset])(%%rdi) | |
| 420 | \\ movq %%rdx, (%[rdx_offset])(%%rdi) | |
| 421 | \\ movq %%rax, (%[rax_offset])(%%rdi) | |
| 422 | \\ movq %%rcx, (%[rcx_offset])(%%rdi) | |
| 423 | \\ movq (%%rsp), %%rcx | |
| 424 | \\ movq %%rcx, (%[rip_offset])(%%rdi) | |
| 425 | \\ leaq 8(%%rsp), %%rcx | |
| 426 | \\ movq %%rcx, (%[rsp_offset])(%%rdi) | |
| 423 | 427 | \\ pushfq |
| 424 | \\ popq (%[efl_offset])(%[context]) | |
| 425 | \\ leaq (%[fpmem_offset])(%[context]), %%rcx | |
| 426 | \\ movq %%rcx, (%[fpstate_offset])(%[context]) | |
| 428 | \\ popq (%[efl_offset])(%%rdi) | |
| 429 | \\ leaq (%[fpmem_offset])(%%rdi), %%rcx | |
| 430 | \\ movq %%rcx, (%[fpstate_offset])(%%rdi) | |
| 427 | 431 | \\ fnstenv (%%rcx) |
| 428 | 432 | \\ fldenv (%%rcx) |
| 429 | \\ stmxcsr (%[mxcsr_offset])(%[context]) | |
| 433 | \\ stmxcsr (%[mxcsr_offset])(%%rdi) | |
| 434 | \\ leaq (%[stack_offset])(%%rdi), %%rsi | |
| 435 | \\ movq %%rdi, %%r8 | |
| 436 | \\ xorq %%rdi, %%rdi | |
| 437 | \\ movq %[sigaltstack], %%rax | |
| 438 | \\ syscall | |
| 439 | \\ cmpq $0, %%rax | |
| 440 | \\ jne return | |
| 441 | \\ movq %[sigprocmask], %%rax | |
| 442 | \\ xorq %%rsi, %%rsi | |
| 443 | \\ leaq (%[sigmask_offset])(%%r8), %%rdx | |
| 444 | \\ movq %[sigset_size], %%r10 | |
| 445 | \\ syscall | |
| 446 | \\ return: | |
| 430 | 447 | : |
| 431 | : [context] "{rdi}" (context), | |
| 448 | : [flags_offset] "p" (@offsetOf(ucontext_t, "flags")), | |
| 449 | [link_offset] "p" (@offsetOf(ucontext_t, "link")), | |
| 432 | 450 | [r8_offset] "p" (comptime gpRegisterOffset(REG.R8)), |
| 433 | 451 | [r9_offset] "p" (comptime gpRegisterOffset(REG.R9)), |
| 434 | 452 | [r10_offset] "p" (comptime gpRegisterOffset(REG.R10)), |
| ... | ... | @@ -450,17 +468,24 @@ pub inline fn getcontext(context: *ucontext_t) usize { |
| 450 | 468 | [fpstate_offset] "p" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")), |
| 451 | 469 | [fpmem_offset] "p" (@offsetOf(ucontext_t, "fpregs_mem")), |
| 452 | 470 | [mxcsr_offset] "p" (@offsetOf(ucontext_t, "fpregs_mem") + @offsetOf(fpstate, "mxcsr")), |
| 453 | : "memory", "rcx" | |
| 471 | [sigaltstack] "i" (@intFromEnum(linux.SYS.sigaltstack)), | |
| 472 | [stack_offset] "p" (@offsetOf(ucontext_t, "stack")), | |
| 473 | [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)), | |
| 474 | [sigmask_offset] "p" (@offsetOf(ucontext_t, "sigmask")), | |
| 475 | [sigset_size] "i" (linux.NSIG / 8), | |
| 476 | : "memory", "rcx", "rdx", "rdi", "rsi", "r8", "r10", "r11" | |
| 454 | 477 | ); |
| 478 | } | |
| 455 | 479 | |
| 456 | // TODO: Read GS/FS registers? | |
| 457 | ||
| 458 | // TODO: `flags` isn't present in the getcontext man page, figure out what to write here | |
| 459 | context.flags = 0; | |
| 460 | context.link = null; | |
| 461 | ||
| 462 | const altstack_result = linux.sigaltstack(null, &context.stack); | |
| 463 | if (altstack_result != 0) return altstack_result; | |
| 464 | ||
| 465 | return linux.sigprocmask(0, null, &context.sigmask); | |
| 480 | pub inline fn getcontext(context: *ucontext_t) usize { | |
| 481 | // This method is used so that getContextInternal can control | |
| 482 | // its prologue in order to read RSP from a constant offset | |
| 483 | // The unused &getContextInternal input is required so the function is included in the binary. | |
| 484 | return asm volatile ( | |
| 485 | \\ call os.linux.x86_64.getContextInternal | |
| 486 | : [ret] "={rax}" (-> usize), | |
| 487 | : [context] "{rdi}" (context), | |
| 488 | [getContextInternal] "X" (&getContextInternal), | |
| 489 | : "memory", "rcx", "rdx", "rdi", "rsi", "r8", "r10", "r11" | |
| 490 | ); | |
| 466 | 491 | } |