X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=plugin%2Fsaveasm.cpp;h=bfe7e364c1b68203096ddc35787510baf22f8c47;hb=4e81a3a2e191ccf8498da6d23e96c03fc8b36c83;hp=0732e092c0148d2bccb134ce710caeee0cef3a33;hpb=fc1c61f5af4e34ed1a813cfdcbe4b9f1b585763c;p=ia32rtools.git diff --git a/plugin/saveasm.cpp b/plugin/saveasm.cpp index 0732e09..bfe7e36 100644 --- a/plugin/saveasm.cpp +++ b/plugin/saveasm.cpp @@ -23,6 +23,9 @@ #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; @@ -37,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; } //-------------------------------------------------------------------------- @@ -54,6 +67,7 @@ static const char *reserved_names[] = { "text", "size", "c", + "align", }; static int is_name_reserved(const char *name) @@ -122,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; @@ -141,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; @@ -158,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); @@ -204,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); } } @@ -248,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); @@ -263,15 +361,8 @@ static void idaapi run(int /*arg*/) && 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? @@ -292,6 +383,15 @@ static void idaapi run(int /*arg*/) } } } + 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) @@ -370,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++) { @@ -382,7 +482,7 @@ static void idaapi run(int /*arg*/) } } - set_name(ea, buf); + my_rename(ea, buf); } } @@ -439,7 +539,7 @@ static void idaapi run(int /*arg*/) for (;;) { int drop_large = 0, do_rva = 0, set_scale = 0, jmp_near = 0; - int word_imm = 0, dword_imm = 0, do_pushf = 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; @@ -497,6 +597,12 @@ 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 @@ -539,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 == ' ') @@ -547,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) { @@ -593,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)