32x: interpreter-wrap drc works (demos only). SVP drc refactoring.
[libpicofe.git] / linux / host_dasm.c
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
10 extern char **g_argv;
11
12 static struct disassemble_info di;
13
14 /* symbols */
15 static asymbol **symbols;
16 static long symcount;
17
18 /* Filter out (in place) symbols that are useless for disassembly.
19    COUNT is the number of elements in SYMBOLS.
20    Return the number of useful symbols.  */
21 static long
22 remove_useless_symbols (asymbol **symbols, long count)
23 {
24   asymbol **in_ptr = symbols, **out_ptr = symbols;
25
26   while (--count >= 0)
27     {
28       asymbol *sym = *in_ptr++;
29
30       if (sym->name == NULL || sym->name[0] == '\0')
31         continue;
32       if (sym->flags & (BSF_DEBUGGING | BSF_SECTION_SYM))
33         continue;
34       if (bfd_is_und_section (sym->section)
35           || bfd_is_com_section (sym->section))
36         continue;
37       if (sym->value + sym->section->vma == 0)
38         continue;
39 /*
40       printf("sym: %08lx %04x %08x v %08x \"%s\"\n",
41         (unsigned int)sym->value, (unsigned int)sym->flags, (unsigned int)sym->udata.i,
42         (unsigned int)sym->section->vma, sym->name);
43 */
44       *out_ptr++ = sym;
45     }
46   return out_ptr - symbols;
47 }
48
49 static void slurp_symtab(const char *filename)
50 {
51   bfd *abfd;
52   long storage;
53
54   symcount = 0;
55
56   abfd = bfd_openr(filename, NULL);
57   if (abfd == NULL) {
58     fprintf(stderr, "failed to open: %s\n", filename);
59     goto no_symbols;
60   }
61
62   if (!bfd_check_format(abfd, bfd_object))
63     goto no_symbols;
64
65   if (!(bfd_get_file_flags(abfd) & HAS_SYMS))
66     goto no_symbols;
67
68   storage = bfd_get_symtab_upper_bound(abfd);
69   if (storage <= 0)
70     goto no_symbols;
71
72   symbols = malloc(storage);
73   symcount = bfd_canonicalize_symtab(abfd, symbols);
74   if (symcount < 0)
75     goto no_symbols;
76
77   symcount = remove_useless_symbols(symbols, symcount);
78 //  bfd_close(abfd);
79   return;
80
81 no_symbols:
82   fprintf(stderr, "no symbols in %s\n", bfd_get_filename(abfd));
83   if (abfd != NULL)
84     bfd_close(abfd);
85 }
86
87
88 /* Like target_read_memory, but slightly different parameters.  */
89 static int
90 dis_asm_read_memory(bfd_vma memaddr, bfd_byte *myaddr, unsigned int len,
91                      struct disassemble_info *info)
92 {
93   memcpy(myaddr, (void *)(int)memaddr, len);
94   return 0;
95 }
96
97 static void
98 dis_asm_memory_error(int status, bfd_vma memaddr,
99                       struct disassemble_info *info)
100 {
101   fprintf(stderr, "memory_error %p\n", (void *)(int)memaddr);
102 }
103
104 static void
105 dis_asm_print_address(bfd_vma addr, struct disassemble_info *info)
106 {
107   asymbol **sptr = symbols;
108   int i;
109
110   printf("%08x", (int)addr);
111
112   for (i = 0; i < symcount; i++) {
113     asymbol *sym = *sptr++;
114
115     if (addr == sym->value + sym->section->vma) {
116       printf(" <%s>", sym->name);
117       break;
118     }
119   }
120 }
121
122 static int insn_printf(void *f, const char *format, ...)
123 {
124   va_list args;
125   size_t n;
126
127   va_start(args, format);
128   n = vprintf(format, args);
129   va_end(args);
130
131   return n;
132 }
133
134 static void host_dasm_init(void)
135 {
136   slurp_symtab(g_argv[0]);
137
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_i386;
145   di.mach = bfd_mach_i386_i386_intel_syntax;
146   di.endian = BFD_ENDIAN_LITTLE;
147   disassemble_init_for_target(&di);
148 }
149
150 void host_dasm(void *addr, int len)
151 {
152   bfd_vma vma_end, vma = (bfd_vma)(int)addr;
153   static int init_done = 0;
154
155   if (!init_done) {
156     host_dasm_init();
157     init_done = 1;
158   }
159
160   vma_end = vma + len;
161   while (vma < vma_end) {
162     printf("  %p ", (void *)(long)vma);
163     vma += print_insn_i386_intel(vma, &di);
164     printf("\n");
165   }
166 }
167