diff options
author | Daniel Borkmann <daniel@iogearbox.net> | 2015-07-30 10:04:22 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-07-31 18:13:14 -0400 |
commit | a6ed38361b1e0f08d630bd491051c254d1fc71b9 (patch) | |
tree | 25d6223bb7b2a4a85e73881acc409f9f35b4c484 | |
parent | 1df33a11454de804661c8e19cd0e464914eefc6d (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.c | 109 |
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 | ||
29 | static void get_exec_path(char *tpath, size_t size) | 34 | static 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 | ||
90 | static char *get_klog_buff(int *klen) | 95 | static 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 | ||
115 | static 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; |
142 | out_free: | ||
143 | free(buff); | ||
144 | out: | ||
145 | close(fd); | ||
146 | return NULL; | ||
147 | } | ||
148 | |||
149 | static 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 | ||
103 | static void put_klog_buff(char *buff) | 154 | static 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(®ex); | ||
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 | ||
225 | static 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 | |||
172 | int main(int argc, char **argv) | 233 | int 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 | } |