Skip to content

Commit

Permalink
add opcodes and correct offset in UI
Browse files Browse the repository at this point in the history
  • Loading branch information
hitchhooker committed Apr 16, 2024
1 parent 19b221c commit cc8d9a2
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 160 deletions.
18 changes: 9 additions & 9 deletions app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ name = "polkarun"
crate-type = ["cdylib", "rlib"]

[dependencies]
polkavm = { git = "https://github.com/koute/polkavm" }
polkavm-common = { git = "https://github.com/koute/polkavm" }
gloo-net = { version = "0.5.0", features = ["http"] }
leptos = { version = "0.5.4", features = ["csr", "nightly", "experimental-islands"] }
leptos_meta = { version = "0.5.4", features = ["csr", "nightly"] }
leptos_router = { version = "0.5.4", features = ["csr", "nightly"] }
reqwest = { version = "0.11.23" }
toml = "0.8.8"
js-sys = { version = "0.3.66" }
web-sys = { version = "0.3.66", features = ["HtmlInputElement", "DataTransfer", "DragEvent", "File", "FileList", "FileReader", "ProgressEvent"] }
leptos = { version = "0.6.11", features = ["csr", "nightly", "experimental-islands"] }
leptos_meta = { version = "0.6.11", features = ["csr", "nightly"] }
leptos_router = { version = "0.6.11", features = ["csr", "nightly"] }
reqwest = { version = "0.12.3" }
toml = "0.8.12"
js-sys = { version = "0.3.69" }
web-sys = { version = "0.3.69", features = ["HtmlInputElement", "DataTransfer", "DragEvent", "File", "FileList", "FileReader", "ProgressEvent"] }

# serialization
ron = "0.8.1"
Expand All @@ -25,7 +25,7 @@ serde = { version = "1", features = ["derive"] }

# dependecies for client (enable when csr or hydrate set)
wasm-bindgen = { version = "0.2.92" }
log = "0.4.20"
log = "0.4.21"
cached = { version = "0.47.0", optional = true }
console_log = { version = "1"}
console_error_panic_hook = { version = "0.1.7"}
Expand Down
10 changes: 5 additions & 5 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
"license": "MIT",
"publish": false,
"devDependencies": {
"@iconify-json/mdi": "1.1.64",
"@unocss/cli": "0.56.5",
"@unocss/preset-icons": "^0.58.3",
"inter-ui": "3.19.3",
"unocss": "0.56.5"
"@iconify-json/mdi": "1.1.66",
"@unocss/cli": "0.59.3",
"@unocss/preset-icons": "^0.59.3",
"inter-ui": "4.0.2",
"unocss": "0.59.3"
}
}
160 changes: 90 additions & 70 deletions app/src/disassembler.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
use leptos::*;
use polkavm::ProgramBlob;
use polkavm_common::program::{ProgramBlob, Instruction};
use crate::file_upload::FileUploadComponent;
use serde::{Deserialize, Serialize};
use std::fmt::Write;
// use ron::de::from_str;

#[derive(Clone, Debug)]
struct DisassembledLine {
offset: String,
hex: String,
assembly: String,
operation: String,
}

