Skip to content

Commit

Permalink
[move-decompiler] Model import from binary and basic decompiler setup
Browse files Browse the repository at this point in the history
This PR closes the loop on the needed components for the decompiler and sets up basic plumbing for the command line tool.

- A major addition is a way to import Move bytecode into the move-model. Until now, this wasn't directly possible. The new module `binary_module_loader` now takes care of this. The code is mostly complete, what is missing is a way to analyze metadata to synthesize attributes. (Future PRs.)
- The crate `move-decompiler` has been added, which glues the various parts which have been created in the last few PRs into a command line tool.
- Some tests have been added together with the decompiler, which is also a good way to test the new `binary_module_loader`, by replicating parts of the move-stdlib. However, the decompiler isn't functional yet, the code isn't correct in multiple instances. This has to be fixed in subsequent PRs, until the tests in `move-decompiler` allow to compile and executed decompiled code.
  • Loading branch information
wrwg committed Oct 15, 2024
1 parent 2a0e7d6 commit dc2d715
Show file tree
Hide file tree
Showing 47 changed files with 4,175 additions and 184 deletions.
21 changes: 21 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ members = [
"third_party/move/tools/move-bytecode-viewer",
"third_party/move/tools/move-cli",
"third_party/move/tools/move-coverage",
"third_party/move/tools/move-decompiler",
"third_party/move/tools/move-disassembler",
"third_party/move/tools/move-explain",
"third_party/move/tools/move-package",
Expand Down Expand Up @@ -825,6 +826,7 @@ move-coverage = { path = "third_party/move/tools/move-coverage" }
move-compiler = { path = "third_party/move/move-compiler" }
move-compiler-v2 = { path = "third_party/move/move-compiler-v2" }
move-core-types = { path = "third_party/move/move-core/types" }
move-decompiler = { path = "third_party/move/tools/move-decompiler" }
move-docgen = { path = "third_party/move/move-prover/move-docgen" }
move-disassembler = { path = "third_party/move/tools/move-disassembler" }
move-ir-types = { path = "third_party/move/move-ir/types" }
Expand Down
8 changes: 8 additions & 0 deletions third_party/move/move-binary-format/src/views.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,10 @@ impl<'a, T: ModuleAccess> StructDefinitionView<'a, T> {
self.struct_handle_view.abilities()
}

pub fn handle_idx(&self) -> StructHandleIndex {
self.struct_def.struct_handle
}

pub fn is_native(&self) -> bool {
match &self.struct_def.field_information {
StructFieldInformation::Native => true,
Expand Down Expand Up @@ -491,6 +495,10 @@ impl<'a, T: ModuleAccess> FunctionDefinitionView<'a, T> {
}
}

pub fn handle_idx(&self) -> FunctionHandleIndex {
self.function_def.function
}

pub fn visibility(&self) -> Visibility {
self.function_def.visibility
}
Expand Down
6 changes: 5 additions & 1 deletion third_party/move/move-command-line-common/src/files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ pub struct FileHash(pub [u8; 32]);

impl FileHash {
pub fn new(file_contents: &str) -> Self {
Self(sha2::Sha256::digest(file_contents.as_bytes()).into())
Self::new_from_bytes(file_contents.as_bytes())
}

pub fn new_from_bytes(bytes: &[u8]) -> Self {
Self(sha2::Sha256::digest(bytes).into())
}

pub const fn empty() -> Self {
Expand Down
13 changes: 2 additions & 11 deletions third_party/move/move-compiler-v2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ use crate::{
variable_coalescing::VariableCoalescing,
},
};
use anyhow::bail;
use codespan_reporting::{
diagnostic::Severity,
term::termcolor::{ColorChoice, StandardStream, WriteColor},
Expand Down Expand Up @@ -596,21 +595,13 @@ fn get_vm_error_loc(env: &GlobalEnv, source_map: &SourceMap, e: &VMError) -> Opt
}

/// Report any diags in the env to the writer and fail if there are errors.
pub fn check_errors<W>(
env: &GlobalEnv,
error_writer: &mut W,
msg: &'static str,
) -> anyhow::Result<()>
pub fn check_errors<W>(env: &GlobalEnv, error_writer: &mut W, msg: &str) -> anyhow::Result<()>
where
W: WriteColor + Write,
{
let options = env.get_extension::<Options>().unwrap_or_default();
env.report_diag(error_writer, options.report_severity());
if env.has_errors() {
bail!("exiting with {}", msg);
} else {
Ok(())
}
env.check_diag(error_writer, options.report_severity(), msg)
}

/// Annotate the given compiled units.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,18 @@ module 0x815::m {
}
fun update_common_field(): u64 {
let common = CommonFields::Bar{x: 30,y: 40u8,z: 50u32};
common.Foo.x = 15;
common.Foo.x
common.x = 15;
common.x
}
fun update_common_field_different_offset(): u8 {
let common = CommonFields::Bar{x: 30,y: 40u8,z: 50u32};
common.Foo.y = 15u8;
common.Foo.y
common.y = 15u8;
common.y
}
fun update_non_common_field(): u32 {
let common = CommonFields::Bar{x: 30,y: 40u8,z: 50u32};
common.Bar.z = 15u32;
common.Bar.z
common.z = 15u32;
common.z
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ module 0x815::m {
}
fun test_common_access(): u8 {
let x = Positional::A(42u8);
x.A.0 = 19u8;
x.0 = 19u8;
20u8
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,13 @@ module 0xc0ffee::m {
}
}
fun select_common_fields(s: CommonFields): u64 {
s.Foo.x + (match (s) {
s.x + (match (s) {
CommonFields::Foo{x: _,y: y} => y,
CommonFields::Bar{x: _,z: z} => z,
})
}
fun select_common_fields_different_offset(s: CommonFieldsAtDifferentOffset): u64 {
s.Bar.z
s.z
}
fun test_common(s: CommonFields): bool {
s is Foo | Bar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,17 +122,14 @@ module 0x42::m {
}
fun f10(x: u64)
acquires *(m::make_up_address(x))

{
}
fun f11()
!reads *(0x42)
!reads *(0x43)

{
}
fun f12()

{
}
fun f2()
Expand Down Expand Up @@ -161,16 +158,18 @@ module 0x42::m {
}
fun f8()
acquires *(0x42)

{
}
fun f9(a: address)
acquires *(a)

{
}
fun f_multiple()
acquires Rreads Rwrites Twrites Sreads G<u64>
acquires R
reads R
writes T
writes S
reads G<u64>
{
}
fun make_up_address(x: u64): address {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,19 @@ module 0x8675309::M {
struct X has key {
}
fun t0()
acquires Racquires Xacquires R
acquires R
acquires X
acquires R
{
borrow_global_mut<R>(0x1);
borrow_global_mut<X>(0x1);
}
fun t1()
acquires Racquires Xacquires Racquires Racquires R
acquires R
acquires X
acquires R
acquires R
acquires R
{
borrow_global_mut<R>(0x1);
borrow_global_mut<X>(0x1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ module 0x42::test {
}
}
fun common_access(x: Foo): u8 {
x.A.0
x.0
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ module 0x42::M {
}

*/
native fun contains<K, V>(t: &MyTable2<K, V>, k: K): bool ;
native fun borrow<K, V>(t: &MyTable2<K, V>, k: K): &V ;
native fun borrow_mut<K, V>(t: &mut MyTable1<K, V>, k: K): &mut V ;
native fun destroy_empty<K, V>(t: MyTable1<K, V>) ;
native fun length<K, V>(t: &MyTable1<K, V>): u64 ;
native fun remove<K, V>(t: &mut MyTable2<K, V>, k: K): V ;
native fun new<K, V>(): MyTable1<K, V> ;
native fun new2<K, V>(): MyTable2<K, V> ;
native fun contains<K, V>(t: &MyTable2<K, V>, k: K): bool;
native fun borrow<K, V>(t: &MyTable2<K, V>, k: K): &V;
native fun borrow_mut<K, V>(t: &mut MyTable1<K, V>, k: K): &mut V;
native fun destroy_empty<K, V>(t: MyTable1<K, V>);
native fun length<K, V>(t: &MyTable1<K, V>): u64;
native fun remove<K, V>(t: &mut MyTable2<K, V>, k: K): V;
native fun new<K, V>(): MyTable1<K, V>;
native fun new2<K, V>(): MyTable2<K, V>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ module 0x8675309::M {
}
fun unused_local_suppressed2() {
}
native fun unused_native_ok(x: u64, y: bool) ;
native fun unused_native_ok(x: u64, y: bool);
fun unused_param(x: u64) {
}
fun unused_param1_used_param2(x: u64, y: bool): bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,12 +337,12 @@ module 0x2::Token {
module 0x2::Map {
struct T<K, V> has copy, drop, store {
}
public native fun empty<K, V>(): T<K, V> ;
public native fun remove<K, V>(m: &T<K, V>, k: &K): V ;
public native fun contains_key<K, V>(m: &T<K, V>, k: &K): bool ;
public native fun get<K, V>(m: &T<K, V>, k: &K): &V ;
public native fun get_mut<K, V>(m: &mut T<K, V>, k: &K): &mut V ;
public native fun insert<K, V>(m: &T<K, V>, k: K, v: V) ;
public native fun empty<K, V>(): T<K, V>;
public native fun remove<K, V>(m: &T<K, V>, k: &K): V;
public native fun contains_key<K, V>(m: &T<K, V>, k: &K): bool;
public native fun get<K, V>(m: &T<K, V>, k: &K): &V;
public native fun get_mut<K, V>(m: &mut T<K, V>, k: &K): &mut V;
public native fun insert<K, V>(m: &T<K, V>, k: K, v: V);
}
module 0x3::OneToOneMarket {
use 0x2::Token;
Expand All @@ -360,15 +360,19 @@ module 0x3::OneToOneMarket {
price: u64,
}
public fun borrow<In: copy + drop + store, Out: copy + drop + store>(account: &signer, pool_owner: address, amount: u64): Token::Coin<Out>
acquires Priceacquires Poolacquires DepositRecordacquires BorrowRecord
acquires Price
acquires Pool
acquires DepositRecord
acquires BorrowRecord
{
if (amount <= max_borrow_amount<In,Out>(account, pool_owner)) () else abort 1025;
update_borrow_record<In,Out>(account, pool_owner, amount);
let pool = borrow_global_mut<Pool<Out>>(pool_owner);
Token::withdraw<Out>(&mut pool.coin, amount)
}
public fun deposit<In: copy + drop + store, Out: copy + drop + store>(account: &signer, pool_owner: address, coin: Token::Coin<In>)
acquires Poolacquires DepositRecord
acquires Pool
acquires DepositRecord
{
let amount = Token::value<In>(&coin);
update_deposit_record<In,Out>(account, pool_owner, amount);
Expand Down Expand Up @@ -397,7 +401,10 @@ module 0x3::OneToOneMarket {
if (Map::contains_key<address,u64>(record, &pool_owner)) *Map::get<address,u64>(record, &pool_owner) else 0
}
fun max_borrow_amount<In: copy + drop + store, Out: copy + drop + store>(account: &signer, pool_owner: address): u64
acquires Priceacquires Poolacquires DepositRecordacquires BorrowRecord
acquires Price
acquires Pool
acquires DepositRecord
acquires BorrowRecord
{
let input_deposited = deposited_amount<In,Out>(account, pool_owner);
let output_deposited = borrowed_amount<In,Out>(account, pool_owner);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,15 +317,19 @@ module 0xb055::OneToOneMarket {
price: u64,
}
public fun borrow<In: copy + drop + store, Out: copy + drop + store>(account: &signer, amount: u64): Token::Coin<Out>
acquires Priceacquires Poolacquires DepositRecordacquires BorrowRecord
acquires Price
acquires Pool
acquires DepositRecord
acquires BorrowRecord
{
if (amount <= max_borrow_amount<In,Out>(account)) () else abort 1025;
update_borrow_record<In,Out>(account, amount);
let pool = borrow_global_mut<Pool<Out>>(0xb055);
Token::withdraw<Out>(&mut pool.coin, amount)
}
public fun deposit<In: copy + drop + store, Out: copy + drop + store>(account: &signer, coin: Token::Coin<In>)
acquires Poolacquires DepositRecord
acquires Pool
acquires DepositRecord
{
let amount = Token::value<In>(&coin);
update_deposit_record<In,Out>(account, amount);
Expand All @@ -352,7 +356,10 @@ module 0xb055::OneToOneMarket {
borrow_global<DepositRecord<In, Out>>(sender).record
}
fun max_borrow_amount<In: copy + drop + store, Out: copy + drop + store>(account: &signer): u64
acquires Priceacquires Poolacquires DepositRecordacquires BorrowRecord
acquires Price
acquires Pool
acquires DepositRecord
acquires BorrowRecord
{
let input_deposited = deposited_amount<In,Out>(account);
let output_deposited = borrowed_amount<In,Out>(account);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,19 +59,19 @@ module 0x815::m {
}
fun t0(): bool {
let c = Color::Red{};
c.RGB.red == 1
c.red == 1
}
fun t1(): bool {
let c = Color::Red{};
c.RGB.red == 1
c.red == 1
}
fun t2(): bool {
let c = Color::Blue{};
c.RGB.red == 1
c.red == 1
}
fun t3(): bool {
let c = Color::Blue{};
c.RGB.red == 1
c.red == 1
}
fun t4(c: &Color) {
match (c) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,9 +331,9 @@ module 0x815::m {
}
}
fun t9_common_field(self: CommonFields): u64 {
self.Foo.x
self.x
}
fun t9_common_field_ref(self: &CommonFields): &u64 {
&self.Foo.x
&self.x
}
}
Loading

0 comments on commit dc2d715

Please sign in to comment.