重新编译Erlang的beam_disasm.file的输出
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重新编译Erlang的beam_disasm.file的输出相关的知识,希望对你有一定的参考价值。
我正在尝试修改一个梁文件,使本地函数调用被解释为外部模块调用,即使函数可以在调用它的同一模块中定义。
鉴于m作为模块,我尝试了几种重新编译反汇编光束文件的排列无效。这是一个例子,在elixir中,我的一个尝试:
IO.inspect(:file.write_file(“/ tmp / disasm.asm”,:io_lib.fwrite(“~p。 n”,[:beam_disasm.file(:code.which m)])))
IO.inspect(:compile.noenv_file(“/ tmp / disasm.asm”,[:from_asm]))
我非常感谢有关如何轻松地将:beam_disasm.file
的输出重新编译回.beam
文件的任何输入。
谢谢!
编辑:证明更多信息
假设我有一个如下所示的elixir模块:
defmodule MyApp.IndirectMod do
def value do
1
end
def indirect_value do
value()
end
def indirect_value_2 do
MyApp.IndirectMod.value()
end
end
编译应用程序后,:beam.disasm
提供其梁文件的以下输出:
[ {:attribute, 1, :file, {'lib/temp.ex', 1}}, {:attribute, 1, :module, MyApp.IndirectMod}, {:attribute, 1, :compile, :no_auto_import}, {:attribute, 1, :export, [__info__: 1, indirect_value: 0, indirect_value_2: 0, value: 0]}, {:attribute, 1, :spec, {{:__info__, 1},
[
{:type, 1, :fun,
[
{:type, 1, :product,
[
{:type, 1, :union,
[
{:atom, 1, :attributes},
{:atom, 1, :compile},
{:atom, 1, :functions},
{:atom, 1, :macros},
{:atom, 1, :md5},
{:atom, 1, :module},
{:atom, 1, :deprecated}
]}
]},
{:type, 1, :any, []}
]}
]}}, {:function, 0, :__info__, 1, [
{:clause, 0, [{:atom, 0, :module}], [], [{:atom, 0, MyApp.IndirectMod}]},
{:clause, 0, [{:atom, 0, :functions}], [],
[
{:cons, 0, {:tuple, 0, [{:atom, 0, :indirect_value}, {:integer, 0, 0}]},
{:cons, 0,
{:tuple, 0, [{:atom, 0, :indirect_value_2}, {:integer, 0, 0}]},
{:cons, 0, {:tuple, 0, [{:atom, 0, :value}, {:integer, 0, 0}]},
{nil, 0}}}}
]},
{:clause, 0, [{:atom, 0, :macros}], [], [nil: 0]},
{:clause, 0, [{:atom, 0, :attributes}], [],
[
{:call, 0,
{:remote, 0, {:atom, 0, :erlang}, {:atom, 0, :get_module_info}},
[{:atom, 0, MyApp.IndirectMod}, {:atom, 0, :attributes}]}
]},
{:clause, 0, [{:atom, 0, :compile}], [],
[
{:call, 0,
{:remote, 0, {:atom, 0, :erlang}, {:atom, 0, :get_module_info}},
[{:atom, 0, MyApp.IndirectMod}, {:atom, 0, :compile}]}
]},
{:clause, 0, [{:atom, 0, :md5}], [],
[
{:call, 0,
{:remote, 0, {:atom, 0, :erlang}, {:atom, 0, :get_module_info}},
[{:atom, 0, MyApp.IndirectMod}, {:atom, 0, :md5}]}
]},
{:clause, 0, [{:atom, 0, :deprecated}], [], [nil: 0]} ]}, {:function, 7, :indirect_value, 0, [{:clause, 7, [], [], [{:call, 8, {:atom, 8, :value}, []}]}]}, {:function, 11, :indirect_value_2, 0, [
{:clause, 11, [], [],
[
{:call, 12,
{:remote, 12, {:atom, 0, MyApp.IndirectMod}, {:atom, 12, :value}}, []}
]} ]}, {:function, 3, :value, 0, [{:clause, 3, [], [], [{:integer, 0, 1}]}]} ]
我想提请你注意的特定信息是这样的:
{:function, 7, :indirect_value, 0,
[{:clause, 7, [], [], [{:call, 8, {:atom, 8, :value}, []}]}]},
{:function, 11, :indirect_value_2, 0,
[
{:clause, 11, [], [],
[
{:call, 12,
{:remote, 12, {:atom, 0, MyApp.IndirectMod}, {:atom, 12, :value}}, []}
]}
]},
indirect_value2
是一个“远程”电话,而indirect_value
是一个“本地”电话。我想要实现的是将indirect_value
模仿/看作是像indirect_value_2这样的远程调用。
我正在尝试在编译过程中实现这一目标。我认为唯一的方法是拆卸光束文件,适当改变它并重新组装。我非常愿意接受其他建议。
通过erlc -S xxx.erl
编译将产生xxx.S
,当你修改时可以用erlc xxx.S
编译成BEAM文件。但是您没有指定用例是什么,输入来自何处以及输出位于何处?可以使用解析变换吗?是否可以使用命令行编译器或必须从代码中调用?
是否有必要从代码编译?如果是这样,那么更熟悉compiler
模块的人会建议你的案件正确。
或者对于你的情况,使用解析转换是完全没问题的,你用?MODULE:call()
替换所有本地调用,然后将透明地编译而不会侵入你想要的内容。
好的,这是Elixir编译时处理。我不熟悉它在Elixir中是如何工作的,但它们更依赖于宏,并且在编译之前的预处理被弃用/不可用,如Erlang或难以获得。如果这是Erlang,你可以找到你想要的工具。在Slack上挖掘Elixir聊天。
同样,Erlang编译器能够编译编译过程的中间结果。您正在考虑修改梁组件,在Erlang中您也可以使用to_asm
标志或在带有+S
选项的shell中生成,它可以发送回编译器输入。我只是不确定如何在代码中执行此操作,但在shell中,您只需调用erlc file.asm
或您的文件名。即它可以在理论上工作,所有的作品都在那里。这只是感觉有点不对,因为梁装配是编译的最终结果,高度优化并且许多东西被重写或删除。
请注意,您提供的beam.disasm文件是使用Elixir语法编写的,erlc编译器不会读取它,也许elixir编译器可以。
还要注意你在低级别的编译器领域,如果龙来吃你,只有少数人可以真正帮助你,所以在Slack或邮件列表中找到它们。
我将如何在Erlang中执行此操作:我将通过编写解析转换来修改Erlang AST http://www.erlang-factory.com/upload/presentations/521/yrashk_parse_transformations_sf12.pdf还有更多的文档来自2010-2013 Is there a good, complete tutorial on Erlang parse transforms available?
我无法想象一个可能的用例。你想做什么?
以上是关于重新编译Erlang的beam_disasm.file的输出的主要内容,如果未能解决你的问题,请参考以下文章
如何重新编译 Elixir 项目并从 iex 中重新加载它?