代码束文件在哪里? [英] where is code beam file?

查看:128
本文介绍了代码束文件在哪里?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已打印出所有加载的代码,如下所示,为什么
{lager_default_tracer,[]}在梁文件所在的位置?

I have printed all code loaded as follows, why {lager_default_tracer,[]}, where beam file?

(lager_test_1@macbook.local)10> io:format("~p",[code:all_loaded()]).
[{io,"/usr/local/lib/erlang/lib/stdlib-2.3/ebin/io.beam"},
 {erl_distribution,"/usr/local/lib/erlang/lib/kernel-3.1/ebin/erl_distribution.beam"},
 {edlin,"/usr/local/lib/erlang/lib/stdlib-2.3/ebin/edlin.beam"},
 {beam_clean,"/usr/local/lib/erlang/lib/compiler-5.0.3/ebin/beam_clean.beam"},
 {v3_core,"/usr/local/lib/erlang/lib/compiler-5.0.3/ebin/v3_core.beam"},
 {erl_epmd,"/usr/local/lib/erlang/lib/kernel-3.1/ebin/erl_epmd.beam"},
 {love_misc,"/usr/local/bin/lager_test/lib/hanoch-0.0.1.6/ebin/love_misc.beam"},
 {zlib,preloaded},
 {error_handler,"/usr/local/lib/erlang/lib/kernel-3.1/ebin/error_handler.beam"},
 {io_lib,"/usr/local/lib/erlang/lib/stdlib-2.3/ebin/io_lib.beam"},
 {lib,"/usr/local/lib/erlang/lib/stdlib-2.3/ebin/lib.beam"},
 {mnesia,"/usr/local/lib/erlang/lib/mnesia-4.12.4/ebin/mnesia.beam"},
 {lager_test_app,"/usr/local/bin/lager_test/lib/lager_test-0.0.1.0/ebin/lager_test_app.beam"},
 {beam_jump,"/usr/local/lib/erlang/lib/compiler-5.0.3/ebin/beam_jump.beam"},
 {v3_codegen,"/usr/local/lib/erlang/lib/compiler-5.0.3/ebin/v3_codegen.beam"},
 {beam_flatten,"/usr/local/lib/erlang/lib/compiler-5.0.3/ebin/beam_flatten.beam"},
 {mnesia_tm,"/usr/local/lib/erlang/lib/mnesia-4.12.4/ebin/mnesia_tm.beam"},
 {prim_eval,preloaded},
 {beam_bool,"/usr/local/lib/erlang/lib/compiler-5.0.3/ebin/beam_bool.beam"},
 {error_logger_lager_h,"/usr/local/bin/lager_test/lib/lager-2.0.0/ebin/error_logger_lager_h.beam"},
 {lager_msg,"/usr/local/bin/lager_test/lib/lager-2.0.0/ebin/lager_msg.beam"},
 {mnesia_frag,"/usr/local/lib/erlang/lib/mnesia-4.12.4/ebin/mnesia_frag.beam"},
 {filename,"/usr/local/lib/erlang/lib/stdlib-2.3/ebin/filename.beam"},
 {lager_default_tracer,[]},
 {lager_default_formatter,"/usr/local/bin/lager_test/lib/lager-2.0.0/ebin/lager_default_formatter.beam"},
 {mnesia_locker,"/usr/local/lib/erlang/lib/mnesia-4.12.4/ebin/mnesia_locker.beam"},
 {mnesia_recover,"/usr/local/lib/erlang/lib/mnesia-4.12.4/ebin/mnesia_recover.beam"},
 {mnesia_dumper,"/usr/local/lib/erlang/lib/mnesia-4.12.4/ebin/mnesia_dumper.beam"},
 {mnesia_kernel_sup,"/usr/local/lib/erlang/lib/mnesia-4.12.4/ebin/mnesia_kernel_sup.beam"},
 {mnesia_sp,"/usr/local/lib/erlang/lib/mnesia-4.12.4/ebin/mnesia_sp.beam"},
 {erts_internal,preloaded},
 {unicode,"/usr/local/lib/erlang/lib/stdlib-2.3/ebin/unicode.beam"},
 {lager_backend_throttle,"/usr/local/bin/lager_test/lib/lager-2.0.0/ebin/lager_backend_throttle.beam"},
 {beam_type,"/usr/local/lib/erlang/lib/compiler-5.0.3/ebin/beam_type.beam"},
 {orddict,"/usr/local/lib/erlang/lib/stdlib-2.3/ebin/orddict.beam"},
 {gb_sets,"/usr/local/lib/erlang/lib/stdlib-2.3/ebin/gb_sets.beam"},
 {sofs,"/usr/local/lib/erlang/lib/stdlib-2.3/ebin/sofs.beam"},
 {inet_db,"/usr/local/lib/erlang/lib/kernel-3.1/ebin/inet_db.beam"},
 {lager_test_a,"/usr/local/bin/lager_test/lib/lager_test-0.0.1.0/ebin/lager_test_a.beam"},
 {inet,"/usr/local/lib/erlang/lib/kernel-3.1/ebin/inet.beam"},

当我调用module_info()时,如下所示:

When I call module_info(), it is as follows:

(lager_test_1@macbook.local)11> lager_default_tracer:module_info().
[{exports,[{table,1},
           {handle,1},
           {module_info,0},
           {module_info,1},
           {info,1}]},
 {imports,[]},
 {attributes,[{vsn,[203040246025344403396962742072895880482]}]},
 {compile,[{options,[]},
           {version,"5.0.3"},
           {time,{2017,8,27,5,43,32}},
           {source,"/private/tmp/lager_test-0.0.1.0"}]}]

当我呼叫 lager_default_tracer时:表(111),如下所示:

(lager_test_1@macbook.local)12> lager_default_tracer:table(aaa).
** exception error: bad argument
     in function  lager_default_tracer:table/1 

中的错误参数

推荐答案

lager_default_tracer 模块没有关联的梁文件,因为它是在运行时创建的。 lager 应用程序使用 goldrush ,它使用运行时代码编译和加载。

The lager_default_tracer module has no associated beam file because it's created at runtime. The lager application uses goldrush, which uses runtime code compilation and loading.

如果您浏览 goldrush 资源,您会看到它在调用标准 compile:forms / 2 用于动态编译。通过跟踪该调用,我们可以使用以下步骤重构 lager_default_tracer 的源代码,假定您已经克隆了 lager 源存储库,并成功对其进行了编译。在某些步骤中,Erlang shell命令的输出太大而不能放在此处,因此使用省略号来缩写这些部分。

If you look through the goldrush sources you'll see that it calls the standard compile:forms/2 for dynamic compilation. By tracing that call, we can reconstruct the source code for lager_default_tracer using the steps below, which assume you've already cloned the lager source repository and successfully compiled it. In some of the steps, the output of the Erlang shell command is too large to put here, so those parts are abbreviated using ellipses.


  1. 在已经编译的克隆 lager 仓库目录中,运行 rebar shell 启动Erlang shell,这可以确保所有必需的目录都在Erlang加载路径中。

  1. In your already-compiled cloned lager repo directory, run rebar shell to start an Erlang shell, which ensures all necessary directories are in the Erlang load path.

在外壳程序中,打开 dbg 跟踪并跟踪 compile:forms / 2

In the shell, turn on dbg tracing and trace compile:forms/2:

1> dbg:tracer(), dbg:p(all, call).
{ok,[{matched,nonode@nohost,34}]}
2> dbg:tpl(compile, forms, []).
{ok,[{matched,nonode@nohost,2}]}


  • 启动 lager 应用程序及其依赖项:

  • Start the lager application and its dependencies:

    3> application:ensure_all_started(lager).
    

    这将导致生成 dbg 跟踪像这样一些冗长的输出:

    This will cause the dbg trace to produce some lengthy output like this:

    (< 0.94.0>)调用compile:forms([{{attribute,0,module,lager_default_tracer} ,
    ...
    {tuple,0,[{integer,0,2},{integer,0,1}]}}}}}}}]]]],[nowarn_unused_vars])
    {ok,[syntax_tools,compiler,goldrush,lager]}
    08:29:21.478 [info]应用程序lager在节点nonode @ nohost

    此处,输出缩写为仅显示第一行和最后几行。最后两行是 application:ensure_all_started / 1 的结果。这些行上方的所有内容都是抽象格式。 lager_default_tracer 模块。

    Here, the output is abbreviated to show only the first line and last few lines. The final two lines are the results from application:ensure_all_started/1. Everything above those lines is the abstract format for the lager_default_tracer module.

    复制从开始的跟踪输出[{attribute,0,module,lager_default_tracer} 在输出的第一行中一直跟踪到 {tuple,0,[{integer,0,2},{integer,0,1}]}]}} ]}]}] 在输出跟踪的最后一行。复制的内容中不要包含结尾文本 [nowarn_unused_vars])

    Copy the traced output starting from [{attribute,0,module,lager_default_tracer} in the first line of the output trace all the way to {tuple,0,[{integer,0,2},{integer,0,1}]}]}]}]}] in the final line of output trace. Do not include the ending text [nowarn_unused_vars]) in what you copy.

    粘贴复制的数据在Erlang shell中将其分配给名为 M 的变量:

    Paste the copied data to assign it to a variable named M in the Erlang shell:

    4> M = [{attribute,0,module,lager_default_tracer},
    ...
    {tuple,0,[{integer,0,2},{integer,0,1}]}}}}]] }]}]。

    别忘了添加最后一个句点(也称为句号)来完成表达式。

    Don't forget to add the final period (aka full stop) to complete the expression.

    关闭 dbg 跟踪:

    5> dbg:stop_clear()。
    ok

    编译抽象格式:

    6> {ok,_,B} = compile:forms(M,[no_unused_vars,debug_info])。
    {ok,lager_default_tracer,
    << <70,79,82,49,0,0,0,6,164,66,69,65,77,65,116,85,56,0,0,1 ,9,
    0,0,0,23,20,108,...>>}}

    变量 B 现在以二进制形式保存 lager_default_tracer 模块的编译代码。

    The variable B now holds, as a binary, the compiled code for the lager_default_tracer module.

    从存储在 B 中的已编译二进制文件中提取抽象代码块:

    Extract the abstract code chunk from the compiled binary stored in B:

    7> {ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(B,[abstract_code])。
    {ok,{lager_default_tracer,
    [{abstract_code,
    ...
    [{clause,0,[{var,0,'Event'}]],[], [{call,...}]}}}}}}}}}}

    变量 AC 现在保存抽象代码。

    The variable AC now holds the abstract code.

    使用抽象代码为 lager_default_tracer 模块:

    8> io:fwrite(〜s〜n,[erl_prettypr:format(erl_syntax:form_list(AC))])。
    -module(lager_default_tracer)。
    -export([info / 1,reset_counters / 1,table / 1,handle / 1])。
    ...
    handle_(Event)->
    gr_counter:update_counter(table(counters),filter,
    {2,1})。
    ok

    此最后一步和之前的一步来自 beam_lib 文档,位于重构源代码下。

    This final step and the one before it are taken from the beam_lib documentation, under "Reconstructing Source Code".

    毫不奇怪,重建的源代码显示了其他 goldrush 函数的调用,因此您需要访问 goldrush 来源如果您想尝试理解重构的代码。

    Unsurprisingly, the reconstructed source code shows calls of other goldrush functions, so you'll need access to the goldrush sources if you want to try to understand the reconstructed code.

    这篇关于代码束文件在哪里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