1 /* 2 * Based on: 3 * 4 * Minimal BPF JIT image disassembler 5 * 6 * Disassembles BPF JIT compiler emitted opcodes back to asm insn's for 7 * debugging or verification purposes. 8 * 9 * Copyright 2013 Daniel Borkmann <daniel@iogearbox.net> 10 * Licensed under the GNU General Public License, version 2.0 (GPLv2) 11 */ 12 13 #include <stdint.h> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <assert.h> 17 #include <unistd.h> 18 #include <string.h> 19 #include <bfd.h> 20 #include <dis-asm.h> 21 #include <sys/types.h> 22 #include <sys/stat.h> 23 24 static void get_exec_path(char *tpath, size_t size) 25 { 26 ssize_t len; 27 char *path; 28 29 snprintf(tpath, size, "/proc/%d/exe", (int) getpid()); 30 tpath[size - 1] = 0; 31 32 path = strdup(tpath); 33 assert(path); 34 35 len = readlink(path, tpath, size - 1); 36 assert(len > 0); 37 tpath[len] = 0; 38 39 free(path); 40 } 41 42 void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes) 43 { 44 disassembler_ftype disassemble; 45 struct disassemble_info info; 46 int count, i, pc = 0; 47 char tpath[256]; 48 bfd *bfdf; 49 50 if (!len) 51 return; 52 53 memset(tpath, 0, sizeof(tpath)); 54 get_exec_path(tpath, sizeof(tpath)); 55 56 bfdf = bfd_openr(tpath, NULL); 57 assert(bfdf); 58 assert(bfd_check_format(bfdf, bfd_object)); 59 60 init_disassemble_info(&info, stdout, (fprintf_ftype) fprintf); 61 info.arch = bfd_get_arch(bfdf); 62 info.mach = bfd_get_mach(bfdf); 63 info.buffer = image; 64 info.buffer_length = len; 65 66 disassemble_init_for_target(&info); 67 68 disassemble = disassembler(bfdf); 69 assert(disassemble); 70 71 do { 72 printf("%4x:\t", pc); 73 74 count = disassemble(pc, &info); 75 76 if (opcodes) { 77 printf("\n\t"); 78 for (i = 0; i < count; ++i) 79 printf("%02x ", (uint8_t) image[pc + i]); 80 } 81 printf("\n"); 82 83 pc += count; 84 } while (count > 0 && pc < len); 85 86 bfd_close(bfdf); 87 } 88