some func ptr arg type checking
authornotaz <notasas@gmail.com>
Sat, 8 Mar 2014 00:52:39 +0000 (02:52 +0200)
committernotaz <notasas@gmail.com>
Sat, 8 Mar 2014 16:51:59 +0000 (18:51 +0200)
tools/cvt_data.c
tools/protoparse.h
tools/translate.c
winelib.mak

index 2c5bbbf..237abef 100644 (file)
@@ -247,7 +247,8 @@ static const struct parsed_proto *check_var(FILE *fhdr,
   const char *sym, const char *varname)
 {
   const struct parsed_proto *pp, *pp_sym;
-  char fp_sym[256], fp_var[256];
+  char fp_sym[256], fp_var[256], *p;
+  int i;
 
   pp = proto_parse(fhdr, varname, 1);
   if (pp == NULL) {
@@ -277,6 +278,20 @@ static const struct parsed_proto *check_var(FILE *fhdr,
   }
 
 check_sym:
+  // fptrs must use 32bit args, callsite might have no information and
+  // lack a cast to smaller types, which results in incorrectly masked
+  // args passed (callee may assume masked args, it does on ARM)
+  for (i = 0; i < pp->argc; i++) {
+    if (pp->arg[i].type.is_ptr)
+      continue;
+    p = pp->arg[i].type.name;
+    if (strstr(p, "int8") || strstr(p, "int16")
+      || strstr(p, "char") || strstr(p, "short"))
+    {
+      awarn("reference to %s with arg%d '%s'\n", pp->name, i + 1, p);
+    }
+  }
+
   sprint_pp_short(pp, g_comment, sizeof(g_comment));
 
   if (sym != NULL) {
index 0ae46f6..27752cf 100644 (file)
@@ -41,7 +41,8 @@ struct parsed_proto {
        unsigned int is_noreturn:1;
        unsigned int is_unresolved:1;
        unsigned int is_userstack:1;
-       unsigned int is_arg:1;        // decl in func arg
+       unsigned int is_oslib:1;      // OS/system library func
+       unsigned int is_arg:1;        // declared in some func arg
        unsigned int has_structarg:1;
        unsigned int has_retreg:1;
 };
@@ -52,7 +53,7 @@ static int hdrfline = 0;
 static void pp_copy_arg(struct parsed_proto_arg *d,
        const struct parsed_proto_arg *s);
 
-static int b_pp_c_handler(char *proto, const char *fname);
+static int b_pp_c_handler(char *proto, const char *fname, int is_oslib);
 
 static int do_protostrs(FILE *fhdr, const char *fname)
 {
@@ -61,6 +62,7 @@ static int do_protostrs(FILE *fhdr, const char *fname)
        char protostr[256];
        char path[256];
        char fname_inc[256];
+       int is_oslib;
        FILE *finc;
        int line = 0;
        int ret;
@@ -69,6 +71,9 @@ static int do_protostrs(FILE *fhdr, const char *fname)
        hdrfn_saved = hdrfn;
        hdrfn = fname;
 
+       is_oslib = strstr(fname, "stdc.hlist")
+                || strstr(fname, "win32.hlist");
+
        while (fgets(protostr, sizeof(protostr), fhdr))
        {
                line++;
@@ -110,7 +115,7 @@ static int do_protostrs(FILE *fhdr, const char *fname)
 
                hdrfline = line;
 
-               ret = b_pp_c_handler(protostr, hdrfn);
+               ret = b_pp_c_handler(protostr, hdrfn, is_oslib);
                if (ret < 0)
                        break;
        }
@@ -653,7 +658,7 @@ static struct parsed_proto *pp_cache;
 static int pp_cache_size;
 static int pp_cache_alloc;
 
-static int b_pp_c_handler(char *proto, const char *fname)
+static int b_pp_c_handler(char *proto, const char *fname, int is_oslib)
 {
        int ret;
 
@@ -671,6 +676,7 @@ static int b_pp_c_handler(char *proto, const char *fname)
        if (ret < 0)
                return -1;
 
+       pp_cache[pp_cache_size].is_oslib = is_oslib;
        pp_cache_size++;
        return 0;
 }
index ff65fda..c697f32 100644 (file)
@@ -473,7 +473,7 @@ static int guess_lmod_from_c_type(enum opr_lenmod *lmod,
   static const char *dword_types[] = {
     "int", "_DWORD", "UINT_PTR", "DWORD",
     "WPARAM", "LPARAM", "UINT", "__int32",
-    "LONG", "HIMC",
+    "LONG", "HIMC", "BOOL",
   };
   static const char *word_types[] = {
     "uint16_t", "int16_t", "_WORD", "WORD",
@@ -1561,7 +1561,9 @@ static void stack_frame_access(struct parsed_op *po,
 static void check_func_pp(struct parsed_op *po,
   const struct parsed_proto *pp, const char *pfx)
 {
+  enum opr_lenmod tmp_lmod;
   char buf[256];
+  int ret, i;
 
   if (pp->argc_reg != 0) {
     if (/*!g_allow_regfunc &&*/ !pp->is_fastcall) {
@@ -1572,6 +1574,18 @@ static void check_func_pp(struct parsed_op *po,
       ferr(po, "%s: %d reg arg(s) with %d stack arg(s)\n",
         pfx, pp->argc_reg, pp->argc_stack);
   }
+
+  // fptrs must use 32bit args, callsite might have no information and
+  // lack a cast to smaller types, which results in incorrectly masked
+  // args passed (callee may assume masked args, it does on ARM)
+  if (!pp->is_oslib) {
+    for (i = 0; i < pp->argc; i++) {
+      ret = guess_lmod_from_c_type(&tmp_lmod, &pp->arg[i].type);
+      if (ret && tmp_lmod != OPLM_DWORD)
+        ferr(po, "reference to %s with arg%d '%s'\n", pp->name,
+          i + 1, pp->arg[i].type.name);
+    }
+  }
 }
 
 static const char *check_label_read_ref(struct parsed_op *po,
index 77da421..a0558d3 100644 (file)
@@ -10,7 +10,7 @@ LDFLAGS += -ggdb
 
 ifdef ARM
 CFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfloat-abi=softfp -mfpu=neon
-CFLAGS += -Wno-unused
+CFLAGS += -Wno-unused -fsigned-char
 WGCC_FLAGS += -marm -b$(patsubst %-,%,$(CROSS_COMPILE))
 # wine defines wchar_t correctly, doesn't use -fshort-wchar, we can't too
 WGCC_FLAGS += -fno-short-wchar