This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Add support for BPF


I'm using the following to aid in debugging objects similar to what's
produced by the llvm-bpf backend.

(Really, the only change I've made so far is to give the objects a
proper e_machine value.  The stock llvm compiler produces e_machine = 0.
I chose EM_BPF = 0xeb9f, as a sort-of leet-speak spelling of "ebpf".)

The most important part of the patch, for me, is the disassembler,
since there isn't any published tool for that at the moment, much less
one that could take its data out of the object file.  I followed the
dumping code in linux/kernel/bpf/verifier.c in producing C-like output.
(Though the kernel's output for 32-bit ALU ops is ugly so I cleaned
that up, as well as tweaking the signed shift and compare ops.)

What's lacking so far are test cases.  Although there needn't be too
many of those, considering the simplicity of the target.

Signed-off-by: Richard Henderson <rth@redhat.com>
---
 backends/Makefile.am    |  10 +-
 backends/bpf_init.c     |  58 ++++++++++
 backends/bpf_regs.c     |  59 ++++++++++
 backends/bpf_reloc.def  |  31 +++++
 backends/common-reloc.c |   7 +-
 libcpu/Makefile.am      |   5 +-
 libcpu/bpf_disasm.c     | 301 ++++++++++++++++++++++++++++++++++++++++++++++++
 libebl/eblopenbackend.c |   1 +
 libelf/elf.h            |   5 +
 9 files changed, 472 insertions(+), 5 deletions(-)
 create mode 100644 backends/bpf_init.c
 create mode 100644 backends/bpf_regs.c
 create mode 100644 backends/bpf_reloc.def
 create mode 100644 libcpu/bpf_disasm.c

diff --git a/backends/Makefile.am b/backends/Makefile.am
index bf52391..02f1fa6 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -33,12 +33,12 @@ AM_CPPFLAGS += -I$(top_srcdir)/libebl -I$(top_srcdir)/libasm \
 
 
 modules = i386 sh x86_64 ia64 alpha arm aarch64 sparc ppc ppc64 s390 \
-	  tilegx m68k
+	  tilegx m68k bpf
 libebl_pic = libebl_i386_pic.a libebl_sh_pic.a libebl_x86_64_pic.a    \
 	     libebl_ia64_pic.a libebl_alpha_pic.a libebl_arm_pic.a    \
 	     libebl_aarch64_pic.a libebl_sparc_pic.a libebl_ppc_pic.a \
 	     libebl_ppc64_pic.a libebl_s390_pic.a libebl_tilegx_pic.a \
-	     libebl_m68k_pic.a
+	     libebl_m68k_pic.a libebl_bpf_pic.a
 noinst_LIBRARIES = $(libebl_pic)
 noinst_DATA = $(libebl_pic:_pic.a=.so)
 
@@ -118,6 +118,11 @@ m68k_SRCS = m68k_init.c m68k_symbol.c m68k_regs.c \
 libebl_m68k_pic_a_SOURCES = $(m68k_SRCS)
 am_libebl_m68k_pic_a_OBJECTS = $(m68k_SRCS:.c=.os)
 
+bpf_SRCS = bpf_init.c bpf_regs.c
+cpu_bpf = ../libcpu/libcpu_bpf.a
+libebl_bpf_pic_a_SOURCES = $(bpf_SRCS)
+am_libebl_bpf_pic_a_OBJECTS = $(bpf_SRCS:.c=.os)
+
 
 libebl_%.so libebl_%.map: libebl_%_pic.a $(libelf) $(libdw)
 	@rm -f $(@:.so=.map)
@@ -131,6 +136,7 @@ libebl_%.so libebl_%.map: libebl_%_pic.a $(libelf) $(libdw)
 
 libebl_i386.so: $(cpu_i386)
 libebl_x86_64.so: $(cpu_x86_64)
+libebl_bpf.so: $(cpu_bpf)
 
 install: install-am install-ebl-modules
 install-ebl-modules:
