handle stuff, add funcs
[ia32rtools.git] / ida / saveasm / saveasm.cpp
index 5be0dda..ea09fc2 100644 (file)
@@ -64,10 +64,12 @@ static const char *reserved_names[] = {
   "type",
   "offset",
   "aam",
+  "aas",
   "text",
   "size",
   "c",
   "align",
+  "addr",
 };
 
 static int is_name_reserved(const char *name)
@@ -107,11 +109,14 @@ static int is_insn_jmp(uint16 itype)
 }
 
 static void do_def_line(char *buf, size_t buf_size, const char *line,
-  ea_t ea)
+  ea_t ea, func_t *func)
 {
+  char func_name[256] = "<nf>";
+  int is_libfunc = 0;
+  int global_label;
   ea_t *ea_ret;
+  int i, len;
   char *p;
-  int len;
 
   tag_remove(line, buf, buf_size); // remove color codes
   len = strlen(buf);
@@ -127,7 +132,22 @@ static void do_def_line(char *buf, size_t buf_size, const char *line,
   if (*p == ':') {
     ea_ret = (ea_t *)bsearch(&ea, nonlocal_bt, nonlocal_bt_cnt,
       sizeof(nonlocal_bt[0]), nonlocal_bt_cmp);
-    if (ea_ret != 0) {
+    global_label = (ea_ret != NULL);
+    if (!global_label) {
+      if (func != NULL) {
+        get_func_name(ea, func_name, sizeof(func_name));
+        is_libfunc = func->flags & FUNC_LIB;
+      }
+      for (i = 0; i < get_item_size(ea); i++) {
+        xrefblk_t xb;
+        if (xb.first_to(ea + i, XREF_DATA)) {
+          if (!is_libfunc && xb.type == dr_O)
+            msg("%x: offset xref in %s\n", ea, func_name);
+          global_label = 1;
+        }
+      }
+    }
+    if (global_label) {
       if (p[1] != ' ')
         msg("no trailing blank in '%s'\n", buf);
       else
@@ -220,6 +240,7 @@ static void idaapi run(int /*arg*/)
   char buf[MAXSTR];
   char buf2[MAXSTR];
   const char *name;
+  const char *cp;
   struc_t *frame;
   func_t *func;
   ea_t ui_ea_block = 0, ea_size;
@@ -309,6 +330,18 @@ static void idaapi run(int /*arg*/)
       }
     }
 
+    // detect tailcalls to next func with 'jmp $+5' (offset 0)
+    if (f_area.endEA - f_area.startEA >= 5
+      && decode_insn(f_area.endEA - 5) && cmd.itype == NN_jmp
+      && cmd.Operands[0].type == o_near
+      && cmd.Operands[0].addr == f_area.endEA
+      && get_name(BADADDR, f_area.endEA, buf, sizeof(buf))
+      && get_cmt(f_area.endEA - 5, false, buf2, sizeof(buf2)) <= 0)
+    {
+      qsnprintf(buf2, sizeof(buf2), "sctpatch: jmp %s", buf);
+      set_cmt(f_area.endEA - 5, buf2, false);
+    }
+
     func = get_next_func(ea);
   }
 
@@ -342,14 +375,18 @@ 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);
-            // ..but base float is ok..
-            int is_flt = isDwrd(tmp_ea_flags) || isFloat(tmp_ea_flags);
-            if (!is_flt && !isUnknown(tmp_ea_flags))
+            flags_t tmp_flg = get_flags_novalue(tmp_ea);
+            buf[0] = 0;
+            if (isDouble(tmp_flg))
+            {
+              get_name(ea, tmp_ea, buf, sizeof(buf));
+              msg("%x: converting dbl %x '%s'\n", ea, tmp_ea, buf);
+              doQwrd(tmp_ea, 8);
+            }
+            if (isOwrd(tmp_flg) || isYwrd(tmp_flg) || isTbyt(tmp_flg))
             {
-              buf[0] = 0;
               get_name(ea, tmp_ea, buf, sizeof(buf));
-              msg("%x: undefining %x '%s'\n", ea, tmp_ea, buf);
+              msg("%x: undefining lrg %x '%s'\n", ea, tmp_ea, buf);
               do_unknown(tmp_ea, DOUNK_EXPAND);
             }
           }
