Panic filename (#4625)

automerge
This commit is contained in:
Jack May 2019-06-10 11:00:15 -07:00 committed by Grimes
parent 1fa31c9410
commit 9f6496d38a
13 changed files with 129 additions and 75 deletions

View File

@ -67,7 +67,7 @@ fn main() {
.expect("Unable to create BPF install directory")
.success());
let rust_programs = ["alloc", "iter", "noop"];
let rust_programs = ["alloc", "iter", "noop", "panic"];
for program in rust_programs.iter() {
println!(
"cargo:warning=(not a warning) Building Rust-based BPF programs: solana_bpf_rust_{}",

View File

@ -1,5 +1,3 @@
[dependencies.compiler_builtins]
path = "../../../../sdk/bpf/rust-bpf-sysroot/src/compiler-builtins"
features = ["c", "mem"]

View File

@ -1,5 +1,4 @@
//! @brief Example Rust-based BPF program that prints out the parameters passed to it
//! @brief Example Rust-based BPF program that test dynamic memory allocation
#![no_std]
#[macro_use]

View File

@ -1,5 +1,3 @@
[dependencies.compiler_builtins]
path = "../../../../sdk/bpf/rust-bpf-sysroot/src/compiler-builtins"
features = ["c", "mem"]

View File

@ -1,4 +1,4 @@
//! @brief Example Rust-based BPF program that prints out the parameters passed to it
//! @brief Example Rust-based BPF program tests loop iteration
#![no_std]

View File

@ -1,5 +1,3 @@
[dependencies.compiler_builtins]
path = "../../../../sdk/bpf/rust-bpf-sysroot/src/compiler-builtins"
features = ["c", "mem"]

3
programs/bpf/rust/panic/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/target/
Cargo.lock

View File

@ -0,0 +1,22 @@
# Note: This crate must be built using build.sh
[package]
name = "solana-bpf-rust-panic"
version = "0.15.0"
description = "Solana BPF iter program written in Rust"
authors = ["Solana Maintainers <maintainers@solana.com>"]
repository = "https://github.com/solana-labs/solana"
license = "Apache-2.0"
homepage = "https://solana.com/"
edition = "2018"
[dependencies]
solana-sdk-bpf-utils = { path = "../../../../sdk/bpf/rust-utils", version = "0.16.0" }
[workspace]
members = []
[lib]
name = "solana_bpf_rust_panic"
crate-type = ["cdylib"]

View File

@ -0,0 +1,6 @@
[dependencies.compiler_builtins]
path = "../../../../sdk/bpf/rust-bpf-sysroot/src/compiler-builtins"
features = ["c", "mem"]
[target.bpfel-unknown-unknown.dependencies]
alloc = { path = "../../../../sdk/bpf/rust-bpf-sysroot/src/liballoc" }

View File

@ -0,0 +1,10 @@
//! @brief Example Rust-based BPF program that panics
#![no_std]
extern crate solana_sdk_bpf_utils;
#[no_mangle]
pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
panic!();
}

View File

@ -41,15 +41,15 @@ mod bpf {
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
let (genesis_block, alice_keypair) = create_genesis_block(50);
let (genesis_block, mint_keypair) = create_genesis_block(50);
let bank = Bank::new(&genesis_block);
let bank_client = BankClient::new(bank);
// Call user program
let program_id = load_program(&bank_client, &alice_keypair, &bpf_loader::id(), elf);
let instruction = create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8);
let program_id = load_program(&bank_client, &mint_keypair, &bpf_loader::id(), elf);
let instruction = create_invoke_instruction(mint_keypair.pubkey(), program_id, &1u8);
bank_client
.send_instruction(&alice_keypair, instruction)
.send_instruction(&mint_keypair, instruction)
.unwrap();
}
@ -72,23 +72,23 @@ mod bpf {
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
let (genesis_block, alice_keypair) = create_genesis_block(50);
let (genesis_block, mint_keypair) = create_genesis_block(50);
let bank = Bank::new(&genesis_block);
let bank_client = BankClient::new(bank);
let loader_pubkey = load_program(
&bank_client,
&alice_keypair,
&mint_keypair,
&native_loader::id(),
"solana_bpf_loader".as_bytes().to_vec(),
);
// Call user program
let program_id = load_program(&bank_client, &alice_keypair, &loader_pubkey, elf);
let program_id = load_program(&bank_client, &mint_keypair, &loader_pubkey, elf);
let instruction =
create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8);
create_invoke_instruction(mint_keypair.pubkey(), program_id, &1u8);
bank_client
.send_instruction(&alice_keypair, instruction)
.send_instruction(&mint_keypair, instruction)
.unwrap();
}
}
@ -107,38 +107,42 @@ mod bpf {
solana_logger::setup();
let programs = [
"solana_bpf_rust_alloc",
"solana_bpf_rust_iter",
"solana_bpf_rust_noop",
("solana_bpf_rust_alloc", true),
("solana_bpf_rust_iter", true),
("solana_bpf_rust_noop", true),
("solana_bpf_rust_panic", false),
];
for program in programs.iter() {
let filename = create_bpf_path(program);
println!("Test program: {:?} from {:?}", program, filename);
let filename = create_bpf_path(program.0);
println!("Test program: {:?} from {:?}", program.0, filename);
let mut file = File::open(filename).unwrap();
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
let (genesis_block, alice_keypair) = create_genesis_block(50);
let (genesis_block, mint_keypair) = create_genesis_block(50);
let bank = Bank::new(&genesis_block);
let bank_client = BankClient::new(bank);
let loader_pubkey = load_program(
&bank_client,
&alice_keypair,
&mint_keypair,
&native_loader::id(),
"solana_bpf_loader".as_bytes().to_vec(),
);
// Call user program
let program_id = load_program(&bank_client, &alice_keypair, &loader_pubkey, elf);
let program_id = load_program(&bank_client, &mint_keypair, &loader_pubkey, elf);
let account_metas = vec![
AccountMeta::new(alice_keypair.pubkey(), true),
AccountMeta::new(mint_keypair.pubkey(), true),
AccountMeta::new(Keypair::new().pubkey(), false),
];
let instruction = Instruction::new(program_id, &1u8, account_metas);
bank_client
.send_instruction(&alice_keypair, instruction)
.unwrap();
let result = bank_client.send_instruction(&mint_keypair, instruction);
if program.1 {
assert!(result.is_ok());
} else {
assert!(result.is_err());
}
}
}
}

