aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2015-07-30 10:04:22 -0400
committerDavid S. Miller <davem@davemloft.net>2015-07-31 18:13:14 -0400
commita6ed38361b1e0f08d630bd491051c254d1fc71b9 (patch)
tree25d6223bb7b2a4a85e73881acc409f9f35b4c484
parent1df33a11454de804661c8e19cd0e464914eefc6d (diff)
bpf_jit_disasm: also support reading jit dump from file
This patch adds support to read the dmesg BPF JIT dump also from a file instead of the klog buffer. I found this quite useful when going through some 'before/after patch' logs. It also fixes a regex leak found by valgrind when no image dump was found. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--tools/net/bpf_jit_disasm.c109
1 files changed, 90 insertions, 19 deletions
diff --git a/tools/net/bpf_jit_disasm.c b/tools/net/bpf_jit_disasm.c
index 618c2bcd4eab..2cd3d4c99738 100644
--- a/tools/net/bpf_jit_disasm.c
+++ b/tools/net/bpf_jit_disasm.c
@@ -22,9 +22,14 @@
22#include <string.h> 22#include <string.h>
23#include <bfd.h> 23#include <bfd.h>
24#include <dis-asm.h> 24#include <dis-asm.h>
25#include <regex.h>
26#include <fcntl.h>
25#include <sys/klog.h> 27#include <sys/klog.h>
26#include <sys/types.h> 28#include <sys/types.h>
27#include <regex.h> 29#include <sys/stat.h>
30
31#define CMD_ACTION_SIZE_BUFFER 10
32#define CMD_ACTION_READ_ALL 3
28 33
29static void get_exec_path(char *tpath, size_t size) 34static void get_exec_path(char *tpath, size_t size)
30{ 35{
@@ -87,20 +92,66 @@ static void get_asm_insns(uint8_t *image, size_t len, int opcodes)
87 bfd_close(bfdf); 92 bfd_close(bfdf);
88} 93}
89 94
90static char *get_klog_buff(int *klen) 95static char *get_klog_buff(unsigned int *klen)
91{ 96{
92 int ret, len = klogctl(10, NULL, 0); 97 int ret, len;
93 char *buff = malloc(len); 98 char *buff;
99
100 len = klogctl(CMD_ACTION_SIZE_BUFFER, NULL, 0);
101 buff = malloc(len);
102 if (!buff)
103 return NULL;
104
105 ret = klogctl(CMD_ACTION_READ_ALL, buff, len);
106 if (ret < 0) {
107 free(buff);
108 return NULL;
109 }
94 110
95 assert(buff && klen);
96 ret = klogctl(3, buff, len);
97 assert(ret >= 0);
98 *klen = ret; 111 *klen = ret;
112 return buff;
113}
99 114
115static char *get_flog_buff(const char *file, unsigned int *klen)
116{
117 int fd, ret, len;
118 struct stat fi;
119 char *buff;
120
121 fd = open(file, O_RDONLY);
122 if (fd < 0)
123 return NULL;
124
125 ret = fstat(fd, &fi);
126 if (ret < 0 || !S_ISREG(fi.st_mode))
127 goto out;
128
129 len = fi.st_size + 1;
130 buff = malloc(len);
131 if (!buff)
132 goto out;
133
134 memset(buff, 0, len);
135 ret = read(fd, buff, len - 1);
136 if (ret <= 0)
137 goto out_free;
138
139 close(fd);
140 *klen = ret;
100 return buff; 141 return buff;
142out_free:
143 free(buff);
144out:
145 close(fd);
146 return NULL;
147}
148
149static char *get_log_buff(const char *file, unsigned int *klen)
150{
151 return file ? get_flog_buff(file, klen) : get_klog_buff(klen);
101} 152}
102 153
103static void put_klog_buff(char *buff) 154static void put_log_buff(char *buff)
104{ 155{
105 free(buff); 156 free(buff);
106} 157}
@@ -138,8 +189,10 @@ static int get_last_jit_image(char *haystack, size_t hlen,
138 ptr = haystack + off - (pmatch[0].rm_eo - pmatch[0].rm_so); 189 ptr = haystack + off - (pmatch[0].rm_eo - pmatch[0].rm_so);
139 ret = sscanf(ptr, "flen=%d proglen=%d pass=%d image=%lx", 190 ret = sscanf(ptr, "flen=%d proglen=%d pass=%d image=%lx",
140 &flen, &proglen, &pass, &base); 191 &flen, &proglen, &pass, &base);
141 if (ret != 4) 192 if (ret != 4) {
193 regfree(&regex);
142 return 0; 194 return 0;
195 }
143 196
144 tmp = ptr = haystack + off; 197 tmp = ptr = haystack + off;
145 while ((ptr = strtok(tmp, "\n")) != NULL && ulen < ilen) { 198 while ((ptr = strtok(tmp, "\n")) != NULL && ulen < ilen) {
@@ -169,31 +222,49 @@ static int get_last_jit_image(char *haystack, size_t hlen,
169 return ulen; 222 return ulen;
170} 223}
171 224
225static void usage(void)
226{
227 printf("Usage: bpf_jit_disasm [...]\n");
228 printf(" -o Also display related opcodes (default: off).\n");
229 printf(" -f <file> Read last image dump from file or stdin (default: klog).\n");
230 printf(" -h Display this help.\n");
231}
232
172int main(int argc, char **argv) 233int main(int argc, char **argv)
173{ 234{
174 int len, klen, opcodes = 0; 235 unsigned int len, klen, opt, opcodes = 0;
175 char *kbuff;
176 static uint8_t image[32768]; 236 static uint8_t image[32768];
237 char *kbuff, *file = NULL;
177 238
178 if (argc > 1) { 239 while ((opt = getopt(argc, argv, "of:")) != -1) {
179 if (!strncmp("-o", argv[argc - 1], 2)) { 240 switch (opt) {
241 case 'o':
180 opcodes = 1; 242 opcodes = 1;
181 } else { 243 break;
182 printf("usage: bpf_jit_disasm [-o: show opcodes]\n"); 244 case 'f':
183 exit(0); 245 file = optarg;
246 break;
247 default:
248 usage();
249 return -1;
184 } 250 }
185 } 251 }
186 252
187 bfd_init(); 253 bfd_init();
188 memset(image, 0, sizeof(image)); 254 memset(image, 0, sizeof(image));
189 255
190 kbuff = get_klog_buff(&klen); 256 kbuff = get_log_buff(file, &klen);
257 if (!kbuff) {
258 fprintf(stderr, "Could not retrieve log buffer!\n");
259 return -1;
260 }
191 261
192 len = get_last_jit_image(kbuff, klen, image, sizeof(image)); 262 len = get_last_jit_image(kbuff, klen, image, sizeof(image));
193 if (len > 0) 263 if (len > 0)
194 get_asm_insns(image, len, opcodes); 264 get_asm_insns(image, len, opcodes);
265 else
266 fprintf(stderr, "No JIT image found!\n");
195 267
196 put_klog_buff(kbuff); 268 put_log_buff(kbuff);
197
198 return 0; 269 return 0;
199} 270}