LCOV - code coverage report
Current view: top level - libcpu - bpf_disasm.c (source / functions) Hit Total Coverage
Test: elfutils-0.172 Lines: 303 316 95.9 %
Date: 2018-06-11 22:52:14 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Disassembler for BPF.
       2             :    Copyright (C) 2016 Red Hat, Inc.
       3             :    This file is part of elfutils.
       4             : 
       5             :    This file is free software; you can redistribute it and/or modify
       6             :    it under the terms of either
       7             : 
       8             :      * the GNU Lesser General Public License as published by the Free
       9             :        Software Foundation; either version 3 of the License, or (at
      10             :        your option) any later version
      11             : 
      12             :    or
      13             : 
      14             :      * the GNU General Public License as published by the Free
      15             :        Software Foundation; either version 2 of the License, or (at
      16             :        your option) any later version
      17             : 
      18             :    or both in parallel, as here.
      19             : 
      20             :    elfutils is distributed in the hope that it will be useful, but
      21             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      22             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      23             :    General Public License for more details.
      24             : 
      25             :    You should have received copies of the GNU General Public License and
      26             :    the GNU Lesser General Public License along with this program.  If
      27             :    not, see <http://www.gnu.org/licenses/>.  */
      28             : 
      29             : #ifdef HAVE_CONFIG_H
      30             : # include <config.h>
      31             : #endif
      32             : 
      33             : #include <assert.h>
      34             : #include <string.h>
      35             : #include <stdio.h>
      36             : #include <gelf.h>
      37             : #include <inttypes.h>
      38             : #include "bpf.h"
      39             : 
      40             : #include "../libelf/common.h"
      41             : #include "../libebl/libeblP.h"
      42             : 
      43             : static const char class_string[8][8] = {
      44             :   [BPF_LD]    = "ld",
      45             :   [BPF_LDX]   = "ldx",
      46             :   [BPF_ST]    = "st",
      47             :   [BPF_STX]   = "stx",
      48             :   [BPF_ALU]   = "alu",
      49             :   [BPF_JMP]   = "jmp",
      50             :   [BPF_RET]   = "6",          /* completely unused in ebpf */
      51             :   [BPF_ALU64] = "alu64",
      52             : };
      53             : 
      54             : 
      55             : #define REG(N)          "r%" #N "$d"
      56             : #define REGU(N)         "(u32)" REG(N)
      57             : #define REGS(N)         "(s64)" REG(N)
      58             : 
      59             : #define IMMS(N)         "%" #N "$d"
      60             : #define IMMX(N)         "%" #N "$#x"
      61             : 
      62             : #define OFF(N)          "%" #N "$+d"
      63             : #define JMP(N)          "%" #N "$#x"
      64             : 
      65             : #define A32(O, S)       REG(1) " = " REGU(1) " " #O " " S
      66             : #define A64(O, S)       REG(1) " " #O "= " S
      67             : #define J64(D, O, S)    "if " D " " #O " " S " goto " JMP(3)
      68             : #define LOAD(T)         REG(1) " = *(" #T " *)(" REG(2) OFF(3) ")"
      69             : #define STORE(T, S)     "*(" #T " *)(" REG(1) OFF(3) ") = " S
      70             : #define XADD(T, S)      "lock *(" #T " *)(" REG(1) OFF(3) ") += " S
      71             : #define LDSKB(T, S)     "r0 = *(" #T " *)skb[" S "]"
      72             : 
      73             : static void
      74             : bswap_bpf_insn (struct bpf_insn *p)
      75             : {
      76             :   /* Note that the dst_reg and src_reg fields are 4-bit bitfields.
      77             :      That means these two nibbles are (typically) layed out in the
      78             :      opposite order between big- and little-endian hosts.  This is
      79             :      not required by any standard, but does happen to be true for
      80             :      at least ppc, s390, arm and mips as big-endian hosts.  */
      81           0 :   int t = p->dst_reg;
      82           0 :   p->dst_reg = p->src_reg;
      83           0 :   p->src_reg = t;
      84             : 
      85             :   /* The other 2 and 4 byte fields are trivially converted.  */
      86           0 :   CONVERT (p->off);
      87           0 :   CONVERT (p->imm);
      88             : }
      89             : 
      90             : int
      91           1 : bpf_disasm (Ebl *ebl, const uint8_t **startp, const uint8_t *end,
      92             :             GElf_Addr addr, const char *fmt __attribute__((unused)),
      93             :             DisasmOutputCB_t outcb,
      94             :             DisasmGetSymCB_t symcb __attribute__((unused)),
      95             :             void *outcbarg,
      96             :             void *symcbarg __attribute__((unused)))
      97             : {
      98           1 :   const bool need_bswap = MY_ELFDATA != ebl->data;
      99           1 :   const uint8_t *start = *startp;
     100             :   char buf[128];
     101           1 :   int len, retval = 0;
     102             : 
     103         258 :   while (start + sizeof(struct bpf_insn) <= end)
     104             :     {
     105             :       struct bpf_insn i;
     106             :       unsigned code, class, jmp;
     107             :       const char *code_fmt;
     108             : 
     109         256 :       memcpy(&i, start, sizeof(struct bpf_insn));
     110         256 :       if (need_bswap)
     111             :         bswap_bpf_insn (&i);
     112             : 
     113         256 :       start += sizeof(struct bpf_insn);
     114         256 :       addr += sizeof(struct bpf_insn);
     115         256 :       jmp = addr + i.off * sizeof(struct bpf_insn);
     116             : 
     117         256 :       code = i.code;
     118         256 :       switch (code)
     119             :         {
     120           1 :         case BPF_LD | BPF_IMM | BPF_DW:
     121           1 :           {
     122             :             struct bpf_insn i2;
     123             :             uint64_t imm64;
     124             : 
     125           1 :             if (start + sizeof(struct bpf_insn) > end)
     126             :               {
     127           0 :                 start -= sizeof(struct bpf_insn);
     128           0 :                 *startp = start;
     129             :                 goto done;
     130             :               }
     131           1 :             memcpy(&i2, start, sizeof(struct bpf_insn));
     132           1 :             if (need_bswap)
     133             :               bswap_bpf_insn (&i2);
     134           1 :             start += sizeof(struct bpf_insn);
     135           1 :             addr += sizeof(struct bpf_insn);
     136             : 
     137           1 :             imm64 = (uint32_t)i.imm | ((uint64_t)i2.imm << 32);
     138           1 :             switch (i.src_reg)
     139             :               {
     140             :               case 0:
     141             :                 code_fmt = REG(1) " = %2$#" PRIx64;
     142             :                 break;
     143           0 :               case BPF_PSEUDO_MAP_FD:
     144           0 :                 code_fmt = REG(1) " = map_fd(%2$#" PRIx64 ")";
     145           0 :                 break;
     146           0 :               default:
     147           0 :                 code_fmt = REG(1) " = ld_pseudo(%3$d, %2$#" PRIx64 ")";
     148           0 :                 break;
     149             :               }
     150           2 :             len = snprintf(buf, sizeof(buf), code_fmt,
     151           1 :                            i.dst_reg, imm64, i.src_reg);
     152             :           }
     153           1 :           break;
     154             : 
     155           1 :         case BPF_JMP | BPF_EXIT:
     156           1 :           len = snprintf(buf, sizeof(buf), "exit");
     157           1 :           break;
     158           1 :         case BPF_JMP | BPF_JA:
     159           1 :           len = snprintf(buf, sizeof(buf), "goto " JMP(1), jmp);
     160           1 :           break;
     161             :         case BPF_JMP | BPF_CALL:
     162             :           code_fmt = "call " IMMS(1);
     163             :           goto do_imm;
     164             : 
     165             :         case BPF_ALU | BPF_END | BPF_TO_LE:
     166             :           /* The imm field contains {16,32,64}.  */
     167             :           code_fmt = REG(1) " = le" IMMS(2) "(" REG(1) ")";
     168             :           goto do_dst_imm;
     169           1 :         case BPF_ALU | BPF_END | BPF_TO_BE:
     170           1 :           code_fmt = REG(1) " = be" IMMS(2) "(" REG(1) ")";
     171           1 :           goto do_dst_imm;
     172             : 
     173           1 :         case BPF_ALU | BPF_ADD | BPF_K:
     174           1 :           code_fmt = A32(+, IMMS(2));
     175           1 :           goto do_dst_imm;
     176           1 :         case BPF_ALU | BPF_SUB | BPF_K:
     177           1 :           code_fmt = A32(-, IMMS(2));
     178           1 :           goto do_dst_imm;
     179           1 :         case BPF_ALU | BPF_MUL | BPF_K:
     180           1 :           code_fmt = A32(*, IMMS(2));
     181           1 :           goto do_dst_imm;
     182           1 :         case BPF_ALU | BPF_DIV | BPF_K:
     183           1 :           code_fmt = A32(/, IMMS(2));
     184           1 :           goto do_dst_imm;
     185           1 :         case BPF_ALU | BPF_OR | BPF_K:
     186           1 :           code_fmt = A32(|, IMMX(2));
     187           1 :           goto do_dst_imm;
     188           1 :         case BPF_ALU | BPF_AND | BPF_K:
     189           1 :           code_fmt = A32(&, IMMX(2));
     190           1 :           goto do_dst_imm;
     191           1 :         case BPF_ALU | BPF_LSH | BPF_K:
     192           1 :           code_fmt = A32(<<, IMMS(2));
     193           1 :           goto do_dst_imm;
     194           1 :         case BPF_ALU | BPF_RSH | BPF_K:
     195           1 :           code_fmt = A32(>>, IMMS(2));
     196           1 :           goto do_dst_imm;
     197           1 :         case BPF_ALU | BPF_MOD | BPF_K:
     198           1 :           code_fmt = A32(%%, IMMS(2));
     199           1 :           goto do_dst_imm;
     200           1 :         case BPF_ALU | BPF_XOR | BPF_K:
     201           1 :           code_fmt = A32(^, IMMX(2));
     202           1 :           goto do_dst_imm;
     203           1 :         case BPF_ALU | BPF_MOV | BPF_K:
     204           1 :           code_fmt = REG(1) " = " IMMX(2);
     205           1 :           goto do_dst_imm;
     206           1 :         case BPF_ALU | BPF_ARSH | BPF_K:
     207           1 :           code_fmt = REG(1) " = (u32)((s32)" REG(1) " >> " IMMS(2) ")";
     208           1 :           goto do_dst_imm;
     209             : 
     210             :         case BPF_ALU | BPF_ADD | BPF_X:
     211             :           code_fmt = A32(+, REGU(2));
     212             :           goto do_dst_src;
     213           1 :         case BPF_ALU | BPF_SUB | BPF_X:
     214           1 :           code_fmt = A32(-, REGU(2));
     215           1 :           goto do_dst_src;
     216           1 :         case BPF_ALU | BPF_MUL | BPF_X:
     217           1 :           code_fmt = A32(*, REGU(2));
     218           1 :           goto do_dst_src;
     219           1 :         case BPF_ALU | BPF_DIV | BPF_X:
     220           1 :           code_fmt = A32(/, REGU(2));
     221           1 :           goto do_dst_src;
     222           1 :         case BPF_ALU | BPF_OR | BPF_X:
     223           1 :           code_fmt = A32(|, REGU(2));
     224           1 :           goto do_dst_src;
     225           1 :         case BPF_ALU | BPF_AND | BPF_X:
     226           1 :           code_fmt = A32(&, REGU(2));
     227           1 :           goto do_dst_src;
     228           1 :         case BPF_ALU | BPF_LSH | BPF_X:
     229           1 :           code_fmt = A32(<<, REGU(2));
     230           1 :           goto do_dst_src;
     231           1 :         case BPF_ALU | BPF_RSH | BPF_X:
     232           1 :           code_fmt = A32(>>, REGU(2));
     233           1 :           goto do_dst_src;
     234           1 :         case BPF_ALU | BPF_MOD | BPF_X:
     235           1 :           code_fmt = A32(%%, REGU(2));
     236           1 :           goto do_dst_src;
     237           1 :         case BPF_ALU | BPF_XOR | BPF_X:
     238           1 :           code_fmt = A32(^, REGU(2));
     239           1 :           goto do_dst_src;
     240           1 :         case BPF_ALU | BPF_MOV | BPF_X:
     241           1 :           code_fmt = REG(1) " = " REGU(2);
     242           1 :           goto do_dst_src;
     243           1 :         case BPF_ALU | BPF_ARSH | BPF_X:
     244           1 :           code_fmt = REG(1) " = (u32)((s32)" REG(1) " >> " REG(2) ")";
     245           1 :           goto do_dst_src;
     246             : 
     247           1 :         case BPF_ALU64 | BPF_ADD | BPF_K:
     248           1 :           code_fmt = A64(+, IMMS(2));
     249           1 :           goto do_dst_imm;
     250           1 :         case BPF_ALU64 | BPF_SUB | BPF_K:
     251           1 :           code_fmt = A64(-, IMMS(2));
     252           1 :           goto do_dst_imm;
     253           1 :         case BPF_ALU64 | BPF_MUL | BPF_K:
     254           1 :           code_fmt = A64(*, IMMS(2));
     255           1 :           goto do_dst_imm;
     256           1 :         case BPF_ALU64 | BPF_DIV | BPF_K:
     257           1 :           code_fmt = A64(/, IMMS(2));
     258           1 :           goto do_dst_imm;
     259           1 :         case BPF_ALU64 | BPF_OR | BPF_K:
     260           1 :           code_fmt = A64(|, IMMS(2));
     261           1 :           goto do_dst_imm;
     262           1 :         case BPF_ALU64 | BPF_AND | BPF_K:
     263           1 :           code_fmt = A64(&, IMMS(2));
     264           1 :           goto do_dst_imm;
     265           1 :         case BPF_ALU64 | BPF_LSH | BPF_K:
     266           1 :           code_fmt = A64(<<, IMMS(2));
     267           1 :           goto do_dst_imm;
     268           1 :         case BPF_ALU64 | BPF_RSH | BPF_K:
     269           1 :           code_fmt = A64(>>, IMMS(2));
     270           1 :           goto do_dst_imm;
     271           1 :         case BPF_ALU64 | BPF_MOD | BPF_K:
     272           1 :           code_fmt = A64(%%, IMMS(2));
     273           1 :           goto do_dst_imm;
     274           1 :         case BPF_ALU64 | BPF_XOR | BPF_K:
     275           1 :           code_fmt = A64(^, IMMS(2));
     276           1 :           goto do_dst_imm;
     277           1 :         case BPF_ALU64 | BPF_MOV | BPF_K:
     278           1 :           code_fmt = REG(1) " = " IMMS(2);
     279           1 :           goto do_dst_imm;
     280           1 :         case BPF_ALU64 | BPF_ARSH | BPF_K:
     281           1 :           code_fmt = REG(1) " = (s64)" REG(1) " >> " IMMS(2);
     282           1 :           goto do_dst_imm;
     283             : 
     284           1 :         case BPF_ALU64 | BPF_ADD | BPF_X:
     285           1 :           code_fmt = A64(+, REG(2));
     286           1 :           goto do_dst_src;
     287           1 :         case BPF_ALU64 | BPF_SUB | BPF_X:
     288           1 :           code_fmt = A64(-, REG(2));
     289           1 :           goto do_dst_src;
     290           1 :         case BPF_ALU64 | BPF_MUL | BPF_X:
     291           1 :           code_fmt = A64(*, REG(2));
     292           1 :           goto do_dst_src;
     293           1 :         case BPF_ALU64 | BPF_DIV | BPF_X:
     294           1 :           code_fmt = A64(/, REG(2));
     295           1 :           goto do_dst_src;
     296           1 :         case BPF_ALU64 | BPF_OR | BPF_X:
     297           1 :           code_fmt = A64(|, REG(2));
     298           1 :           goto do_dst_src;
     299           1 :         case BPF_ALU64 | BPF_AND | BPF_X:
     300           1 :           code_fmt = A64(&, REG(2));
     301           1 :           goto do_dst_src;
     302           1 :         case BPF_ALU64 | BPF_LSH | BPF_X:
     303           1 :           code_fmt = A64(<<, REG(2));
     304           1 :           goto do_dst_src;
     305           1 :         case BPF_ALU64 | BPF_RSH | BPF_X:
     306           1 :           code_fmt = A64(>>, REG(2));
     307           1 :           goto do_dst_src;
     308           1 :         case BPF_ALU64 | BPF_MOD | BPF_X:
     309           1 :           code_fmt = A64(%%, REG(2));
     310           1 :           goto do_dst_src;
     311           1 :         case BPF_ALU64 | BPF_XOR | BPF_X:
     312           1 :           code_fmt = A64(^, REG(2));
     313           1 :           goto do_dst_src;
     314           1 :         case BPF_ALU64 | BPF_MOV | BPF_X:
     315           1 :           code_fmt = REG(1) " = " REG(2);
     316           1 :           goto do_dst_src;
     317           1 :         case BPF_ALU64 | BPF_ARSH | BPF_X:
     318           1 :           code_fmt = REG(1) " = (s64)" REG(1) " >> " REG(2);
     319           1 :           goto do_dst_src;
     320             : 
     321           1 :         case BPF_ALU | BPF_NEG:
     322           1 :           code_fmt = REG(1) " = (u32)-" REG(1);
     323           1 :           goto do_dst_src;
     324           1 :         case BPF_ALU64 | BPF_NEG:
     325           1 :           code_fmt = REG(1) " = -" REG(1);
     326           1 :           goto do_dst_src;
     327             : 
     328             :         case BPF_JMP | BPF_JEQ | BPF_K:
     329             :           code_fmt = J64(REG(1), ==, IMMS(2));
     330             :           goto do_dst_imm_jmp;
     331           1 :         case BPF_JMP | BPF_JGT | BPF_K:
     332           1 :           code_fmt = J64(REG(1), >, IMMS(2));
     333           1 :           goto do_dst_imm_jmp;
     334           1 :         case BPF_JMP | BPF_JGE | BPF_K:
     335           1 :           code_fmt = J64(REG(1), >=, IMMS(2));
     336           1 :           goto do_dst_imm_jmp;
     337           1 :         case BPF_JMP | BPF_JSET | BPF_K:
     338           1 :           code_fmt = J64(REG(1), &, IMMS(2));
     339           1 :           goto do_dst_imm_jmp;
     340           1 :         case BPF_JMP | BPF_JNE | BPF_K:
     341           1 :           code_fmt = J64(REG(1), !=, IMMS(2));
     342           1 :           goto do_dst_imm_jmp;
     343           1 :         case BPF_JMP | BPF_JSGT | BPF_K:
     344           1 :           code_fmt = J64(REGS(1), >, IMMS(2));
     345           1 :           goto do_dst_imm_jmp;
     346           1 :         case BPF_JMP | BPF_JSGE | BPF_K:
     347           1 :           code_fmt = J64(REGS(1), >=, IMMS(2));
     348           1 :           goto do_dst_imm_jmp;
     349             : 
     350             :         case BPF_JMP | BPF_JEQ | BPF_X:
     351             :           code_fmt = J64(REG(1), ==, REG(2));
     352             :           goto do_dst_src_jmp;
     353           1 :         case BPF_JMP | BPF_JGT | BPF_X:
     354           1 :           code_fmt = J64(REG(1), >, REG(2));
     355           1 :           goto do_dst_src_jmp;
     356           1 :         case BPF_JMP | BPF_JGE | BPF_X:
     357           1 :           code_fmt = J64(REG(1), >=, REG(2));
     358           1 :           goto do_dst_src_jmp;
     359           1 :         case BPF_JMP | BPF_JSET | BPF_X:
     360           1 :           code_fmt = J64(REG(1), &, REG(2));
     361           1 :           goto do_dst_src_jmp;
     362           1 :         case BPF_JMP | BPF_JNE | BPF_X:
     363           1 :           code_fmt = J64(REG(1), !=, REG(2));
     364           1 :           goto do_dst_src_jmp;
     365           1 :         case BPF_JMP | BPF_JSGT | BPF_X:
     366           1 :           code_fmt = J64(REGS(1), >, REGS(2));
     367           1 :           goto do_dst_src_jmp;
     368           1 :         case BPF_JMP | BPF_JSGE | BPF_X:
     369           1 :           code_fmt = J64(REGS(1), >=, REGS(2));
     370           1 :           goto do_dst_src_jmp;
     371             : 
     372             :         case BPF_LDX | BPF_MEM | BPF_B:
     373             :           code_fmt = LOAD(u8);
     374             :           goto do_dst_src_off;
     375           1 :         case BPF_LDX | BPF_MEM | BPF_H:
     376           1 :           code_fmt = LOAD(u16);
     377           1 :           goto do_dst_src_off;
     378           1 :         case BPF_LDX | BPF_MEM | BPF_W:
     379           1 :           code_fmt = LOAD(u32);
     380           1 :           goto do_dst_src_off;
     381           1 :         case BPF_LDX | BPF_MEM | BPF_DW:
     382           1 :           code_fmt = LOAD(u64);
     383           1 :           goto do_dst_src_off;
     384             : 
     385           1 :         case BPF_STX | BPF_MEM | BPF_B:
     386           1 :           code_fmt = STORE(u8, REG(2));
     387           1 :           goto do_dst_src_off;
     388           1 :         case BPF_STX | BPF_MEM | BPF_H:
     389           1 :           code_fmt = STORE(u16, REG(2));
     390           1 :           goto do_dst_src_off;
     391           1 :         case BPF_STX | BPF_MEM | BPF_W:
     392           1 :           code_fmt = STORE(u32, REG(2));
     393           1 :           goto do_dst_src_off;
     394           1 :         case BPF_STX | BPF_MEM | BPF_DW:
     395           1 :           code_fmt = STORE(u64, REG(2));
     396           1 :           goto do_dst_src_off;
     397             : 
     398           1 :         case BPF_STX | BPF_XADD | BPF_W:
     399           1 :           code_fmt = XADD(u32, REG(2));
     400           1 :           goto do_dst_src_off;
     401           1 :         case BPF_STX | BPF_XADD | BPF_DW:
     402           1 :           code_fmt = XADD(u64, REG(2));
     403           1 :           goto do_dst_src_off;
     404             : 
     405             :         case BPF_ST | BPF_MEM | BPF_B:
     406             :           code_fmt = STORE(u8, IMMS(2));
     407             :           goto do_dst_imm_off;
     408           1 :         case BPF_ST | BPF_MEM | BPF_H:
     409           1 :           code_fmt = STORE(u16, IMMS(2));
     410           1 :           goto do_dst_imm_off;
     411           1 :         case BPF_ST | BPF_MEM | BPF_W:
     412           1 :           code_fmt = STORE(u32, IMMS(2));
     413           1 :           goto do_dst_imm_off;
     414           1 :         case BPF_ST | BPF_MEM | BPF_DW:
     415           1 :           code_fmt = STORE(u64, IMMS(2));
     416           1 :           goto do_dst_imm_off;
     417             : 
     418           1 :         case BPF_LD | BPF_ABS | BPF_B:
     419           1 :           code_fmt = LDSKB(u8, IMMS(1));
     420           1 :           goto do_imm;
     421           1 :         case BPF_LD | BPF_ABS | BPF_H:
     422           1 :           code_fmt = LDSKB(u16, IMMS(1));
     423           1 :           goto do_imm;
     424           1 :         case BPF_LD | BPF_ABS | BPF_W:
     425           1 :           code_fmt = LDSKB(u32, IMMS(1));
     426           1 :           goto do_imm;
     427             : 
     428             :         case BPF_LD | BPF_IND | BPF_B:
     429             :           code_fmt = LDSKB(u8, REG(1) "+" IMMS(2));
     430             :           goto do_src_imm;
     431           1 :         case BPF_LD | BPF_IND | BPF_H:
     432           1 :           code_fmt = LDSKB(u16, REG(1) "+" IMMS(2));
     433           1 :           goto do_src_imm;
     434           1 :         case BPF_LD | BPF_IND | BPF_W:
     435           1 :           code_fmt = LDSKB(u32, REG(1) "+" IMMS(2));
     436           1 :           goto do_src_imm;
     437             : 
     438           4 :         do_imm:
     439           8 :           len = snprintf(buf, sizeof(buf), code_fmt, i.imm);
     440           4 :           break;
     441          26 :         do_dst_imm:
     442          52 :           len = snprintf(buf, sizeof(buf), code_fmt, i.dst_reg, i.imm);
     443          26 :           break;
     444           3 :         do_src_imm:
     445           6 :           len = snprintf(buf, sizeof(buf), code_fmt, i.src_reg, i.imm);
     446           3 :           break;
     447          26 :         do_dst_src:
     448          52 :           len = snprintf(buf, sizeof(buf), code_fmt, i.dst_reg, i.src_reg);
     449          26 :           break;
     450           7 :         do_dst_imm_jmp:
     451          14 :           len = snprintf(buf, sizeof(buf), code_fmt, i.dst_reg, i.imm, jmp);
     452           7 :           break;
     453           7 :         do_dst_src_jmp:
     454          21 :           len = snprintf(buf, sizeof(buf), code_fmt,
     455          14 :                          i.dst_reg, i.src_reg, jmp);
     456           7 :           break;
     457           4 :         do_dst_imm_off:
     458           8 :           len = snprintf(buf, sizeof(buf), code_fmt, i.dst_reg, i.imm, i.off);
     459           4 :           break;
     460          10 :         do_dst_src_off:
     461          40 :           len = snprintf(buf, sizeof(buf), code_fmt,
     462          20 :                          i.dst_reg, i.src_reg, i.off);
     463          10 :           break;
     464             : 
     465         166 :         default:
     466         166 :           class = BPF_CLASS(code);
     467         166 :           len = snprintf(buf, sizeof(buf), "invalid class %s",
     468         166 :                          class_string[class]);
     469         166 :           break;
     470             :         }
     471             : 
     472         256 :       *startp = start;
     473         256 :       retval = outcb (buf, len, outcbarg);
     474         256 :       if (retval != 0)
     475             :         goto done;
     476             :     }
     477             : 
     478           1 :  done:
     479           1 :   return retval;
     480             : }

Generated by: LCOV version 1.13