X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Ftypes%2Fdecl.c;h=780b924566d90c8d57ac8296e5ea5ffe844f7df0;hp=9c1b0c558b0ece04f22dc72c690824b2f56e332e;hb=a7ac1c0a3c855321f21682c127a4b707de33a303;hpb=9bcb1df0786a8193d65949c857baaba2f4296e84 diff --git a/src/types/decl.c b/src/types/decl.c index 9c1b0c5..780b924 100644 --- a/src/types/decl.c +++ b/src/types/decl.c @@ -24,27 +24,25 @@ *******************************************************************************/ #include "php_psi_stdinc.h" - -#if __GNUC__ >= 5 -# pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" -#endif -#include "php_psi_macros.h" -#include "php_psi_redirs.h" -#if __GNUC__ >= 5 -# pragma GCC diagnostic pop -#endif +#include "php_psi.h" #include +#include + +#include #include "data.h" -struct psi_decl *psi_decl_init(struct psi_decl_abi *abi, - struct psi_decl_arg *func, struct psi_plist *args) +#define PSI_FUNC_REDIRS +#include "php_psi_posix.h" + +struct psi_decl *psi_decl_init(struct psi_decl_arg *func, struct psi_plist *args) { - struct psi_decl *d = calloc(1, sizeof(*d)); - d->abi = abi; + struct psi_decl *d = pecalloc(1, sizeof(*d), 1); + d->func = func; d->args = args; + return d; } @@ -60,14 +58,20 @@ void psi_decl_free(struct psi_decl **d_ptr) if (d->args) { psi_plist_free(d->args); } + if (d->redir) { + zend_string_release(d->redir); + } free(d); } } void psi_decl_dump(int fd, struct psi_decl *decl) { - psi_decl_abi_dump(fd, decl->abi); + if (decl->abi) { + psi_decl_abi_dump(fd, decl->abi); + } dprintf(fd, " "); + /* FIXME: functions returning arrays */ psi_decl_arg_dump(fd, decl->func, 0); dprintf(fd, "("); if (decl->args) { @@ -84,60 +88,72 @@ void psi_decl_dump(int fd, struct psi_decl *decl) dprintf(fd, ", ..."); } } - dprintf(fd, ");"); + if (decl->func->var->array_size) { + dprintf(fd, ")[%u]", decl->func->var->array_size); + } + if (decl->redir) { + dprintf(fd, ") __asm__ (\"%s\");", decl->redir->val); + } else { + dprintf(fd, ");"); + } } static inline bool psi_decl_validate_func(struct psi_data *data, - struct psi_decl *decl, struct psi_decl_arg *func, void *dl) + struct psi_decl *decl, struct psi_decl_arg *func) { struct psi_func_redir *redir; - if (!strcmp(func->var->name, "dlsym")) { - data->error(data, func->token, PSI_WARNING, - "Cannot dlsym dlsym (sic!)"); + if (!func->var->name) { + data->error(data, func->token, PSI_WARNING, "Cannot load anonymous decl"); return false; } for (redir = &psi_func_redirs[0]; redir->name; ++redir) { - if (!strcmp(func->var->name, redir->name)) { + if (!strcmp(func->var->name->val, redir->name)) { decl->sym = redir->func; + break; } } if (!decl->sym) { -#ifndef RTLD_NEXT -# define RTLD_NEXT ((void *) -1l) -#endif - decl->sym = dlsym(dl ?: RTLD_NEXT, func->var->name); - if (!decl->sym) { - data->error(data, func->token, PSI_WARNING, - "Failed to locate symbol '%s': %s", func->var->name, - dlerror() ?: "not found"); - return false; - } + decl->sym = psi_dlsym(data->file.dlopened, func->var->name->val, + decl->redir ? decl->redir->val : NULL); + } + if (!decl->sym) { + data->error(data, func->token, PSI_WARNING, + "Failed to locate symbol '%s(%s)': %s", + func->var->name->val, + decl->redir ? decl->redir->val : "", + dlerror() ?: "not found"); + return false; } return true; } -bool psi_decl_validate(struct psi_data *data, struct psi_decl *decl, void *dl) +bool psi_decl_validate(struct psi_data *data, struct psi_decl *decl, + struct psi_validate_scope *scope) { - if (!psi_decl_validate_nodl(data, decl)) { + if (!psi_decl_validate_nodl(data, decl, scope)) { return false; } - if (!psi_decl_validate_func(data, decl, decl->func, dl)) { + if (!psi_decl_validate_func(data, decl, decl->func)) { return false; } return true; } -bool psi_decl_validate_nodl(struct psi_data *data, struct psi_decl *decl) +bool psi_decl_validate_nodl(struct psi_data *data, struct psi_decl *decl, + struct psi_validate_scope *scope) { - if (!psi_decl_abi_validate(data, decl->abi)) { + if (!decl->abi) { + decl->abi = psi_decl_abi_init(NULL); + } else if (!psi_decl_abi_validate(data, decl->abi)) { data->error(data, decl->abi->token, PSI_WARNING, - "Invalid calling convention: '%s'", decl->abi->token->text); + "Invalid calling convention: '%s'", + decl->abi->token->text->val); return false; } - if (!psi_decl_arg_validate(data, decl->func)) { + if (!psi_decl_arg_validate(data, decl->func, scope)) { return false; } if (decl->args) { @@ -145,7 +161,16 @@ bool psi_decl_validate_nodl(struct psi_data *data, struct psi_decl *decl) struct psi_decl_arg *arg; while (psi_plist_get(decl->args, i++, &arg)) { - if (!psi_decl_arg_validate(data, arg)) { + if (!arg->var->name) { + smart_str name = {0}; + + smart_str_appendl_ex(&name, ZEND_STRL("arg"), 1); + smart_str_append_unsigned_ex(&name, i, 1); + + arg->var->name = smart_str_extract(&name); + arg->var->fqn = zend_string_copy(arg->var->name); + } + if (!psi_decl_arg_validate(data, arg, scope)) { return false; } } @@ -153,3 +178,31 @@ bool psi_decl_validate_nodl(struct psi_data *data, struct psi_decl *decl) return true; } + +bool psi_decl_is_blacklisted(const char *name) +{ + char *blacklisted; + size_t i = 0; + + while (psi_plist_get(PSI_G(blacklist).decls, i++, &blacklisted)) { + if (!fnmatch(blacklisted, name, 0)) { + return true; + } + } + return false; +} + +struct psi_decl_arg *psi_decl_get_arg(struct psi_decl *decl, struct psi_decl_var *var) { + if (var->arg) { + size_t i = 0; + struct psi_decl_arg *arg = decl->func; + + do { + if (var->arg == arg) { + return arg; + } + } while (psi_plist_get(decl->args, i++, &arg)); + } + + return psi_decl_arg_get_by_var(var, decl->args, decl->func); +}