|
|
- -module(utBeamToSrc).
-
- -export([
- genSrc/2
- , genSrcs/2
- , notCan/2
- , reToDir/2
- , delFile/2
- , isHasUnicode/1
- ]).
-
- %% 通过beam生成erl文件,生成的beam编译选项必要带debug_info才能反编译生成代码
- genSrc(Module, SrcDir) ->
- case beam_lib:chunks(code:which(Module), [abstract_code]) of
- {ok, {_, [{abstract_code, {_, AC}}]}} ->
- Code = erl_prettypr:format(erl_syntax:form_list(AC)),
- %% 如果代码中有unicode码 需要下面的函数转换一下 第二个函数效率更高
- %% SrcStr = io_lib:fwrite("~ts~n", [erl_prettypr:format(erl_syntax:form_list(AC))]),
- SrcBin = unicode:characters_to_binary(Code),
- file:write_file(lists:concat([SrcDir, Module, ".erl"]), SrcBin),
- io:format("build beam:~p to erl:~p success.~n", [Module, Module]);
- {error, beam_lib, Reason} ->
- io:format("code_gen_erl_file error, reason:~p~n", [Reason]);
- _Err ->
- io:format("code_gen_erl_file error, reason:~p~n", [_Err])
- end.
-
- %% 通过beam生成erl文件,生成的beam编译选项必要带debug_info才能反编译生成代码
- genSrcs(BeamDir, SrcDir) ->
- FunDeal =
- fun(File, ProAcc) ->
- ModName = filename:basename(File, ".beam"),
- Module = list_to_atom(ModName),
- case beam_lib:chunks(code:which(Module), [abstract_code]) of
- {ok, {_, [{abstract_code, {_, AC}}]}} ->
- Code = erl_prettypr:format(erl_syntax:form_list(AC)),
- %% 如果代码中有unicode码 需要下面的函数转换一下 第二个函数效率更高
- %% SrcStr = io_lib:fwrite("~ts~n", [erl_prettypr:format(erl_syntax:form_list(AC))]),
- SrcBin = unicode:characters_to_binary(Code),
- file:write_file(lists:concat([SrcDir, Module, ".erl"]), SrcBin),
- io:format("build beam:~p to erl:~p success.~n", [Module, Module]);
- {error, beam_lib, Reason} ->
- io:format("code_gen_erl_file error, reason:~p~n", [Reason]);
- _Err ->
- io:format("code_gen_erl_file error, reason:~p~n", [_Err])
- end,
- ProAcc
- end,
- filelib:fold_files(BeamDir, "\\.beam$", true, FunDeal, []).
-
- %% 将反编译出来的源文件 -file 属性删除掉
- delFile(SrcDir, NewDir) ->
- FunDeal =
- fun(File, ProAcc) ->
- ModName = filename:basename(File, ".erl"),
- Module = list_to_atom(ModName),
- {ok, CodeBin} = file:read_file(File),
- SrcBin = doDelFile(CodeBin, <<>>),
- file:write_file(lists:concat([NewDir, Module, ".erl"]), SrcBin),
- io:format("build beam:~p to erl:~p success.~n", [Module, Module]),
- ProAcc
- end,
- filelib:fold_files(SrcDir, "\\.erl$", true, FunDeal, []).
-
- doDelFile(CodeBin, SrcBin) ->
- case binary:split(CodeBin, <<"-file(">>) of
- [Part1] ->
- <<SrcBin/binary, Part1/binary>>;
- [Part1, Part2] ->
- [_, LeftPart] = binary:split(Part2, <<").">>),
- doDelFile(LeftPart, <<SrcBin/binary, Part1/binary>>)
- end.
-
- %% 检查源码中是否存在unicode字符 主要是为了检查是否存在中文
- isHasUnicode(SrcDir) ->
- FunDeal =
- fun(File, ProAcc) ->
- ModName = filename:basename(File, ".erl"),
- Module = list_to_atom(ModName),
- {ok, CodeBin} = file:read_file(File),
- IsHas = checkUnicode(CodeBin),
-
- case IsHas of
- true ->
- [Module | ProAcc];
- _ ->
- ProAcc
- end
- end,
- AllMods = filelib:fold_files(SrcDir, "\\.erl$", true, FunDeal, []),
- ModStr = <<<<(erlang:atom_to_binary(OneMod))/binary, "\n">> || OneMod <- AllMods>>,
- file:write_file("hasUnicodeMod.txt", ModStr).
-
- checkUnicode(<<>>) ->
- false;
- checkUnicode(<<Word/utf8, Left/binary>>) ->
- case Word > 256 of
- true ->
- true;
- _ ->
- checkUnicode(Left)
- end.
-
- %% 将不能反编译的beam文件复制到指定的目录
- notCan(BeamDir, SrcDir) ->
- FunDeal =
- fun(File, ProAcc) ->
- ModName = filename:basename(File, ".beam"),
- Module = list_to_atom(ModName),
- case beam_lib:chunks(code:which(Module), [abstract_code]) of
- {ok, {_, [{abstract_code, {_, _AC}}]}} ->
- ProAcc;
- {error, beam_lib, Reason} ->
- io:format("code_gen_erl_file error, reason:~p~n", [Reason]),
- file:copy(File, lists:concat([SrcDir, ModName, ".beam"]));
- _Err ->
- io:format("code_gen_erl_file error, reason:~p~n", [_Err]),
- file:copy(File, lists:concat([SrcDir, ModName, ".beam"]))
- end,
- ProAcc
- end,
- filelib:fold_files(BeamDir, "\\.beam$", true, FunDeal, []).
-
- %% 将反编译的文件根据最前面的-file信息 重新复制到正确的目录
- reToDir(SSrcDir, DSrcDir) ->
- FunDeal =
- fun(File, ProAcc) ->
- case file:read_file(File) of
- {ok, <<"-file(", _/binary>> = BinStr} ->
- case binary:split(BinStr, <<"-module">>) of
- [AllFileInfo, _] ->
- FileInfo = binary:replace(AllFileInfo, [<<" ">>, <<"\n">>, <<"\"">>], <<"">>, [global]),
- [_, LeftFileInfo] = binary:split(FileInfo, <<"(">>),
- [DirInfo, _] = binary:split(LeftFileInfo, <<",">>),
- FileDir = filename:join(DSrcDir, DirInfo),
- filelib:ensure_dir(FileDir),
- {ok, _} = file:copy(File, FileDir),
- ok;
- _ ->
- ProAcc
- end;
- _ ->
- ProAcc
- end
- end,
- filelib:fold_files(SSrcDir, "\\.erl$", true, FunDeal, []).
-
- %% 还可以根据反编译的内容恢复头文件 暂时没这个需求
|