From e129da8cc212bf01c0ca94e6707c0f1dbfceb7a0 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Sun, 30 Oct 2016 17:52:40 +0100 Subject: [PATCH] Better Exception Messages: Take stack_frame argument as reference --- blog/post/10-better-exception-messages.md | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/blog/post/10-better-exception-messages.md b/blog/post/10-better-exception-messages.md index b670ce5a..e424ddfb 100644 --- a/blog/post/10-better-exception-messages.md +++ b/blog/post/10-better-exception-messages.md @@ -55,12 +55,11 @@ Now we need a way to find the memory address of this stack frame. When we look a // in src/interrupts/mod.rs extern "C" fn divide_by_zero_handler() -> ! { - let stack_frame: *const ExceptionStackFrame; + let stack_frame: &ExceptionStackFrame; unsafe { asm!("mov $0, rsp" : "=r"(stack_frame) ::: "intel"); - println!("\nEXCEPTION: DIVIDE BY ZERO\n{:#?}", - *stack_frame); - }; + } + println!("\nEXCEPTION: DIVIDE BY ZERO\n{:#?}", stack_frame); loop {} } ``` @@ -169,7 +168,7 @@ extern "C" fn divide_by_zero_wrapper() -> ! { } } -extern "C" fn divide_by_zero_handler(stack_frame: *const ExceptionStackFrame) +extern "C" fn divide_by_zero_handler(stack_frame: &ExceptionStackFrame) -> ! { println!("\nEXCEPTION: DIVIDE BY ZERO\n{:#?}", @@ -433,7 +432,7 @@ macro_rules! handler { sub rsp, 8 // align the stack pointer call $0" :: "i"($name as extern "C" fn( - *const ExceptionStackFrame) -> !) + &ExceptionStackFrame) -> !) : "rdi" : "intel"); ::core::intrinsics::unreachable(); } @@ -442,7 +441,7 @@ macro_rules! handler { }} } ``` -The macro takes a single Rust identifier (`ident`) as argument and expands to a `{}` block (hence the double braces). The block defines a new wrapper function that calls the function `$name` and passes a pointer to the exception stack frame. Note that we're fixing the argument type to `*const ExceptionStackFrame`. If we used a `_` like before, the passed function could accept an arbitrary argument, which would lead to ugly bugs at runtime. +The macro takes a single Rust identifier (`ident`) as argument and expands to a `{}` block (hence the double braces). The block defines a new wrapper function that calls the function `$name` and passes a pointer to the exception stack frame. Note that we're fixing the argument type to `&ExceptionStackFrame`. If we used a `_` like before, the passed function could accept an arbitrary argument, which would lead to ugly bugs at runtime. Now we can remove the `divide_by_zero_wrapper` and use our new `handler!` macro instead: @@ -475,7 +474,7 @@ lazy_static! { }; } -extern "C" fn invalid_opcode_handler(stack_frame: *const ExceptionStackFrame) +extern "C" fn invalid_opcode_handler(stack_frame: &ExceptionStackFrame) -> ! { let stack_frame = unsafe { &*stack_frame }; @@ -527,7 +526,7 @@ macro_rules! handler_with_error_code { sub rsp, 8 // align the stack pointer call $0" :: "i"($name as extern "C" fn( - *const ExceptionStackFrame, u64) -> !) + &ExceptionStackFrame, u64) -> !) : "rdi","rsi" : "intel"); ::core::intrinsics::unreachable(); } @@ -544,7 +543,7 @@ Let's write a page fault handler which analyzes and prints the error code: ```rust // in src/interrupts/mod.rs -extern "C" fn page_fault_handler(stack_frame: *const ExceptionStackFrame, +extern "C" fn page_fault_handler(stack_frame: &ExceptionStackFrame, error_code: u64) -> ! { println!( @@ -626,7 +625,7 @@ bitflags! { Now we can improve our page fault error message by using the new `PageFaultErrorCode`. We also print the accessed memory address: ```rust -extern "C" fn page_fault_handler(stack_frame: *const ExceptionStackFrame, +extern "C" fn page_fault_handler(stack_frame: &ExceptionStackFrame, error_code: u64) -> ! { use x86::controlregs;