BeamFile (beam_file v0.4.2)

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.

Same as eleixir_code/1 but raises BeamFile.Error

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()
@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}
              ]}
           ]},
          {: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, :exports_md5}], [],
       [
         {:bin, 0,
          [
            {:bin_element, 0,
             {:string, 0,
              [240, 105, 247, 119, 22, 50, 219, 207, 90, 95, 127, 92, 159, 46, 131, 169]},
             :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, 10}, {:module_info, 0, 12}, {:module_info, 1, 14}]
]
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: false the docs will not 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 eleixir_code/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!(input()) :: 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