Bläddra i källkod

fix panic_handler (#84)

* add  and update docs

* update doc

* add syscalls
publicqi 8 månader sedan
förälder
incheckning
94872e64ba
3 ändrade filer med 46 tillägg och 8 borttagningar
  1. 4 2
      README.md
  2. 40 6
      sdk/pinocchio/src/entrypoint/mod.rs
  3. 2 0
      sdk/pinocchio/src/syscalls.rs

+ 4 - 2
README.md

@@ -55,13 +55,15 @@ This will add `pinocchio` as a dependency to your project.
 
 
 ## Defining the program entrypoint
 ## Defining the program entrypoint
 
 
-A Solana program needs to define an entrypoint, which will be called by the runtime to begin the program execution. The `entrypoint!` macro emits the common boilerplate to set up the program entrypoint. The macro will also set up [global allocator](https://doc.rust-lang.org/stable/core/alloc/trait.GlobalAlloc.html) and [panic handler](https://doc.rust-lang.org/nomicon/panic-handler.html) using the [default_allocator!](https://docs.rs/pinocchio/latest/pinocchio/macro.default_allocator.html) and [default_panic_handler!](https://docs.rs/pinocchio/latest/pinocchio/macro.default_panic_handler.html) macros.
+A Solana program needs to define an entrypoint, which will be called by the runtime to begin the program execution. The `entrypoint!` macro emits the common boilerplate to set up the program entrypoint. The macro will also set up [global allocator](https://doc.rust-lang.org/stable/core/alloc/trait.GlobalAlloc.html) and [custom panic hook](https://github.com/anza-xyz/rust/blob/2830febbc59d44bdd7ad2c3b81731f1d08b96eba/library/std/src/sys/pal/sbf/mod.rs#L49) using the [default_allocator!](https://docs.rs/pinocchio/latest/pinocchio/macro.default_allocator.html) and [default_panic_handler!](https://docs.rs/pinocchio/latest/pinocchio/macro.default_panic_handler.html) macros.
 
 
 The [`entrypoint!`](https://docs.rs/pinocchio/latest/pinocchio/macro.entrypoint.html) is a convenience macro that invokes three other macros to set all symbols required for a program execution:
 The [`entrypoint!`](https://docs.rs/pinocchio/latest/pinocchio/macro.entrypoint.html) is a convenience macro that invokes three other macros to set all symbols required for a program execution:
 
 
 * [`program_entrypoint!`](https://docs.rs/pinocchio/latest/pinocchio/macro.program_entrypoint.html): declares the program entrypoint
 * [`program_entrypoint!`](https://docs.rs/pinocchio/latest/pinocchio/macro.program_entrypoint.html): declares the program entrypoint
 * [`default_allocator!`](https://docs.rs/pinocchio/latest/pinocchio/macro.default_allocator.html): declares the default (bump) global allocator
 * [`default_allocator!`](https://docs.rs/pinocchio/latest/pinocchio/macro.default_allocator.html): declares the default (bump) global allocator
-* [`default_panic_hanlder!`](https://docs.rs/pinocchio/latest/pinocchio/macro.default_panic_handler.html): declares the default panic handler
+* [`default_panic_handler!`](https://docs.rs/pinocchio/latest/pinocchio/macro.default_panic_handler.html): declares the default panic handler
+
+If all dependencies are `no_std`, you should append [`nostd_panic_handler!`](https://docs.rs/pinocchio/latest/pinocchio/macro.nostd_panic_handler.html) to declare a rust runtime panic handler. There's no need to do this if any dependency is `std` since rust compiler will emit std panic handler.
 
 
 To use the `entrypoint!` macro, use the following in your entrypoint definition:
 To use the `entrypoint!` macro, use the following in your entrypoint definition:
 ```rust
 ```rust

+ 40 - 6
sdk/pinocchio/src/entrypoint/mod.rs

@@ -220,10 +220,11 @@ pub unsafe fn deserialize<'a, const MAX_ACCOUNTS: usize>(
     (program_id, processed, instruction_data)
     (program_id, processed, instruction_data)
 }
 }
 
 
-/// Default panic handler.
+/// Default panic hook (std).
 ///
 ///
-/// This macro sets up a default panic handler that logs the panic message and the file where the
-/// panic occurred.
+/// This macro sets up a default panic hook that logs the panic message and the file where the
+/// panic occurred. Syscall "abort()" will be called after it returns. It acts as a hook after
+/// rust runtime panics.
 ///
 ///
 /// Note that this requires the `"std"` feature to be enabled.
 /// Note that this requires the `"std"` feature to be enabled.
 #[cfg(feature = "std")]
 #[cfg(feature = "std")]
@@ -240,11 +241,11 @@ macro_rules! default_panic_handler {
     };
     };
 }
 }
 
 
-/// Default panic handler.
+/// Default panic hook (no std).
 ///
 ///
-/// This macro sets up a default panic handler that logs the file where the panic occurred.
+/// This macro sets up a default panic hook that logs the file where the panic occurred.
 ///
 ///
-/// This is used when the `"std"` feature is disabled.
+/// This is used when the `"std"` feature is disabled and program is `std`.
 #[cfg(not(feature = "std"))]
 #[cfg(not(feature = "std"))]
 #[macro_export]
 #[macro_export]
 macro_rules! default_panic_handler {
 macro_rules! default_panic_handler {
@@ -262,6 +263,39 @@ macro_rules! default_panic_handler {
     };
     };
 }
 }
 
 
+/// A rust panic handler for `no_std`.
+///
+/// When all crates are `no_std`, we need to define a global `#[panic_handler]`.
+/// It takes over the default rust panic handler.
+///
+/// This macro is used when the `"std"` feature is disabled.
+#[cfg(not(feature = "std"))]
+#[macro_export]
+macro_rules! nostd_panic_handler {
+    () => {
+        /// A panic handler for `no_std`.
+        #[cfg(target_os = "solana")]
+        #[no_mangle]
+        #[panic_handler]
+        fn handler(info: &core::panic::PanicInfo<'_>) -> ! {
+            if let Some(location) = info.location() {
+                unsafe {
+                    $crate::syscalls::sol_panic_(
+                        location.file().as_ptr(),
+                        location.file().len() as u64,
+                        location.line() as u64,
+                        location.column() as u64,
+                    )
+                }
+            } else {
+                // Panic reporting.
+                $crate::log::sol_log("** PANICKED **");
+                unsafe { $crate::syscalls::abort() }
+            }
+        }
+    };
+}
+
 /// Default global allocator.
 /// Default global allocator.
 ///
 ///
 /// This macro sets up a default global allocator that uses a bump allocator to allocate memory.
 /// This macro sets up a default global allocator that uses a bump allocator to allocate memory.

+ 2 - 0
sdk/pinocchio/src/syscalls.rs

@@ -75,6 +75,8 @@ define_syscall!(fn sol_get_epoch_rewards_sysvar(addr: *mut u8) -> u64);
 define_syscall!(fn sol_poseidon(parameters: u64, endianness: u64, vals: *const u8, val_len: u64, hash_result: *mut u8) -> u64);
 define_syscall!(fn sol_poseidon(parameters: u64, endianness: u64, vals: *const u8, val_len: u64, hash_result: *mut u8) -> u64);
 define_syscall!(fn sol_remaining_compute_units() -> u64);
 define_syscall!(fn sol_remaining_compute_units() -> u64);
 define_syscall!(fn sol_alt_bn128_compression(op: u64, input: *const u8, input_size: u64, result: *mut u8) -> u64);
 define_syscall!(fn sol_alt_bn128_compression(op: u64, input: *const u8, input_size: u64, result: *mut u8) -> u64);
+define_syscall!(fn abort() -> !);
+define_syscall!(fn sol_panic_(filename: *const u8, filename_len: u64, line: u64, column: u64) -> !);
 
 
 #[cfg(target_feature = "static-syscalls")]
 #[cfg(target_feature = "static-syscalls")]
 pub const fn sys_hash(name: &str) -> usize {
 pub const fn sys_hash(name: &str) -> usize {