summaryrefslogtreecommitdiffstats
path: root/kernel/tools/net/bpf_jit_disasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/tools/net/bpf_jit_disasm.c')
-rw-r--r--kernel/tools/net/bpf_jit_disasm.c113
1 files changed, 92 insertions, 21 deletions
diff --git a/kernel/tools/net/bpf_jit_disasm.c b/kernel/tools/net/bpf_jit_disasm.c
index 618c2bcd4..5b3241340 100644
--- a/kernel/tools/net/bpf_jit_disasm.c
+++ b/kernel/tools/net/bpf_jit_disasm.c
@@ -22,9 +22,14 @@
#include <string.h>
#include <bfd.h>
#include <dis-asm.h>
+#include <regex.h>
+#include <fcntl.h>
#include <sys/klog.h>
#include <sys/types.h>
-#include <regex.h>
+#include <sys/stat.h>
+
+#define CMD_ACTION_SIZE_BUFFER 10
+#define CMD_ACTION_READ_ALL 3
static void get_exec_path(char *tpath, size_t size)
{
@@ -87,26 +92,72 @@ static void get_asm_insns(uint8_t *image, size_t len, int opcodes)
bfd_close(bfdf);
}
-static char *get_klog_buff(int *klen)
+static char *get_klog_buff(unsigned int *klen)
{
- int ret, len = klogctl(10, NULL, 0);
- char *buff = malloc(len);
+ int ret, len;
+ char *buff;
+
+ len = klogctl(CMD_ACTION_SIZE_BUFFER, NULL, 0);
+ buff = malloc(len);
+ if (!buff)
+ return NULL;
+
+ ret = klogctl(CMD_ACTION_READ_ALL, buff, len);
+ if (ret < 0) {
+ free(buff);
+ return NULL;
+ }
- assert(buff && klen);
- ret = klogctl(3, buff, len);
- assert(ret >= 0);
*klen = ret;
+ return buff;
+}
+static char *get_flog_buff(const char *file, unsigned int *klen)
+{
+ int fd, ret, len;
+ struct stat fi;
+ char *buff;
+
+ fd = open(file, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+
+ ret = fstat(fd, &fi);
+ if (ret < 0 || !S_ISREG(fi.st_mode))
+ goto out;
+
+ len = fi.st_size + 1;
+ buff = malloc(len);
+ if (!buff)
+ goto out;
+
+ memset(buff, 0, len);
+ ret = read(fd, buff, len - 1);
+ if (ret <= 0)
+ goto out_free;
+
+ close(fd);
+ *klen = ret;
return buff;
+out_free:
+ free(buff);
+out:
+ close(fd);
+ return NULL;
+}
+
+static char *get_log_buff(const char *file, unsigned int *klen)
+{
+ return file ? get_flog_buff(file, klen) : get_klog_buff(klen);
}
-static void put_klog_buff(char *buff)
+static void put_log_buff(char *buff)
{
free(buff);
}
-static int get_last_jit_image(char *haystack, size_t hlen,
- uint8_t *image, size_t ilen)
+static unsigned int get_last_jit_image(char *haystack, size_t hlen,
+ uint8_t *image, size_t ilen)
{
char *ptr, *pptr, *tmp;
off_t off = 0;
@@ -138,8 +189,10 @@ static int get_last_jit_image(char *haystack, size_t hlen,
ptr = haystack + off - (pmatch[0].rm_eo - pmatch[0].rm_so);
ret = sscanf(ptr, "flen=%d proglen=%d pass=%d image=%lx",
&flen, &proglen, &pass, &base);
- if (ret != 4)
+ if (ret != 4) {
+ regfree(&regex);
return 0;
+ }
tmp = ptr = haystack + off;
while ((ptr = strtok(tmp, "\n")) != NULL && ulen < ilen) {
@@ -169,31 +222,49 @@ static int get_last_jit_image(char *haystack, size_t hlen,
return ulen;
}
+static void usage(void)
+{
+ printf("Usage: bpf_jit_disasm [...]\n");
+ printf(" -o Also display related opcodes (default: off).\n");
+ printf(" -f <file> Read last image dump from file or stdin (default: klog).\n");
+ printf(" -h Display this help.\n");
+}
+
int main(int argc, char **argv)
{
- int len, klen, opcodes = 0;
- char *kbuff;
+ unsigned int len, klen, opt, opcodes = 0;
static uint8_t image[32768];
+ char *kbuff, *file = NULL;
- if (argc > 1) {
- if (!strncmp("-o", argv[argc - 1], 2)) {
+ while ((opt = getopt(argc, argv, "of:")) != -1) {
+ switch (opt) {
+ case 'o':
opcodes = 1;
- } else {
- printf("usage: bpf_jit_disasm [-o: show opcodes]\n");
- exit(0);
+ break;
+ case 'f':
+ file = optarg;
+ break;
+ default:
+ usage();
+ return -1;
}
}
bfd_init();
memset(image, 0, sizeof(image));
- kbuff = get_klog_buff(&klen);
+ kbuff = get_log_buff(file, &klen);
+ if (!kbuff) {
+ fprintf(stderr, "Could not retrieve log buffer!\n");
+ return -1;
+ }
len = get_last_jit_image(kbuff, klen, image, sizeof(image));
if (len > 0)
get_asm_insns(image, len, opcodes);
+ else
+ fprintf(stderr, "No JIT image found!\n");
- put_klog_buff(kbuff);
-
+ put_log_buff(kbuff);
return 0;
}