bpf: include, bfd, opcodes: add EF_BPF_CPUVER ELF header flags
authorJose E. Marchesi <jose.marchesi@oracle.com>
Sun, 30 Jul 2023 20:39:30 +0000 (22:39 +0200)
committerJose E. Marchesi <jose.marchesi@oracle.com>
Sun, 30 Jul 2023 20:39:30 +0000 (22:39 +0200)
This patch adds support for EF_BPF_CPUVER bits in the ELF
machine-dependent header flags.  These bits encode the BPF CPU
version for which the object file has been compiled for.

The BPF assembler is updated so it annotates the object files it
generates with these bits.

The BPF disassembler is updated so it honors EF_BPF_CPUVER to use the
appropriate ISA version if the user didn't specify an explicit ISA
version in the command line.  Note that a value of zero in
EF_BPF_CPUVER is interpreted by the disassembler as "use the later
supported version" (the BPF CPU versions start with v1.)

The readelf utility is updated to pretty print EF_BPF_CPUVER when it
prints out the ELF header:

   $ readelf -h a.out
   ELF Header:
     ...
     Flags:                             0x4, CPU Version: 4

Tested in bpf-unknown-none.

include/ChangeLog:

2023-07-30  Jose E. Marchesi  <jose.marchesi@oracle.com>

* elf/bpf.h (EF_BPF_CPUVER): Define.
* opcode/bpf.h (BPF_XBPF): Change from 0xf to 0xff so it fits in
EF_BPF_CPUVER.

binutils/ChangeLog:

2023-07-30  Jose E. Marchesi  <jose.marchesi@oracle.com>

* readelf.c (get_machine_flags): Recognize and pretty print BPF
machine flags.

opcodes/ChangeLog:

2023-07-30  Jose E. Marchesi  <jose.marchesi@oracle.com>

* bpf-dis.c: Initialize asm_bpf_version to -1.
(print_insn_bpf): Set BPF ISA version from the cpu version ELF
header flags if no explicit version set in the command line.
* disassemble.c (disassemble_init_for_target): Remove unused code.

gas/ChangeLog:

2023-07-30  Jose E. Marchesi  <jose.marchesi@oracle.com>

* config/tc-bpf.h (elf_tc_final_processing): Define.
* config/tc-bpf.c (bpf_elf_final_processing): New function.

12 files changed:
binutils/ChangeLog
binutils/readelf.c
gas/ChangeLog
gas/config/tc-bpf.c
gas/config/tc-bpf.h
gas/config/tc-sparc.c
include/ChangeLog
include/elf/bpf.h
include/opcode/bpf.h
opcodes/ChangeLog
opcodes/bpf-dis.c
opcodes/disassemble.c

index cfd4d1ad45e742eef6ebf2d94a54da157b12427c..65cff807bec7f9ec4de320b510e6aeedee6033a5 100644 (file)
@@ -1,3 +1,8 @@
+2023-07-30  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+       * readelf.c (get_machine_flags): Recognize and pretty print BPF
+       machine flags.
+
 2023-07-24  Johannes Schauer Marin Rodrigues  <josch@debian.org>
 
        * doc/binutils.texi (objcopy): Document change in behaviour of
index bb488ef2a5e68e5c07b40d8c2bb3486638f5f98c..4ecff4c393387f961ce5a398897982b6c7e90c27 100644 (file)
 #include "elf/xtensa.h"
 #include "elf/z80.h"
 #include "elf/loongarch.h"
+#include "elf/bpf.h"
 
 #include "getopt.h"
 #include "libiberty.h"
@@ -4191,6 +4192,11 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine)
             strcat (buf, ", no delay");
           break;
 
+        case EM_BPF:
+          sprintf (buf + strlen (buf), ", CPU Version: %u",
+                   e_flags & EF_BPF_CPUVER);
+          break;
+
        case EM_SPARCV9:
          if (e_flags & EF_SPARC_32PLUS)
            strcat (buf, ", v8+");
