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

Access to call stack when calling native functions #3779

Open
sasq64 opened this issue Sep 9, 2024 · 5 comments
Open

Access to call stack when calling native functions #3779

sasq64 opened this issue Sep 9, 2024 · 5 comments

Comments

@sasq64
Copy link

sasq64 commented Sep 9, 2024

Feature

When a native function is called, I would like to be able to get the call stack
from the WASM side to see how the call originated.

Benefit

If anything goes wrong in the native code, it is often very helpful to see which file and line caused the issue in the web assembly code. For instance if I implement a load_file() function, and the file could not be found I can show an exception with information where this call was performed so it can be fixed.

Implementation

Since call stack dumps can already be performed, this information should already be available?
Also it is fine if only addresses are provided, the native side can use separate debug info file to look up actual file name and line.

Alternatives

...

@sasq64
Copy link
Author

sasq64 commented Sep 9, 2024

NOTE: Calling wasm_runtime_dump_call_stack(env) from the native function does nothing since at that point module->frames is empty...
(wasm code built with debug, stack trace enabled, classic interpreter)

@loganek
Copy link
Collaborator

loganek commented Sep 9, 2024

Not sure if that helps, but native function has access to the exec_env structure, so in order to obtain the call stack, you could do something like (haven't tested, so there might be some syntax issues):

static void your_native_function(wasm_exec_env_t exec_env)
{
  struct WASMInterpFrame *frame = exec_env->cur_frame; // please note that for AOT this is an instance of `AOTFrame`
  while (frame) {
    // do something with the frame
    frame = frame->prev_frame;
  }
}

@sasq64
Copy link
Author

sasq64 commented Sep 9, 2024

Not sure how to get the relevant info from the frame - there is an ip ptr that I can maybe use if I know the start of the memory to subtract from it.

I have a solution now where I dump a stack trace to a string, through

    std::array<char, 1024> buf;
    wasm_interp_create_call_stack(env);
    wasm_interp_dump_call_stack(env, false, buf.data(), buf.size());

Then I parse the string to get the addresses and use it agains a lookup table I have created from a .map file...

@sasq64
Copy link
Author

sasq64 commented Sep 9, 2024

Actually this works;

    auto* inst = wasm_runtime_get_module_inst(env);
    auto* module = wasm_runtime_get_module(inst);
    auto ip = (uint32)(cur_frame->prev_frame->ip - ((WASMModule*)module)->load_addr);

@loganek
Copy link
Collaborator

loganek commented Sep 10, 2024

Yes, similarly, the function index can be calculated by doing the following:

auto* inst = wasm_runtime_get_module_inst(env);
(uint32)(frame->function - inst->e->functions);

see implementation of the wasm_interp_create_call_stack function

wasm_interp_create_call_stack(struct WASMExecEnv *exec_env)
for more details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants