starting a plugin
[ia32rtools.git] / plugin / saveasm.cpp
CommitLineData
d8891fcc 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//--------------------------------------------------------------------------
17static int idaapi init(void)
18{
19 return PLUGIN_OK;
20}
21
22//--------------------------------------------------------------------------
23static void idaapi term(void)
24{
25}
26
27//--------------------------------------------------------------------------
28
29static const char *reserved_names[] = {
30 "name",
31 "offset",
32};
33
34static 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
44static 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
57static 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
178pass:
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
208static const char comment[] = "Generate disassembly lines for one address";
209static const char help[] = "Generate asm file\n";
210static const char wanted_name[] = "Save asm";
211static const char wanted_hotkey[] = "Ctrl-F6";
212
213//--------------------------------------------------------------------------
214//
215// PLUGIN DESCRIPTION BLOCK
216//
217//--------------------------------------------------------------------------
218plugin_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