View File

@ -37,7 +37,31 @@ use allocator_bump::BPFAllocator;
/// are expected to enforce this
const DEFAULT_HEAP_SIZE: usize = 32 * 1024;
/// Verifies a string passed out of the program
fn verify_string(addr: u64, ro_regions: &[MemoryRegion]) -> Result<(()), Error> {
for region in ro_regions.iter() {
if region.addr <= addr && (addr as u64) < region.addr + region.len {
let c_buf: *const c_char = addr as *const c_char;
let max_size = region.addr + region.len - addr;
unsafe {
for i in 0..max_size {
if std::ptr::read(c_buf.offset(i as isize)) == 0 {
return Ok(());
}
}
}
return Err(Error::new(ErrorKind::Other, "Error, Unterminated string"));
}
}
Err(Error::new(
ErrorKind::Other,
"Error: Load segfault, bad string pointer",
))
}
/// Abort helper functions, called when the BPF program calls `abort()`
/// The verify function returns an error which will cause the BPF program
/// to be halted immediately
pub fn helper_abort_verify(
_arg1: u64,
_arg2: u64,
@ -69,16 +93,29 @@ pub fn helper_abort(
/// The verify function returns an error which will cause the BPF program
/// to be halted immediately
pub fn helper_sol_panic_verify(
_arg1: u64,
_arg2: u64,
_arg3: u64,
file: u64,
line: u64,
column: u64,
_arg4: u64,
_arg5: u64,
_context: &mut Option<Box<Any + 'static>>,
_ro_regions: &[MemoryRegion],
ro_regions: &[MemoryRegion],
_rw_regions: &[MemoryRegion],
) -> Result<(()), Error> {
Err(Error::new(ErrorKind::Other, "Error: BPF program Panic!"))
if verify_string(file, ro_regions).is_ok() {
let c_buf: *const c_char = file as *const c_char;
let c_str: &CStr = unsafe { CStr::from_ptr(c_buf) };
if let Ok(slice) = c_str.to_str() {
return Err(Error::new(
ErrorKind::Other,
format!(
"Error: BPF program Panicked at {}, {}:{}",
slice, line, column
),
));
}
}
Err(Error::new(ErrorKind::Other, "Error: BPF program Panicked"))
}
pub fn helper_sol_panic(
_arg1: u64,
@ -105,24 +142,7 @@ pub fn helper_sol_log_verify(
ro_regions: &[MemoryRegion],
_rw_regions: &[MemoryRegion],
) -> Result<(()), Error> {
for region in ro_regions.iter() {
if region.addr <= addr && (addr as u64) < region.addr + region.len {
let c_buf: *const c_char = addr as *const c_char;
let max_size = region.addr + region.len - addr;
unsafe {
for i in 0..max_size {
if std::ptr::read(c_buf.offset(i as isize)) == 0 {
return Ok(());
}
}
}
return Err(Error::new(ErrorKind::Other, "Error, Unterminated string"));
}
}
Err(Error::new(
ErrorKind::Other,
"Error: Load segfault, bad string pointer",
))
verify_string(addr, ro_regions)
}
pub fn helper_sol_log(
addr: u64,

View File

@ -1,36 +1,32 @@
//! @brief Solana Rust-based BPF program panic handling
use crate::log::*;
use core::fmt::{self, Write};
use core::panic::PanicInfo;
#[cfg(not(test))]
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
sol_log("Panic!");
// TODO crashes! sol_log(_info.payload().downcast_ref::<&str>().unwrap());
if let Some(location) = info.location() {
if !location.file().is_empty() {
// TODO location.file() returns empty str, if we get here its been fixed
sol_log(location.file());
sol_log("location.file() is fixed!!");
match info.location() {
Some(location) => {
let mut file: [u8; 128] = [0; 128];
for (i, c) in location.file().as_bytes().iter().enumerate() {
if i >= 126 {
break;
}
file[i] = *c;
}
unsafe {
sol_panic_();
sol_panic_(
file.as_ptr(),
u64::from(location.line()),
u64::from(location.column()),
);
}
}
sol_log_64(
0,
0,
0,
u64::from(location.line()),
u64::from(location.column()),
);
} else {
sol_log("Panic!, but could not get location information");
}
unsafe {
sol_panic_();
None => unsafe { sol_panic_(0 as *const u8, 0, 0) },
}
}
extern "C" {
pub fn sol_panic_() -> !;
pub fn sol_panic_(message: *const u8, line: u64, column: u64) -> !;
}