BPF rust language updates (#4752)

This commit is contained in:
Jack May
2019-06-20 16:07:12 -07:00
committed by GitHub
parent aacb38864c
commit e59b53dfa8
21 changed files with 230 additions and 180 deletions

View File

@ -81,8 +81,9 @@ fn main() {
"cargo:warning=(not a warning) Building Rust-based BPF programs: solana_bpf_rust_{}",
program
);
assert!(Command::new("./build.sh")
assert!(Command::new("./do.sh")
.current_dir("rust")
.arg("build")
.arg(program)
.status()
.expect(&format!(

View File

@ -6,11 +6,10 @@
extern crate alloc;
extern crate solana_sdk_bpf_utils;
use solana_sdk_bpf_utils::log::*;
use alloc::vec::Vec;
use core::alloc::Layout;
use core::mem;
use solana_sdk_bpf_utils::info;
#[no_mangle]
pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
@ -20,7 +19,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
let layout = Layout::from_size_align(core::usize::MAX, mem::align_of::<u8>()).unwrap();
let ptr = alloc::alloc::alloc(layout);
if !ptr.is_null() {
sol_log("Error: Alloc of very larger buffer should fail");
info!("Error: Alloc of very larger buffer should fail");
panic!();
}
}
@ -31,7 +30,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
let layout = Layout::from_size_align(100, mem::align_of::<u8>()).unwrap();
let ptr = alloc::alloc::alloc(layout);
if ptr.is_null() {
sol_log("Error: Alloc of 100 bytes failed");
info!("Error: Alloc of 100 bytes failed");
alloc::alloc::handle_alloc_error(layout);
}
alloc::alloc::dealloc(ptr, layout);
@ -44,7 +43,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
let layout = Layout::from_size_align(100, mem::align_of::<u8>()).unwrap();
let ptr = alloc::alloc::alloc(layout);
if ptr.is_null() {
sol_log("Error: Alloc failed");
info!("Error: Alloc failed");
alloc::alloc::handle_alloc_error(layout);
}
for i in 0..ITERS {
@ -53,7 +52,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
for i in 0..ITERS {
assert_eq!(*ptr.add(i as usize), i as u8);
}
sol_log_64(0x3, 0, 0, 0, u64::from(*ptr.add(42)));
info!(0x3, 0, 0, 0, u64::from(*ptr.add(42)));
assert_eq!(*ptr.add(42), 42);
alloc::alloc::dealloc(ptr, layout);
}
@ -65,13 +64,13 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
// let layout = Layout::from_size_align(2048, mem::align_of::<u8>()).unwrap();
// let ptr = alloc::alloc::alloc(layout);
// if ptr.is_null() {
// sol_log("Error: Alloc of 2048 bytes failed");
// info!("Error: Alloc of 2048 bytes failed");
// alloc::alloc::handle_alloc_error(layout);
// }
// let layout = Layout::from_size_align(1, mem::align_of::<u8>()).unwrap();
// let ptr_fail = alloc::alloc::alloc(layout);
// if !ptr_fail.is_null() {
// sol_log("Error: Able to alloc 1 more then max");
// info!("Error: Able to alloc 1 more then max");
// panic!();
// }
// alloc::alloc::dealloc(ptr, layout);
@ -87,7 +86,7 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
for v in ones.iter() {
sum += ones[*v];
}
sol_log_64(0x0, 0, 0, 0, sum as u64);
info!(0x0, 0, 0, 0, sum as u64);
assert_eq!(sum, ITERS);
}
@ -98,13 +97,12 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
let mut v = Vec::new();
for i in 0..ITERS {
sol_log_64(i as u64, 0, 0, 0, 0);
v.push(i);
}
sol_log_64(0x4, 0, 0, 0, v.len() as u64);
info!(0x4, 0, 0, 0, v.len() as u64);
assert_eq!(v.len(), ITERS);
}
sol_log("Success");
info!("Success");
true
}

View File

@ -1,12 +0,0 @@
#!/usr/bin/env bash
if [ "$#" -ne 1 ]; then
# Build all projects
for project in */ ; do
./../../../sdk/bpf/rust/build.sh "$PWD/$project"
done
else
# Build requested project
./../../../sdk/bpf/rust/build.sh "$PWD/$1"
fi

View File

@ -1,12 +0,0 @@
#!/usr/bin/env bash
if [ "$#" -ne 1 ]; then
# Clean all projects
for project in */ ; do
./../../../sdk/bpf/rust/clean.sh "$PWD/$project"
done
else
# Clean requested project
./../../../sdk/bpf/rust/clean.sh "$PWD/$1"
fi

View File

@ -6,7 +6,7 @@
extern crate solana_sdk_bpf_utils;
use byteorder::{ByteOrder, LittleEndian};
use solana_sdk_bpf_utils::log::*;
use solana_sdk_bpf_utils::info;
#[no_mangle]
pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
@ -18,6 +18,6 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
LittleEndian::write_i16(&mut buf, -5_000);
assert_eq!(-5_000, LittleEndian::read_i16(&buf));
sol_log("Success");
info!("Success");
true
}

