[PATCH 1/2] bfd: add basic support for BTF debug info

Jose E. Marchesi jemarch@gnu.org
Wed Sep 30 18:36:00 GMT 2026


Hi Faust.

The patch LGTM.

Assuming that BTF falls within the BPF realm (which I think it is a fair
assumption, but please wait for a day or so in case some global
maintainer has some objection) this patch is OK.

> This patch adds basic support for the BPF Type Format (BTF) to BFD.
> This includes definitions for data structures and helper functions for
> decoding the format.
>
> The added include/btf.h is copied from gcc and extended with prototypes
> for helper functions implemented in BFD.  The intent is to keep the data
> structure names, definitions, macros, etc in sync with that of gcc's
> btf.h (which in turn is based off of the Linux kernel BTF definitions).
>
> Signed-off-by: David Faust <david.faust@oss.qualcomm.com>
> ---
>  bfd/Makefile.am |  10 +-
>  bfd/Makefile.in |  12 +--
>  bfd/btf.c       | 265 +++++++++++++++++++++++++++++++++++++++++++++
>  include/btf.h   | 282 ++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 558 insertions(+), 11 deletions(-)
>  create mode 100644 bfd/btf.c
>  create mode 100644 include/btf.h
>
> diff --git a/bfd/Makefile.am b/bfd/Makefile.am
> index e4df05441eb..506e84b0470 100644
> --- a/bfd/Makefile.am
> +++ b/bfd/Makefile.am
> @@ -75,7 +75,7 @@ BFD_H = bfd.h
>  # need two copies of the executable, one to download and one for the
>  # debugger).
>  BFD32_LIBS = \
> -	archive.lo archures.lo bfd.lo bfdio.lo cache.lo \
> +	archive.lo archures.lo bfd.lo bfdio.lo btf.lo cache.lo \
>  	coff-bfd.lo compress.lo corefile.lo format.lo \
>  	hash.lo libbfd.lo linker.lo merge.lo opncls.lo reloc.lo \
>  	section.lo simple.lo stab-syms.lo stabs.lo syms.lo targets.lo \
> @@ -84,7 +84,7 @@ BFD32_LIBS = \
>  BFD64_LIBS = archive64.lo
>  
>  BFD32_LIBS_CFILES = \
> -	archive.c archures.c bfd.c bfdio.c cache.c coff-bfd.c \
> +	archive.c archures.c bfd.c bfdio.c btf.c cache.c coff-bfd.c \
>  	compress.c corefile.c format.c hash.c \
>  	libbfd.c linker.c merge.c opncls.c reloc.c \
>  	section.c simple.c stab-syms.c stabs.c syms.c targets.c \
> @@ -700,7 +700,7 @@ CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
>  ## This is a list of all .h files in the source tree minus those that
>  ## are processed to produce other .h files
>  SOURCE_HFILES = \
> -	aout-target.h aoutx.h arc-got.h arc-plt.h \
> +	aout-target.h aoutx.h arc-got.h arc-plt.h btf.h \
>  	coff-arm.h coff-bfd.h coffcode.h coffswap.h \
>  	cpu-aarch64.h cpu-arm.h cpu-h8300.h cpu-m68k.h cpu-riscv.h \
>  	ecoff-bfd.h ecoffswap.h \
> @@ -926,11 +926,11 @@ stmp-bfd-h: bfd-in3.h
>  	touch stmp-bfd-h
>  
>  BFD_H_FILES = bfd-in.h libbfd.c hash.c section.c syms.c \
> -	archive.c archures.c bfd.c bfdio.c \
> +	archive.c archures.c bfd.c bfdio.c btf.c \
>  	cache.c compress.c corefile.c format.c linker.c opncls.c \
>  	reloc.c simple.c stab-syms.c stabs.c targets.c
>  BFD64_H_FILES = archive64.c
> -LIBBFD_H_FILES = libbfd-in.h libbfd.c bfd.c bfdio.c \
> +LIBBFD_H_FILES = libbfd-in.h libbfd.c bfd.c bfdio.c btf.c \
>  	archive.c archures.c cache.c hash.c linker.c opncls.c \
>  	reloc.c section.c stabs.c targets.c
>  LIBCOFF_H_FILES = libcoff-in.h coffcode.h
> diff --git a/bfd/Makefile.in b/bfd/Makefile.in
> index 14512cf61fb..ee97aa48e86 100644
> --- a/bfd/Makefile.in
> +++ b/bfd/Makefile.in
> @@ -180,7 +180,7 @@ am__installdirs = "$(DESTDIR)$(bfdlibdir)" "$(DESTDIR)$(infodir)" \
>  	"$(DESTDIR)$(bfdincludedir)"
>  LTLIBRARIES = $(bfdlib_LTLIBRARIES) $(noinst_LTLIBRARIES)
>  am__DEPENDENCIES_1 =
> -am__objects_1 = archive.lo archures.lo bfd.lo bfdio.lo cache.lo \
> +am__objects_1 = archive.lo archures.lo bfd.lo bfdio.lo btf.lo cache.lo \
>  	coff-bfd.lo compress.lo corefile.lo format.lo hash.lo \
>  	libbfd.lo linker.lo merge.lo opncls.lo reloc.lo section.lo \
>  	simple.lo stab-syms.lo stabs.lo syms.lo targets.lo binary.lo \
> @@ -544,7 +544,7 @@ BFD_H = bfd.h
>  # need two copies of the executable, one to download and one for the
>  # debugger).
>  BFD32_LIBS = \
> -	archive.lo archures.lo bfd.lo bfdio.lo cache.lo \
> +	archive.lo archures.lo bfd.lo bfdio.lo btf.lo cache.lo \
>  	coff-bfd.lo compress.lo corefile.lo format.lo \
>  	hash.lo libbfd.lo linker.lo merge.lo opncls.lo reloc.lo \
>  	section.lo simple.lo stab-syms.lo stabs.lo syms.lo targets.lo \
> @@ -552,7 +552,7 @@ BFD32_LIBS = \
>  
>  BFD64_LIBS = archive64.lo
>  BFD32_LIBS_CFILES = \
> -	archive.c archures.c bfd.c bfdio.c cache.c coff-bfd.c \
> +	archive.c archures.c bfd.c bfdio.c btf.c cache.c coff-bfd.c \
>  	compress.c corefile.c format.c hash.c \
>  	libbfd.c linker.c merge.c opncls.c reloc.c \
>  	section.c simple.c stab-syms.c stabs.c syms.c targets.c \
> @@ -1166,7 +1166,7 @@ BUILD_CFILES = \
>  
>  CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
>  SOURCE_HFILES = \
> -	aout-target.h aoutx.h arc-got.h arc-plt.h \
> +	aout-target.h aoutx.h arc-got.h arc-plt.h btf.h \
>  	coff-arm.h coff-bfd.h coffcode.h coffswap.h \
>  	cpu-aarch64.h cpu-arm.h cpu-h8300.h cpu-m68k.h cpu-riscv.h \
>  	ecoff-bfd.h ecoffswap.h \
> @@ -1219,12 +1219,12 @@ EXTRA_libbfd_la_SOURCES = $(CFILES)
>  libbfd_la_DEPENDENCIES = $(OFILES) ofiles ../libsframe/libsframe.la
>  libbfd_la_LIBADD = `cat ofiles` @SHARED_LIBADD@ $(LIBDL) $(ZLIB) $(ZSTD_LIBS) ../libsframe/libsframe.la
>  BFD_H_FILES = bfd-in.h libbfd.c hash.c section.c syms.c \
> -	archive.c archures.c bfd.c bfdio.c \
> +	archive.c archures.c bfd.c bfdio.c btf.c \
>  	cache.c compress.c corefile.c format.c linker.c opncls.c \
>  	reloc.c simple.c stab-syms.c stabs.c targets.c
>  
>  BFD64_H_FILES = archive64.c
> -LIBBFD_H_FILES = libbfd-in.h libbfd.c bfd.c bfdio.c \
> +LIBBFD_H_FILES = libbfd-in.h libbfd.c bfd.c bfdio.c btf.c \
>  	archive.c archures.c cache.c hash.c linker.c opncls.c \
>  	reloc.c section.c stabs.c targets.c
>  
> diff --git a/bfd/btf.c b/bfd/btf.c
> new file mode 100644
> index 00000000000..638ac84cd92
> --- /dev/null
> +++ b/bfd/btf.c
> @@ -0,0 +1,265 @@
> +/* btf.c -- display BTF contents of a BFD binary file
> +   Copyright (C) 2026 Free Software Foundation, Inc.
> +
> +   This file is part of GNU Binutils.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program; if not, write to the Free Software
> +   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
> +   02110-1301, USA.  */
> +
> +#include "sysdep.h"
> +#include "bfd.h"
> +#include "libbfd.h"
> +#include "btf.h"
> +
> +struct btf_header *
> +btf_read_header (bfd *abfd, bfd_byte *buf)
> +{
> +  struct btf_header *header = bfd_zmalloc (sizeof (struct btf_header));
> +
> +  header->magic = bfd_get_16 (abfd, buf);
> +  buf += 2;
> +  header->version = bfd_get_8 (abfd, buf);
> +  buf += 1;
> +  header->flags = bfd_get_8 (abfd, buf);
> +  buf += 1;
> +  header->hdr_len = bfd_get_32 (abfd, buf);
> +  buf += 4;
> +  header->type_off = bfd_get_32 (abfd, buf);
> +  buf += 4;
> +  header->type_len = bfd_get_32 (abfd, buf);
> +  buf += 4;
> +  header->str_off = bfd_get_32 (abfd, buf);
> +  buf += 4;
> +  header->str_len = bfd_get_32 (abfd, buf);
> +
> +  return header;
> +}
> +
> +struct btf_type *
> +btf_read_type (bfd *abfd, bfd_byte *buf)
> +{
> +  struct btf_type *typ = bfd_zmalloc (sizeof (struct btf_type));
> +
> +  typ->name_off = bfd_get_32 (abfd, buf);
> +  buf += 4;
> +  typ->info = bfd_get_32 (abfd, buf);
> +  buf += 4;
> +  typ->size = bfd_get_32 (abfd, buf);
> +
> +  return typ;
> +}
> +
> +struct btf_member *
> +btf_read_member (bfd *abfd, bfd_byte *buf)
> +{
> +  struct btf_member *member = bfd_zmalloc (sizeof (struct btf_member));
> +
> +  member->name_off = bfd_get_32 (abfd, buf);
> +  buf += 4;
> +  member->type = bfd_get_32 (abfd, buf);
> +  buf += 4;
> +  member->offset = bfd_get_32 (abfd, buf);
> +
> +  return member;
> +}
> +
> +struct btf_decl_tag *
> +btf_read_decl_tag (bfd *abfd, bfd_byte *buf)
> +{
> +  struct btf_decl_tag *decl_tag = bfd_zmalloc (sizeof (struct btf_decl_tag));
> +
> +  decl_tag->component_idx = bfd_get_32 (abfd, buf);
> +  return decl_tag;
> +}
> +
> +struct btf_var_secinfo *
> +btf_read_var_secinfo (bfd *abfd, bfd_byte *buf)
> +{
> +  struct btf_var_secinfo *var_secinfo = bfd_zmalloc (sizeof (struct btf_var_secinfo));
> +
> +  var_secinfo->type = bfd_get_32 (abfd, buf);
> +  buf += 4;
> +  var_secinfo->offset = bfd_get_32 (abfd, buf);
> +  buf += 4;
> +  var_secinfo->size = bfd_get_32 (abfd, buf);
> +
> +  return var_secinfo;
> +}
> +
> +struct btf_var *
> +btf_read_var (bfd *abfd, bfd_byte *buf)
> +{
> +  struct btf_var *var = bfd_zmalloc (sizeof (struct btf_var));
> +
> +  var->linkage = bfd_get_32 (abfd, buf);
> +  return var;
> +}
> +
> +struct btf_param *
> +btf_read_param (bfd *abfd, bfd_byte *buf)
> +{
> +  struct btf_param *param = bfd_zmalloc (sizeof (struct btf_param));
> +
> +  param->name_off = bfd_get_32 (abfd, buf);
> +  buf += 4;
> +  param->type = bfd_get_32 (abfd, buf);
> +
> +  return param;
> +}
> +
> +struct btf_enum64 *
> +btf_read_enum64 (bfd *abfd, bfd_byte *buf)
> +{
> +  struct btf_enum64 *enum64 = bfd_zmalloc (sizeof (struct btf_enum64));
> +
> +  enum64->name_off = bfd_get_32 (abfd, buf);
> +  buf += 4;
> +  enum64->val_lo32 = bfd_get_32 (abfd, buf);
> +  buf += 4;
> +  enum64->val_hi32 = bfd_get_32 (abfd, buf);
> +
> +  return enum64;
> +}
> +
> +struct btf_enum *
> +btf_read_enum (bfd *abfd, bfd_byte *buf)
> +{
> +  struct btf_enum *anenum = bfd_zmalloc (sizeof (struct btf_enum));
> +
> +  anenum->name_off = bfd_get_32 (abfd, buf);
> +  buf += 4;
> +  anenum->val = bfd_get_32 (abfd, buf);
> +
> +  return anenum;
> +}
> +
> +struct btf_array *
> +btf_read_array (bfd *abfd, bfd_byte *buf)
> +{
> +  struct btf_array *array = bfd_zmalloc (sizeof (struct btf_array));
> +
> +  array->type = bfd_get_32 (abfd, buf);
> +  buf += 4;
> +  array->index_type = bfd_get_32 (abfd, buf);
> +  buf += 4;
> +  array->nelems = bfd_get_32 (abfd, buf);
> +
> +  return array;
> +}
> +
> +uint32_t
> +btf_read_integral (bfd *abfd, bfd_byte *buf)
> +{
> +  return bfd_get_32 (abfd, buf);
> +}
> +
> +bfd_vma
> +btf_type_size (struct btf_type *entry)
> +{
> +  bfd_vma size = sizeof (struct btf_type);
> +  uint16_t vlen = BTF_INFO_VLEN (entry->info);
> +
> +  switch (BTF_INFO_KIND (entry->info))
> +    {
> +    case BTF_KIND_INT:
> +      size += 4;
> +      break;
> +    case BTF_KIND_ARRAY:
> +      size += sizeof (struct btf_array);
> +      break;
> +    case BTF_KIND_ENUM:
> +      size += sizeof (struct btf_enum) * vlen;
> +      break;
> +    case BTF_KIND_ENUM64:
> +      size += sizeof (struct btf_enum64) * vlen;
> +      break;
> +    case BTF_KIND_FUNC_PROTO:
> +      size += sizeof (struct btf_param) * vlen;
> +      break;
> +    case BTF_KIND_VAR:
> +      size += sizeof (struct btf_var);
> +      break;
> +    case BTF_KIND_UNION:
> +      /* Fallthrough.  */
> +    case BTF_KIND_STRUCT:
> +      size += sizeof (struct btf_member) * vlen;
> +      break;
> +    case BTF_KIND_DATASEC:
> +      size += sizeof (struct btf_var_secinfo) * vlen;
> +      break;
> +    case BTF_KIND_DECL_TAG:
> +      size += sizeof (struct btf_decl_tag);
> +      break;
> +    default:
> +      /* No entry specific additional data follows this entry.  */
> +      break;
> +    }
> +
> +  return size;
> +}
> +
> +bool
> +btf_map (bfd *abfd, asection *sec, btf_type_map_cb cb)
> +{
> +  bfd_byte *btfdata = NULL;
> +  struct btf_header *header = NULL;
> +  bfd_size_type section_size = bfd_section_size (sec);
> +
> +  if (!bfd_malloc_and_get_section (abfd, sec, &btfdata))
> +    goto error;
> +
> +  header = btf_read_header (abfd, btfdata);
> +  if (header->magic != 0xeb9f)
> +    goto error;
> +
> +  if (header->version != 1)
> +    goto error;
> +
> +  /* Make sure the BTF regions specified by the header (entries and
> +     string table) fall within the section.  A corrupted header may
> +     lead to a buffer overflow below.  */
> +
> +  if (header->hdr_len + header->str_off + header->str_len > section_size
> +      || header->hdr_len + header->type_off + header->type_len > section_size)
> +    goto error;
> +
> +  /* Iterate over all the entries in the section and invoke the user
> +     provided callback.  */
> +  {
> +    bfd_byte *str_base = btfdata + header->hdr_len + header->str_off;
> +    bfd_byte *type_base = btfdata + header->hdr_len + header->type_off;
> +    bfd_byte *type_off = type_base;
> +    uint32_t type_id = 1;
> +
> +    while (type_off < type_base + header->type_len)
> +      {
> +	struct btf_type *t = btf_read_type (abfd, type_off);
> +
> +	(*cb) (abfd, btfdata,
> +	       str_base - btfdata,
> +	       type_off - btfdata,
> +	       type_id++, t);
> +	type_off += btf_type_size (t);
> +	free (t);
> +      }
> +  }
> +
> +  free (btfdata);
> +  return true;
> +
> + error:
> +  free (btfdata);
> +  return false;
> +}
> diff --git a/include/btf.h b/include/btf.h
> new file mode 100644
> index 00000000000..2a81c35ebe5
> --- /dev/null
> +++ b/include/btf.h
> @@ -0,0 +1,282 @@
> +/* btf.h - BTF support header file
> +   Copyright (C) 2026 Free Software Foundation, Inc.
> +
> +   This file is part of GNU Binutils.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program; if not, write to the Free Software
> +   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
> +   MA 02110-1301, USA.  */
> +
> +#ifndef BTF_H
> +#define BTF_H
> +
> +/* BTF magic number to identify header, endianness.  */
> +#define BTF_MAGIC	0xeb9f
> +/* Data format version number.  */
> +#define BTF_VERSION 	1
> +
> +struct btf_header
> +{
> +  uint16_t magic;	/* Magic number (BTF_MAGIC).  */
> +  uint8_t  version;	/* Data format version (BTF_VERSION).  */
> +  uint8_t  flags;	/* Flags. Currently unused.  */
> +  uint32_t hdr_len;	/* Length of this header (sizeof (struct btf_header)).  */
> +
> +  /* Following offsets are relative to the end of this header.  */
> +  uint32_t type_off;	/* Offset of type section, in bytes.  */
> +  uint32_t type_len;	/* Length of type section, in bytes.  */
> +  uint32_t str_off;	/* Offset of string section, in bytes.  */
> +  uint32_t str_len;	/* Length of string section, in bytes.  */
> +};
> +
> +/* Maximum type identifier.  */
> +#define BTF_MAX_TYPE	0x000fffff
> +/* Maximum offset into the string section.  */
> +#define BTF_MAX_NAME_OFFSET	0x00ffffff
> +/* Maximum number of struct, union, enum members or func args.  */
> +#define BTF_MAX_VLEN	0xffff
> +
> +/* Type ID 0 represents the void type.  */
> +#define BTF_VOID_TYPEID 0
> +/* Initial type ID for regular types.  */
> +#define BTF_INIT_TYPEID 1
> +
> +struct btf_type
> +{
> +  uint32_t name_off; 	/* Offset in string section of type name.  */
> +  uint32_t info;	/* Encoded kind, variant length, kind flag:
> +			   - bits  0-15: vlen
> +			   - bits 16-23: unused
> +			   - bits 24-28: kind
> +			   - bits 29-30: unused
> +			   - bit     31: kind_flag
> +			   See accessor macros below.  */
> +
> +  /* SIZE is used by INT, ENUM, STRUCT, UNION, DATASEC kinds.
> +     TYPE is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, FUNC,
> +     FUNC_PROTO and VAR kinds.  */
> +  union
> +  {
> +    uint32_t size;	/* Size of the entire type, in bytes.  */
> +    uint32_t type;	/* A type_id referring to another type.  */
> +  };
> +};
> +
> +/* The following macros access the information encoded in btf_type.info.  */
> +/* Type kind. See below.  */
> +#define BTF_INFO_KIND(info)	(((info) >> 24) & 0x1f)
> +/* Number of entries of variable length data following certain type kinds.
> +   For example, number of structure members, number of function parameters.  */
> +#define BTF_INFO_VLEN(info)	((info) & 0xffff)
> +/* For BTF_KIND_FWD, 1 if forward to union, 0 if forward to struct.
> +   For BTF_KIND_STRUCT and BTF_KIND_UNION, 1 if the struct/union contains
> +   a bitfield.  */
> +#define BTF_INFO_KFLAG(info)	((info) >> 31)
> +
> +/* Encoding for struct btf_type.info.  */
> +#define BTF_TYPE_INFO(kind, kflag, vlen) \
> +  ((((kflag) ? 1 : 0 ) << 31) | ((kind & 0x1f) << 24) | ((vlen) & 0xffff))
> +
> +#define BTF_KIND_UNKN		0	/* Unknown or invalid.  */
> +#define BTF_KIND_INT		1	/* Integer.  */
> +#define BTF_KIND_PTR		2	/* Pointer.  */
> +#define BTF_KIND_ARRAY		3	/* Array.  */
> +#define BTF_KIND_STRUCT		4	/* Struct.  */
> +#define BTF_KIND_UNION		5	/* Union.  */
> +#define BTF_KIND_ENUM		6	/* Enumeration.  */
> +#define BTF_KIND_FWD		7	/* Forward.  */
> +#define BTF_KIND_TYPEDEF	8	/* Typedef.  */
> +#define BTF_KIND_VOLATILE	9	/* Referenced type is volatile.  */
> +#define BTF_KIND_CONST		10	/* Referenced type is const.  */
> +#define BTF_KIND_RESTRICT	11	/* Restrict.  */
> +#define BTF_KIND_FUNC		12	/* Subprogram.  */
> +#define BTF_KIND_FUNC_PROTO	13	/* Function Prototype.  */
> +#define BTF_KIND_VAR		14	/* Variable.  */
> +#define BTF_KIND_DATASEC	15	/* Section such as .bss or .data.  */
> +#define BTF_KIND_FLOAT		16	/* Floating point.  */
> +#define BTF_KIND_DECL_TAG	17	/* Declaration tag.  */
> +#define BTF_KIND_TYPE_TAG	18	/* Type tag.  */
> +#define BTF_KIND_ENUM64 	19	/* Enumeration up to 64 bits.  */
> +#define BTF_KIND_MAX		BTF_KIND_ENUM64
> +#define NR_BTF_KINDS		(BTF_KIND_MAX + 1)
> +
> +/* For some BTF_KINDs, struct btf_type is immediately followed by
> +   additional data describing the type.  */
> +
> +/* BTF_KIND_INT is followed by a 32-bit word, with the following
> +   bit arrangement.  */
> +#define BTF_INT_ENCODING(VAL)	(((VAL) & 0x0f000000) >> 24)
> +#define BTF_INT_OFFSET(VAL)	(((VAL) & 0x00ff0000) >> 16)
> +#define BTF_INT_BITS(VAL)	((VAL)  & 0x000000ff)
> +
> +#define BTF_INT_DATA(encoding, offset, bits) \
> +  ((((encoding) & 0x0f) << 24) | (((offset) & 0xff) << 16) | ((bits) & 0xff))
> +
> +/* BTF_INT_ENCODING holds the following attribute flags.  */
> +#define BTF_INT_SIGNED 	(1 << 0)
> +#define BTF_INT_CHAR 	(1 << 1)
> +#define BTF_INT_BOOL	(1 << 2)
> +
> +/* BTF_KIND_ENUM is followed by VLEN struct btf_enum entries,
> +   which describe the enumerators. */
> +struct btf_enum
> +{
> +  uint32_t name_off;	/* Offset in string section of enumerator name.  */
> +  int32_t  val;		/* Enumerator value.  */
> +};
> +
> +/* BTF_KF_ENUM_ holds the flags for kflags in BTF_KIND_ENUM{,64}.  */
> +#define BTF_KF_ENUM_UNSIGNED	(0)
> +#define BTF_KF_ENUM_SIGNED 	(1 << 0)
> +
> +/* BTF_KIND_ARRAY is followed by a single struct btf_array.  */
> +struct btf_array
> +{
> +  uint32_t type;	/* Type of array elements.  */
> +  uint32_t index_type;	/* Type of array index.  */
> +  uint32_t nelems;	/* Number of elements. 0 for unsized/variable length.  */
> +};
> +
> +/* BTF_KIND_STRUCT and BTF_KIND_UNION are followed by VLEN
> +   struct btf_member.  */
> +struct btf_member
> +{
> +  uint32_t name_off;	/* Offset in string section of member name.  */
> +  uint32_t type;	/* Type of member.  */
> +  uint32_t offset;	/* If the type info kind_flag is set, this contains
> +			   both the member bitfield size and bit offset,
> +			   according to the macros below. If kind_flag is not
> +			   set, offset contains only the bit offset (from the
> +			   beginning of the struct).  */
> +};
> +
> +/* If struct or union type info kind_flag is set, used to access member
> +   bitfield size from btf_member.offset.  */
> +#define BTF_MEMBER_BITFIELD_SIZE(VAL) 	((VAL) >> 24)
> +/* If struct or union type info kind_flag is set, used to access member
> +   bit offset from btf_member.offset.  */
> +#define BTF_MEMBER_BITFIELD_OFFSET(VAL)	((VAL) & 0x00ffffff)
> +
> +/* BTF_KIND_FUNC_PROTO is followed by VLEN struct btf_param entries, which
> +   describe the types of the function parameters.  */
> +struct btf_param
> +{
> +  uint32_t name_off;	/* Offset in string section of parameter name.  */
> +  uint32_t type;	/* Type of parameter.  */
> +};
> +
> +/* BTF_KIND_FUNC records encode linkage information in the VLEN bits
> +   of the type record.  These are the supported values.  */
> +enum btf_func_linkage
> +{
> +  BTF_FUNC_STATIC = 0,
> +  BTF_FUNC_GLOBAL = 1,
> +  BTF_FUNC_EXTERN = 2,
> +};
> +
> +/* BTF_KIND_VAR records encode linkage information in a single
> +   trailing struct btf_var.  These are the supported values.  */
> +enum btf_var_linkage
> +{
> +  BTF_VAR_STATIC = 0,
> +  BTF_VAR_GLOBAL_ALLOCATED = 1,
> +  BTF_VAR_GLOBAL_EXTERN = 2,
> +};
> +
> +/* BTF_KIND_VAR is followed by a single struct btf_var, which describes
> +   information about the variable.  */
> +struct btf_var
> +{
> +  uint32_t linkage;	/* 0=static, 1=global, 2=extern.  */
> +};
> +
> +/* BTF_KIND_DATASEC is followed by VLEN struct btf_var_secinfo entries,
> +   which describe all BTF_KIND_VAR or extern BTF_KIND_FUNC types contained
> +   in the section.  */
> +struct btf_var_secinfo
> +{
> +  uint32_t type;	/* Type of BTF_KIND_VAR or BTF_KIND_FUNC item.  */
> +  uint32_t offset;	/* In-section offset (in bytes) of item.  */
> +  uint32_t size;	/* Size (in bytes) of item.  */
> +};
> +
> +/* BTF_KIND_ENUM64 is followed by VLEN struct btf_enum64 entries,
> +   which describe the 64 bits enumerators.  */
> +struct btf_enum64
> +{
> +  uint32_t name_off;	/* Offset in string section of enumerator name.  */
> +  uint32_t val_lo32;	/* lower 32-bit value for a 64-bit value Enumerator */
> +  uint32_t val_hi32;	/* high 32-bit value for a 64-bit value Enumerator */
> +};
> +
> +/* BTF_KIND_DECL_TAG is followed by a single struct btf_decl_tag, which
> +   describes the item to which the tag applies:
> +   - If component_idx == (uint32_t) -1, then the tag applies to item referred
> +     to by the type_id.
> +   - Otherwise, the tag applies to the struct or union member, or function
> +     argument of the type referred to by type_id with the 0-based index
> +     given by component_idx.  */
> +struct btf_decl_tag
> +{
> +  uint32_t component_idx;
> +};
> +
> +#define BTF_ENUM64_VALUE(ENUM64) \
> +  ((int64_t) ((((uint64_t) (ENUM64)->val_hi32) << 32) | (ENUM64)->val_lo32))
> +
> +/* Type for callback to be passed to btf_map below.
> +
> +   ABFD is the bfd containing the BTF section.
> +   BUF is a pointer to the BTF section content.
> +   STRTAB_OFFSET is the offset of the BTF string table in BUF.
> +   TYPE_OFFSET is the offset of T in BUF.
> +   TYPE_ID is the ID of the type being handled.
> +   T is the type to be handled.  */
> +
> +typedef void (*btf_type_map_cb) (bfd *abfd, bfd_byte *buf,
> +				 bfd_vma strtab_offset, bfd_vma type_offset,
> +				 uint32_t type_id, struct btf_type *entry);
> +
> +/* Iterate over the entries in a BTF section.
> +
> +   ABFD is the bfd containing the BTF section.
> +   SEC is the section containing BTF data.
> +
> +   This function returns `false' if the section doesn't contain valid
> +   BTF data or if there is an out of memory condition.  */
> +
> +bool btf_map (bfd *abfd, asection *sec, btf_type_map_cb cb);
> +
> +/* Get the total size in bytes of a given BTF entry, including its
> +   payload.  */
> +
> +bfd_vma btf_type_size (struct btf_type *entry);
> +
> +/* Decoding functions.  The functions returning pointers to structures
> +   allocate memory, and it is up to the user to free that memory when
> +   no longer used. */
> +
> +struct btf_header *btf_read_header (bfd *abfd, bfd_byte *buf);
> +struct btf_type *btf_read_type (bfd *abfd, bfd_byte *buf);
> +struct btf_member *btf_read_member (bfd *abfd, bfd_byte *buf);
> +struct btf_decl_tag *btf_read_decl_tag (bfd *abfd, bfd_byte *buf);
> +struct btf_var_secinfo *btf_read_var_secinfo (bfd *abfd, bfd_byte *buf);
> +struct btf_var *btf_read_var (bfd *abfd, bfd_byte *buf);
> +struct btf_param *btf_read_param (bfd *abfd, bfd_byte *buf);
> +struct btf_enum64 *btf_read_enum64 (bfd *abfd, bfd_byte *buf);
> +struct btf_enum *btf_read_enum (bfd *abdf, bfd_byte *buf);
> +struct btf_array *btf_read_array (bfd *abfd, bfd_byte *buf);
> +uint32_t btf_read_integral (bfd *abfd, bfd_byte *buf);
> +
> +#endif /* ! BTF_H */


More information about the Binutils mailing list