其中是代码光束文件?(where is code beam file?)

2019-09-27 13:56发布

我已打印如下装载,为什么{lager_default_tracer,[]},其中光束文件中的所有代码?

(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(),其计算方法如下:

(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:table(111)其计算方法如下:

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

Answer 1:

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

如果你去翻goldrush来源 ,你会看到,它调用标准compile:forms/2的动态编译。 通过跟踪这一号召,我们可以重建的源代码lager_default_tracer使用下面的步骤,即假定你已经克隆了lager源代码库和编译成功了。 在一些步骤,Erlang的shell命令的输出太大,放在这里,所以这些部分使用省略号缩写。

  1. 在你已经编译克隆lager回购目录,运行rebar shell启动一个Erlang的外壳,从而确保所有必需的目录是用Erlang负载路径。

  2. 在壳,打开dbg跟踪和跟踪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}]} 
  3. 启动lager的应用和它的依赖:

     3> application:ensure_all_started(lager). 

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

    (<0.94.0>) call 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] Application lager started on node nonode@nohost

    这里,输出简称为只显示第一行和最后几行。 最后两行是从结果application:ensure_all_started/1 。 上述这些行一切是抽象的格式为lager_default_tracer模块。

  4. 所追踪的输出从起始拷贝[{attribute,0,module,lager_default_tracer}在输出轨迹的第一行一路{tuple,0,[{integer,0,2},{integer,0,1}]}]}]}]}]在输出轨迹的最后一行。 不包括结尾的文本[nowarn_unused_vars])在你复制的内容。

  5. 粘贴复制的数据以将其分配给一个指定的变量M用Erlang壳:

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

    不要忘了加最后一期(又名句号)来完成表达。

  6. 关闭dbg跟踪:

    5> dbg:stop_clear(). ok

  7. 编译摘要格式:

    6> {ok, _, B} = compile:forms(M, [no_unused_vars, debug_info]). {ok,lager_default_tracer, <<70,79,82,49,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模块。

  8. 提取存储在编译的二进制的抽象代码块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现持有的抽象代码。

  9. 使用抽象的代码打印重建的源代码, 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文档中的“重建源代码”。

不出所料,重建的源代码显示的其他呼叫goldrush功能,所以你需要访问goldrush来源 ,如果你想试着去了解重构代码。



文章来源: where is code beam file?
标签: erlang lager