100
programs/bpf/rust/do.sh Executable file
View File

@ -0,0 +1,100 @@
#!/usr/bin/env bash
usage() {
echo ""
echo " Usage: do.sh action <project>"
echo ""
echo " If relative_project_path is ommitted then action will"
echo " be performed on all projects"
echo ""
echo " Supported actions:"
echo " build"
echo " clean"
echo " clippy"
echo " fmt"
echo ""
}
perform_action() {
set -e
case "$1" in
build)
./../../../sdk/bpf/rust/build.sh "$2"
;;
clean)
./../../../sdk/bpf/rust/clean.sh "$2"
;;
clippy)
(
cd "$2"
echo "clippy $2"
cargo +nightly clippy
)
;;
fmt)
(
cd "$2"
echo "formatting $2"
cargo fmt
)
;;
dump)
# Dump depends on tools that are not installed by default and must be installed manually
# - greadelf
# - llvm-objdump
# - rustfilt
(
pwd
./do.sh clean "$3"
./do.sh build "$3"
cd "$3"
set +e
cp ./target/dump.txt ./targetdump-last.txt 2>/dev/null
set -e
ls \
-la \
./target/bpfel-unknown-unknown/release/solana_bpf_rust_"${3%/}".so \
> ./target/dump_mangled.txt
greadelf \
-aW \
./target/bpfel-unknown-unknown/release/solana_bpf_rust_"${3%/}".so \
>> ./target/dump_mangled.txt
llvm-objdump \
-print-imm-hex \
--source \
--disassemble \
./target/bpfel-unknown-unknown/release/solana_bpf_rust_"${3%/}".so \
>> ./target/dump_mangled.txt
sed \
s/://g \
< ./target/dump_mangled.txt \
| rustfilt \
> ./target/dump.txt
)
;;
help)
usage
exit
;;
*)
echo "Error: Unknown command"
usage
exit
;;
esac
}
set -e
if [ "$#" -ne 2 ]; then
# Build all projects
for project in */ ; do
perform_action "$1" "$PWD/$project" "$project"
done
else
# Build requested project
perform_action "$1" "$PWD/$2" "$2"
fi

View File

@ -1,21 +0,0 @@
#!/usr/bin/env bash
if [ "$#" -ne 1 ]; then
echo "Error: Must provide the name of the project to dump"
exit 1
fi
./clean.sh "$1"
./build.sh "$1"
cd "$1"
cp ./target/dump.txt ./targetdump-last.txt 2>/dev/null
set -ex
ls -la ./target/bpfel-unknown-unknown/release/solana_bpf_rust_"${1%/}".so > ./target/dump_mangled.txt
greadelf -aW ./target/bpfel-unknown-unknown/release/solana_bpf_rust_"${1%/}".so >> ./target/dump_mangled.txt
llvm-objdump -print-imm-hex --source --disassemble ./target/bpfel-unknown-unknown/release/solana_bpf_rust_"${1%/}".so >> ./target/dump_mangled.txt
sed s/://g < ./target/dump_mangled.txt | rustfilt > ./target/dump.txt

View File

@ -5,7 +5,7 @@
extern crate solana_sdk_bpf_utils;
use solana_sdk_bpf_utils::log::*;
use solana_sdk_bpf_utils::info;
#[no_mangle]
pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
@ -16,9 +16,9 @@ pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
for v in ones.iter() {
sum += *v;
}
sol_log_64(0xff, 0, 0, 0, sum);
info!(0xff, 0, 0, 0, sum);
assert_eq!(sum, ITERS as u64);
sol_log("Success");
info!("Success");
true
}

View File

@ -7,18 +7,18 @@ mod helper;
extern crate solana_sdk_bpf_utils;
use solana_sdk_bpf_utils::log::*;
use solana_sdk_bpf_utils::info;
#[no_mangle]
pub extern "C" fn entrypoint(_input: *mut u8) -> bool {
sol_log("call same package");
info!("call same package");
assert_eq!(crate::helper::many_args(1, 2, 3, 4, 5, 6, 7, 8, 9), 45);
sol_log("call another package");
info!("call another package");
assert_eq!(
solana_bpf_rust_many_args_dep::many_args(1, 2, 3, 4, 5, 6, 7, 8, 9),
45
);
sol_log("Success");
info!("Success");
true
}

View File

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

View File

