<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt"?>
  <!-- generated by https://github.com/dthaler/rst2rfcxml version 0.1 -->

<!DOCTYPE rfc [
]>

<?rfc rfcedstyle="yes"?>
<?rfc toc="yes"?>
<?rfc tocindent="yes"?>
<?rfc sortrefs="yes"?>
<?rfc symrefs="yes"?>
<?rfc strict="yes"?>
<?rfc comments="yes"?>
<?rfc inline="yes"?>
<?rfc text-list-symbols="-o*+"?>
<?rfc docmapping="yes"?>

<rfc ipr="trust200902" docName="draft-thaler-bpf-elf-00" category="std" submissionType="IETF">

 <front>
  <title abbrev="eBPF ISA">
eBPF ELF Profile Specification, v0.1
  </title>
  <author initials="D." surname="Thaler" fullname="Dave Thaler" role="editor">
    <organization>Microsoft</organization>
   <address>
    <postal>
    <city>Redmond</city>
    <code>98052</code>
    <country>USA</country>
    <region>WA</region>
    </postal>
    <email>dthaler@microsoft.com</email>
   </address>
  </author>
  <abstract>
   <t>
    The Executable and Linking Format (ELF) is specified in Chapter 4 of the
    System V Application Binary Interface.
    This document specifies version 0.1 of the eBPF profile for ELF files.
   </t>
  </abstract>
 </front>
 <middle>
  <section anchor="documentation-conventions" title="Documentation conventions">
   <t>
    This specification is a extension to the ELF file format as specified in Chapter 4 of the
    <xref target="ELF">System V Application Binary Interface</xref>.
    As such, the same data representation convention is used as specified in the Data Representation
    section of the ELF specification, where structures are represented in a C-style format with types
    such as <tt>Elf64_Word</tt> for an unsigned 64-bit integer.
   </t>
   <t>
    NOTE: Some content in this draft will eventually move to a separate BTF draft.
   </t>
  </section>
  <section anchor="elf-header" title="ELF Header">
   <t>
    The ELF header must have values set as follows:
   </t>
   <ul>
    <li>
     <tt>e_ident[EI_CLASS]</tt> must be set to <tt>ELFCLASS64</tt> (2).
    </li>
   </ul>
   <ul>
    <li>
     <tt>e_type</tt> must be set to <tt>ET_REL</tt> (1).
    </li>
   </ul>
   <ul>
    <li>
     <tt>e_machine</tt> must be set to <tt>EM_BPF</tt> (247).
    </li>
   </ul>
  </section>
  <section anchor="text-sections" title="TEXT Sections">
   <t>
    <xref target="BPF-ISA">eBPF programs</xref> are stored in TEXT sections.
    A TEXT section can contain multiple eBPF programs, each with a different program name
    which is stored as a function in a TEXT section.  The ".text" section can be empty if
    eBPF programs are stored in other TEXT sections.
   </t>
   <t>
    This specification does not mandate any particular convention for TEXT section names,
    as there are multiple different conventions in use today, including:
   </t>
   <ul>
    <li>
     Prefix Convention: The section name is prefixed with a string that
     identifies the program type, so that the program type of any programs in the section
     can be determined by finding the longest substring match across all program type prefixes.
    </li>
   </ul>
   <ul>
    <li>
     Exact Match Convention: The section name is a string that identifies the program type
     of any programs in the section.
    </li>
   </ul>
   <ul>
    <li>
     Arbitrary Convention: The section name can be anything and the program type of any
     programs in the section must be determined without consulting the section name.
    </li>
   </ul>
  </section>
  <section anchor="data-sections" title="DATA Sections">
   <section anchor="classic-map-definitions" title="Classic Map Definitions">
    <t>
     Classic eBPF map definitions are stored in DATA sections named "maps" or matching
     "maps/&lt;map-name&gt;".  Each such section can contain 0 or more map definitions.
     The number of map definitions in a section can be determined by counting the
     number of symbols in the ".symtab" section that point into that maps section.
    </t>
    <t>
     The size of a map definition can be calculated as:
    </t>
    <t>
     <tt>(size of maps section) / (count of map definitions in that section)</tt>
    </t>
    <t>
     The format of a map definition is as follows, where fields are in the byte
     order indicated in <tt>e_ident[EI_DATA]</tt> in the ELF header:
    </t>
    <sourcecode>
    typedef struct {
       Elf64_Word    type;
       Elf64_Word    key_size;
       Elf64_Word    value_size;
       Elf64_Word    max_entries;
       Elf64_Word    inner_map_idx;
       unsigned char platform_specific_data[];
    } Elf64_BpfMapDefinition;
    </sourcecode>
    <dl>
     <dt>
      <strong>type</strong>
     </dt>
     <dd>
      An integer identifying the map type.  Its value and meaning are platform-specific.
     </dd>
     <dt>
      <strong>key_size</strong>
     </dt>
     <dd>
      Size in bytes of keys in the map, if any.
     </dd>
     <dt>
      <strong>value_size</strong>
     </dt>
     <dd>
      Size in bytes of values in the map, if any.
     </dd>
     <dt>
      <strong>max_entries</strong>
     </dt>
     <dd>
      Maximum number of entries in the map, if the map type has a maximum.
     </dd>
     <dt>
      <strong>inner_map_idx</strong>
     </dt>
     <dd>
      If the map type is one whose values contain ids of other maps, then the inner
      map index must be set to the 0-based index of another map definition in the section.
      The referenced map definition is used to enforce that any maps must match it
      for their ids to be allowed as values of this map.  If the map type is not
      one whose values contain ids of other maps, this must be set to 0.
     </dd>
     <dt>
      <strong>platform_specific_data</strong>
     </dt>
     <dd>
      This field and its size is up to the runtime platform to define.  For example,
      on Linux 4.14 and later, this can hold a NUMA node value.
     </dd>
    </dl>
   </section>
   <section anchor="btf-map-definitions" title="BTF Map Definitions">
    <t>
     BTF eBPF map definitions are stored in a DATA section named ".maps".
     The number of map definitions in a section can be determined by counting the
     number of symbols in the ".symtab" section that point into the ".maps" section.
    </t>
    <t>
     TODO: add format description here
    </t>
   </section>
  </section>
  <section anchor="other-sections" title="Other Sections">
   <table><thead><tr>
     <th>section name</th>
     <th>reference</th>
    </tr></thead>
    <tbody>
     <tr>
      <td>
       <t>
        license
       </t>
      </td>
      <td>
       <t>
        <xref target="program-license">Program License</xref>
       </t>
      </td>
     </tr>
     <tr>
      <td>
       <t>
        version
       </t>
      </td>
      <td>
       <t>
        <xref target="runtime-version-restriction">Runtime Version restriction</xref>
       </t>
      </td>
     </tr>
     <tr>
      <td>
       <t>
        .BTF
       </t>
      </td>
      <td>
       <t>
        <xref target="type-and-string-data">Type and String Data</xref>
       </t>
      </td>
     </tr>
     <tr>
      <td>
       <t>
        .BTF.ext
       </t>
      </td>
      <td>
       <t>
        <xref target="function-and-line-information">Function and Line Information</xref>
       </t>
      </td>
     </tr>
     <tr>
      <td>
       <t>
        .BTF_ids
       </t>
      </td>
      <td>
       <t>
        <xref target="btf-id-values">BTF ID Values</xref>
       </t>
      </td>
     </tr>
    </tbody>
   </table>
   <section anchor="program-license" title="Program License">
    <t>
     A runtime can optionally restrict what program types and/or helper functions
     can be used based on what license the eBPF program is under.  This information
     can be placed into the ELF file in a section named "license" whose contents
     is a null-terminated SPDX license expression as specified in Annex D of
     <xref target="SPDX">ISO/IEC 5962:2021, "Information technology -- SPDX® Specification V22.1</xref>.
    </t>
   </section>
   <section anchor="runtime-version-restriction" title="Runtime Version restriction">
    <t>
     A runtime can optionally restrict whether an eBPF program can load based
     on what runtime version it was designed to interact with.  This information
     can be placed into the ELF file in a section named "version" containing
     a 4-byte version identifier whose use is runtime-specific.
    </t>
   </section>
   <section anchor="type-and-string-data" title="Type and String Data">
    <t>
     The optional ".BTF" section contains type and string data.
     The format of this section is the same as specified in
     <xref target="BTF">BTF Type and String Encoding</xref>.
    </t>
   </section>
   <section anchor="function-and-line-information" title="Function and Line Information">
    <t>
     The optional ".BTF.ext" section contains source line information for the first eBPF instruction
     for each source line.
    </t>
    <t>
     The section starts with the following header:
    </t>
    <sourcecode>
    typedef struct {
       Elf64_Half    magic;
       unsigned char version;
       unsigned char flags;
       Elf64_Word    hdr_len;
       Elf64_Word    func_info_off;
       Elf64_Word    func_info_len;
       Elf64_Word    line_info_off;
       Elf64_Word    line_info_len;
       unsigned char platform_specific_data[];
    } Elf64_BtfExtHeader;
    </sourcecode>
    <dl>
     <dt>
      <strong>magic</strong>
     </dt>
     <dd>
      Must be set to 0xeB9F, which can be used by a parser to determine whether multi-byte fields
      are in little-endian or big-endian byte order.
     </dd>
     <dt>
      <strong>version</strong>
     </dt>
     <dd>
      Must be set to 1 (0x01).
     </dd>
     <dt>
      <strong>flags</strong>
     </dt>
     <dd>
      Must be set to 0.
     </dd>
     <dt>
      <strong>hdr_len</strong>
     </dt>
     <dd>
      The size in bytes of this structure including the platform_specific_data.
     </dd>
     <dt>
      <strong>func_info_off</strong>
     </dt>
     <dd>
      Offset in bytes past the end of the header, of the start of the <xref target="function-information">Function information</xref>.
     </dd>
     <dt>
      <strong>func_info_len</strong>
     </dt>
     <dd>
      Size in bytes of the <xref target="function-information">Function information</xref>.  Must be set to 8 (0x00000008).
     </dd>
     <dt>
      <strong>line_info_off</strong>
     </dt>
     <dd>
      Offset in bytes past the end of the header, of the start of the <xref target="line-information">Line Information</xref>.
     </dd>
     <dt>
      <strong>line_info_len</strong>
     </dt>
     <dd>
      Size in bytes of the <xref target="line-information">Line Information</xref>.  Must be set to 16 (0x00000010).
     </dd>
     <dt>
      <strong>platform_specific_data</strong>
     </dt>
     <dd>
      This field and its size is up to the runtime platform to define.
     </dd>
    </dl>
    <section anchor="function-information" title="Function information">
     <sourcecode>
    typedef struct {
        Elf64_Word           func_info_rec_size;
        Elf64_BtfExtInfoSec  btf_ext_info_sec[];
    } Elf64_BpfFunctionInfo;
     </sourcecode>
     <dl>
      <dt>
       <strong>func_info_rec_size</strong>
      </dt>
      <dd>
       Size in bytes of each function record contained in an <xref target="info-block">Info block</xref>.
       Must be set to 8 (0x00000008).
      </dd>
      <dt>
       <strong>btf_ext_info_sec</strong>
      </dt>
      <dd>
       A set of <xref target="info-block">Info block</xref> data blobs, as many as will fit in the size given
       as the <tt>func_info_len</tt>, where each record within an info block is
       formatted as shown under <xref target="function-record">Function Record</xref> below.
      </dd>
     </dl>
    </section>
    <section anchor="info-block" title="Info block">
     <sourcecode>
    typedef struct {
       Elf64_Word    sec_name_off;
       Elf64_Word    num_info;
       unsigned char data[];
    } Elf64_BtfExtInfoSec;
     </sourcecode>
     <dl>
      <dt>
       <strong>sec_name_off</strong>
      </dt>
      <dd>
       Offset in bytes of the section name within the <xref target="type-and-string-data">Type and String Data</xref>.
      </dd>
      <dt>
       <strong>num_info</strong>
      </dt>
      <dd>
       Number of records that follow.  Must be greater than 0.
      </dd>
      <dt>
       <strong>data</strong>
      </dt>
      <dd>
       A series of function or line records.  The total length of data is
       <tt>num_info * record_size</tt> bytes, where <tt>record_size</tt> is the size
       of a function record or line record.
      </dd>
     </dl>
    </section>
    <section anchor="function-record" title="Function Record">
     <sourcecode>
    typedef struct {
        Elf64_Word insn_off;
        Elf64_Word type_id;
    } Elf64_BpfFunctionInfo;
     </sourcecode>
     <dl>
      <dt>
       <strong>insn_off</strong>
      </dt>
      <dd>
       Number 8 byte units from the start of the section whose name is
       given by "Section name offset" to the start of the function.
       Must be 0 for the first record, and for subsequent records it must be
       greater than the instruction offset of the previous record.
      </dd>
      <dt>
       <strong>type_id</strong>
      </dt>
      <dd>
       TODO: Add a definition of this field, which is "a BTF_KIND_FUNC type".
      </dd>
     </dl>
    </section>
    <section anchor="line-information" title="Line Information">
     <sourcecode>
    typedef struct {
        Elf64_Word           line_info_rec_size;
        Elf64_BtfExtInfoSec  btf_ext_info_sec[];
    } Elf64_BpfLineInfo;
     </sourcecode>
     <dl>
      <dt>
       <strong>line_info_rec_size</strong>
      </dt>
      <dd>
       Size in bytes of each line record in an <xref target="info-block">Info block</xref>.  Must be set to 16 (0x00000010).
      </dd>
      <dt>
       <strong>btf_ext_info_sec</strong>
      </dt>
      <dd>
       A set of <xref target="info-block">Info block</xref> data blobs, as many as will fit in the size given as the <tt>line_info_len</tt>,
       where each record within an info block is formatted as shown under <xref target="line-record">Line Record</xref> below.
      </dd>
     </dl>
    </section>
    <section anchor="line-record" title="Line Record">
     <sourcecode>
    typedef struct {
        Elf64_Word insn_off;
        Elf64_Word file_name_off;
        Elf64_Word line_off;
        Elf64_Word line_col;
    } ELF32_BpfLineInfo;
     </sourcecode>
     <dl>
      <dt>
       <strong>insn_off</strong>
      </dt>
      <dd>
       0-based instruction index into the eBPF program contained
       in the section whose name is referenced in the <xref target="info-block">Info block</xref>.
      </dd>
      <dt>
       <strong>file_name_off</strong>
      </dt>
      <dd>
       Offset in bytes of the file name within the <xref target="type-and-string-data">Type and String Data</xref>.
      </dd>
      <dt>
       <strong>line_off</strong>
      </dt>
      <dd>
       Offset in bytes of the source line within the <xref target="type-and-string-data">Type and String Data</xref>.
      </dd>
      <dt>
       <strong>line_col</strong>
      </dt>
      <dd>
       The line and column number value, computed as
       <tt>(line number &lt;&lt; 10) | (column number)</tt>.
      </dd>
     </dl>
    </section>
   </section>
   <section anchor="btf-id-values" title="BTF ID Values">
    <t>
     TODO: make this secction adhere to the ELF specification data format
    </t>
    <t>
     The <tt>.BTF_ids</tt> section encodes BTF ID values that are used within the Linux kernel.
    </t>
    <t>
     This section is created during the Linux kernel compilation with the help of
     macros defined in <tt>include/linux/btf_ids.h</tt> header file. Kernel code can
     use them to create lists and sets (sorted lists) of BTF ID values.
    </t>
    <t>
     The <tt>BTF_ID_LIST</tt> and <tt>BTF_ID</tt> macros define unsorted list of BTF ID values,
     with following syntax:
     <artwork>
  BTF_ID_LIST(list)
  BTF_ID(type1, name1)
  BTF_ID(type2, name2)
     </artwork>
    </t>
    <t>
     resulting in the following layout in the <tt>.BTF_ids</tt> section:
    </t>
    <artwork>
  __BTF_ID__type1__name1__1:
  .zero 4
  __BTF_ID__type2__name2__2:
  .zero 4
    </artwork>
    <t>
     The <tt>u32 list[]</tt> variable is defined to access the list.
    </t>
    <t>
     The <tt>BTF_ID_UNUSED</tt> macro defines 4 zero bytes. It's used when we
     want to define an unused entry in BTF_ID_LIST, like:
     <artwork>
      BTF_ID_LIST(bpf_skb_output_btf_ids)
      BTF_ID(struct, sk_buff)
      BTF_ID_UNUSED
      BTF_ID(struct, task_struct)
     </artwork>
    </t>
    <t>
     The <tt>BTF_SET_START/END</tt> macros pair defines a sorted list of BTF ID values
     and their count, with following syntax:
     <artwork>
  BTF_SET_START(set)
  BTF_ID(type1, name1)
  BTF_ID(type2, name2)
  BTF_SET_END(set)
     </artwork>
    </t>
    <t>
     resulting in the following layout in the <tt>.BTF_ids</tt> section:
    </t>
    <artwork>
  __BTF_ID__set__set:
  .zero 4
  __BTF_ID__type1__name1__3:
  .zero 4
  __BTF_ID__type2__name2__4:
  .zero 4
    </artwork>
    <t>
     The <tt>struct btf_id_set set;</tt> variable is defined to access the list.
    </t>
    <t>
     The <tt>typeX</tt> name can be one of following:
    </t>
    <artwork>
   struct, union, typedef, func
    </artwork>
    <t>
     and is used as a filter when resolving the BTF ID value.
    </t>
    <t>
     All the BTF ID lists and sets are compiled in the <tt>.BTF_ids</tt> section and
     resolved during the linking phase of Linux kernel build by <tt>resolve_btfids</tt> tool.
    </t>
   </section>
  </section>
  <section anchor="acknowledgements" title="Acknowledgements">
   <t>
    Portions of this draft were derived from information in btf.rst in the
    Linux kernel repository, to which a number of individuals have contributed
    over time, including Andrii Nakryiko, Dave Tucker, David S. Miller, Gary Lin,
    Ilya Leoshkevich, Indu Bhagat, Jesper Dangaard Brouer, Jiri Olsa, Jonathan Corbet,
    Mauro Carvalho Chehab, Rong Tao, and Yonghong Song.
   </t>
  </section>
 </middle>
 <back>
 <references><name>Normative References</name>
  <reference anchor="BPF-ISA">
   <front>
      <title>eBPF Instruction Set Specification, v1.0</title>
      <author fullname='Dave Thaler' initials='D.' surname='Thaler' role='editor'>
      </author>
      <date day='13' month='March' year='2023'/>
   </front>
   <seriesInfo name='Internet-Draft' value='draft-thaler-bpf-isa-00'/>
  </reference>
  <reference anchor="BTF" target="https://elixir.bootlin.com/linux/latest/source/Documentation/bpf/btf.rst">
   <front>
    <title>BPF Type Format (BTF)</title>
    <author></author>
   </front>
  </reference>
  <reference anchor="ELF" target="http://www.sco.com/developers/gabi/latest/contents.html">
   <front>
    <title>System V Application Binary Interface</title>
    <author></author>
   </front>
  </reference>
  <reference anchor="SPDX" target="https://www.iso.org/standard/81870.html">
   <front>
    <title>Information technology -- SPDX® Specification V.2.1</title>
    <author></author>
   </front>
  </reference>
 </references>
 </back>
</rfc>
