xref: /linux/tools/bpf/bpftool/jit_disasm.c (revision 83a37b3292f4aca799b355179ad6fbdd78a08e10)
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