diff --git a/binutils/ChangeLog b/binutils/ChangeLog index cfd4d1ad45e..65cff807bec 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,8 @@ +2023-07-30 Jose E. Marchesi + + * readelf.c (get_machine_flags): Recognize and pretty print BPF + machine flags. + 2023-07-24 Johannes Schauer Marin Rodrigues * doc/binutils.texi (objcopy): Document change in behaviour of diff --git a/binutils/readelf.c b/binutils/readelf.c index bb488ef2a5e..4ecff4c3933 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -168,6 +168,7 @@ #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+"); diff --git a/gas/ChangeLog b/gas/ChangeLog index ab139a9257b..26d7dc1623b 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,8 @@ +2023-07-30 Jose E. Marchesi + + * 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 * config/tc-bpf.c (signed_overflow): Copy function from diff --git a/gas/config/tc-bpf.c b/gas/config/tc-bpf.c index 7e1bd5d40b8..b4566d89ddf 100644 --- a/gas/config/tc-bpf.c +++ b/gas/config/tc-bpf.c @@ -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); +} diff --git a/gas/config/tc-bpf.h b/gas/config/tc-bpf.h index d57a66fe460..9fb71eddd14 100644 --- a/gas/config/tc-bpf.h +++ b/gas/config/tc-bpf.h @@ -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); diff --git a/gas/config/tc-sparc.c b/gas/config/tc-sparc.c index eada5e5a0da..c273bd75c08 100644 --- a/gas/config/tc-sparc.c +++ b/gas/config/tc-sparc.c @@ -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; } + diff --git a/include/ChangeLog b/include/ChangeLog index 11c1c09306b..4d407403944 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,9 @@ +2023-07-30 Jose E. Marchesi + + * 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 * opcode/bpf.h (BPF_IMM32_BSWAP16): Define. diff --git a/include/elf/bpf.h b/include/elf/bpf.h index d0fad08c24a..e4d416290a7 100644 --- a/include/elf/bpf.h +++ b/include/elf/bpf.h @@ -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 */ diff --git a/include/opcode/bpf.h b/include/opcode/bpf.h index 20e323a065b..6decae4a9a3 100644 --- a/include/opcode/bpf.h +++ b/include/opcode/bpf.h @@ -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. */ diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index f611ec5bb0f..9d33da21627 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,10 @@ +2023-07-30 Jose E. Marchesi + + * 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 * bpf-opc.c (bpf_opcodes): Fix BPF_INSN_NEGR to not use a src diff --git a/opcodes/bpf-dis.c b/opcodes/bpf-dis.c index 4fe0efc2f96..a8cb9e8e6db 100644 --- a/opcodes/bpf-dis.c +++ b/opcodes/bpf-dis.c @@ -24,6 +24,8 @@ #include "libiberty.h" #include "opintl.h" #include "opcode/bpf.h" +#include "elf-bfd.h" +#include "elf/bpf.h" #include #include @@ -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; diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c index a5cb396badb..8aac42ec96c 100644 --- a/opcodes/disassemble.c +++ b/opcodes/disassemble.c @@ -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