|
22 | 22 | #include <string.h>
|
23 | 23 | #include <bfd.h>
|
24 | 24 | #include <dis-asm.h>
|
| 25 | +#include <regex.h> |
| 26 | +#include <fcntl.h> |
25 | 27 | #include <sys/klog.h>
|
26 | 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 | 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 | 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); |
93 |
| - char *buff = malloc(len); |
| 97 | + int ret, 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 | 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 | 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 | 156 | free(buff);
|
106 | 157 | }
|
@@ -138,8 +189,10 @@ static int get_last_jit_image(char *haystack, size_t hlen,
|
138 | 189 | ptr = haystack + off - (pmatch[0].rm_eo - pmatch[0].rm_so);
|
139 | 190 | ret = sscanf(ptr, "flen=%d proglen=%d pass=%d image=%lx",
|
140 | 191 | &flen, &proglen, &pass, &base);
|
141 |
| - if (ret != 4) |
| 192 | + if (ret != 4) { |
| 193 | + regfree(®ex); |
142 | 194 | return 0;
|
| 195 | + } |
143 | 196 |
|
144 | 197 | tmp = ptr = haystack + off;
|
145 | 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 | 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 | 233 | int main(int argc, char **argv)
|
173 | 234 | {
|
174 |
| - int len, klen, opcodes = 0; |
175 |
| - char *kbuff; |
| 235 | + unsigned int len, klen, opt, opcodes = 0; |
176 | 236 | static uint8_t image[32768];
|
| 237 | + char *kbuff, *file = NULL; |
177 | 238 |
|
178 |
| - if (argc > 1) { |
179 |
| - if (!strncmp("-o", argv[argc - 1], 2)) { |
| 239 | + while ((opt = getopt(argc, argv, "of:")) != -1) { |
| 240 | + switch (opt) { |
| 241 | + case 'o': |
180 | 242 | opcodes = 1;
|
181 |
| - } else { |
182 |
| - printf("usage: bpf_jit_disasm [-o: show opcodes]\n"); |
183 |
| - exit(0); |
| 243 | + break; |
| 244 | + case 'f': |
| 245 | + file = optarg; |
| 246 | + break; |
| 247 | + default: |
| 248 | + usage(); |
| 249 | + return -1; |
184 | 250 | }
|
185 | 251 | }
|
186 | 252 |
|
187 | 253 | bfd_init();
|
188 | 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 | 262 | len = get_last_jit_image(kbuff, klen, image, sizeof(image));
|
193 | 263 | if (len > 0)
|
194 | 264 | get_asm_insns(image, len, opcodes);
|
| 265 | + else |
| 266 | + fprintf(stderr, "No JIT image found!\n"); |
195 | 267 |
|
196 |
| - put_klog_buff(kbuff); |
197 |
| - |
| 268 | + put_log_buff(kbuff); |
198 | 269 | return 0;
|
199 | 270 | }
|
0 commit comments