X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=plugin%2Fsaveasm.cpp;h=bfe7e364c1b68203096ddc35787510baf22f8c47;hb=66bdb2b07a1f50833ad79ea71a378dafd79030e6;hp=3622cc8e0c893f7d4a60d65a4b98b726f141b659;hpb=b25f320a4cbf26d2b28d9f74ff7c495516a710d0;p=ia32rtools.git diff --git a/plugin/saveasm.cpp b/plugin/saveasm.cpp index 3622cc8..bfe7e36 100644 --- a/plugin/saveasm.cpp +++ b/plugin/saveasm.cpp @@ -1,3 +1,11 @@ +/* + * ia32rtools + * (C) notaz, 2013,2014 + * + * This work is licensed under the terms of 3-clause BSD license. + * See COPYING file in the top-level directory. + */ + #define NO_OBSOLETE_FUNCS #include #include @@ -8,12 +16,16 @@ #include #include #include +#include #include #include #define IS_START(w, y) !strncmp(w, y, strlen(y)) #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +static char **name_cache; +static size_t name_cache_size; + // non-local branch targets static ea_t *nonlocal_bt; static int nonlocal_bt_alloc; @@ -28,11 +40,21 @@ static int idaapi init(void) //-------------------------------------------------------------------------- static void idaapi term(void) { + size_t i; + if (nonlocal_bt != NULL) { free(nonlocal_bt); nonlocal_bt = NULL; } nonlocal_bt_alloc = 0; + + if (name_cache != NULL) { + for (i = 0; i < name_cache_size; i++) + free(name_cache[i]); + free(name_cache); + name_cache = NULL; + } + name_cache_size = 0; } //-------------------------------------------------------------------------- @@ -43,6 +65,9 @@ static const char *reserved_names[] = { "offset", "aam", "text", + "size", + "c", + "align", }; static int is_name_reserved(const char *name) @@ -111,10 +136,84 @@ static void do_def_line(char *buf, size_t buf_size, const char *line, } } +static int name_cache_cmp(const void *p1, const void *p2) +{ + // masm ignores case, so do we + return stricmp(*(char * const *)p1, *(char * const *)p2); +} + +static void rebuild_name_cache(void) +{ + size_t i, newsize; + void *tmp; + + // build a sorted name cache + newsize = get_nlist_size(); + if (newsize > name_cache_size) { + tmp = realloc(name_cache, newsize * sizeof(name_cache[0])); + if (tmp == NULL) { + msg("OOM for name cache\n"); + return; + } + name_cache = (char **)tmp; + } + for (i = 0; i < name_cache_size; i++) + free(name_cache[i]); + for (i = 0; i < newsize; i++) + name_cache[i] = strdup(get_nlist_name(i)); + + name_cache_size = newsize; + qsort(name_cache, name_cache_size, sizeof(name_cache[0]), + name_cache_cmp); +} + +static void my_rename(ea_t ea, char *name) +{ + char buf[256]; + char *p, **pp; + int n = 0; + + qsnprintf(buf, sizeof(buf), "%s", name); + do { + p = buf; + pp = (char **)bsearch(&p, name_cache, name_cache_size, + sizeof(name_cache[0]), name_cache_cmp); + if (pp == NULL) + break; + + qsnprintf(buf, sizeof(buf), "%s_g%d", name, n); + n++; + } + while (n < 100); + + if (n == 100) + msg("rename failure? '%s'\n", name); + + do_name_anyway(ea, buf); + rebuild_name_cache(); +} + +static void make_align(ea_t ea) +{ + ea_t tmp_ea; + int n; + + tmp_ea = next_head(ea, inf.maxEA); + if ((tmp_ea & 0x03) == 0) { + n = calc_max_align(tmp_ea); + if (n > 4) // masm doesn't like more.. + n = 4; + msg("%x: align %d\n", ea, 1 << n); + do_unknown(ea, DOUNK_SIMPLE); + doAlign(ea, tmp_ea - ea, n); + } +} + static void idaapi run(int /*arg*/) { // isEnabled(ea) // address belongs to disassembly // ea_t ea = get_screen_ea(); + // extern foo; // foo = DecodeInstruction(ScreenEA()); FILE *fout = NULL; int fout_line = 0; @@ -130,6 +229,7 @@ static void idaapi run(int /*arg*/) uval_t idx; int i, o, m, n; int ret; + char **pp; char *p; nonlocal_bt_cnt = 0; @@ -147,8 +247,11 @@ static void idaapi run(int /*arg*/) idx = get_first_struc_idx(); } + rebuild_name_cache(); + // 1st pass: walk through all funcs - func = get_func(inf.minEA); + ea = inf.minEA; + func = get_func(ea); while (func != NULL) { func_tail_iterator_t fti(func); @@ -193,13 +296,16 @@ static void idaapi run(int /*arg*/) } } - tmp_ea = get_name_ea(ea, buf); - if (tmp_ea == 0 || tmp_ea == ~0) + p = buf; + pp = (char **)bsearch(&p, name_cache, name_cache_size, + sizeof(name_cache[0]), name_cache_cmp); + if (pp == NULL) continue; - msg("%x: from %x: renaming '%s'\n", tmp_ea, ea, buf); - qstrncat(buf, "_g", sizeof(buf)); - set_name(tmp_ea, buf); + tmp_ea = get_name_ea(BADADDR, *pp); + msg("%x: renaming '%s' because of '%s' at %x\n", + tmp_ea, *pp, buf, ea); + my_rename(tmp_ea, *pp); } } @@ -237,7 +343,10 @@ static void idaapi run(int /*arg*/) if (cmd.Operands[o].type == o_mem) { tmp_ea = cmd.Operands[o].addr; flags_t tmp_ea_flags = get_flags_novalue(tmp_ea); - if (!isUnknown(tmp_ea_flags)) { + // ..but base float is ok.. + int is_flt = isDwrd(tmp_ea_flags) || isFloat(tmp_ea_flags); + if (!is_flt && !isUnknown(tmp_ea_flags)) + { buf[0] = 0; get_name(ea, tmp_ea, buf, sizeof(buf)); msg("%x: undefining %x '%s'\n", ea, tmp_ea, buf); @@ -246,23 +355,43 @@ static void idaapi run(int /*arg*/) } } } - // detect code alignment else if (cmd.itype == NN_lea) { + // detect code alignment if (cmd.Operands[0].reg == cmd.Operands[1].reg && cmd.Operands[1].type == o_displ && cmd.Operands[1].addr == 0) { - tmp_ea = next_head(ea, inf.maxEA); - if ((tmp_ea & 0x03) == 0) { - n = calc_max_align(tmp_ea); - if (n > 4) // masm doesn't like more.. - n = 4; - msg("%x: align %d\n", ea, 1 << n); - do_unknown(ea, DOUNK_SIMPLE); - doAlign(ea, tmp_ea - ea, n); + // lea eax, [eax+0] + make_align(ea); + } + else if (!isDefArg1(ea_flags) + && cmd.Operands[1].type == o_mem // why o_mem? + && cmd.Operands[1].dtyp == dt_dword) + { + if (inf.minEA <= cmd.Operands[1].addr + && cmd.Operands[1].addr < inf.maxEA) + { + // lea to segments, like ds:58D6A8h[edx*8] + msg("%x: lea offset to %x\n", ea, cmd.Operands[1].addr); + op_offset(ea, 1, REF_OFF32); + } + else + { + // ds:0[eax*8] -> [eax*8+0] + msg("%x: dropping ds: for %x\n", ea, cmd.Operands[1].addr); + op_hex(ea, 1); } } } + else if (cmd.itype == NN_mov && cmd.segpref == 0x1e // 2e? + && cmd.Operands[0].type == o_reg + && cmd.Operands[1].type == o_reg + && cmd.Operands[0].dtyp == cmd.Operands[1].dtyp + && cmd.Operands[0].reg == cmd.Operands[1].reg) + { + // db 2Eh; mov eax, eax + make_align(ea); + } // find non-local branches if (is_insn_jmp(cmd.itype) && cmd.Operands[0].type == o_near) @@ -341,7 +470,7 @@ static void idaapi run(int /*arg*/) if (change_qat || is_name_reserved(name)) { msg("%x: renaming name '%s'\n", ea, name); - qsnprintf(buf, sizeof(buf), "%s_g", name); + qsnprintf(buf, sizeof(buf), "%s", name); if (change_qat) { for (p = buf; *p != 0; p++) { @@ -353,7 +482,7 @@ static void idaapi run(int /*arg*/) } } - set_name(ea, buf); + my_rename(ea, buf); } } @@ -386,11 +515,6 @@ static void idaapi run(int /*arg*/) do_def_line(buf, sizeof(buf), ln.down(), ea); if (strstr(buf, "include")) continue; - p = strstr(buf, "assume cs"); - if (p != NULL) { - memmove(p + 1, p, strlen(p) + 1); - *p = ';'; - } fout_line++; qfprintf(fout, "%s\n", buf); @@ -406,15 +530,16 @@ static void idaapi run(int /*arg*/) qstrncpy(p, "include imports.inc", sizeof(buf) - (p - buf)); fout_line++; qfprintf(fout, "\n%s\n", buf); - continue; + i++; + break; } } pl.lnnum = i; for (;;) { - int drop_large = 0, drop_rva = 0, set_scale = 0, jmp_near = 0; - int word_imm = 0, dword_imm = 0, do_pushf = 0; + int drop_large = 0, do_rva = 0, set_scale = 0, jmp_near = 0; + int word_imm = 0, dword_imm = 0, do_pushf = 0, do_nops = 0; if ((ea >> 14) != ui_ea_block) { ui_ea_block = ea >> 14; @@ -472,11 +597,17 @@ static void idaapi run(int /*arg*/) if (get_word(ea + opr.offb) == (ushort)opr.value) word_imm = 1; } + else if (opr.type == o_displ && opr.addr == 0 + && opr.offb != 0 && opr.hasSIB && opr.sib == 0x24) + { + // uses [esp+0] with 0 encoded into op + do_nops++; + } } } else { // not code if (isOff0(ea_flags)) - drop_rva = 1; + do_rva = 1; } pass: @@ -494,11 +625,12 @@ pass: if (p != NULL) memmove(p, p + 6, strlen(p + 6) + 1); } - while (drop_rva) { + while (do_rva) { p = strstr(fw, " rva "); if (p == NULL) break; - memmove(p, p + 4, strlen(p + 4) + 1); + memmove(p + 4 + 3, p + 4, strlen(p + 4) + 1); + memcpy(p + 1, "offset", 6); } if (set_scale) { p = strchr(fw, '['); @@ -513,7 +645,9 @@ pass: } } else if (jmp_near) { - p = strchr(fw, 'j'); + p = NULL; + if (fw != buf && fw[0] == 'j') + p = fw; while (p && *p != ' ') p++; while (p && *p == ' ') @@ -521,6 +655,7 @@ pass: if (p != NULL) { memmove(p + 9, p, strlen(p) + 1); memcpy(p, "near ptr ", 9); + jmp_near = 0; } } if (word_imm) { @@ -550,7 +685,12 @@ pass: } } - if (fw[0] == 'e' && IS_START(fw, "end") && fw[3] == ' ') { + if (fw[0] == 'a' && IS_START(fw, "assume cs")) { + // "assume cs" causes problems with ext syms + memmove(fw + 1, fw, strlen(fw) + 1); + *fw = ';'; + } + else if (fw[0] == 'e' && IS_START(fw, "end") && fw[3] == ' ') { fout_line++; qfprintf(fout, "include public.inc\n\n"); @@ -562,6 +702,9 @@ pass: qfprintf(fout, "%s\n", buf); } + while (do_nops-- > 0) + qfprintf(fout, " nop ; adj\n"); + // note: next_head skips some undefined stuff ea = next_not_tail(ea); // correct? if (ea == BADADDR)