我怀疑任何人都可以帮助解决这个问题,因为Erlang's compile documentation中有以下内容:
请注意,汇编程序文件的格式没有记录,可能会在不同版本之间发生变化 - 此选项主要用于内部调试。
...但是为了以防万一,这里是故事的堆栈跟踪:
不幸的是,我只是快速浏览了在编译包含以下函数的模块时生成的.S文件,包含和不注释函数中的第一个表达式:
spawn_worker(Which) ->
%syner:sync_pt(),
case Which of
?NAIVE -> spawn(err1, naive_worker_loop, [])
end.
当我这样做时,我认为唯一改变的是元组:
{call_ext,0,{extfunc,syner,sync_pt,0}}
...所以我认为在程序集中注入一个函数调用唯一需要的就是添加那个元组...但是现在我必须实际注入元组...我看到了程序集生成有一些额外的指示:
没有 syner:sync_pt():
{function, spawn_worker, 1, 4}.
{label,3}.
{func_info,{atom,err1},{atom,spawn_worker},1}.
{label,4}.
{test,is_eq_exact,{f,5},[{x,0},{atom,naive}]}.
{move,{atom,naive_worker_loop},{x,1}}.
{move,nil,{x,2}}.
{move,{atom,err1},{x,0}}.
{call_ext_only,3,{extfunc,erlang,spawn,3}}.
{label,5}.
{case_end,{x,0}}.
使用 syner:sync_pt():
{function, spawn_worker, 1, 4}.
{label,3}.
{func_info,{atom,err1},{atom,spawn_worker},1}.
{label,4}.
{allocate,1,1}.
{move,{x,0},{y,0}}.
{call_ext,0,{extfunc,syner,sync_pt,0}}.
{test,is_eq_exact,{f,5},[{y,0},{atom,naive}]}.
{move,{atom,naive_worker_loop},{x,1}}.
{move,nil,{x,2}}.
{move,{atom,err1},{x,0}}.
{call_ext_last,3,{extfunc,erlang,spawn,3},1}.
{label,5}.
{case_end,{y,0}}.
我不能只是总结说添加如下内容:
{allocate,1,1}.
{move,{x,0},{y,0}}.
{call_ext,0,{extfunc,syner,sync_pt,0}}.
对于我想要注入外部函数调用的每个函数,都会有所作为。
所以现在的问题是,是否有任何资源可用于理解和操作Erlang编译生成的程序集:file / 2?
为了以防万一,我问这个问题。我怀疑有这方面的资源,因为文件清楚地说明没有,但我猜没有什么可失去的。即使有,似乎操纵汇编代码会比我想要的更棘手。使用parse_transform / 2肯定更容易,我确实设法得到类似的东西来处理...只是尝试不同的替代方案。
感谢您的时间。
答案 0 :(得分:2)
我不确定你想用这个来实现什么,但核心erlang可能是一个更好的代码操作级别。这是有记录的(无论如何它的一个版本,但这仍然比没有好)这里(并且还有更多只是谷歌的核心erlang):
要在核心erlang之间进行编译,请使用'to_core'和'from_core'(遗憾的是未记录的)选项:
c(my_module, to_core). %%this generates my_module.core
c(my_module, from_core). %%this loads my_module.core
答案 1 :(得分:2)
我所知道的唯一使用beam asm的工具是HiPE,在https://github.com/erlang/otp/tree/master/lib/hipe/icode中有很多代码示例等,但我不建议使用这种格式,因为它一直在变化。
答案 2 :(得分:1)
在我看来,通过操纵抽象代码可以轻松解决您尝试做的事情。只需编写一个parse_transform模块,您可以在其中将函数调用插入到相关函数中。
我根据erlang ?funclog
写了一个decorators
。见https://github.com/nicoster/erl-decorator-pt#funclog