erlang各种有用的函数包括一些有用nif封装,还有一些性能测试case。
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

147 řádky
5.7 KiB

před 1 rokem
před 1 rokem
  1. -module(utBeamToSrc).
  2. -export([
  3. genSrc/2
  4. , genSrcs/2
  5. , notCan/2
  6. , reToDir/2
  7. , delFile/2
  8. , isHasUnicode/1
  9. ]).
  10. %% 通过beam生成erl文件,生成的beam编译选项必要带debug_info才能反编译生成代码
  11. genSrc(Module, SrcDir) ->
  12. case beam_lib:chunks(code:which(Module), [abstract_code]) of
  13. {ok, {_, [{abstract_code, {_, AC}}]}} ->
  14. Code = erl_prettypr:format(erl_syntax:form_list(AC)),
  15. %% 如果代码中有unicode码 需要下面的函数转换一下 第二个函数效率更高
  16. %% SrcStr = io_lib:fwrite("~ts~n", [erl_prettypr:format(erl_syntax:form_list(AC))]),
  17. SrcBin = unicode:characters_to_binary(Code),
  18. file:write_file(lists:concat([SrcDir, Module, ".erl"]), SrcBin),
  19. io:format("build beam:~p to erl:~p success.~n", [Module, Module]);
  20. {error, beam_lib, Reason} ->
  21. io:format("code_gen_erl_file error, reason:~p~n", [Reason]);
  22. _Err ->
  23. io:format("code_gen_erl_file error, reason:~p~n", [_Err])
  24. end.
  25. %% 通过beam生成erl文件,生成的beam编译选项必要带debug_info才能反编译生成代码
  26. genSrcs(BeamDir, SrcDir) ->
  27. FunDeal =
  28. fun(File, ProAcc) ->
  29. ModName = filename:basename(File, ".beam"),
  30. Module = list_to_atom(ModName),
  31. case beam_lib:chunks(code:which(Module), [abstract_code]) of
  32. {ok, {_, [{abstract_code, {_, AC}}]}} ->
  33. Code = erl_prettypr:format(erl_syntax:form_list(AC)),
  34. %% 如果代码中有unicode码 需要下面的函数转换一下 第二个函数效率更高
  35. %% SrcStr = io_lib:fwrite("~ts~n", [erl_prettypr:format(erl_syntax:form_list(AC))]),
  36. SrcBin = unicode:characters_to_binary(Code),
  37. file:write_file(lists:concat([SrcDir, Module, ".erl"]), SrcBin),
  38. io:format("build beam:~p to erl:~p success.~n", [Module, Module]);
  39. {error, beam_lib, Reason} ->
  40. io:format("code_gen_erl_file error, reason:~p~n", [Reason]);
  41. _Err ->
  42. io:format("code_gen_erl_file error, reason:~p~n", [_Err])
  43. end,
  44. ProAcc
  45. end,
  46. filelib:fold_files(BeamDir, "\\.beam$", true, FunDeal, []).
  47. %% 将反编译出来的源文件 -file 属性删除掉
  48. delFile(SrcDir, NewDir) ->
  49. FunDeal =
  50. fun(File, ProAcc) ->
  51. ModName = filename:basename(File, ".erl"),
  52. Module = list_to_atom(ModName),
  53. {ok, CodeBin} = file:read_file(File),
  54. SrcBin = doDelFile(CodeBin, <<>>),
  55. file:write_file(lists:concat([NewDir, Module, ".erl"]), SrcBin),
  56. io:format("build beam:~p to erl:~p success.~n", [Module, Module]),
  57. ProAcc
  58. end,
  59. filelib:fold_files(SrcDir, "\\.erl$", true, FunDeal, []).
  60. doDelFile(CodeBin, SrcBin) ->
  61. case binary:split(CodeBin, <<"-file(">>) of
  62. [Part1] ->
  63. <<SrcBin/binary, Part1/binary>>;
  64. [Part1, Part2] ->
  65. [_, LeftPart] = binary:split(Part2, <<").">>),
  66. doDelFile(LeftPart, <<SrcBin/binary, Part1/binary>>)
  67. end.
  68. %% 检查源码中是否存在unicode字符 主要是为了检查是否存在中文
  69. isHasUnicode(SrcDir) ->
  70. FunDeal =
  71. fun(File, ProAcc) ->
  72. ModName = filename:basename(File, ".erl"),
  73. Module = list_to_atom(ModName),
  74. {ok, CodeBin} = file:read_file(File),
  75. IsHas = checkUnicode(CodeBin),
  76. case IsHas of
  77. true ->
  78. [Module | ProAcc];
  79. _ ->
  80. ProAcc
  81. end
  82. end,
  83. AllMods = filelib:fold_files(SrcDir, "\\.erl$", true, FunDeal, []),
  84. ModStr = <<<<(erlang:atom_to_binary(OneMod))/binary, "\n">> || OneMod <- AllMods>>,
  85. file:write_file("hasUnicodeMod.txt", ModStr).
  86. checkUnicode(<<>>) ->
  87. false;
  88. checkUnicode(<<Word/utf8, Left/binary>>) ->
  89. case Word > 256 of
  90. true ->
  91. true;
  92. _ ->
  93. checkUnicode(Left)
  94. end.
  95. %% 将不能反编译的beam文件复制到指定的目录
  96. notCan(BeamDir, SrcDir) ->
  97. FunDeal =
  98. fun(File, ProAcc) ->
  99. ModName = filename:basename(File, ".beam"),
  100. Module = list_to_atom(ModName),
  101. case beam_lib:chunks(code:which(Module), [abstract_code]) of
  102. {ok, {_, [{abstract_code, {_, _AC}}]}} ->
  103. ProAcc;
  104. {error, beam_lib, Reason} ->
  105. io:format("code_gen_erl_file error, reason:~p~n", [Reason]),
  106. file:copy(File, lists:concat([SrcDir, ModName, ".beam"]));
  107. _Err ->
  108. io:format("code_gen_erl_file error, reason:~p~n", [_Err]),
  109. file:copy(File, lists:concat([SrcDir, ModName, ".beam"]))
  110. end,
  111. ProAcc
  112. end,
  113. filelib:fold_files(BeamDir, "\\.beam$", true, FunDeal, []).
  114. %% 将反编译的文件根据最前面的-file信息 重新复制到正确的目录
  115. reToDir(SSrcDir, DSrcDir) ->
  116. FunDeal =
  117. fun(File, ProAcc) ->
  118. case file:read_file(File) of
  119. {ok, <<"-file(", _/binary>> = BinStr} ->
  120. case binary:split(BinStr, <<"-module">>) of
  121. [AllFileInfo, _] ->
  122. FileInfo = binary:replace(AllFileInfo, [<<" ">>, <<"\n">>, <<"\"">>], <<"">>, [global]),
  123. [_, LeftFileInfo] = binary:split(FileInfo, <<"(">>),
  124. [DirInfo, _] = binary:split(LeftFileInfo, <<",">>),
  125. FileDir = filename:join(DSrcDir, DirInfo),
  126. filelib:ensure_dir(FileDir),
  127. {ok, _} = file:copy(File, FileDir),
  128. ok;
  129. _ ->
  130. ProAcc
  131. end;
  132. _ ->
  133. ProAcc
  134. end
  135. end,
  136. filelib:fold_files(SSrcDir, "\\.erl$", true, FunDeal, []).
  137. %% 还可以根据反编译的内容恢复头文件 暂时没这个需求