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