EOSIO / eosio.cdt

EOSIO.CDT (Contract Development Toolkit) is a suite of tools used to build EOSIO contracts
http://eosio.github.io/eosio.cdt
MIT License
511 stars 288 forks source link

eosio::wasm_entry not creating an export #757

Open MrToph opened 4 years ago

MrToph commented 4 years ago

Hi, I'm trying to export another symbol besides the apply function for WASM which seems to be possible using the eosio::wasm_entry attribute.

But it doesn't work for me. The exported function is just not part of the WASM at all. Here's my example contract:

#include <eosio/eosio.hpp>

extern "C" __attribute__((eosio_wasm_entry)) void initialize() {}

extern "C" {
[[eosio::wasm_entry]] void foobarbaz() {
   eosio::print("do you see me in wasm?");
}
[[eosio::wasm_entry]] void apply(uint64_t receiver, uint64_t code, uint64_t action) {
  eosio::print("hello!");
}

}

When i compile it and check the WAT, it's missing:

(module
  (type (;0;) (func (param i32 i32)))
  (type (;1;) (func (param i32 i32 i32) (result i32)))
  (type (;2;) (func (param i32)))
  (type (;3;) (func))
  (type (;4;) (func (param i64 i64 i64)))
  (import "env" "eosio_assert" (func (;0;) (type 0)))
  (import "env" "memset" (func (;1;) (type 1)))
  (import "env" "prints" (func (;2;) (type 2)))
  (func (;3;) (type 3)
    (call 4))
  (func (;4;) (type 3)
    (local i32)
    (i32.store offset=12
      (local.tee 0
        (i32.sub
          (global.get 0)
          (i32.const 16)))
      (i32.const 0))
    (i32.store offset=8196
      (i32.const 0)
      (local.tee 0
        (i32.and
          (i32.add
            (i32.load
              (i32.load offset=12
                (local.get 0)))
            (i32.const 7))
          (i32.const -8))))
    (i32.store offset=8192
      (i32.const 0)
      (local.get 0))
    (i32.store offset=8204
      (i32.const 0)
      (memory.size)))
  (func (;5;) (type 2) (param i32))
  (func (;6;) (type 4) (param i64 i64 i64)
    (call 3)
    (call 2
      (i32.const 8208))
    (call 5
      (i32.const 0)))
  (table (;0;) 1 1 funcref)
  (memory (;0;) 1)
  (global (;0;) (mut i32) (i32.const 8192))
  (global (;1;) i32 (i32.const 8215))
  (global (;2;) i32 (i32.const 8215))
  (export "apply" (func 6))
  (data (;0;) (i32.const 8208) "hello!\00")
  (data (;1;) (i32.const 0) "\18 \00\00"))
swatanabe-b1 commented 4 years ago

IIRC, you can work around this by adding __attribute__((visibility("default")))

MrToph commented 4 years ago

That helped with including the function in the WASM 👍 But it's still not marked as an export.

#include <eosio/eosio.hpp>

extern "C" __attribute__((visibility("default"), eosio_wasm_entry)) void
initialize() {
  eosio::print("in init!");
}

extern "C" {
[[eosio::wasm_entry]] void apply(uint64_t receiver, uint64_t code,
                                 uint64_t action) {
  eosio::print("hello!");
}

[[eosio::wasm_entry]] __attribute__((visibility("default"))) void
foobarbaz(const std::vector<char> &payload) {
  eosio::print("do you see me?");
}
}
(module
  (type $t0 (func (param i32)))
  (type $t1 (func (param i32 i32)))
  (type $t2 (func (param i32 i32 i32) (result i32)))
  (type $t3 (func))
  (type $t4 (func (param i64 i64 i64)))
  (import "env" "prints" (func $env.prints (type $t0)))
  (import "env" "eosio_assert" (func $env.eosio_assert (type $t1)))
  (import "env" "memset" (func $env.memset (type $t2)))
  (func $f3 (type $t3)
    (call $f4))
  (func $f4 (type $t3)
    (local $l0 i32)
    (i32.store offset=12
      (local.tee $l0
        (i32.sub
          (global.get $g0)
          (i32.const 16)))
      (i32.const 0))
    (i32.store offset=8196
      (i32.const 0)
      (local.tee $l0
        (i32.and
          (i32.add
            (i32.load
              (i32.load offset=12
                (local.get $l0)))
            (i32.const 7))
          (i32.const -8))))
    (i32.store offset=8192
      (i32.const 0)
      (local.get $l0))
    (i32.store offset=8204
      (i32.const 0)
      (memory.size)))
  (func $f5 (type $t0) (param $p0 i32))
  (func $f6 (type $t3)
    (call $f3)
    (call $env.prints
      (i32.const 8208))
    (call $f5
      (i32.const 0)))
  (func $apply (type $t4) (param $p0 i64) (param $p1 i64) (param $p2 i64)
    (call $f3)
    (call $env.prints
      (i32.const 8217))
    (call $f5
      (i32.const 0)))
  (func $f8 (type $t0) (param $p0 i32)
    (call $f3)
    (call $env.prints
      (i32.const 8224))
    (call $f5
      (i32.const 0)))
  (table $T0 1 1 funcref)
  (memory $M0 1)
  (global $g0 (mut i32) (i32.const 8192))
  (global $g1 i32 (i32.const 8239))
  (global $g2 i32 (i32.const 8239))
  (export "apply" (func $apply))
  (data $d0 (i32.const 8208) "in init!\00")
  (data $d1 (i32.const 8217) "hello!\00")
  (data $d2 (i32.const 8224) "do you see me?\00")
  (data $d3 (i32.const 0) "0 \00\00"))

Any other attribute I can add so it's marked as an export?

swatanabe-b1 commented 4 years ago

What you need isn't an attribute. It's an undocumented linker option:

eosio-ld -only-export=foobarbaz:function foobarbaz.o -o foobarbaz.wasm
MrToph commented 4 years ago

This PR seems to expose it, but it was not included in the recent v1.7 release :(

I'm still getting this error on 1.7:

eosio-ld: Unknown command line argument '-only-export'.  Try: 'eosio-ld -help'
eosio-ld: Did you mean '-eosio-imports'?