index ab139a9257b470215288d049476a7051e1dadef1..26d7dc1623b33add58d21360ddf438472c653546 100644 (file)
@@ -1,3 +1,8 @@
+2023-07-30  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+       * config/tc-bpf.h (elf_tc_final_processing): Define.
+       * config/tc-bpf.c (bpf_elf_final_processing): New function.
+
 2023-07-30  Jose E. Marchesi  <jose.marchesi@oracle.com>
 
        * config/tc-bpf.c (signed_overflow): Copy function from
index 7e1bd5d40b8d3a4a8ec3ed78d8b2da22a24cf2fd..b4566d89ddf8c5e15bf209bf55e4efedfc953ae7 100644 (file)
@@ -1679,3 +1679,12 @@ bpf_tc_equal_in_insn (int c ATTRIBUTE_UNUSED, char *str ATTRIBUTE_UNUSED)
 
   return 0;
 }
+
+/* Some special processing for a BPF ELF file.  */
+
+void
+bpf_elf_final_processing (void)
+{
+  /* Annotate the BPF ISA version in the ELF flag bits.  */
+  elf_elfheader (stdoutput)->e_flags |= (isa_spec & EF_BPF_CPUVER);
+}
index d57a66fe4604a6bf78358cfe3d614305a67cd5fa..9fb71eddd14816980f6c0e1283fef617169711ac 100644 (file)
@@ -53,3 +53,6 @@
 
 #define TC_EQUAL_IN_INSN(c, s) bpf_tc_equal_in_insn ((c), (s))
 extern bool bpf_tc_equal_in_insn (int, char *);
+
+#define elf_tc_final_processing bpf_elf_final_processing
+extern void bpf_elf_final_processing (void);
index eada5e5a0dad855d38a6c00384c906920fa223f6..c273bd75c08ece1c543a6ec3b66cfc16cbd853da 100644 (file)
@@ -4992,3 +4992,4 @@ sparc_cfi_emit_pcrel_expr (expressionS *exp, unsigned int nbytes)
   emit_expr_with_reloc (exp, nbytes, "disp");
   sparc_no_align_cons = 0;
 }
+
index 11c1c09306b97bb60852b10cac95d6f12beb4f04..4d407403944376adac95360d5e6fd181a2384be6 100644 (file)
@@ -1,3 +1,9 @@
+2023-07-30  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+       * elf/bpf.h (EF_BPF_CPUVER): Define.
+       * opcode/bpf.h (BPF_XBPF): Change from 0xf to 0xff so it fits in
+       EF_BPF_CPUVER.
+
 2023-07-24  Jose E. Marchesi  <jose.marchesi@oracle.com>
 
        * opcode/bpf.h (BPF_IMM32_BSWAP16): Define.
index d0fad08c24ac44453112aece52b9d6ef7f601ce9..e4d416290a7915c1c28b52066f43499a229c84d8 100644 (file)
@@ -37,4 +37,9 @@ START_RELOC_NUMBERS (elf_bpf_reloc_type)
   RELOC_NUMBER (R_BPF_GNU_64_16,                256)
 END_RELOC_NUMBERS (R_BPF_max)
 
+/* Processor specific flags for the ELF header e_flags field.  */
+
+/* Version of the BPF ISA used in the file.  */
+#define EF_BPF_CPUVER 0x0000000f
+
 #endif /* _ELF_BPF_H  */
index 20e323a065b5555c4b9e2b4a651e4e4dbb4a04fd..6decae4a9a3b1b0089c9be38f26d5d96c17ae37b 100644 (file)
@@ -44,7 +44,7 @@ typedef uint64_t bpf_insn_word;
 #define BPF_V2 0x2
 #define BPF_V3 0x3
 #define BPF_V4 0x4
-#define BPF_XBPF 0xff
+#define BPF_XBPF 0xf
 
 /* Masks for the several instruction fields in a BPF instruction.
    These assume big-endian BPF instructions.  */