@ -4,7 +4,7 @@
extern crate solana_sdk_bpf_utils;
use solana_sdk_bpf_utils::log::*;
use solana_sdk_bpf_utils::info;
pub fn many_args(
arg1: u64,
@ -17,8 +17,8 @@ pub fn many_args(
arg8: u64,
arg9: u64,
) -> u64 {
sol_log("another package");
sol_log_64(arg1, arg2, arg3, arg4, arg5);
sol_log_64(arg6, arg7, arg8, arg9, 0);
info!("another package");
info!(arg1, arg2, arg3, arg4, arg5);
info!(arg6, arg7, arg8, arg9, 0);
arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9
}

View File

@ -2,12 +2,13 @@
#![no_std]
#![allow(unreachable_code)]
#![allow(unused_attributes)]
extern crate solana_sdk_bpf_utils;
use solana_sdk_bpf_utils::entrypoint;
use solana_sdk_bpf_utils::entrypoint::*;
use solana_sdk_bpf_utils::log::*;
use solana_sdk_bpf_utils::{entrypoint, info};
struct SStruct {
x: u64,
@ -21,18 +22,14 @@ fn return_sstruct() -> SStruct {
}
entrypoint!(process_instruction);
fn process_instruction(
ka: &mut [Option<SolKeyedAccount>; MAX_ACCOUNTS],
info: &SolClusterInfo,
data: &[u8],
) -> bool {
sol_log("Program identifier:");
fn process_instruction(ka: &mut [SolKeyedAccount], info: &SolClusterInfo, data: &[u8]) -> bool {
info!("Program identifier:");
sol_log_key(&info.program_id);
// Log the provided account keys and instruction input data. In the case of
// the no-op program, no account keys or input data are expected but real
// programs will have specific requirements so they can do their work.
sol_log("Account keys and instruction input data:");
info!("Account keys and instruction input data:");
sol_log_params(ka, data);
{
@ -49,7 +46,7 @@ fn process_instruction(
let result_str = core::str::from_utf8(&sparkle_heart).unwrap();
assert_eq!(4, result_str.len());
assert_eq!("💖", result_str);
sol_log(result_str);
info!(result_str);
}
{
@ -59,6 +56,6 @@ fn process_instruction(
assert_eq!(s.x + s.y + s.z, 6);
}
sol_log("Success");
info!("Success");
true
}

View File

@ -6,22 +6,14 @@
extern crate solana_sdk_bpf_utils;
use byteorder::{ByteOrder, LittleEndian};
use solana_sdk_bpf_utils::entrypoint;
use solana_sdk_bpf_utils::entrypoint::*;
use solana_sdk_bpf_utils::log::*;
use solana_sdk_bpf_utils::{entrypoint, info};
entrypoint!(process_instruction);
fn process_instruction(
ka: &mut [Option<SolKeyedAccount>; MAX_ACCOUNTS],
_info: &SolClusterInfo,
_data: &[u8],
) -> bool {
sol_log("Tick Height:");
if let Some(k) = &ka[2] {
let tick_height = LittleEndian::read_u64(k.data);
assert_eq!(10u64, tick_height);
sol_log("Success");
return true;
}
panic!();
fn process_instruction(ka: &mut [SolKeyedAccount], _info: &SolClusterInfo, _data: &[u8]) -> bool {
let tick_height = LittleEndian::read_u64(ka[2].data);
assert_eq!(10u64, tick_height);
info!("Success");
true
}

View File

@ -87,10 +87,10 @@ mod bpf {
let programs = [
("solana_bpf_rust_alloc", true),
("solana_bpf_rust_dep_crate", true),
("solana_bpf_rust_iter", true),
// ("solana_bpf_rust_many_args", true), // Issue #3099
("solana_bpf_rust_noop", true),
("solana_bpf_rust_dep_crate", true),
("solana_bpf_rust_panic", false),
("solana_bpf_rust_tick_height", true),
];

View File

@ -164,7 +164,7 @@ pub fn helper_sol_log(
let c_buf: *const c_char = addr as *const c_char;
let c_str: &CStr = unsafe { CStr::from_ptr(c_buf) };
match c_str.to_str() {
Ok(slice) => info!("sol_log: {:?}", slice),
Ok(slice) => info!("info!: {:?}", slice),
Err(e) => warn!("Error: Cannot print invalid string: {}", e),
};
0
@ -178,7 +178,7 @@ pub fn helper_sol_log_u64(
_context: &mut Option<Box<Any + 'static>>,
) -> u64 {
info!(
"sol_log_u64: {:#x}, {:#x}, {:#x}, {:#x}, {:#x}",
"info!: {:#x}, {:#x}, {:#x}, {:#x}, {:#x}",
arg1, arg2, arg3, arg4, arg5
);
0