// Helper function to create a new DisassembledLine
impl DisassembledLine {
fn new(offset: usize, hex: String, assembly: String) -> Self {
fn new(offset: usize, hex: String, assembly: String, operation: String) -> Self {
Self {
offset: format!("{:06X}", offset),
hex,
assembly,
operation,
}
}
}
Expand All @@ -42,66 +42,20 @@ struct MainMenu {

#[component]
fn MenuButton(item: MenuItem) -> impl IntoView {
// let (toggle_submenu, set_toggle_submenu) = create_signal(false);

// let item_type = item.item_type.clone();
// let toggle_submenu_handler = move || {
// match item_type {
// MenuItemType::SubMenu(_) => {
// set_toggle_submenu(!toggle_submenu.get());
// }
// _ => {}
// }
// };

view! {
<div
role="menuitem"
class="menu-button px-4 py-2 text-md font-semibold text-gray-700 bg-white hover:bg-gray-100 focus:bg-gray-200 rounded-xs border border-gray-300 shadow-sm cursor-pointer focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50"
>
// onclick=toggle_submenu_handler
{&item.label}
// <Show when=move || match &item.item_type {
// MenuItemType::SubMenu(_) => true,
// _ => false,
// }>
//
// <div
// role="menu"
// class="menu"
// tabindex="-1"
// aria-orientation="vertical"
// aria-labelledby="radix-:R1mqrnnnlaH1:"
// style="outline:none"
// >
// <ul>
// <For
// each=move || match &item.item_type {
// MenuItemType::SubMenu(items) => items.clone().into_iter(),
// _ => vec![].into_iter(),
// }
// key=|item| item.label.clone()
// children=move |item| {
// view! { <li><MenuButton item=item.clone() /></li> }
// }
// />
// </ul>
// </div>
// </Show>
</div>
}
}

// MainMenu
#[component]
fn MainMenu() -> impl IntoView {
// fn load_menu() -> Result<MainMenu, ron::Error> {
// let content = include_str!("pages/disassembler.ron");
// println!("{}", content);
// from_str(content).map_err(|e| e.into())
// }
//
// let menu = load_menu().expect("Failed to load menu");

let menu = MainMenu {
items: vec![
Expand Down Expand Up @@ -243,30 +197,97 @@ pub fn Disassembler() -> impl IntoView {
}


fn serialize_instruction(instruction: &Instruction) -> (String, usize) {
let mut buffer = [0u8; 16]; // maximum instruction size?
let size = instruction.serialize_into(&mut buffer);

let hex_representation = buffer[..size].iter()
.map(|byte| format!("{:02x}", byte))
.collect::<Vec<String>>()
.join(" ");

(hex_representation, size)
}

fn find_first_instruction_binary(blob: &ProgramBlob) -> Result<Vec<u8>, String> {
let first_instruction = blob.instructions().next()
.ok_or("No instructions in the blob")?
.map_err(|e| format!("Error parsing first instruction: {}", e))?;

let (binary, _) = serialize_instruction(&first_instruction);

// Convert the binary string to a byte array
let mut result = Vec::new();
for byte_str in binary.split_whitespace() {
let byte = u8::from_str_radix(byte_str, 16)
.map_err(|e| format!("Error parsing byte: {}", e))?;
result.push(byte);
}

Ok(result)
}

// Function to find the true byte offset of the first instruction in the blob
fn find_true_byte_offset(blob: &ProgramBlob, first_instruction_binary: &[u8]) -> Result<usize, String> {
let blob_bytes = blob.as_bytes();

blob_bytes.windows(first_instruction_binary.len())
.position(|window| window == first_instruction_binary)
.ok_or_else(|| "Binary sequence not found".to_string())
}

// Updated calculate_program_base_address function
fn calculate_program_base_address(blob: &ProgramBlob) -> Result<usize, String> {
let first_instruction_binary = find_first_instruction_binary(blob)?;
println!("First instruction binary: {:?}", first_instruction_binary);
find_true_byte_offset(blob, &first_instruction_binary)

}

fn disassemble_into_lines(data: &[u8]) -> Result<Vec<DisassembledLine>, &'static str> {
let blob = ProgramBlob::parse(data).map_err(|_| "Failed to parse blob")?;

// Assuming you have a function that calculates the true base address of the program
let program_base_address = calculate_program_base_address(&blob)
.map_err(|_| "Failed to calculate program base address")?;

let mut result = Vec::new();
let mut offset = 0usize;
let mut hex_buffer = String::with_capacity(64); // Adjust size as needed
let mut current_byte_offset: usize = 0; // Start from the calculated program base address

for maybe_instruction in blob.instructions() {
hex_buffer.clear();

match maybe_instruction {
Ok(instruction) => {
let mut serialized = [0u8; 32]; // Adjust hard coded size as needed
let mut serialized = [0u8; 32]; // Adjust size as needed
let size = instruction.serialize_into(&mut serialized);

for &byte in &serialized[..size] {
write!(hex_buffer, "{:02X} ", byte).expect("Writing to string failed");
}

result.push(DisassembledLine::new(offset, hex_buffer.clone(), instruction.to_string()));
offset += size;
let hex_buffer = serialized[..size]
.iter()
.map(|byte| format!("{:02X} ", byte))
.collect::<String>();

// Extract the opcode name from the instruction
let opcode_name = format!("{:?}", instruction.opcode());

// Calculate the true offset for this instruction
let true_offset = current_byte_offset + program_base_address;

result.push(DisassembledLine::new(
true_offset,
hex_buffer,
instruction.to_string(),
opcode_name, // Pass the opcode name to the operation field
));
current_byte_offset += size;
},
Err(error) => {
result.push(DisassembledLine::new(offset, "ERROR".to_string(), format!("Error: {}", error)));
// Even in case of an error, calculate the true offset
let true_offset = current_byte_offset + program_base_address;

result.push(DisassembledLine::new(
true_offset,
"ERROR".to_string(),
format!("Error: {}", error),
"Unknown".to_string(), // Use a placeholder like "Unknown" for errors
));
}
}
}
Expand Down Expand Up @@ -316,7 +337,7 @@ pub fn Disassembler() -> impl IntoView {
</Show>
<div class="flex flex-1 overflow-auto">
<div class="w-full h-full">
<div class="h-50vh flex flex-row p-4">
<div class="h-60vh flex flex-row p-4">
<Show when=move || unified_data().is_empty()>
<div class="border-dashed border-4 w-full h-full p-4">
<FileUploadComponent on_file_uploaded=move |
Expand Down Expand Up @@ -387,10 +408,10 @@ pub fn Disassembler() -> impl IntoView {
<div class="w-full mt-4 border-t border-gray-200 dark:border-gray-800 overflow-x-auto">
{/* flex container for headers */}
<div class="flex divide-x divide-gray-200">
<div class="flex-1 p-2 font-bold text-left bg-gray-200">Offset</div>
<div class="flex-1 p-2 font-bold text-left bg-gray-200">Hex</div>
<div class="flex-1 p-2 font-bold text-left bg-gray-200">Assembly</div>
<div class="flex-1 p-2 font-bold text-left bg-gray-200">Hint</div>
<div class="flex-1 p-2 font-bold text-left bg-gray-200">"Offset"</div>
<div class="flex-1 p-2 font-bold text-left bg-gray-200">"Hex"</div>
<div class="flex-1 p-2 font-bold text-left bg-gray-200">"Assembly"</div>
<div class="flex-1 p-2 font-bold text-left bg-gray-200">"Operation"</div>
</div>

{/* Flex container for content */}
Expand All @@ -408,8 +429,7 @@ pub fn Disassembler() -> impl IntoView {
<pre class="whitespace-pre-wrap overflow-x-auto">{&line.assembly}</pre>
</div>
<div class="flex-1 p-2 bg-white">
{/* Placeholder for Hint */}
<pre class="whitespace-pre-wrap overflow-x-auto"></pre>
<pre class="whitespace-pre-wrap overflow-x-auto">{&line.operation}</pre>
</div>
</div>
}
Expand Down
75 changes: 7 additions & 68 deletions app/src/home.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,70 +6,15 @@ pub fn Home() -> impl IntoView {
<div class="container p-8 mx-auto">
<h1 class="text-2xl font-bold text-center md:text-4xl lg:text-5xl">"polka.run"</h1>
<div class="flex flex-col lg:flex-row gap-6 mt-6">
<div class="w-full lg:w-1/4 p-4">
<h1 class="text-xl font-bold">
"PolkaVM: Stepping up the Blockchain Virtual Machines"
</h1>
<div class="w-full lg:w-2/4 p-4">
<p class="text-md leading-relaxed mt-4">
"PolkaVM, a new RISC-V based virtual machine by Polkadot, promises to transform the blockchain landscape. Jan from Polkadot's team at Parity introduced this innovative VM, highlighting its unique features and potential benefits."
"PolkaVM is general purpose virtual machine for user-level applications. "
"It runs on x86 architechture linux based operating systems and transpiles. "
"Rust/C/asm guest programs into RISC-V based bytecode. We have built graphical "
"interface for disassembler to improve accessibility to understand binaries PolkaVM produces. "
</p>
<h2 class="text-xl mt-4 font-semibold">
"Background: Polkadot and WebAssembly"
</h2>
<p class="text-md leading-relaxed mt-2">
"Polkadot has heavily utilized WebAssembly (WASM) since its inception, utilizing it for both its state transition function, known as the runtime, and its native smart contract solution. WASM's speed and efficiency initially made it an attractive choice. However, it presented several challenges."
</p>
<ul class="list-disc pl-5 mt-2">
<li>
<strong>"Complexity"</strong>
" - WASM's instruction set grew from 172 to over 400 instructions, creating a complex and constantly evolving environment."
</li>
<li>
<strong>Determinism</strong>
" - Blockchain technology demands 100% determinism, but WASM does not fully meet this requirement."
</li>
</ul>
</div>
<div class="w-full lg:w-1/4 p-4">
<h2 class="text-xl font-semibold">"PolkaVM's Advantages"</h2>
<ul class="list-disc pl-5 mt-2">
<li>
<strong>"Performance"</strong>
" - Early benchmarks show PolkaVM nearly matching native performance."
</li>
<li>
<strong>"Efficiency"</strong>
" - Exceptional compile-time performance, significantly outpacing competitors."
</li>
<li>
<strong>"Simplicity and Stability"</strong>
" - Leverages the RISC-V architecture for a simpler, stable baseline."
</li>
<li>
<strong>"Security"</strong>
" - Runs guest programs in separate processes and namespaces, similar to Docker containers."
</li>
</ul>
<h2 class="text-xl mt-4 font-semibold">"Future Prospects"</h2>
<p class="text-md leading-relaxed mt-2">
"PolkaVM, still in its research phase, has shown impressive results in a short period."
</p>
<ul class="list-disc pl-5 mt-2">
<li>
<strong>"Time-Travel Debugging"</strong>
" - A unique feature allowing backward navigation during debugging."
</li>
<li>
<strong>"Cross-Platform Compatibility"</strong>
" - Aiming to support different CPU architectures."
</li>
<li>
<strong>"Optimization and Extensions"</strong>
" - Continuous improvements in performance and support for RISC-V extensions."
</li>
</ul>
</div>
<div class="w-full lg:w-1/2">
<div class="w-full lg:w-2/4">
<pre class="text-xs xl:text-sm">
"╔══════════════════════════════════════════════════════════════════════════════╗\n"
"║...:OdKK; ;OK;..OcXXXd0XxdkdOXNX0oX0lNdNWNWWx0WkWo0OdWXkWdK ; kNMX0d0XMMx;XMk║\n"
Expand Down Expand Up @@ -109,13 +54,7 @@ pub fn Home() -> impl IntoView {
"╚══════════════════════════════════════════════════════════════════════════════╝\n"
</pre>
</div>
</div>
<div class="mt-6">
<p class="text-md">
"PolkaVM's combination of security, determinism, and performance positions it as a promising
lightweight virtual machine, making it ideal for a wide range of applications."
</p>
</div>
</div>
</div>
}
}
Loading

0 comments on commit cc8d9a2

Please sign in to comment.