X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=ia32rtools.git;a=blobdiff_plain;f=tools%2Fprotoparse.h;h=8e88ba0e5da9d3578f116ec1ee5a1e013cd7b3b2;hp=897171e86197b0c7e236e4fd75dd4e3a9785780a;hb=75b4a70dafd7faf3c27b963fa8e67462538f91d4;hpb=2c31fb4cf1427f5a24c4eed0a08dbd3f3a2dacce diff --git a/tools/protoparse.h b/tools/protoparse.h index 897171e..8e88ba0 100644 --- a/tools/protoparse.h +++ b/tools/protoparse.h @@ -16,14 +16,16 @@ struct parsed_type { unsigned int is_retreg:1; // register to return to caller unsigned int is_va_list:1; unsigned int is_64bit:1; + unsigned int is_float:1; // float, double }; struct parsed_proto_arg { char *reg; struct parsed_type type; struct parsed_proto *pp; // fptr or struct - void *datap; unsigned int is_saved:1; // not set here, for tool use + void **push_refs; + int push_ref_cnt; }; struct parsed_proto { @@ -32,7 +34,7 @@ struct parsed_proto { struct parsed_type ret_type; struct parsed_type type; }; - struct parsed_proto_arg arg[16]; + struct parsed_proto_arg arg[32]; int argc; int argc_stack; int argc_reg; @@ -41,8 +43,10 @@ struct parsed_proto { unsigned int is_fastcall:1; unsigned int is_vararg:1; // vararg func unsigned int is_fptr:1; + unsigned int is_import:1; // data import unsigned int is_noreturn:1; unsigned int is_unresolved:1; + unsigned int is_guessed:1; // for extra checking unsigned int is_userstack:1; unsigned int is_include:1; // not from top-level header unsigned int is_osinc:1; // OS/system library func @@ -212,11 +216,15 @@ static const char *known_ptr_types[] = { "HRGN", "HRSRC", "HKEY", + "HKL", "HMENU", + "HMONITOR", "HWAVEOUT", "HWND", + "PAPPBARDATA", "PBYTE", "PCRITICAL_SECTION", + "PDEVMODEA", "PDWORD", "PFILETIME", "PLARGE_INTEGER", @@ -231,7 +239,10 @@ static const char *known_ptr_types[] = { "PCVOID", "PWORD", "REFCLSID", + "REFGUID", "REFIID", + "SC_HANDLE", + "SERVICE_STATUS_HANDLE", "HOOKPROC", "DLGPROC", "TIMERPROC", @@ -242,6 +253,7 @@ static const char *known_ptr_types[] = { static const char *ignored_keywords[] = { "extern", + "static", "WINBASEAPI", "WINUSERAPI", "WINGDIAPI", @@ -398,6 +410,9 @@ static int parse_arg(char **p_, struct parsed_proto_arg *arg, int xarg) if (ret < 0) return -1; + if (IS_START(arg->pp->name, "guess")) + arg->pp->is_guessed = 1; + // we don't use actual names right now... snprintf(arg->pp->name, sizeof(arg->pp->name), "a%d", xarg); @@ -458,6 +473,11 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) p = sskip(p + l + 1); } + if (IS_START(p, "DECL_IMPORT ")) { + pp->is_import = 1; + p = sskip(p + 12); + } + ret = check_type(p, &pp->ret_type); if (ret <= 0) { printf("%s:%d:%zd: unhandled return in '%s'\n", @@ -624,6 +644,12 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) return -1; } + if (xarg >= ARRAY_SIZE(pp->arg)) { + printf("%s:%d:%zd: too many args\n", + hdrfn, hdrfline, (p - protostr) + 1); + return -1; + } + arg = &pp->arg[xarg]; xarg++; @@ -668,6 +694,12 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) pp->has_retreg |= is_retreg; } + if (IS(arg->type.name, "float") + || IS(arg->type.name, "double")) + { + arg->type.is_float = 1; + } + if (!arg->type.is_ptr && (strstr(arg->type.name, "int64") || IS(arg->type.name, "double"))) { @@ -970,22 +1002,43 @@ static inline int pp_cmp_func(const struct parsed_proto *pp1, if (pp1->argc != pp2->argc || pp1->argc_reg != pp2->argc_reg) return 1; - else { - for (i = 0; i < pp1->argc; i++) { - if ((pp1->arg[i].reg != NULL) != (pp2->arg[i].reg != NULL)) - return 1; - - if ((pp1->arg[i].reg != NULL) - && !IS(pp1->arg[i].reg, pp2->arg[i].reg)) - { - return 1; - } + if (pp1->is_stdcall != pp2->is_stdcall) + return 1; + + // because of poor void return detection, return is not + // checked for now to avoid heaps of false positives + + for (i = 0; i < pp1->argc; i++) { + if ((pp1->arg[i].reg != NULL) != (pp2->arg[i].reg != NULL)) + return 1; + + if ((pp1->arg[i].reg != NULL) + && !IS(pp1->arg[i].reg, pp2->arg[i].reg)) + { + return 1; } } return 0; } +static inline int pp_compatible_func( + const struct parsed_proto *pp_site, + const struct parsed_proto *pp_callee) +{ + if (pp_cmp_func(pp_site, pp_callee) == 0) + return 1; + + if (pp_site->argc_stack == 0 && pp_site->is_fastcall + && pp_callee->argc_stack == 0 + && (pp_callee->is_fastcall || pp_callee->argc_reg == 0) + && pp_site->argc_reg > pp_callee->argc_reg) + /* fascall compatible callee doesn't use all args -> ok */ + return 1; + + return 0; +} + static inline void pp_print(char *buf, size_t buf_size, const struct parsed_proto *pp) { @@ -1013,12 +1066,10 @@ static inline void proto_release(struct parsed_proto *pp) int i; for (i = 0; i < pp->argc; i++) { - if (pp->arg[i].reg != NULL) - free(pp->arg[i].reg); - if (pp->arg[i].type.name != NULL) - free(pp->arg[i].type.name); - if (pp->arg[i].pp != NULL) - free(pp->arg[i].pp); + free(pp->arg[i].reg); + free(pp->arg[i].type.name); + free(pp->arg[i].pp); + free(pp->arg[i].push_refs); } if (pp->ret_type.name != NULL) free(pp->ret_type.name);