Created
January 5, 2021 16:58
-
-
Save cararemixed/a3e64090429e93c8951e473a59fbb868 to your computer and use it in GitHub Desktop.
Some utility code.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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