Skip to content

Instantly share code, notes, and snippets.

@kevsmith
Last active November 2, 2021 09:15
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save kevsmith/7e6f6426634e9bb2d87e to your computer and use it in GitHub Desktop.
Save kevsmith/7e6f6426634e9bb2d87e to your computer and use it in GitHub Desktop.
Erlang/Elixir BEAM decompiler
#! /usr/bin/env escript
%% -*- mode: erlang -*-
%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*-
%% ex: ts=4 sw=4 ft=erlang et
%%
%% Copyright 2016 Operable, Inc. All Rights Reserved.
%%
%% This file is provided to you under the Apache License,
%% Version 2.0 (the "License"); you may not use this file
%% except in compliance with the License. You may obtain
%% a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing,
%% software distributed under the License is distributed on an
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
%% KIND, either express or implied. See the License for the
%% specific language governing permissions and limitations
%% under the License.
%%
main([Cmd]) when Cmd == "help";
Cmd == "--help";
Cmd == "-h" ->
io:format("b2f: Beam To Function decompiler~n"),
io:format("Usage: b2f beam_file [function_names]~n"),
io:format("Notes: beam_file must be a valid path to a BEAM file with debug info.~n"),
io:format(" function_names are optional. If given, they must be a space-delimited list of~n"),
io:format(" function names to dump.~n");
main([FileName|Funs]) ->
case file:read_file(FileName) of
{error, Reason} ->
exit(Reason);
{ok, Contents} ->
{ok, Chunk} = beam_lib:chunks(Contents, [abstract_code]),
{Mod, [{abstract_code, {raw_abstract_v1, Code}}]} = Chunk,
dump_function(Mod, Code, Funs)
end.
dump_function(Mod, Code, Funs) ->
MaskF = function_mask(Funs),
FinalFuns = [F || F <- Code,
MaskF(F) == true],
pretty_print(Mod, FinalFuns).
function_mask("") ->
fun({function, _, _, _, _}) ->
true;
(_) ->
false
end;
function_mask(Names0) ->
Names = [list_to_atom(N) || N <- Names0],
fun({function, _, Name, _, _}) ->
lists:member(Name, Names);
(_) ->
false
end.
pretty_print(_Mod, []) ->
ok;
pretty_print(Mod, [{function, _Line, Name, _Arity, Body0}|T]) ->
Body = erl_prettypr:format(erl_syntax:form_list(Body0)),
io:format("~p~s~n", [Name, Body]),
case T of
[] ->
ok;
_ ->
pretty_print(Mod, T)
end.
@2666fff
Copy link

2666fff commented Nov 5, 2020

why bad argument for io:format("ps~n", [Name, Body]),

escript: exception error: bad argument
in function io:format/3
called as io:format(<0.48.0>,"ps~n",
[get_base,
[40,49,48,49,48,49,41,32,45,62,10,32,32,32,32,35,
112,97,114,116,110,101,114,95,98,97,115,101,95,100,
97,116,97,123,98,105,100,32,61,32,49,48,49,48|...]])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment