Skip to content

v7.3.0

Compare
Choose a tag to compare
@KronicDeth KronicDeth released this 07 Feb 03:46

Thanks

Changelog

v7.3.0

Enhancements

  • #988 - @KronicDeth
    • Update build matrix
      • Update IntelliJ IDEA version 2017.3 to 2017.3.2
      • Update Elixir version 1.5.2 to 1.5.3
  • #1015 - @KronicDeth
    • Add supplemental file editor for .beam files: "BEAM Chunks". The decompiled binary file will continue to be shown on the default "Text" editor tab.
      screen shot 2018-02-01 at 6 38 07 pm
      The BEAM Chunks editor is subdivided into further tabs, one for each chunk in the .beam file.
      screen shot 2018-02-01 at 6 45 23 pm
      The tabs are listed in the order that the chunks occur in the .beam file.
      • The Atom chunk holds LATIN-1 atoms while AtU8 holds UTF8 atoms. There will only be one of these atom-related chunks in any given .beam file. AtU8 is used in newer versions of OTP that support UTF8 atoms.

        The Atom/AtU8 tab shows a table with the columns

        Column Description Source
        Index Which is 1-based to match Erlang convention. In the Code chunk, atom(0) is reserved to always translate to nil Derived
        Byte Count The byte count for the atom's bytes Raw
        Characters From encoding the bytes as LATIN-1 for Atom chunk or UTF-8 for AtU8 chunk Derived

        screen shot 2018-02-01 at 7 01 43 pm

        Index 1 is always the module name for the .beam file. Since .beam is originally an Erlang format, for Elixir modules, you'll see the full atom name of with the Elixir. prefix instead of the Alias name used in Elixir source.

      • The Attr chunk holds the module attributes, but only those that are persisted.

        The Attr tab shows a table with the columns

        Column Description Source
        Key Attribute name Raw
        Value Attribute value. Note: The value always appears as a list as read from the binary format. I don't know why. Raw

        screen shot 2018-02-02 at 2 34 22 pm

        All modules will have a :vsn attribute that is either set explicitly or defaults to the MD5 of the module.

      • The CInf chunk is the Compilation Information for the Erlang or Erlang Core compiler. Even Elixir modules have it because Elixir code passes through this part of the Erlang Core compiler.

        The CInf tab shows a table with the columns

        Column Description Source
        Key Option name Raw
        Value Inspected value Raw

        screen shot 2018-02-02 at 3 19 50 pm

      • The Code chunk contains the byte code for the module. It is encoded in BEAM Compact Term Encoding, which differs from the binary format produced by term_to_binary.

        The Code tab shows a read-only editor with one byte code operation on each line. For ease of reading, operations are grouped by function and then label block with indentation indicating scope.

        screen shot 2018-02-02 at 9 35 59 pm

        By default as many references to other chunks and references to other parts of Code chunk are inlined to ease understanding. If you want to see the raw byte code operations, you can turn off the various inliners.

      • The Dbgi chunk contains Debug Info. It was introduced in OTP 20 as a replacement for the Abst chunk. While the Abst chunk was required to contain the Erlang AST, the Dbgi format can contain the debug info for other languages, such as Elixir quoted form AST.

        Because the format is language neutral, the format is a set of nested, versioned formats. The outer most layer is

        {:debug_info_v1, backend, metadata | :none}

        For :debug_info_v1, Elixir's backend is :elixir_erl. The metadata for :elixir_erl is further versioned: {:elixir_v1, map, specs}.

        map contains the bulk of the data.

        Key Value
        :attributes Attributes similar to the Attr chunk, but at the Elixir, instead of Core Erlang level. Usually they match with the exception that attributes doesn't contain vsn when Attr contains the MD5 version
        :compile_opts Compilation options similar to CInf chunk's options key, but at for Elixir, instead of Core Erlang level.
        :definitions The Elixir quoted AST for reach function clause.
        :file The name of the file the module was generated from.
        :line The line in :file where the module was defined, such as the line defmodule occurred.
        :module The name of the module as an atom
        :unreachable Unreachable functions

        The Dbgi tag show the single value map entries: :file, :line, and :module

        screen shot 2018-02-02 at 5 26 04 pm

        For the multi-value keys: :attributes, :compile_opts, and :definitions, there are individual tabs.

        screen shot 2018-02-02 at 5 27 29 pm

        The Attributes tab has the same format as the Attrs chunk

        screen shot 2018-02-02 at 6 47 49 pm

        The Compile Options tab is usually empty, much like the CInf options key for Erlang.

        screen shot 2018-02-02 at 6 48 34 pm

        The Definitions tab is split between a tree of Module, Function/Arity and clauses.

        screen shot 2018-02-02 at 6 50 14 pm

        Clicking on a clause will show only that clause, but clicking on a higher level in the tree will show all clauses in the function or the entire Module.

        screen shot 2018-02-02 at 6 53 17 pm

        screen shot 2018-02-02 at 8 47 05 pm

        screen shot 2018-02-02 at 8 47 20 pm

        The AST stored in the definitions tab and the process of converting it back to code is not format preserves, so it will not look precisely like the source code as the AST has undergone some macro expansion before its put in the Dbgi chunk. As common idioms are understood, reversals will be add to the renderer.

      • The ExDc chunk stores ExDoc. Not the rendered HTML from the ex_doc package, but the the @doc, @moduledoc, and @typedoc attribute values that work even without ex_doc installed. This chunk is what is consulted when the h helper is used in iex.

        The ExDc binary format is from term_to_binary, so it can be reversed with binary_to_term. The term format is a versioned as {version, versioned_format}. The current version tag is :elixir_docs_v1 and the versioned_format is a Keyword.t with :callback_docs, :docs, :moduledoc, and :type_docs keys.

        Like Dbgi, the ExDc tab is split between a tree to navigate and an editor to show the decompiled value.

        screen shot 2018-02-02 at 8 58 38 pm

        screen shot 2018-02-02 at 9 07 03 pm

        Node Description
        Root All docs
        Module @moduledoc
        Types All @typedocs
        Types child A specific @typedoc
        Callbacks All @callback @docs
        Callbacks child A specific @callback's @doc
        Functions/Macros All @docs for functions/macros
        Functions/Macros child A specific function/macro's @doc
      • The ExpT chunk is the Export Table. The name "Export" derives from the Erlang module attribute -export, which is used to "export" functions from a module. It is the equivalent of making a function or macro public with def and defmacro as opposed to making it private with defp and defmacrop in Elixir.

        The ExpT tab shows a table with the columns

        Column Description Source
        Atom Index Index into the Atom or AtU8 chunk for the function's name Raw
        Name The atom referenced by "Atom Index" Derived
        Arity The arity (argument count) of the function Raw
        Label Label index in the Code chunk where the function is defined. This label is usually immediately after the func_info operation and before the first pattern match or guard operation. Raw

        screen shot 2018-02-01 at 8 21 13 pm

        You'll notice the first entry starts with MACRO-. This is because the BEAM, being made for Erlang has no concept of macros. It only understands functions, so Elixir macros, like __using__/1 called by use are compiled to plain Erlang functions with MACRO- prefixed to their name and an extra argument (the __CALLER__ environment) as the first argument, which increases the arity, yielding a full MFA of MACRO-__using__/2 as seen above.

      • The ImpT chunk is the Import Table. It DOES NOT encode just the Erlang -import attributes or Elixir import macro calls: it tracks any external function or macro called from another module. call_ext_* operations in the Code chunk don't store the Module and Function (MF) of the function they will call directly in the bytecode, instead, one of the arguments is an index into the ImpT chunk. This way, all external calls are normalized into the ImpT chunk instead of being denormalized to the call site. The arity still appears at the call site to help with checking the argument count.

        The ImpT tab shows a table with the columns

        Column Description Source
        Index 0-based index used by references in the Code chunk. Derived
        Module Atom Index Index into the Atom or AtU8 chunk for the Module's name Raw
        Module Atom The atom referenced by "Module Atom Index". Derived
        Function Atom Index Index into the Atom or AtU8 chunk for the functon's name Raw
        Function Atom The atom referened by "Function Atom Index". Derived

        screen shot 2018-02-01 at 8 07 15 pm

        You may notice that erlang.byte_size/1 is included in the table. This is because even bifs are referenced by MFA and not a pre-assigned number as would be the case for system calls in operating systems like Linux. BEAM is like an Operation System, but not in all ways.

      • The LitT chunk contains literals loaded as arguments in Code chunk. Confusingly, in the Code chunk sometimes the literal(N) term is used to encode integer N, an index into another chunk, or an actual index into the LitT. How literal terms are handled is completely dependent on the specific operation, so without having outside knowledge about the bytecode operation arguments for BEAM, the best way to figure out if literal terms are an integer or an index is to toggle the various controls in the Code tab to see if literal with no inlining turns into a LitT literal, FunT function reference, ImpT function reference, or integer.

        The LitT tab shows a table with the columns

        Column Description Source
        # 0-based index used by references in the Code chunk. Derived
        Term The equivalent of `raw > binary_to_term()

        screen shot 2018-02-01 at 9 25 07 pm

      • The LocT chunk is the dual to the ExpT chunk: it contains all private functions and macros.

        The LocT tab shows a table with the columns

        Column Description Source
        Atom Index Index into the Atom or AtU8 chunk for the function's name Raw
        Name The atom referenced by "Atom Index" Derived
        Arity The arity (argument count) of the function Raw
        Label Label index in the Code chunk where the function is defined. This label is usually immediately after the func_info operation and before the first pattern match or guard operation. Raw

        screen shot 2018-02-01 at 9 27 49 pm

        You'll notice the first entry -__struct__/1-fun-0-, starts with - and have a / suffix with fun in it. This naming scheme is used for anonymous functions such as those defined with fn or the capture operator (&) in Elixir. Much like how macros don't really exist and use a MACRO- suffix, anonymous functions/lambdas don't exist, and instead use a distinct naming scheme -<PARENT_FUNCTION>/*fun*. Unlike MACRO-, which is an Elixir invention, anonymous functions/lambdas really being local named functions with derived names is also done in pure Erlang modules. Erlang's anonymous functions are defined with fun, which is where the fun part of the naming scheme comes from.

      • The StrT chunk contains a single contiguous pool of all Erlang strings (that is, Elixir charlists) used in the Code chunk. These strings are used for byte code operations like bs_put_string. Not all strings appear in StrT. Some strings, including most Elixir strings (Erlang binaries) appear in the LitT chunk that holds literals.

        screen shot 2018-02-01 at 7 56 15 pm

        The StrT is contiguous with no separation of strings. Instead of encoding the start and length of each string in the chunk itself, the start and length for any given string is passed as arguments to the byte code operations in the Code chunk. By doing this, shared substrings can be efficiently encoded in StrT.

  • #1021 - @KronicDeth
    • Support for elixir-lang/elixir@23c7542

      Version Struct Started Event Finished Event %ExUnit.Test{} field
      < 1.6.0 %ExUnit.TestCase{} :case_started :case_finished case
      >= 1.6.0 %ExUnit.TestCase{} :module_started :module_finished module

      Because Elixir 1.6.0 could not introduce a breaking change, the < 1.6.0 events are fired, but resources/exunit/1.6.0/team_city_ex_unit_formatting.ex will ignore them and only convert the >= 1.6.0 events to TeamCity event used in the JetBrains Test Runner UI.

  • #1018 - Expose Declarations > Functions and Declarations > Macros in Color Settings - @dimcha

Bug Fixes

  • #1019 - Don't use StreamEx because support is inconsistent across IDEs - @KronicDeth
  • #999 - @ronanboiteau
    • Jetbrains' Gogland is now named GoLand, updated README accordingly
    • In donors list, Garrett Hart had his GitHub URL (@https://github.com/thirdshift) shown instead of his GitHub username (@thirdshift)

README.md Updates

.beam Files

.beam files are the compiled version of modules on the BEAM virtual machine used by Elixir and Erlang. They are the equivalent of .class files in Java.

.beam files are not detected purely by their file extension: the BEAM file format starts with a magic number, FOR1, that is checked for before decompiling.

.beam files have 2 editors registered: decompiled Text and BEAM Chunks

.beam file Editor Tabs

Decompression

If the .beam module was compiled with the compressed compiler directive, which in Erlang looks like

-compile([compressed])

and in Elixir looks like

@compile [:compressed]

then the outer file format is GZip (which is detected by checking for the gzip magic number, 1f 8b, at the start of the file) and the .beam will be (stream) decompressed before the .beam header is checked and the chunks decoded.

BEAM Chunks

.beam files are composed of binary chunks. Each chunk is formatted

Offset +0 +1 +2 +3
0 Name (ASCII Characters)
4 Length (`unsigned-big-integer`)
8+ Chunk-Specific

This format is generically referred to as Type-Length-Value

The BEAM Chunks editor tab is subdivided into further tabs, one for each chunk in the .beam file.

BEAM Chunks editor chunk tabs

The tabs are listed in the order that the chunks occur in the .beam file.

Atom / AtU8

The Atom chunk holds LATIN-1 encoded atoms while AtU8 chunk holds UTF-8 atoms. There will only be one of these atom-related chunks in any given .beam file. AtU8 is used in newer versions of OTP that support UTF-8 atoms. AtU8 was introduced in OTP 20.

Format
Offset +0 +1 +2 +3
0 atom count (`unsigned-big-integer`)
4 length1 (`unsigned-byte`) bytes (for length1)
4+length1+...+lengthn-1 lengthn (`unsigned-byte`) bytes (for lengthn)
Tab

The Atom/AtU8 tab shows a table with the columns

Column Description Source
Index 1-based to match Erlang convention. In the Code chunk, atom(0) is reserved to always translate to nil Derived
Byte Count The byte count for the atom's bytes Raw
Characters From encoding the bytes as LATIN-1 for Atom chunk or UTF-8 for AtU8 chunk Derived

AtU8 Table

Attr

The Attr chunk holds the module attributes, but only those that are persisted. Erlang module attributes are persisted by default, but in Elixir module attributes need to be marked as persisted with Module.register_attribute/3

Format

The Attr chunk uses External Term Format (term_to_binary's output) to encode a proplist, which is similar to, but not quite the same an Elixir Keyword list

All modules will have a :vsn attribute that is either set explicitly or defaults to the MD5 of the module.

Tab

The Attr tab shows a table with the columns

Column Description Source
Key Attribute name Raw
Value Attribute value. Note: The value always appears as a list as read from the binary format. I don't know why. Raw

Attr Table

CInf

The CInf chunk is the Compilation Information for the Erlang or Erlang Core compiler. Even Elixir modules have it because Elixir code passes through this part of the Erlang Core compiler

Format

The CInf chunk uses External Term Format (term_to_binary's output) to encode a proplist, which is similar to, but not quite the same an Elixir Keyword list

Tab

The CInf tab shows a table with the columns

Column Description Source
Key Option name Raw
Value Inspected value Raw

CInf Table

Code

The Code chunk contains the byte code for the module.

Format

It is encoded in BEAM Compact Term Encoding, which differs from the binary format produced by term_to_binary.

Tab

The Code tab shows a read-only editor with one byte code operation on each line. For ease of reading, operations are grouped by function and then label block with indentation indicating scope.

Code Chunk Read-Only Editor

By default as many references to other chunks and references to other parts of Code chunk are inlined to ease understanding. If you want to see the raw byte code operations, you can turn off the various inliners.

####### Controls

Control On Off
Inline Atoms atom(0) is inlined as nil atom(N) if "Inline Integers" is Off
atom(n) looks up index `n` in `Atom`/`AtU8` chunk and inlines its `inspect`ed version N if "Inline Integers" is On and the argument supports "Inline Integers"
Inline Functions literal(n) looks up index n in FunT chunk and inlines the name if the argument supports "Inline Functions" literal(n) if "Inline Integers" is Off
n if "Inline Integers" is On and the argument supports "Inline Integers"
Inline Imports literal(n) looks up index n in ImpT and inlines it as a function reference: &module.name/arity if argument supports "Inline Functions" literal(n) if "Inline Integers" Is Off
n if "Inline Integers" is On and the argument supports "Inline Integers"
Inline Integers atom(n) and literal(n) inline as n if argument supports "Inline Integers" atom(n), integer(n), and literal(n)
integer(n) inlines as n
Inline Labels label(n) inlines as n if argument supports "Inline Labels" label(n)
Inline Lines line(literal(n)) looks up index `n` in the "Line Reference" table in the `Lines` chunk. The Line Reference contains a file name index and line. The file name index is looked up in the "File Name" table in the `Lines` chunk. The line from the Line Reference and the File name from the "File Name" table are inlined as `line(file_name: file_name, line: line)`. line operations are left as is
Inline Literals literal(n) looks up index n in LitT chunk and inlines its `inspect`ed version if the argument supports "Inline Literals" literal(n)
Inline Local Calls label(n) finds label(n) in Code chunk, then searches back for the previous func_info operation, then inlines it as a function reference: &module.name/arity if argument supports "Inline Local Calls" label(n)
Inline Strings Looks up bit_length and byte_offset into `StrT` chunk as their CharList value if supported by operation as value to string argument name bit_length and byte_offsetarguments are left as is
Show Argument Names Adds keyword argument names before each argument value Leaves values as positional arguments

If any of the inliners are incorrect or you have an argument name that makes more sense, please open an issue.

Dbgi

The Dbgi chunk contains Debug Info. It was introduced in OTP 20 as a replacement for the Abst chunk. While the Abst chunk was required to contain the Erlang AST, the Dbgi format can contain the debug info for other languages, such as Elixir quoted form AST.

Format

Because the format is language neutral, the format is a set of nested, versioned formats. The outer most layer is

{:debug_info_v1, backend, metadata | :none}

For :debug_info_v1, Elixir's backend is :elixir_erl. The metadata for :elixir_erl is further versioned: {:elixir_v1, map, specs}.

map contains the bulk of the data.

Key Value
:attributes Attributes similar to the Attr chunk, but at the Elixir, instead of Core Erlang level. Usually they match with the exception that attributes doesn't contain vsn when Attr contains the MD5 version
:compile_opts Compilation options similar to CInf chunk's options key, but at for Elixir, instead of Core Erlang level.
:definitions The Elixir quoted AST for reach function clause.
:file The name of the file the module was generated from.
:line The line in :file where the module was defined, such as the line defmodule occurred.
:module The name of the module as an atom
:unreachable Unreachable functions
Tab

The Dbgi tag show the single value map entries: :file, :line, and :module.

Singletons

For the multi-value keys: :attributes, :compile_opts, and :definitions, there are individual tabs.

Multivalue Tabs

####### Attributes

The Attributes tab has the same format as the Attrs chunk.

Dbgi Attributes Table

####### Compile Options

The Compile Options tab is usually empty, much like the CInf options key for Erlang.

Table

####### Definitions

The Definitions tab is split between a tree of Module, Function/Arity and clauses.

Tree

Clicking on a clause will show only that clause, but clicking on a higher level in the tree will show all clauses in the function or the entire Module.

Clause
Function
Module

The AST stored in the definitions tab and the process of converting it back to code is not format preserves, so it will not look precisely like the source code as the AST has undergone some macro expansion before its put in the Dbgi chunk. As common idioms are understood, reversals will be add to the renderer.

ExDc

The ExDc chunk stores ExDoc. Not the rendered HTML from the ex_doc package, but the the @doc, @moduledoc, and @typedoc attribute values that work even without ex_doc installed. This chunk is what is consulted when the h helper is used in iex.

Format

The ExDc chunk is the encoded with term_to_binary. The term format is a versioned as {version, versioned_format}. The current version tag is :elixir_docs_v1 and the versioned_format is a Keyword.t with keys matching the Code.get_docs/2 tags :callback_docs, :docs, :moduledoc, and :type_docs keys.

Tab

Like Dbgi, the ExDc tab is split between a tree to navigate and an editor to show the decompiled value.

ExDc Tree
Function selected in ExDc tree

Click on a node in the tree will show all docs at that level and any descendants.

Node Description
Root All docs
Module @moduledoc
Types All @typedocs
Types child A specific @typedoc
Callbacks All @callback @docs
Callbacks child A specific @callback's @doc
Functions/Macros All @docs for functions/macros
Functions/Macros child A specific function/macro's @doc
ExpT

The ExpT chunk is the Export Table. The name "Export" derives from the Erlang module attribute -export, which is used to "export" functions from a module. It is the equivalent of making a function or macro public with def and defmacro as opposed to making it private with defp and defmacrop in Elixir.

Format

The BEAM format and the ExpT chunk, being made for Erlang, has no concept of macros. It only understands functions, so Elixir macros, like __using__/1 called by use are compiled to plain Erlang functions with MACRO- prefixed to their name and an extra argument (the __CALLER__ environment) as the first argument, which increases the arity, yielding a full MFA of MACRO-__using__/2 as seen above.

Tab

The ExpT tab shows a table with the columns

Column Description Source
Atom Index Index into the Atom or AtU8 chunk for the function's name Raw
Name The atom referenced by "Atom Index" Derived
Arity The arity (argument count) of the function Raw
Label Label index in the Code chunk where the function is defined. This label is usually immediately after the func_info operation and before the first pattern match or guard operation. Raw

ExpT Table

ImpT

The ImpT chunk is the Import Table. It DOES NOT encode just the Erlang -import attributes or Elixir import macro calls: it tracks any external function or macro called from another module. call_ext_* operations in the Code chunk don't store the Module and Function (MF) of the function they will call directly in the bytecode, instead, one of the arguments is an index into the ImpT chunk. This way, all external calls are normalized into the ImpT chunk instead of being denormalized to the call site. The arity still appears at the call site to help with checking the argument count.

Format

You may notice that erlang.byte_size/1 is included in the table. This is because even BIFs are referenced by MFA and not a pre-assigned number as would be the case for system calls in operating systems like Linux. BEAM is like an Operation System, but not in all ways.

Tab

The ImpT tab shows a table with the columns

Column Description Source
Index 0-based index used by references in the Code chunk. Derived
Module Atom Index Index into the Atom or AtU8 chunk for the Module's name Raw
Module Atom The atom referenced by "Module Atom Index". Derived
Function Atom Index Index into the Atom or AtU8 chunk for the functon's name Raw
Function Atom The atom referened by "Function Atom Index". Derived

ImpT Table

LitT

The LitT chunk contains literals loaded as arguments in Code chunk.

Format

Confusingly, in the Code chunk sometimes the literal(N) term is used to encode integer N, an index into another chunk, or an actual index into the LitT. How literal terms are handled is completely dependent on the specific operation, so without having outside knowledge about the bytecode operation arguments for BEAM, the best way to figure out if literal terms are an integer or an index is to toggle the various controls in the Code tab to see if literal with no inlining turns into a LitT literal, FunT function reference, ImpT function reference, or integer.

Tab

The LitT tab shows a table with the columns

Column Description Source
# 0-based index used by references in the Code chunk. Derived
Term The equivalent of `raw > binary_to_term()

