jit_disasm.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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. #include <stdarg.h>
  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. #include <limits.h>
  24. #include "json_writer.h"
  25. #include "main.h"
  26. static void get_exec_path(char *tpath, size_t size)
  27. {
  28. ssize_t len;
  29. char *path;
  30. snprintf(tpath, size, "/proc/%d/exe", (int) getpid());
  31. tpath[size - 1] = 0;
  32. path = strdup(tpath);
  33. assert(path);
  34. len = readlink(path, tpath, size - 1);
  35. assert(len > 0);
  36. tpath[len] = 0;
  37. free(path);
  38. }
  39. static int oper_count;
  40. static int fprintf_json(void *out, const char *fmt, ...)
  41. {
  42. va_list ap;
  43. char *s;
  44. va_start(ap, fmt);
  45. if (!oper_count) {
  46. int i;
  47. s = va_arg(ap, char *);
  48. /* Strip trailing spaces */
  49. i = strlen(s) - 1;
  50. while (s[i] == ' ')
  51. s[i--] = '\0';
  52. jsonw_string_field(json_wtr, "operation", s);
  53. jsonw_name(json_wtr, "operands");
  54. jsonw_start_array(json_wtr);
  55. oper_count++;
  56. } else if (!strcmp(fmt, ",")) {
  57. /* Skip */
  58. } else {
  59. s = va_arg(ap, char *);
  60. jsonw_string(json_wtr, s);
  61. oper_count++;
  62. }
  63. va_end(ap);
  64. return 0;
  65. }
  66. void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
  67. const char *arch)
  68. {
  69. disassembler_ftype disassemble;
  70. struct disassemble_info info;
  71. int count, i, pc = 0;
  72. char tpath[PATH_MAX];
  73. bfd *bfdf;
  74. if (!len)
  75. return;
  76. memset(tpath, 0, sizeof(tpath));
  77. get_exec_path(tpath, sizeof(tpath));
  78. bfdf = bfd_openr(tpath, NULL);
  79. assert(bfdf);
  80. assert(bfd_check_format(bfdf, bfd_object));
  81. if (json_output)
  82. init_disassemble_info(&info, stdout,
  83. (fprintf_ftype) fprintf_json);
  84. else
  85. init_disassemble_info(&info, stdout,
  86. (fprintf_ftype) fprintf);
  87. /* Update architecture info for offload. */
  88. if (arch) {
  89. const bfd_arch_info_type *inf = bfd_scan_arch(arch);
  90. if (inf) {
  91. bfdf->arch_info = inf;
  92. } else {
  93. p_err("No libfd support for %s", arch);
  94. return;
  95. }
  96. }
  97. info.arch = bfd_get_arch(bfdf);
  98. info.mach = bfd_get_mach(bfdf);
  99. info.buffer = image;
  100. info.buffer_length = len;
  101. disassemble_init_for_target(&info);
  102. #ifdef DISASM_FOUR_ARGS_SIGNATURE
  103. disassemble = disassembler(info.arch,
  104. bfd_big_endian(bfdf),
  105. info.mach,
  106. bfdf);
  107. #else
  108. disassemble = disassembler(bfdf);
  109. #endif
  110. assert(disassemble);
  111. if (json_output)
  112. jsonw_start_array(json_wtr);
  113. do {
  114. if (json_output) {
  115. jsonw_start_object(json_wtr);
  116. oper_count = 0;
  117. jsonw_name(json_wtr, "pc");
  118. jsonw_printf(json_wtr, "\"0x%x\"", pc);
  119. } else {
  120. printf("%4x:\t", pc);
  121. }
  122. count = disassemble(pc, &info);
  123. if (json_output) {
  124. /* Operand array, was started in fprintf_json. Before
  125. * that, make sure we have a _null_ value if no operand
  126. * other than operation code was present.
  127. */
  128. if (oper_count == 1)
  129. jsonw_null(json_wtr);
  130. jsonw_end_array(json_wtr);
  131. }
  132. if (opcodes) {
  133. if (json_output) {
  134. jsonw_name(json_wtr, "opcodes");
  135. jsonw_start_array(json_wtr);
  136. for (i = 0; i < count; ++i)
  137. jsonw_printf(json_wtr, "\"0x%02hhx\"",
  138. (uint8_t)image[pc + i]);
  139. jsonw_end_array(json_wtr);
  140. } else {
  141. printf("\n\t");
  142. for (i = 0; i < count; ++i)
  143. printf("%02x ",
  144. (uint8_t)image[pc + i]);
  145. }
  146. }
  147. if (json_output)
  148. jsonw_end_object(json_wtr);
  149. else
  150. printf("\n");
  151. pc += count;
  152. } while (count > 0 && pc < len);
  153. if (json_output)
  154. jsonw_end_array(json_wtr);
  155. bfd_close(bfdf);
  156. }