host_dasm.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * PicoDrive
  3. * (C) notaz, 2009,2010
  4. *
  5. * This work is licensed under the terms of MAME license.
  6. * See COPYING file in the top-level directory.
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <stdarg.h>
  12. #include <bfd.h>
  13. #include <dis-asm.h>
  14. #include "host_dasm.h"
  15. extern char **g_argv;
  16. static struct disassemble_info di;
  17. #ifdef __arm__
  18. #define print_insn_func print_insn_little_arm
  19. #define BFD_ARCH bfd_arch_arm
  20. #define BFD_MACH bfd_mach_arm_4T
  21. #else
  22. #define print_insn_func print_insn_i386_intel
  23. #define BFD_ARCH bfd_arch_i386
  24. #define BFD_MACH bfd_mach_i386_i386_intel_syntax
  25. #endif
  26. /* symbols */
  27. static asymbol **symbols;
  28. static long symcount, symstorage;
  29. static int init_done;
  30. /* Filter out (in place) symbols that are useless for disassembly.
  31. COUNT is the number of elements in SYMBOLS.
  32. Return the number of useful symbols. */
  33. static long
  34. remove_useless_symbols (asymbol **symbols, long count)
  35. {
  36. asymbol **in_ptr = symbols, **out_ptr = symbols;
  37. while (--count >= 0)
  38. {
  39. asymbol *sym = *in_ptr++;
  40. if (sym->name == NULL || sym->name[0] == '\0' || sym->name[0] == '$')
  41. continue;
  42. if (sym->flags & (BSF_DEBUGGING | BSF_SECTION_SYM))
  43. continue;
  44. if (bfd_is_und_section (sym->section)
  45. || bfd_is_com_section (sym->section))
  46. continue;
  47. if (sym->value + sym->section->vma == 0)
  48. continue;
  49. /*
  50. printf("sym: %08lx %04x %08x v %08x \"%s\"\n",
  51. (unsigned int)sym->value, (unsigned int)sym->flags, (unsigned int)sym->udata.i,
  52. (unsigned int)sym->section->vma, sym->name);
  53. */
  54. *out_ptr++ = sym;
  55. }
  56. return out_ptr - symbols;
  57. }
  58. static void slurp_symtab(const char *filename)
  59. {
  60. bfd *abfd;
  61. symcount = 0;
  62. abfd = bfd_openr(filename, NULL);
  63. if (abfd == NULL) {
  64. fprintf(stderr, "failed to open: %s\n", filename);
  65. goto no_symbols;
  66. }
  67. if (!bfd_check_format(abfd, bfd_object))
  68. goto no_symbols;
  69. if (!(bfd_get_file_flags(abfd) & HAS_SYMS))
  70. goto no_symbols;
  71. symstorage = bfd_get_symtab_upper_bound(abfd);
  72. if (symstorage <= 0)
  73. goto no_symbols;
  74. symbols = malloc(symstorage);
  75. if (symbols == NULL)
  76. goto no_symbols;
  77. symcount = bfd_canonicalize_symtab(abfd, symbols);
  78. if (symcount < 0)
  79. goto no_symbols;
  80. symcount = remove_useless_symbols(symbols, symcount);
  81. // bfd_close(abfd);
  82. return;
  83. no_symbols:
  84. fprintf(stderr, "no symbols in %s\n", bfd_get_filename(abfd));
  85. if (symbols != NULL)
  86. free(symbols);
  87. symbols = NULL;
  88. if (abfd != NULL)
  89. bfd_close(abfd);
  90. }
  91. static const char *lookup_name(bfd_vma addr)
  92. {
  93. asymbol **sptr = symbols;
  94. int i;
  95. for (i = 0; i < symcount; i++) {
  96. asymbol *sym = *sptr++;
  97. if (addr == sym->value + sym->section->vma)
  98. return sym->name;
  99. }
  100. return NULL;
  101. }
  102. /* Like target_read_memory, but slightly different parameters. */
  103. static int
  104. dis_asm_read_memory(bfd_vma memaddr, bfd_byte *myaddr, unsigned int len,
  105. struct disassemble_info *info)
  106. {
  107. memcpy(myaddr, (void *)(int)memaddr, len);
  108. return 0;
  109. }
  110. static void
  111. dis_asm_memory_error(int status, bfd_vma memaddr,
  112. struct disassemble_info *info)
  113. {
  114. fprintf(stderr, "memory_error %p\n", (void *)(int)memaddr);
  115. }
  116. static void
  117. dis_asm_print_address(bfd_vma addr, struct disassemble_info *info)
  118. {
  119. const char *name;
  120. printf("%08x", (int)addr);
  121. name = lookup_name(addr);
  122. if (name != NULL)
  123. printf(" <%s>", name);
  124. }
  125. static int insn_printf(void *f, const char *format, ...)
  126. {
  127. va_list args;
  128. size_t n;
  129. va_start(args, format);
  130. n = vprintf(format, args);
  131. va_end(args);
  132. return n;
  133. }
  134. static void host_dasm_init(void)
  135. {
  136. bfd_init();
  137. slurp_symtab(g_argv[0]);
  138. init_disassemble_info(&di, NULL, insn_printf);
  139. di.flavour = bfd_target_unknown_flavour;
  140. di.memory_error_func = dis_asm_memory_error;
  141. di.print_address_func = dis_asm_print_address;
  142. // di.symbol_at_address_func = dis_asm_symbol_at_address;
  143. di.read_memory_func = dis_asm_read_memory;
  144. di.arch = BFD_ARCH;
  145. di.mach = BFD_MACH;
  146. di.endian = BFD_ENDIAN_LITTLE;
  147. disassemble_init_for_target(&di);
  148. init_done = 1;
  149. }
  150. void host_dasm(void *addr, int len)
  151. {
  152. bfd_vma vma_end, vma = (bfd_vma)(long)addr;
  153. const char *name;
  154. if (!init_done)
  155. host_dasm_init();
  156. vma_end = vma + len;
  157. while (vma < vma_end) {
  158. name = lookup_name(vma);
  159. if (name != NULL)
  160. printf("%s:\n", name);
  161. printf(" %08lx ", (long)vma);
  162. vma += print_insn_func(vma, &di);
  163. printf("\n");
  164. }
  165. }
  166. void host_dasm_new_symbol_(void *addr, const char *name)
  167. {
  168. bfd_vma vma = (bfd_vma)(long)addr;
  169. asymbol *sym, **tmp;
  170. if (!init_done)
  171. host_dasm_init();
  172. if (symbols == NULL)
  173. return;
  174. if (symstorage <= symcount * sizeof(symbols[0])) {
  175. tmp = realloc(symbols, symstorage * 2);
  176. if (tmp == NULL)
  177. return;
  178. symstorage *= 2;
  179. symbols = tmp;
  180. }
  181. symbols[symcount] = calloc(sizeof(*symbols[0]), 1);
  182. if (symbols[symcount] == NULL)
  183. return;
  184. // a HACK (should use correct section), but ohwell
  185. sym = symbols[symcount];
  186. sym->section = symbols[0]->section;
  187. sym->value = vma - sym->section->vma;
  188. sym->name = name;
  189. symcount++;
  190. }