Skip to content

Instantly share code, notes, and snippets.

@cararemixed
Created January 5, 2021 16:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cararemixed/a3e64090429e93c8951e473a59fbb868 to your computer and use it in GitHub Desktop.
Save cararemixed/a3e64090429e93c8951e473a59fbb868 to your computer and use it in GitHub Desktop.
Some utility code.
defmodule C do
def decompile(module, lang \\ :erlang)
def decompile(module, lang) when is_atom(module) do
decompile(:code.which(module), lang)
end
def decompile('', _) do
# When we get this, it's because a module name was passed
# to code:which/1 which notes the module is loaded but
# can't locate the filename that erl_prim_loader recognizes
# leading to this empty erlang string being returned. Thus
# it's in memory only and we can't directly access the
# module anymore. If you're using iex to define a module,
# use the binary returned from the defmodule call.
:no_file
end
def decompile(path, lang) when is_list(path) do
{:ok, beam} = :file.read_file(path)
decompile(beam, lang)
end
def decompile(beam, :erlang) when is_binary(beam) do
{:ok, {_, chunks}} = :beam_lib.chunks(beam, [:abstract_code])
{_, code} = chunks[:abstract_code]
pretty = :erl_prettypr.format(:erl_syntax.form_list(code))
IO.puts(pretty)
end
def decompile(beam, :elixir) when is_binary(beam) do
{:ok, {_, chunks}} = :beam_lib.chunks(beam, [:debug_info])
{:debug_info_v1, :elixir_erl, {:elixir_v1, ast, _metadata}} = chunks[:debug_info]
# TODO: Consider pretty printing options.
# Overall I prefer the Erlang syntax but the Elixir compiler adds a lot of
# noise sometimes, making things like nest case calls common as well as
# harder to parse out variable labeling (easier for the compiler but
# worse for human consumption). At some point I might put in some effort
# to clean up the Erlang AST output using some variable renaming and
# some basic macros for common things like Access code which always
# looks terrible inline.
IO.inspect(ast, limit: :infinity)
end
def decompile(beam, :asm) when is_binary(beam) do
:beam_disasm.file(beam)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment