BeamFile (beam_file v0.5.1)

An interface to the BEAM file format.

This module is mainly a wrapper around Erlangs :beam_lib.

For more information see the Erlang documentation for the module beam_lib

Furthermore, different code representations can be generated from the file.

To use the functions above with a module name the module must be compiled and loaded. The functions can also be used with the binary of a module.

Link to this section Summary

Functions

Returns the :abstract_code chunk.

Returns chunk data for all chunks.

Same as all_chunks/ but raises BeamFile.Error

Returns the byte code for the BEAM file.

Returns infos for the given chunk reference.

Returns the infos from the :debug_info chunk.

Returns the infos from the :docs chunk.

Same as docs/1 but raises BeamFile.Error

Returns elixir code recreated from the debug_info chunk.

Returns the extended Elixir AST.

Returns the Erlang code for the BEAM file.

Returns true if a BEAM file for the given module exists.

Returns a keyword list containing some information about a BEAM file.

Returns the binary for the given BEAM file.

Same as read/1 but raises BeamFile.Error

Returns the absolute filename for the module.

Link to this section Types

@type chunk_id() :: charlist()

Chunk ID.

'Abst'
| 'Attr'
| 'AtU8'
| 'CInf'
| 'Dbgi'
| 'Dcos'
| 'ExCk'
| 'ExpT'
| 'ImpT'
| 'LocT'
Link to this type

chunk_name()

@type chunk_name() ::
  :abstract_code
  | :atoms
  | :attributes
  | :compile_info
  | :debug_info
  | :docs
  | :elixir_checker
  | :exports
  | :imports
  | :indexed_imports
  | :labeled_exports
  | :labeled_locals
  | :locals
@type chunk_ref() :: chunk_name() | chunk_id()
@type info() :: [
  file: Path.t() | binary(),
  module: module(),
  chunks: [{charlist(), non_neg_integer(), non_neg_integer()}]
]
@type input() :: path() | module() | binary() | {:module, atom(), binary(), any()}
@type path() :: charlist()
@type reason() :: any()

Link to this section Functions

Link to this function

abstract_code(input)

@spec abstract_code(input()) :: {:ok, term()} | {:error, any()}

Returns the :abstract_code chunk.

examples

Examples

iex> BeamFile.abstract_code(BeamFile.Example)
{
  :ok,
  [
    {:attribute, 1, :file, {'test/fixtures/example.ex', 1}},
    {:attribute, 1, :module, BeamFile.Example},
    {:attribute, 1, :compile, [:no_auto_import]},
    {:attribute, 1, :export, [__info__: 1, hello: 0]},
    {
      :attribute,
      1,
      :spec,
      {
        {:__info__, 1},
        [
          {
            :type,
            1,
            :fun,
            [
              {
                :type,
                1,
                :product,
                [
                  {
                    :type,
                    1,
                    :union,
                    [
                      {:atom, 1, :attributes},
                      {:atom, 1, :compile},
                      {:atom, 1, :functions},
                      {:atom, 1, :macros},
                      {:atom, 1, :md5},
                      {:atom, 1, :exports_md5},
                      {:atom, 1, :module},
                      {:atom, 1, :deprecated},
                      {:atom, 1, :struct}
                    ]
                  }
                ]
              },
              {:type, 1, :any, []}
            ]
          }
        ]
      }
    },
    {
      :function,
      0,
      :__info__,
      1,
      [
        {:clause, 0, [{:atom, 0, :module}], [], [{:atom, 0, BeamFile.Example}]},
        {
          :clause,
          0,
          [{:atom, 0, :functions}],
          [],
          [{:cons, 0, {:tuple, 0, [{:atom, 0, :hello}, {:integer, 0, 0}]}, {nil, 0}}]
        },
        {:clause, 0, [{:atom, 0, :macros}], [], [nil: 0]},
        {:clause, 0, [{:atom, 0, :struct}], [], [{:atom, 0, nil}]},
        {
          :clause,
          0,
          [{:atom, 0, :exports_md5}],
          [],
          [
            {
              :bin,
              0,
              [
                {
                  :bin_element,
                  0,
                  {:string, 0,
                    [166, 117, 1, 22, 146, 56, 30, 199, 203, 141, 158, 223, 3, 11, 225, 190]},
                  :default,
                  :default
                }
              ]
            }
          ]
        },
        {
          :clause,
          0,
          [{:match, 0, {:var, 0, :Key}, {:atom, 0, :attributes}}],
          [],
          [
            {
              :call,
              0,
              {:remote, 0, {:atom, 0, :erlang}, {:atom, 0, :get_module_info}},
              [{:atom, 0, BeamFile.Example}, {:var, 0, :Key}]
            }
          ]
        },
        {
          :clause,
          0,
          [{:match, 0, {:var, 0, :Key}, {:atom, 0, :compile}}],
          [],
          [
            {
              :call,
              0,
              {:remote, 0, {:atom, 0, :erlang}, {:atom, 0, :get_module_info}},
              [{:atom, 0, BeamFile.Example}, {:var, 0, :Key}]
            }
          ]
        },
        {
          :clause,
          0,
          [{:match, 0, {:var, 0, :Key}, {:atom, 0, :md5}}],
          [],
          [
            {
              :call,
              0,
              {:remote, 0, {:atom, 0, :erlang}, {:atom, 0, :get_module_info}},
              [{:atom, 0, BeamFile.Example}, {:var, 0, :Key}]
            }
          ]
        },
        {:clause, 0, [{:atom, 0, :deprecated}], [], [nil: 0]}
      ]
    },
    {:function, 2, :hello, 0, [{:clause, 2, [], [], [{:atom, 2, :world}]}]}
  ]
}
Link to this function

abstract_code!(input)

@spec abstract_code!(input()) :: term()

Same as abstract_code/1 but raises BeamFile.Error

Link to this function

all_chunks(input, type \\ :names)

@spec all_chunks(input(), type :: :names | :ids) :: {:ok, map()} | {:error, any()}

Returns chunk data for all chunks.

The type argument forces the use of :ids or :names, defaults to :names.

examples

Examples

iex> {:ok, chunks} = BeamFile.all_chunks(BeamFile.Example, :names)
iex> chunks |> Map.keys() |> Enum.sort()
[
  :abstract_code,
  :atoms,
  :attributes,
  :compile_info,
  :debug_info,
  :docs,
  :elixir_checker,
  :exports,
  :imports,
  :indexed_imports,
  :labeled_exports,
  :labeled_locals,
  :locals
]
iex> Map.get(chunks, :docs)
{:docs_v1, 1, :elixir, "text/markdown", :none, %{},
 [{{:function, :hello, 0}, 2, ["hello()"], :none, %{}}]}

iex> {:ok, chunks} = BeamFile.all_chunks(BeamFile.Example, :ids)
iex> chunks |> Map.keys() |> Enum.sort()
['Abst', 'AtU8', 'Attr', 'CInf', 'Dbgi', 'Docs', 'ExCk', 'ExpT', 'ImpT', 'LocT']
iex> chunks |> Map.get('Docs') |> is_binary()
true
Link to this function

all_chunks!(input, type \\ :names)

@spec all_chunks!(input(), type :: :names | :ids) :: map()

Same as all_chunks/ but raises BeamFile.Error

Link to this function

byte_code(input)

@spec byte_code(input()) :: {:ok, term()} | {:error, any()}

Returns the byte code for the BEAM file.

examples

Examples

iex> {:ok, byte_code} = BeamFile.byte_code(BeamFile.Example)
iex> byte_code |> Tuple.to_list() |> Enum.take(3)
[
  :beam_file,
  BeamFile.Example,
  [{:__info__, 1, 2}, {:hello, 0, 11}, {:module_info, 0, 13}, {:module_info, 1, 15}]
]
Link to this function

byte_code!(input)

@spec byte_code!(input()) :: term()

Same as byte_code/1 but raises BeamFile.Error

Link to this function

chunk(input, chunk)

@spec chunk(input(), chunk_ref()) :: {:ok, term()} | {:error, any()}

Returns infos for the given chunk reference.

examples

Examples

iex> BeamFile.chunk(BeamFile.Example, :exports)
{:ok, [__info__: 1, hello: 0, module_info: 0, module_info: 1]}

iex> {:ok, chunk} = BeamFile.chunk(BeamFile.Example, 'Dbgi')
iex> is_binary(chunk)
true
Link to this function

chunk!(input, chunk)

@spec chunk!(input(), chunk_ref()) :: term()

Same as chunk/2 but raises BeamFile.Error

Link to this function

debug_info(input)

@spec debug_info(input()) :: {:ok, term()} | {:error, any()}

Returns the infos from the :debug_info chunk.

Examples:

iex> {:ok, info} = BeamFile.debug_info(BeamFile.Example)
iex> Map.get(info, :definitions)
[{{:hello, 0}, :def, [line: 2], [{[line: 2], [], [], :world}]}]
iex> Map.get(info, :relative_file)
"test/fixtures/example.ex"
Link to this function

debug_info!(input)

@spec debug_info!(input()) :: term()

Same as debug_info/1 but raises BeamFile.Error

@spec docs(input()) :: {:ok, term()} | {:error, any()}

Returns the infos from the :docs chunk.

examples

Examples

iex> BeamFile.docs(BeamFile.Example)
{:ok, {:none, %{}, [{{:function, :hello, 0}, 2, ["hello()"], :none, %{}}]}}
@spec docs!(input()) :: term()

Same as docs/1 but raises BeamFile.Error

Link to this function

elixir_code(input, opts \\ [])

@spec elixir_code(input(), opts :: keyword()) :: {:ok, String.t()} | {:error, any()}

Returns elixir code recreated from the debug_info chunk.

The recreated code comes with resolved macros and references. For now, types and specs will not be recreated.

Options: :docs: With docs: true the docs will be created.

examples

Examples

iex> BeamFile.elixir_code(BeamFile.Example)
{
  :ok,
  """
  defmodule Elixir.BeamFile.Example do
    def hello do
      :world
    end
  end\
  """
}
Link to this function

elixir_code!(input, opts \\ [])

@spec elixir_code!(input(), opts :: keyword()) :: String.t()

Same as elixir_code/1 but raises BeamFile.Error

Link to this function

elixir_quoted(input)

@spec elixir_quoted(input()) :: {:ok, Macro.t()} | {:error, any()}

Returns the extended Elixir AST.

Link to this function

elixir_quoted!(input)

@spec elixir_quoted!(input()) :: Macro.t()

Same as elixir_quoted/1 but raises BeamFile.Error

Link to this function

erl_code(input)

@spec erl_code(input()) :: {:ok, String.t()} | {:error, any()}

Returns the Erlang code for the BEAM file.

examples

Examples

iex> {:ok, code} = BeamFile.erl_code(BeamFile.Example)
iex> code =~ "-module('Elixir.BeamFile.Example')"
true
Link to this function

erl_code!(input)

@spec erl_code!(input()) :: String.t()

Same as erl_code/1 but raises BeamFile.Error

Link to this function

exists?(module)

@spec exists?(module()) :: boolean()

Returns true if a BEAM file for the given module exists.

examples

Examples

iex> BeamFile.exists?(BeamFile.Example)
true
iex> BeamFile.exists?(Physics.TOE)
false
@spec info(input()) :: {:ok, info()} | {:error, reason()}

Returns a keyword list containing some information about a BEAM file.

  • :file: The name of the BEAM file, or the binary from which the information was extracted.
  • :module: The name of the module.
  • :chunks: For each chunk, the identifier and the position and size of the chunk data, in bytes.

examples

Examples

iex> {:ok, info} = BeamFile.info(BeamFile.Example)
iex> info[:module]
BeamFile.Example
iex> info[:chunks]
...> |> Enum.map(fn {id, _pos, _size} -> id end)
...> |> Enum.sort()
[
  'AtU8',
  'Attr',
  'CInf',
  'Code',
  'Dbgi',
  'Docs',
  'ExCk',
  'ExpT',
  'ImpT',
  'Line',
  'LitT',
  'LocT',
  'StrT',
  'Type'
]
@spec read(Path.t() | path() | module()) ::
  {:ok, binary()}
  | {:error, File.posix()}
  | {:error, :non_existing | :preloaded | :cover_compiled}

Returns the binary for the given BEAM file.

@spec read!(Path.t() | path() | module()) :: binary()

Same as read/1 but raises BeamFile.Error

@spec which(module()) ::
  {:ok, Path.t()} | {:error, :non_existing | :preloaded | :cover_compiled}

Returns the absolute filename for the module.

If the module cannot be found, {:error, :non_existing} is returned.

If the module is preloaded, {:error, :preloaded} is returned.

If the module is Cover-compiled, {:error, :cover_compiled} is returned.

examples

Examples

iex> {:ok, path} = BeamFile.which(BeamFile.Example)
iex> path =~ "/_build/test/lib/beam_file/ebin/Elixir.BeamFile.Example.beam"
@spec which!(module()) :: Path.t()

Same as which/1 but raises BeamFile.Error