如果我有一个用debug_info
从Erlang代码编译的梁文件,则打印相应的源代码非常容易:
{ok, {_, [{debug_info, {debug_info_v1, erl_abstract_code, AbstractCode}}]}} =
beam_lib:chunks("my_module.beam", [debug_info]).
{ok, Forms} = erl_abstract_code:debug_info(erlang_v1, module_name, AbstractCode, []).
io:format("~s~n", [erl_prettypr:format(erl_syntax:form_list(Forms))]).
那Elixir呢?我可以这样做的前两个步骤:
{ok, {_, [{debug_info, {debug_info_v1, elixir_erl, AbstractCode}}]}} =
beam_lib:chunks("Elixir.MyModule.beam", [debug_info]).
{ok, Forms} = elixir_erl:debug_info(elixir_v1, module_name, AbstractCode).
这给出了这种形式的地图:
#{attributes => ...,
compile_opts => [],
definitions => ...,
deprecated => [],
file => <<"my_module.ex">>,
line => 95,
module => 'Elixir.MyModule',
unreachable => []}
如何将其打印为人类可读的Elixir代码?
答案 0 :(得分:3)
有一个Visual Studio extension,可以将BEAM文件解码为Elixir源代码:
要激活扩展名,请从资源管理器视图中的.beam文件的上下文菜单中选择“反汇编BEAM”:
以下参考文献:
1)https://elixirforum.com/t/visual-studio-code-extension-to-view-beam-files/13373/4
2)http://beam-wisdoms.clau.se/en/latest/indepth-beam-file.html
ElixirLS是用于调试Elixir或Erlang代码的另一个工具。
您编译的.beam模块没有必要的函数调用来发送这些消息。在其他语言中,您可能会编译二进制文件的两个版本,一个带有调试调用,另一个没有,但是在Elixir中,它的工作方式略有不同。
当您使用
:debug_info
选项集编译Erlang或Elixir模块时,生成的.beam文件将包含带有代码的Erlang抽象格式表示形式的块。在调试模块之前,您必须通过调用:int.ni/1
来“解释”它,该操作读取此块然后清除该模块。之后,通过评估Erlang抽象形式并在每次评估之后对元过程进行必要的调用来处理对模块的任何将来调用。手动在项目中的每个模块上调用
:int.ni/1
是一件很痛苦的事情,因此,当您在ElixirLS调试器中运行Mix任务时,它将自动解释项目中的所有模块及其依赖项。对于大多数项目而言,这是一个很好的默认值,尽管它可能会在启动任务时引起明显的延迟。将来的ElixirLS版本可能会包含更多配置选项,以指定要解释的模块。注意:由于在调试之前必须先解释模块,所以您无法调试位于模块定义之外的任何代码。
重要链接:
1)https://medium.com/@JakeBeckerCode/debugging-elixir-in-vs-code-400e21814614
2)http://blog.plataformatec.com.br/2016/04/debugging-techniques-in-elixir-lang/
3)https://zorbash.com/post/debugging-elixir-applications/#otp-behaviour-tracing