Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replay osx support #115

Merged
merged 3 commits into from
Nov 7, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 52 additions & 30 deletions main/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ use constants::DEFAULT_ENDPOINT;
use ethers::abi::Bytes;
use ethers::types::{H160, U256};
use eyre::{bail, eyre, Context, Result};
use std::path::PathBuf;
use std::{fmt, path::Path};
use std::{
fmt,
path::{Path, PathBuf},
};
use tokio::runtime::Builder;
use trace::Trace;
use util::{color::Color, sys};
Expand Down Expand Up @@ -487,10 +489,10 @@ fn main() -> Result<()> {
// supported. These extensions are now incorporated as part of the `cargo-stylus` command itself and
// will be the preferred method of running them.
fn is_deprecated_extension(subcommand: &str) -> bool {
match subcommand {
"cargo-stylus-check" | "cargo-stylus-cgen" | "cargo-stylus-replay" => true,
_ => false,
}
matches!(
subcommand,
"cargo-stylus-check" | "cargo-stylus-cgen" | "cargo-stylus-replay"
)
}

async fn main_impl(args: Opts) -> Result<()> {
Expand Down Expand Up @@ -611,43 +613,63 @@ async fn simulate(args: SimulateArgs) -> Result<()> {
}

async fn replay(args: ReplayArgs) -> Result<()> {
let macos = cfg!(target_os = "macos");
if !args.child {
let rust_gdb = sys::command_exists("rust-gdb");
if !rust_gdb {
println!(
"{} not installed, falling back to {}",
"rust-gdb".red(),
"gdb".red()
);
}

let mut cmd = match rust_gdb {
true => sys::new_command("rust-gdb"),
false => sys::new_command("gdb"),
let gdb_args = [
"--quiet",
"-ex=set breakpoint pending on",
"-ex=b user_entrypoint",
"-ex=r",
"--args",
]
.as_slice();
let lldb_args = [
"--source-quietly",
"-o",
"b user_entrypoint",
"-o",
"r",
"--",
]
.as_slice();
let (cmd_name, args) = if sys::command_exists("rust-gdb") && !macos {
("rust-gdb", &gdb_args)
} else if sys::command_exists("rust-lldb") {
("rust-lldb", &lldb_args)
} else {
println!("rust specific debugger not installed, falling back to generic debugger");
if sys::command_exists("gdb") && !macos {
("gdb", &gdb_args)
} else if sys::command_exists("lldb") {
("lldb", &lldb_args)
} else {
bail!("no debugger found")
}
};
cmd.arg("--quiet");
cmd.arg("-ex=set breakpoint pending on");
cmd.arg("-ex=b user_entrypoint");
cmd.arg("-ex=r");
cmd.arg("--args");
let mut cmd = sys::new_command(cmd_name);
for arg in args.iter() {
cmd.arg(arg);
}

for arg in std::env::args() {
cmd.arg(arg);
}
cmd.arg("--child");

#[cfg(unix)]
let err = cmd.exec();
#[cfg(windows)]
let err = cmd.status();

bail!("failed to exec gdb {:?}", err);
bail!("failed to exec {cmd_name} {:?}", err);
}

let provider = sys::new_provider(&args.trace.endpoint)?;
let trace = Trace::new(provider, args.trace.tx, args.trace.use_native_tracer).await?;

build_so(&args.trace.project)?;
let so = find_so(&args.trace.project)?;
build_shared_library(&args.trace.project)?;
let library_extension = if macos { ".dylib" } else { ".so" };
let shared_library = find_shared_library(&args.trace.project, library_extension)?;

// TODO: don't assume the contract is top-level
let args_len = trace.tx.input.len();
Expand All @@ -656,7 +678,7 @@ async fn replay(args: ReplayArgs) -> Result<()> {
*hostio::FRAME.lock() = Some(trace.reader());

type Entrypoint = unsafe extern "C" fn(usize) -> usize;
let lib = libloading::Library::new(so)?;
let lib = libloading::Library::new(shared_library)?;
let main: libloading::Symbol<Entrypoint> = lib.get(b"user_entrypoint")?;

match main(args_len) {
Expand All @@ -668,7 +690,7 @@ async fn replay(args: ReplayArgs) -> Result<()> {
Ok(())
}

pub fn build_so(path: &Path) -> Result<()> {
pub fn build_shared_library(path: &Path) -> Result<()> {
let mut cargo = sys::new_command("cargo");

cargo
Expand All @@ -682,7 +704,7 @@ pub fn build_so(path: &Path) -> Result<()> {
Ok(())
}

pub fn find_so(project: &Path) -> Result<PathBuf> {
pub fn find_shared_library(project: &Path, extension: &str) -> Result<PathBuf> {
let triple = rustc_host::from_cli()?;
let so_dir = project.join(format!("target/{triple}/debug/"));
let so_dir = std::fs::read_dir(&so_dir)
Expand All @@ -698,7 +720,7 @@ pub fn find_so(project: &Path) -> Result<PathBuf> {
};
let ext = ext.to_string_lossy();

if ext.contains(".so") {
if ext.contains(extension) {
if let Some(other) = file {
let other = other.file_name().unwrap().to_string_lossy();
bail!("more than one .so found: {ext} and {other}",);
Expand Down
Loading