From: Michael Wallner Date: Thu, 12 Nov 2015 13:37:00 +0000 (+0100) Subject: flush X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=a6ffb2bfbf83ef3511cc356bd931d460feabe7a2;p=m6w6%2Fext-psi flush --- diff --git a/config.m4 b/config.m4 index 647b0a9..8382435 100644 --- a/config.m4 +++ b/config.m4 @@ -236,6 +236,26 @@ if test "$PHP_PSI" != "no"; then ]) PSI_STRUCTS="{\"$1\", $psi_struct_size, {$psi_struct_members}}, $PSI_STRUCTS" ]) + + AC_PROG_NM + AC_PROG_AWK + PSI_FUNCS= + dnl PSI_FUNC(fn, decl) + AC_DEFUN(PSI_FUNC, [ + AC_CHECK_FUNC($1, [ + AC_MSG_CHECKING(for redirection of function $1) + psi_symbol=$1 + psi_symbol_redirect= + AC_TRY_LINK_FUNC($1, [ + psi_symbol_redirect=`$NM -g conftest$ac_exeext | $AWK -F" *|@" '/_main/ {next} / U / {print$[]3}'` + ]) + AC_MSG_RESULT($psi_symbol_redirect) + if test "$psi_symbol_redirect" && test "$psi_symbol_redirect" != "$psi_symbol" + then + PSI_FUNCS="{\"$psi_symbol\", (void *) $psi_symbol}, $PSI_FUNCS" + fi + ]) + ]) AC_TYPE_INT8_T AC_CHECK_ALIGNOF(int8_t) @@ -364,6 +384,22 @@ if test "$PHP_PSI" != "no"; then PSI_CONST(RAND_MAX, int) PSI_CONST(MB_CUR_MAX, int) dnl sys/stat.h + PSI_FUNC(chmod) + PSI_FUNC(fchmod) + PSI_FUNC(fchmodat) + PSI_FUNC(fstat) + PSI_FUNC(fstatat) + PSI_FUNC(futimens) + PSI_FUNC(lstat) + PSI_FUNC(mkdir) + PSI_FUNC(mkdirat) + PSI_FUNC(mkfifo) + PSI_FUNC(mkfifoat) + PSI_FUNC(mknod) + PSI_FUNC(mknodat) + PSI_FUNC(stat) + PSI_FUNC(umask) + PSI_FUNC(utimensat) PSI_STRUCT(stat, [ [st_dev], [st_ino], @@ -426,6 +462,7 @@ if test "$PHP_PSI" != "no"; then PSI_CONST(ITIMER_VIRTUAL, int, sys/time.h) PSI_CONST(ITIMER_PROF, int, sys/time.h) dnl sys/times.h + PSI_FUNC(times) PSI_STRUCT(tms, [ [tms_utime], [tms_stime], @@ -454,6 +491,7 @@ if test "$PHP_PSI" != "no"; then PSI_TYPE(timer_t, int) PSI_TYPE(uid_t) dnl sys/utsname.h + PSI_FUNC(uname) PSI_STRUCT(utsname, [ [sysname], [nodename], @@ -498,6 +536,7 @@ if test "$PHP_PSI" != "no"; then ]) + AC_DEFINE_UNQUOTED(PHP_PSI_FUNCS, $PSI_FUNCS, Redirected functions) AC_DEFINE_UNQUOTED(PHP_PSI_TYPES, $PSI_TYPES, Predefined types) AC_DEFINE_UNQUOTED(PHP_PSI_CONSTS, $PSI_CONSTS, Predefined constants) AC_DEFINE_UNQUOTED(PHP_PSI_STRUCTS, $PSI_STRUCTS, Predefined structs) diff --git a/src/context.c b/src/context.c index 00126c7..7d353be 100644 --- a/src/context.c +++ b/src/context.c @@ -57,6 +57,15 @@ static const psi_predef_struct psi_predef_structs[] = { }; #define psi_predef_struct_count() psi_predef_count(_struct) +typedef struct psi_predef_func { + const char *name; + void (*func)(void); +} psi_predef_func; +static psi_predef_func psi_predef_funcs[] = { + PHP_PSI_FUNCS{0} +}; +#define psi_predef_func_count() psi_predef_count(_func) + static int validate_lib(PSI_Data *data, void **dlopened) { char lib[MAXPATHLEN]; const char *ptr = data->psi.file.ln; @@ -230,8 +239,20 @@ static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_ #endif decl->dlptr = dlsym(dl ?: RTLD_NEXT, func->var->name); if (!decl->dlptr) { - data->error(PSI_WARNING, "Failed to locate symbol '%s': %s", - func->var->name, dlerror()); + size_t i; + + for (i = 0; i < psi_predef_func_count(); ++i) { + psi_predef_func *pre = &psi_predef_funcs[i]; + + if (!strcmp(func->var->name, pre->name)) { + decl->dlptr = pre->func; + break; + } + } + if (!decl->dlptr) { + data->error(PSI_WARNING, "Failed to locate symbol '%s': %s", + func->var->name, dlerror()); + } } return 1; } @@ -271,6 +292,8 @@ static inline decl_arg *locate_struct_member(decl_struct *s, decl_var *var) { } static inline int validate_set_value(PSI_Data *data, set_value *set, decl_arg *ref) { size_t i; + decl_type *ref_type = real_decl_type(ref->type); + decl_var *set_var = set->vars->vars[0]; switch (set->func->type) { case PSI_T_TO_BOOL: @@ -291,22 +314,22 @@ static inline int validate_set_value(PSI_Data *data, set_value *set, decl_arg *r EMPTY_SWITCH_DEFAULT_CASE(); } - if (strcmp(set->vars->vars[0]->name, ref->var->name)) { + if (strcmp(set_var->name, ref->var->name)) { return 0; } - if (set->count && (set->func->type != PSI_T_TO_ARRAY || real_decl_type(ref->type)->type != PSI_T_STRUCT)) { + if (set->count && (set->func->type != PSI_T_TO_ARRAY || ref_type->type != PSI_T_STRUCT)) { data->error(E_WARNING, "Inner `set` statement casts only work with to_array() casts on structs"); return 0; } for (i = 0; i < set->count; ++i) { - decl_arg *sub_ref = locate_struct_member(real_decl_type(ref->type)->strct, set->inner[i]->vars->vars[0]); + decl_var *sub_var = set->inner[i]->vars->vars[0]; + decl_arg *sub_ref = locate_struct_member(ref_type->strct, sub_var); - if (!sub_ref) { - return 0; - } - if (!validate_set_value(data, set->inner[i], sub_ref)) { - return 0; + if (sub_ref) { + if (!validate_set_value(data, set->inner[i], sub_ref)) { + return 0; + } } } diff --git a/src/module.c b/src/module.c index b8d2300..508fdea 100644 --- a/src/module.c +++ b/src/module.c @@ -360,17 +360,20 @@ void psi_to_array(zval *return_value, token_t t, impl_val *ret_val, set_value *s set_value *sub_set = set->inner[i]; decl_var *sub_var = sub_set->vars->vars[0]; decl_arg *sub_arg = sub_var->arg; - token_t t = real_decl_type(sub_arg->type)->type; - void *ptr = malloc(sub_arg->layout->len); - - memcpy(ptr, (char *) ret_val->ptr + sub_arg->layout->pos, - sub_arg->layout->len); - tmp_ptr = enref_impl_val(ptr, sub_arg->var); - sub_set->func->handler(&ztmp, t, tmp_ptr, sub_set, sub_var); - add_assoc_zval(return_value, sub_var->name, &ztmp); - free(tmp_ptr); - if (tmp_ptr != ptr) { - free(ptr); + + if (sub_arg) { + token_t t = real_decl_type(sub_arg->type)->type; + void *ptr = malloc(sub_arg->layout->len); + + memcpy(ptr, (char *) ret_val->ptr + sub_arg->layout->pos, + sub_arg->layout->len); + tmp_ptr = enref_impl_val(ptr, sub_arg->var); + sub_set->func->handler(&ztmp, t, tmp_ptr, sub_set, sub_var); + add_assoc_zval(return_value, sub_var->name, &ztmp); + free(tmp_ptr); + if (tmp_ptr != ptr) { + free(ptr); + } } } } diff --git a/src/parser.h b/src/parser.h index 3b4c77f..6dcd6bf 100644 --- a/src/parser.h +++ b/src/parser.h @@ -356,7 +356,7 @@ static inline impl_val *enref_impl_val(void *ptr, decl_var *var) { impl_val *val, *val_ptr; unsigned i; - if (!var->pointer_level) { + if (!var->pointer_level && real_decl_type(var->arg->type)->type != PSI_T_STRUCT) { return ptr; } val = val_ptr = calloc(var->pointer_level, sizeof(void *)); diff --git a/tests/stat/stat.psi b/tests/stat/stat.psi index 0017565..e5d8eba 100644 --- a/tests/stat/stat.psi +++ b/tests/stat/stat.psi @@ -1,8 +1,48 @@ -extern int __xstat64(int ver, char *path, struct stat *buf); +extern int stat(char *path, struct stat *buf); function psi\stat(string $path, array &$buf = NULL) : int { - let ver = NULL; let path = strval($path); let buf = calloc(1, struct stat); - return to_int(__xstat64); - set $buf = to_array(*buf); + return to_int(stat); + set $buf = to_array(*buf, + to_int(st_dev), + to_int(st_ino), + to_int(st_mode), + to_int(st_nlink), + to_int(st_uid), + to_int(st_gid), + to_int(st_rdev), + to_int(st_size), + to_array(st_atim, + to_int(tv_sec), + to_int(tv_nsec) + ), + to_array(st_atimespec, + to_int(tv_sec), + to_int(tv_nsec) + ), + to_array(st_mtim, + to_int(tv_sec), + to_int(tv_nsec) + ), + to_array(st_mtimespec, + to_int(tv_sec), + to_int(tv_nsec) + ), + to_array(st_ctim, + to_int(tv_sec), + to_int(tv_nsec) + ), + to_array(st_ctimespec, + to_int(tv_sec), + to_int(tv_nsec) + ), + to_array(st_birthtimespec, + to_int(tv_sec), + to_int(tv_nsec) + ), + to_int(st_blksize), + to_int(st_blocks), + to_int(st_flags), + to_int(st_gen) + ); }