@@ -420,8 +457,12 @@ static void idaapi run(int /*arg*/)
       }
 
       // IDA vs masm float/mmx/xmm type incompatibility
-      if (isDouble(ea_flags) || isTbyt(ea_flags)
-       || isPackReal(ea_flags))
+      if (isDouble(ea_flags))
+      {
+        msg("%x: converting double\n", ea);
+        doQwrd(ea, 8);
+      }
+      else if (isTbyt(ea_flags) || isPackReal(ea_flags))
       {
         do_undef = 1;
       }
@@ -438,7 +479,8 @@ static void idaapi run(int /*arg*/)
         do_undef = 1;
       }
       // masm doesn't understand large aligns
-      else if (isAlign(ea_flags) && ea_size > 0x10) {
+      else if (isAlign(ea_flags) && ea_size >= 0x10)
+      {
         msg("%x: undefining align %d\n", ea, ea_size);
         do_unknown(ea, DOUNK_EXPAND);
       }
@@ -452,7 +494,8 @@ static void idaapi run(int /*arg*/)
     }
   }
 
-  // check namelist for reserved names
+  // check namelist for reserved names and
+  // matching names with different case (nasm ignores case)
   n = get_nlist_size();
   for (i = 0; i < n; i++) {
     ea = get_nlist_ea(i);
@@ -461,16 +504,44 @@ static void idaapi run(int /*arg*/)
       msg("%x: null name?\n", ea);
       continue;
     }
+    qsnprintf(buf, sizeof(buf), "%s", name);
+
+    int need_rename = is_name_reserved(name);
+    if (!need_rename) {
+      p = buf;
+      pp = (char **)bsearch(&p, name_cache, name_cache_size,
+              sizeof(name_cache[0]), name_cache_cmp);
+      if (pp != NULL) {
+        if (pp > name_cache && stricmp(pp[-1], pp[0]) == 0)
+          need_rename = 1;
+        else if (pp < name_cache + name_cache_size - 1
+          && stricmp(pp[0], pp[1]) == 0)
+        {
+          need_rename = 1;
+        }
+      }
+    }
 
     // rename vars with '?@' (funcs are ok)
     int change_qat = 0;
     ea_flags = get_flags_novalue(ea);
-    if (!isCode(ea_flags) && strpbrk(name, "?@"))
-      change_qat = 1;
+    if (!isCode(ea_flags)) {
+      if (IS_START(name, "__imp_"))
+        /* some import */;
+      else if (name[0] == '?' && strstr(name, "@@"))
+        /* c++ import */;
+      else if (strchr(name, '?'))
+        change_qat = 1;
+      else if ((cp = strchr(name, '@'))) {
+        char *endp = NULL;
+        strtol(cp + 1, &endp, 10);
+        if (endp == NULL || *endp != 0)
+          change_qat = 1;
+      }
+    }
 
-    if (change_qat || is_name_reserved(name)) {
+    if (need_rename || change_qat) {
       msg("%x: renaming name '%s'\n", ea, name);
-      qsnprintf(buf, sizeof(buf), "%s", name);
 
       if (change_qat) {
         for (p = buf; *p != 0; p++) {
@@ -512,7 +583,7 @@ static void idaapi run(int /*arg*/)
   ln.set_place(&pl);
   n = ln.get_linecnt();
   for (i = 0; i < n - 1; i++) {
-    do_def_line(buf, sizeof(buf), ln.down(), ea);
+    do_def_line(buf, sizeof(buf), ln.down(), ea, NULL);
     if (strstr(buf, "include"))
       continue;
 
@@ -548,6 +619,8 @@ static void idaapi run(int /*arg*/)
         break;
     }
 
+    func = get_func(ea);
+
     segment_t *seg = getseg(ea);
     if (!seg || (seg->type != SEG_CODE && seg->type != SEG_DATA))
       goto pass;
@@ -613,7 +686,7 @@ static void idaapi run(int /*arg*/)
 pass:
     n = ln.get_linecnt();
     for (i = pl.lnnum; i < n; i++) {
-      do_def_line(buf, sizeof(buf), ln.down(), ea);
+      do_def_line(buf, sizeof(buf), ln.down(), ea, func);
 
       char *fw;
       for (fw = buf; *fw != 0 && *fw == ' '; )