LitT Table

Line

The Line chunk encodes both the file name and line number for each line(literal(n)) operation in the Code chunk. The n in line(literal(n)) is an index in to the Line References table in the Line chunk. This is used in Phoenix view modules to show where code from templates comes from.

Format

The Line chunk is composed of 2 subsections: (1) Line References and (2) File Names. First there is a header setting up the number of each entry to expect.

Offset +0 +1 +2 +3
0 emulator version (`unsigned-big-integer`)
4 flags (`unsigned-big-integer`)
8 Line Instruction Count (`unsigned-big-integer`)
12 Line Reference Count (`unsigned-big-integer`)
16 File Name Count (`unsigned-big-integer`)

####### Line References

This uses the Compact Term Format used for the Code chunk. The format ends up producing {file_name_index, line} pairs using the following algorithm:

Term Interpretation
atom(n) Change file_name_index to n
integer(n) Add {file_name_index, n} to end of Line References

####### File Names

Offset +0 +1 +2 +3
0 Byte Count (`unsigned-big-integer`) Bytes
Tab

The Line tab has one subtab for each subsection in the tab. Each subsection has its own table.

Line References Table
File Names TableTable

LocT

The LocT chunk is the dual to the ExpT chunk: it contains all private functions and macros.

Format

You'll notice entries like -__struct__/1-fun-0-, starts with - and have a / suffix with fun in it. This naming scheme is used for anonymous functions such as those defined with fn or the capture operator (&) in Elixir. Much like how macros don't really exist and use a MACRO- suffix, anonymous functions/lambdas don't exist, and instead use a distinct naming scheme -<PARENT_FUNCTION>/*fun*. Unlike MACRO-, which is an Elixir invention, anonymous functions/lambdas really being local named functions with derived names is also done in pure Erlang modules. Erlang's anonymous functions are defined with fun, which is where the fun part of the naming scheme comes from.

Tab

The LocT tab shows a table with the columns

Column Description Source
Atom Index Index into the Atom or AtU8 chunk for the function's name Raw
Name The atom referenced by "Atom Index" Derived
Arity The arity (argument count) of the function Raw
Label Label index in the Code chunk where the function is defined. This label is usually immediately after the func_info operation and before the first pattern match or guard operation. Raw

LocT Table

StrT

The StrT chunk contains all Erlang strings (that is, Elixir charlists) used in the Code chunk.

Format

The StrT chunk contains a single contiguous pool. These strings are used for byte code operations like bs_put_string. Not all strings appear in StrT. Some strings, including most Elixir strings (Erlang binaries) appear in the LitT chunk that holds literals. I'm not sure how the compiler determines whether to use StrT or LitT. I think it all depends on the byte code operation.

Instead of encoding the start and length of each string in the chunk itself, the start and length for any given string is passed as arguments to the byte code operations in the Code chunk. By doing this, shared substrings can be efficiently encoded in StrT.

Tab

StrT Pool