index f611ec5bb0fa335f50cd6d371c4359b735166cb7..9d33da2162746db4b3e323e95485706751c2a2e1 100644 (file)
@@ -1,3 +1,10 @@
+2023-07-30  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+       * bpf-dis.c: Initialize asm_bpf_version to -1.
+       (print_insn_bpf): Set BPF ISA version from the cpu version ELF
+       header flags if no explicit version set in the command line.
+       * disassemble.c (disassemble_init_for_target): Remove unused code.
+
 2023-07-26  Jose E. Marchesi  <jose.marchesi@oracle.com>
 
        * bpf-opc.c (bpf_opcodes): Fix BPF_INSN_NEGR to not use a src
index 4fe0efc2f96f879945449fa26db20b3f8e59edf1..a8cb9e8e6db2fa33e617a6f59ff2c3a6132b3085 100644 (file)
@@ -24,6 +24,8 @@
 #include "libiberty.h"
 #include "opintl.h"
 #include "opcode/bpf.h"
+#include "elf-bfd.h"
+#include "elf/bpf.h"
 
 #include <string.h>
 #include <inttypes.h>
@@ -42,7 +44,7 @@ enum bpf_dialect
 /* Global configuration for the disassembler.  */
 
 static enum bpf_dialect asm_dialect = BPF_DIALECT_NORMAL;
-static int asm_bpf_version = BPF_V4;
+static int asm_bpf_version = -1;
 static int asm_obase = 10;
 
 /* Print BPF specific command-line options.  */
@@ -141,6 +143,32 @@ print_insn_bpf (bfd_vma pc, disassemble_info *info)
       info->disassembler_options = NULL;
     }
 
+  /* Determine what version of the BPF ISA to use when disassembling.
+     If the user didn't explicitly specify an ISA version, then derive
+     it from the CPU Version flag in the ELF header.  A CPU version of
+     0 in the header means "latest version".  */
+  if (asm_bpf_version == -1)
+    {
+      struct bfd *abfd = info->section->owner;
+      Elf_Internal_Ehdr *header = elf_elfheader (abfd);
+      int cpu_version = header->e_flags & EF_BPF_CPUVER;
+
+      switch (cpu_version)
+        {
+        case 0: asm_bpf_version = BPF_V4; break;
+        case 1: asm_bpf_version = BPF_V1; break;
+        case 2: asm_bpf_version = BPF_V2; break;
+        case 3: asm_bpf_version = BPF_V3; break;
+        case 4: asm_bpf_version = BPF_V4; break;
+        case 0xf: asm_bpf_version = BPF_XBPF; break;
+        default:
+          /* xgettext:c-format */
+          opcodes_error_handler (_("unknown BPF CPU version %u\n"),
+                                 cpu_version);
+          break;
+        }
+    }
+
   /* Print eight bytes per line.  */
   info->bytes_per_chunk = 1;
   info->bytes_per_line = 8;
index a5cb396badb01cfcd796576c4f39c849f1622f43..8aac42ec96cf56f3903c01e613fbf8303cc9985f 100644 (file)
@@ -680,27 +680,7 @@ disassemble_init_for_target (struct disassemble_info * info)
 #endif
 #ifdef ARCH_bpf
     case bfd_arch_bpf:
-      /* XXX option for dialect  */
       info->created_styled_output = true;
-#if 0
-      info->endian_code = BFD_ENDIAN_LITTLE;
-      if (!info->private_data)
-       {
-         info->private_data = cgen_bitset_create (ISA_MAX);
-         if (info->endian == BFD_ENDIAN_BIG)
-           {
-             cgen_bitset_set (info->private_data, ISA_EBPFBE);
-             if (info->mach == bfd_mach_xbpf)
-               cgen_bitset_set (info->private_data, ISA_XBPFBE);
-           }
-         else
-           {
-             cgen_bitset_set (info->private_data, ISA_EBPFLE);
-             if (info->mach == bfd_mach_xbpf)
-               cgen_bitset_set (info->private_data, ISA_XBPFLE);
-           }
-       }
-#endif
       break;
 #endif
 #ifdef ARCH_pru