starting a plugin
[ia32rtools.git] / plugin / saveasm.cpp
1 #define NO_OBSOLETE_FUNCS
2 #include <ida.hpp>
3 #include <idp.hpp>
4 #include <bytes.hpp>
5 #include <loader.hpp>
6 #include <kernwin.hpp>
7
8 #include <name.hpp>
9 #include <frame.hpp>
10 #include <struct.hpp>
11 #include <auto.hpp>
12
13 #define IS_START(w, y) !strncmp(w, y, strlen(y))
14 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
15
16 //--------------------------------------------------------------------------
17 static int idaapi init(void)
18 {
19   return PLUGIN_OK;
20 }
21
22 //--------------------------------------------------------------------------
23 static void idaapi term(void)
24 {
25 }
26
27 //--------------------------------------------------------------------------
28
29 static const char *reserved_names[] = {
30   "name",
31   "offset",
32 };
33
34 static int is_name_reserved(const char *name)
35 {
36   int i;
37   for (i = 0; i < ARRAY_SIZE(reserved_names); i++)
38     if (strcasecmp(name, reserved_names[i]) == 0)
39       return 1;
40
41   return 0;
42 }
43
44 static void do_def_line(char *buf, size_t buf_size, const char *line)
45 {
46   int len;
47
48   tag_remove(line, buf, buf_size); // remove color codes
49   len = strlen(buf);
50   if (len < 9) {
51     buf[0] = 0;
52     return;
53   }
54   memmove(buf, buf + 9, len - 9 + 1); // rm address
55 }
56
57 static void idaapi run(int /*arg*/)
58 {
59   //  isEnabled(ea) // address belongs to disassembly
60   // ea_t ea = get_screen_ea();
61   // nextaddr(ea) - no worky?
62   FILE *fout = NULL;
63   int fout_line = 0;
64   char buf[MAXSTR];
65   struc_t *frame;
66   func_t *func;
67   ea_t ui_ea_block = 0;
68   ea_t tmp_ea;
69   ea_t ea;
70   int i, o, m, n;
71   int ret;
72   char *p;
73
74   // rename global syms which conflict with frame member names
75   ea = inf.minEA;
76   func = get_next_func(ea);
77   while (func != NULL)
78   {
79     frame = get_frame(func);
80     if (frame != NULL)
81     {
82       for (m = 0; m < (int)frame->memqty; m++)
83       {
84         ret = get_member_name(frame->members[m].id, buf, sizeof(buf));
85         if (ret <= 0) {
86           msg("%x: member has no name?\n", ea);
87           return;
88         }
89         if (buf[0] == ' ') // what's this?
90           continue;
91         if (IS_START(buf, "arg_") || IS_START(buf, "var_"))
92           continue;
93
94         if (is_name_reserved(buf)) {
95           msg("%x: renaming '%s'\n", ea, buf);
96           qstrncat(buf, "_", sizeof(buf));
97           ret = set_member_name(frame, frame->members[m].soff, buf);
98           if (!ret) {
99             msg("%x: renaming failed\n", ea);
100             return;
101           }
102         }
103
104         tmp_ea = get_name_ea(ea, buf);
105         if (tmp_ea == 0 || tmp_ea == ~0)
106           continue;
107
108         msg("%x: from %x: renaming '%s'\n", tmp_ea, ea, buf);
109         qstrncat(buf, "_g", sizeof(buf));
110         set_name(tmp_ea, buf);
111       }
112     }
113
114     func = get_next_func(ea);
115     if (func)
116       ea = get_next_func_addr(func, ea);
117   }
118
119   char *fname = askfile_c(1, NULL, "Save asm file");
120   if (fname == NULL)
121     return;
122   fout = qfopen(fname, "w");
123   if (fout == NULL) {
124     msg("couldn't open '%s'\n", fname);
125     return;
126   }
127
128   show_wait_box("Saving..");
129
130   // deal with the beginning
131   ea = inf.minEA;
132   int flags = 0; // calc_default_idaplace_flags();
133   linearray_t ln(&flags);
134   idaplace_t pl;
135   pl.ea = ea;
136   pl.lnnum = 0;
137   ln.set_place(&pl);
138   n = ln.get_linecnt();
139   for (i = 0; i < n - 1; i++) {
140     do_def_line(buf, sizeof(buf), ln.down());
141     if (strstr(buf, "include"))
142       continue;
143
144     fout_line++;
145     qfprintf(fout, "%s\n", buf);
146     p = strstr(buf, ".mmx");
147     if (p != NULL) {
148       memcpy(p, ".xmm", 4);
149       fout_line++;
150       qfprintf(fout, "%s\n", buf);
151     }
152   }
153
154   for (;;)
155   {
156     if ((ea >> 14) != ui_ea_block) {
157       ui_ea_block = ea >> 14;
158       showAddr(ea);
159       if (wasBreak())
160         break;
161     }
162
163     segment_t *seg = getseg(ea);
164     if (!seg || seg->type != SEG_CODE)
165       goto pass;
166     if (!decode_insn(ea))
167       goto pass;
168
169     // note: decode_insn() picks up things like dd, size is then weird
170     //cmd_size = cmd.size;
171
172     for (o = 0; o < UA_MAXOP; o++) {
173       if (cmd.Operands[o].type == o_void)
174         break;
175
176     }
177
178 pass:
179     fout_line++;
180     do_def_line(buf, sizeof(buf), ln.down());
181     qfprintf(fout, "%s\n", buf);
182
183     ea = next_not_tail(ea); // correct?
184     if (ea == 0 || ea == ~0)
185       break;
186
187     pl.ea = ea;
188     pl.lnnum = 0;
189     ln.set_place(&pl);
190     n = ln.get_linecnt();
191     for (i = 0; i < n - 1; i++)
192     {
193       fout_line++;
194       do_def_line(buf, sizeof(buf), ln.down());
195       qfprintf(fout, "%s\n", buf);
196     }
197   }
198
199   if (fout != NULL)
200     qfclose(fout);
201
202   hide_wait_box();
203   msg("%d lines saved.\n", fout_line);
204 }
205
206 //--------------------------------------------------------------------------
207
208 static const char comment[] = "Generate disassembly lines for one address";
209 static const char help[] = "Generate asm file\n";
210 static const char wanted_name[] = "Save asm";
211 static const char wanted_hotkey[] = "Ctrl-F6";
212
213 //--------------------------------------------------------------------------
214 //
215 //      PLUGIN DESCRIPTION BLOCK
216 //
217 //--------------------------------------------------------------------------
218 plugin_t PLUGIN =
219 {
220   IDP_INTERFACE_VERSION,
221   0,                    // plugin flags
222   init,                 // initialize
223   term,                 // terminate. this pointer may be NULL.
224   run,                  // invoke plugin
225   comment,              // long comment about the plugin
226                         // it could appear in the status line
227                         // or as a hint
228   help,                 // multiline help about the plugin
229   wanted_name,          // the preferred short name of the plugin
230   wanted_hotkey         // the preferred hotkey to run the plugin
231 };
232
233 // vim:ts=2:shiftwidth=2:expandtab