disas-common.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. * Common routines for disassembly.
  3. * SPDX-License-Identifier: GPL-2.0-or-later
  4. */
  5. #include "qemu/osdep.h"
  6. #include "disas/disas.h"
  7. #include "disas/capstone.h"
  8. #include "hw/core/cpu.h"
  9. #include "disas-internal.h"
  10. /* Filled in by elfload.c. Simplistic, but will do for now. */
  11. struct syminfo *syminfos = NULL;
  12. /*
  13. * Print an error message. We can assume that this is in response to
  14. * an error return from {host,target}_read_memory.
  15. */
  16. static void perror_memory(int status, bfd_vma memaddr,
  17. struct disassemble_info *info)
  18. {
  19. if (status != EIO) {
  20. /* Can't happen. */
  21. info->fprintf_func(info->stream, "Unknown error %d\n", status);
  22. } else {
  23. /* Address between memaddr and memaddr + len was out of bounds. */
  24. info->fprintf_func(info->stream,
  25. "Address 0x%" PRIx64 " is out of bounds.\n",
  26. memaddr);
  27. }
  28. }
  29. /* Print address in hex. */
  30. static void print_address(bfd_vma addr, struct disassemble_info *info)
  31. {
  32. info->fprintf_func(info->stream, "0x%" PRIx64, addr);
  33. }
  34. /* Stub prevents some fruitless earching in optabs disassemblers. */
  35. static int symbol_at_address(bfd_vma addr, struct disassemble_info *info)
  36. {
  37. return 1;
  38. }
  39. void disas_initialize_debug(CPUDebug *s)
  40. {
  41. memset(s, 0, sizeof(*s));
  42. s->info.arch = bfd_arch_unknown;
  43. s->info.cap_arch = -1;
  44. s->info.cap_insn_unit = 4;
  45. s->info.cap_insn_split = 4;
  46. s->info.memory_error_func = perror_memory;
  47. s->info.symbol_at_address_func = symbol_at_address;
  48. }
  49. void disas_initialize_debug_target(CPUDebug *s, CPUState *cpu)
  50. {
  51. disas_initialize_debug(s);
  52. s->cpu = cpu;
  53. s->info.print_address_func = print_address;
  54. s->info.endian = BFD_ENDIAN_UNKNOWN;
  55. if (cpu->cc->disas_set_info) {
  56. cpu->cc->disas_set_info(cpu, &s->info);
  57. g_assert(s->info.endian != BFD_ENDIAN_UNKNOWN);
  58. }
  59. }
  60. int disas_gstring_printf(FILE *stream, const char *fmt, ...)
  61. {
  62. /* We abuse the FILE parameter to pass a GString. */
  63. GString *s = (GString *)stream;
  64. int initial_len = s->len;
  65. va_list va;
  66. va_start(va, fmt);
  67. g_string_append_vprintf(s, fmt, va);
  68. va_end(va);
  69. return s->len - initial_len;
  70. }
  71. /* Look up symbol for debugging purpose. Returns "" if unknown. */
  72. const char *lookup_symbol(uint64_t orig_addr)
  73. {
  74. const char *symbol = "";
  75. struct syminfo *s;
  76. for (s = syminfos; s; s = s->next) {
  77. symbol = s->lookup_symbol(s, orig_addr);
  78. if (symbol[0] != '\0') {
  79. break;
  80. }
  81. }
  82. return symbol;
  83. }