diff --git a/backends/bpf_init.c b/backends/bpf_init.c
new file mode 100644
index 0000000..8ea1bc1
--- /dev/null
+++ b/backends/bpf_init.c
@@ -0,0 +1,58 @@
+/* Initialization of BPF specific backend library.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		bpf_
+#define RELOC_PREFIX	R_BPF_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on bpf_reloc.def.  */
+#define NO_RELATIVE_RELOC
+#define NO_COPY_RELOC
+#include "common-reloc.c"
+
+
+const char *
+bpf_init (Elf *elf __attribute__ ((unused)),
+	  GElf_Half machine __attribute__ ((unused)),
+	  Ebl *eh, size_t ehlen)
+{
+  /* Check whether the Elf_BH object has a sufficent size.  */
+  if (ehlen < sizeof (Ebl))
+    return NULL;
+
+  /* We handle it.  */
+  eh->name = "BPF";
+  bpf_init_reloc (eh);
+  HOOK (eh, register_info);
+  HOOK (eh, disasm);
+
+  return MODVERSION;
+}
diff --git a/backends/bpf_regs.c b/backends/bpf_regs.c
new file mode 100644
index 0000000..49313ba
--- /dev/null
+++ b/backends/bpf_regs.c
@@ -0,0 +1,59 @@
+/* Register names and numbers for BPF DWARF.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <linux/bpf.h>
+
+#define BACKEND bpf_
+#include "libebl_CPU.h"
+
+ssize_t
+bpf_register_info (Ebl *ebl __attribute__ ((unused)),
+		   int regno, char *name, size_t namelen,
+		   const char **prefix, const char **setname,
+		   int *bits, int *type)
+{
+  ssize_t len;
+
+  if (name == NULL)
+    return MAX_BPF_REG;
+  if (regno < 0 || regno >= MAX_BPF_REG)
+    return -1;
+
+  *prefix = "";
+  *setname = "integer";
+  *bits = 64;
+  *type = DW_ATE_signed;
+
+  len = snprintf(name, namelen, "r%d", regno);
+  return ((size_t)len < namelen ? len : -1);
+}
diff --git a/backends/bpf_reloc.def b/backends/bpf_reloc.def
new file mode 100644
index 0000000..baceaab
--- /dev/null
+++ b/backends/bpf_reloc.def
@@ -0,0 +1,31 @@
+/* List the relocation types for BPF.  -*- C -*-
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		EXEC|DYN)
+RELOC_TYPE (MAP_FD,		REL)
diff --git a/backends/common-reloc.c b/backends/common-reloc.c
index 3317b6c..096ed1c 100644
--- a/backends/common-reloc.c
+++ b/backends/common-reloc.c
@@ -124,12 +124,13 @@ EBLHOOK(reloc_valid_use) (Elf *elf, int reloc)
   return type > ET_NONE && type < ET_CORE && (uses & (1 << (type - 1)));
 }
 
-
+#ifndef NO_COPY_RELOC
 bool
 EBLHOOK(copy_reloc_p) (int reloc)
 {
   return reloc == R_TYPE (COPY);
 }
+#endif
 
 bool
 EBLHOOK(none_reloc_p) (int reloc)
@@ -151,8 +152,10 @@ EBLHOOK(init_reloc) (Ebl *ebl)
   ebl->reloc_type_name = EBLHOOK(reloc_type_name);
   ebl->reloc_type_check = EBLHOOK(reloc_type_check);
   ebl->reloc_valid_use = EBLHOOK(reloc_valid_use);
-  ebl->copy_reloc_p = EBLHOOK(copy_reloc_p);
   ebl->none_reloc_p = EBLHOOK(none_reloc_p);
+#ifndef NO_COPY_RELOC
+  ebl->copy_reloc_p = EBLHOOK(copy_reloc_p);
+#endif
 #ifndef NO_RELATIVE_RELOC
   ebl->relative_reloc_p = EBLHOOK(relative_reloc_p);
 #endif
diff --git a/libcpu/Makefile.am b/libcpu/Makefile.am
index f0caaea..84050b8 100644
--- a/libcpu/Makefile.am
+++ b/libcpu/Makefile.am
@@ -35,10 +35,13 @@ LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS) -P$(<F:lex.l=)
 LEX_OUTPUT_ROOT = lex.$(<F:lex.l=)
 AM_YFLAGS = -p$(<F:parse.y=)
 
-noinst_LIBRARIES = libcpu_i386.a libcpu_x86_64.a
+noinst_LIBRARIES = libcpu_i386.a libcpu_x86_64.a libcpu_bpf.a
 
 libcpu_i386_a_SOURCES = i386_disasm.c i386_dis.h
 libcpu_x86_64_a_SOURCES = x86_64_disasm.c x86_64_dis.h
+libcpu_bpf_a_SOURCES = bpf_disasm.c
+
+libcpu_bpf_a_CFLAGS = $(AM_CFLAGS) -Wno-format-nonliteral
 
 i386_gendis_SOURCES = i386_gendis.c i386_lex.l i386_parse.y
 
diff --git a/libcpu/bpf_disasm.c b/libcpu/bpf_disasm.c
new file mode 100644
index 0000000..d1b4584
--- /dev/null
+++ b/libcpu/bpf_disasm.c
@@ -0,0 +1,301 @@
+/* Disassembler for BPF.
+   Copyright (C) 2016 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <gelf.h>
+#include <inttypes.h>
+#include <linux/bpf.h>
+
+#include "../libebl/libeblP.h"
+
+static const char class_string[8][8] = {
+  [BPF_LD]    = "ld",
+  [BPF_LDX]   = "ldx",
+  [BPF_ST]    = "st",
+  [BPF_STX]   = "stx",
+  [BPF_ALU]   = "alu",
+  [BPF_JMP]   = "jmp",
+  [BPF_RET]   = "6",
+  [BPF_ALU64] = "alu64",
+};
+
+static const char size_string[][4] = {
+  [BPF_W >> 3]  = "u32",
+  [BPF_H >> 3]  = "u16",
+  [BPF_B >> 3]  = "u8",
+  [BPF_DW >> 3] = "u64",
+};
+
+/* Dest = 1$, Src = 2$, Imm = 3$.  */
+static const char * const fmt_alu[32] = {
+  [(BPF_ADD  | BPF_K) >> 3] = "r%1$d = (u32)r%1$d + %3$u",
+  [(BPF_SUB  | BPF_K) >> 3] = "r%1$d = (u32)r%1$d - %3$u",
+  [(BPF_MUL  | BPF_K) >> 3] = "r%1$d = (u32)r%1$d * %3$u",
+  [(BPF_DIV  | BPF_K) >> 3] = "r%1$d = (u32)r%1$d / %3$u",
+  [(BPF_OR   | BPF_K) >> 3] = "r%1$d = (u32)r%1$d | %3$u",
+  [(BPF_AND  | BPF_K) >> 3] = "r%1$d = (u32)r%1$d & %3$u",
+  [(BPF_LSH  | BPF_K) >> 3] = "r%1$d = (u32)r%1$d << %3$u",
+  [(BPF_RSH  | BPF_K) >> 3] = "r%1$d = (u32)r%1$d >> %3$u",
+  /* (BPF_NEG  | BPF_K) invalid */
+  [(BPF_MOD  | BPF_K) >> 3] = "r%1$d = (u32)r%1$d % %3$u",
+  [(BPF_XOR  | BPF_K) >> 3] = "r%1$d = (u32)r%1$d ^ %3$u",
+  [(BPF_MOV  | BPF_K) >> 3] = "r%1$d = %3$u",
+  [(BPF_ARSH | BPF_K) >> 3] = "r%1$d = (u32)((s32)r%1$d >> %3$u)",
+  [(BPF_END  | BPF_TO_LE) >> 3] = "r%1$d = le32(r%2$d)",
+
+  [(BPF_ADD  | BPF_X) >> 3] = "r%1$d = (u32)r%1$d + (u32)r%2$d",
+  [(BPF_SUB  | BPF_X) >> 3] = "r%1$d = (u32)r%1$d - (u32)r%2$d",
+  [(BPF_MUL  | BPF_X) >> 3] = "r%1$d = (u32)r%1$d * (u32)r%2$d",
+  [(BPF_DIV  | BPF_X) >> 3] = "r%1$d = (u32)r%1$d / (u32)r%2$d",
+  [(BPF_OR   | BPF_X) >> 3] = "r%1$d = (u32)r%1$d | (u32)r%2$d",
+  [(BPF_AND  | BPF_X) >> 3] = "r%1$d = (u32)r%1$d & (u32)r%2$d",
+  [(BPF_LSH  | BPF_X) >> 3] = "r%1$d = (u32)r%1$d << r%2$d",
+  [(BPF_RSH  | BPF_X) >> 3] = "r%1$d = (u32)r%1$d >> r%2$d",
+  [(BPF_NEG  | BPF_X) >> 3] = "r%1$d = (u32)-r%2$d",
+  [(BPF_MOD  | BPF_X) >> 3] = "r%1$d = (u32)r%1$d % (u32)r%2$d",
+  [(BPF_XOR  | BPF_X) >> 3] = "r%1$d = (u32)r%1$d ^ (u32)r%2$d",
+  [(BPF_MOV  | BPF_X) >> 3] = "r%1$d = (u32)r%2$d",
+  [(BPF_ARSH | BPF_X) >> 3] = "r%1$d = (u32)((s32)r%1$d >> r%2$d)",
+  [(BPF_END  | BPF_TO_BE) >> 3] = "r%1$d = be32(r%2$d)",
+};
+
+static const char * const fmt_alu64[32] = {
+  [(BPF_ADD  | BPF_K) >> 3] = "r%1$d = r%1$d + %3$d",
+  [(BPF_SUB  | BPF_K) >> 3] = "r%1$d = r%1$d - %3$d",
+  [(BPF_MUL  | BPF_K) >> 3] = "r%1$d = r%1$d * %3$d",
+  [(BPF_DIV  | BPF_K) >> 3] = "r%1$d = r%1$d / %3$d",
+  [(BPF_OR   | BPF_K) >> 3] = "r%1$d = r%1$d | %3$d",
+  [(BPF_AND  | BPF_K) >> 3] = "r%1$d = r%1$d & %3$d",
+  [(BPF_LSH  | BPF_K) >> 3] = "r%1$d = r%1$d << %3$d",
+  [(BPF_RSH  | BPF_K) >> 3] = "r%1$d = r%1$d >> %3$d",
+  /* (BPF_NEG  | BPF_K) invalid */
+  [(BPF_MOD  | BPF_K) >> 3] = "r%1$d = r%1$d % %3$d",
+  [(BPF_XOR  | BPF_K) >> 3] = "r%1$d = r%1$d ^ %3$d",
+  [(BPF_MOV  | BPF_K) >> 3] = "r%1$d = %3$d",
+  [(BPF_ARSH | BPF_K) >> 3] = "r%1$d = (s64)r%1$d >> %3$d",
+  [(BPF_END  | BPF_TO_LE) >> 3] = "r%1$d = le64(r%2$d)",
+
+  [(BPF_ADD  | BPF_X) >> 3] = "r%1$d = r%1$d + r%2$d",
+  [(BPF_SUB  | BPF_X) >> 3] = "r%1$d = r%1$d - r%2$d",
+  [(BPF_MUL  | BPF_X) >> 3] = "r%1$d = r%1$d * r%2$d",
+  [(BPF_DIV  | BPF_X) >> 3] = "r%1$d = r%1$d / r%2$d",
+  [(BPF_OR   | BPF_X) >> 3] = "r%1$d = r%1$d | r%2$d",
+  [(BPF_AND  | BPF_X) >> 3] = "r%1$d = r%1$d & r%2$d",
+  [(BPF_LSH  | BPF_X) >> 3] = "r%1$d = r%1$d << r%2$d",
+  [(BPF_RSH  | BPF_X) >> 3] = "r%1$d = r%1$d >> r%2$d",
+  [(BPF_NEG  | BPF_X) >> 3] = "r%1$d = -r%2$d",
+  [(BPF_MOD  | BPF_X) >> 3] = "r%1$d = r%1$d % r%2$d",
+  [(BPF_XOR  | BPF_X) >> 3] = "r%1$d = r%1$d ^ r%2$d",
+  [(BPF_MOV  | BPF_X) >> 3] = "r%1$d = r%2$d",
+  [(BPF_ARSH | BPF_X) >> 3] = "r%1$d = (s64)r%1$d >> r%2$d",
+  [(BPF_END  | BPF_TO_BE) >> 3] = "r%1$d = be64(r%2$d)",
+};
+
+/* Dest = 1$, Src = 2$, Imm = 3$, Jmp = 4$.  */
+static const char * const fmt_jmp[32] = {
+  [(BPF_JA   | BPF_K) >> 3] = "goto %4$x",
+  [(BPF_JEQ  | BPF_K) >> 3] = "if r%1$d == %3$d goto %4$x",
+  [(BPF_JGT  | BPF_K) >> 3] = "if r%1$d > %3$d goto %4$x",
+  [(BPF_JGE  | BPF_K) >> 3] = "if r%1$d >= %3$d goto %4$x",
+  [(BPF_JSET | BPF_K) >> 3] = "if r%1$d & %3$d goto %4$x",
+  [(BPF_JNE  | BPF_K) >> 3] = "if r%1$d != %3$d goto %4$x",
+  [(BPF_JSGT | BPF_K) >> 3] = "if (s64)r%1$d > %3$d goto %4$x",
+  [(BPF_JSGE | BPF_K) >> 3] = "if (s64)r%1$d >= %3$d goto %4$x",
+  [(BPF_CALL | BPF_K) >> 3] = "call %3$d",
+  [(BPF_EXIT | BPF_K) >> 3] = "exit",
+
+  [(BPF_JEQ  | BPF_X) >> 3] = "if r%1$d == r%2$d goto %4$x",
+  [(BPF_JGT  | BPF_X) >> 3] = "if r%1$d > r%2$d goto %4$x",
+  [(BPF_JGE  | BPF_X) >> 3] = "if r%1$d >= r%2$d goto %4$x",
+  [(BPF_JSET | BPF_X) >> 3] = "if r%1$d & r%2$d goto %4$x",
+  [(BPF_JNE  | BPF_X) >> 3] = "if r%1$d != r%2$d goto %4$x",
+  [(BPF_JSGT | BPF_X) >> 3] = "if (s64)r%1$d > (s64)r%2$d goto %4$x",
+  [(BPF_JSGE | BPF_X) >> 3] = "if (s64)r%1$d >= (s64)r%2$d goto %4$x",
+};
+
+int
+bpf_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
+	    const char *fmt __attribute__((unused)),
+	    DisasmOutputCB_t outcb,
+	    DisasmGetSymCB_t symcb __attribute__((unused)),
+	    void *outcbarg,
+	    void *symcbarg __attribute__((unused)))
+{
+  const uint8_t *start = *startp;
+  char buf[128];
+  int len, retval = 0;
+
+  while (start + sizeof(struct bpf_insn) <= end)
+    {
+      struct bpf_insn i;
+      unsigned code, class, op;
+      const char *op_str;
+
+      memcpy(&i, start, sizeof(struct bpf_insn));
+      start += sizeof(struct bpf_insn);
+      addr += sizeof(struct bpf_insn);
+
+      /* ??? We really should pass in CTX, so that we can detect
+	 wrong endianness and do some swapping.  */
+
+      code = i.code;
+      class = BPF_CLASS(code);
+      op = BPF_OP(code) | BPF_SRC(code);
+      len = -1;
+
+      switch (class)
+	{
+	case BPF_ALU:
+	  op_str = fmt_alu[op >> 3];
+	  goto do_alu;
+	case BPF_ALU64:
+	  op_str = fmt_alu64[op >> 3];
+	do_alu:
+	  if (op_str)
+	    len = snprintf(buf, sizeof(buf), op_str,
+			   i.dst_reg, i.src_reg, i.imm);
+	  break;
+
+	case BPF_STX:
+	  op_str = size_string[BPF_SIZE(code) >> 3];
+	  switch (BPF_MODE(code))
+	    {
+	    case BPF_MEM:
+	      len = snprintf(buf, sizeof(buf),
+			     "*(%s *)(r%d%+d) = r%d",
+			     op_str, i.dst_reg, i.off, i.src_reg);
+	      break;
+
+	    case BPF_XADD:
+	      len = snprintf(buf, sizeof(buf),
+			     "lock *(%s *)(r%d%+d) += r%d",
+			     op_str, i.dst_reg, i.off, i.src_reg);
+	      break;
+	    }
+	  break;
+
+	case BPF_ST:
+	  if (BPF_MODE(code) == BPF_MEM)
+	    {
+	      op_str = size_string[BPF_SIZE(code) >> 3];
+	      len = snprintf(buf, sizeof(buf),
+			     "*(%s *)(r%d%+d) = %d",
+			     op_str, i.dst_reg, i.off, i.imm);
+	    }
+	  break;
+
+	case BPF_LDX:
+	  if (BPF_MODE(code) == BPF_MEM)
+	    {
+	      op_str = size_string[BPF_SIZE(code) >> 3];
+	      len = snprintf(buf, sizeof(buf),
+			     "r%d = *(%s *)(r%d%+d)",
+			     i.dst_reg, op_str, i.src_reg, i.off);
+	    }
+	  break;
+
+	case BPF_LD:
+	  op_str = size_string[BPF_SIZE(code) >> 3];
+	  switch (BPF_MODE(code))
+	    {
+	    case BPF_ABS:
+	      len = snprintf(buf, sizeof(buf),
+			     "r0 = *(%s *)skb[%d]",
+			     op_str, i.imm);
+	      break;
+
+	    case BPF_IND:
+	      len = snprintf(buf, sizeof(buf),
+			     "r0 = *(%s *)skb[r%d%+d]",
+			     op_str, i.src_reg, i.imm);
+	      break;
+
+	    case BPF_IMM:
+	      if (BPF_SIZE(code) == BPF_DW)
+		{
+		  struct bpf_insn i2;
+		  uint64_t imm64;
+
+		  if (start + sizeof(struct bpf_insn) > end)
+		    {
+		      start -= sizeof(struct bpf_insn);
+		      *startp = start;
+		      goto done;
+		    }
+		  memcpy(&i2, start, sizeof(struct bpf_insn));
+		  start += sizeof(struct bpf_insn);
+		  addr += sizeof(struct bpf_insn);
+
+		  imm64 = (uint32_t)i.imm | ((uint64_t)i2.imm << 32);
+		  switch (i.src_reg)
+		    {
+		    case 0:
+		      len = snprintf(buf, sizeof(buf),
+				     "r%d = %#" PRIx64, i.dst_reg, imm64);
+		      break;
+		    case BPF_PSEUDO_MAP_FD:
+		      len = snprintf(buf, sizeof(buf),
+				     "r%d = map_fd", i.dst_reg);
+		      break;
+		    }
+                }
+	      break;
+	    }
+	  break;
+
+	case BPF_JMP:
+	  op_str = fmt_jmp[op >> 3];
+	  if (op_str)
+	    {
+	      unsigned jmp = addr + i.off * sizeof(struct bpf_insn);
+	      len = snprintf(buf, sizeof(buf), op_str,
+			     i.dst_reg, i.src_reg, i.imm, jmp);
+	    }
+	  break;
+	}
+      if (len < 0)
+	{
+	  len = snprintf(buf, sizeof(buf), "invalid class %s",
+			 class_string[class]);
+        }
+
+      *startp = start;
+      retval = outcb (buf, len, outcbarg);
+      if (retval != 0)
+	goto done;
+    }
+
+ done:
+  return retval;
+}
diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c
index 2b92254..16ec1c4 100644
--- a/libebl/eblopenbackend.c
+++ b/libebl/eblopenbackend.c
@@ -132,6 +132,7 @@ static const struct
   { "arc", "elf_arc_a5", "arc_a5", 6, EM_ARC_A5, 0, 0 },
   { "xtensa", "elf_xtensa", "xtensa", 6, EM_XTENSA, 0, 0 },
   { "aarch64", "elf_aarch64", "aarch64", 7, EM_AARCH64, ELFCLASS64, 0 },
+  { "bpf", "elf_bpf", "bpf", 3, EM_BPF, 0, 0 },
 };
 #define nmachines (sizeof (machines) / sizeof (machines[0]))
 
diff --git a/libelf/elf.h b/libelf/elf.h
index ce96bd5..2db03c3 100644
--- a/libelf/elf.h
+++ b/libelf/elf.h
@@ -261,6 +261,7 @@ typedef struct
    chances of collision with official or non-GNU unofficial values.  */
 
 #define EM_ALPHA	0x9026
+#define EM_BPF		0xeb9f
 
 /* Legal values for e_version (version).  */
 
@@ -3566,6 +3567,10 @@ enum
 
 #define R_TILEGX_NUM		130
 
+/* BPF specific declarations.  */
+
+#define R_BPF_NONE		0	/* No reloc */
+#define R_BPF_MAP_FD		1	/* Map fd to pointer */
 
 __END_DECLS
 
-- 
2.5.5

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]