php扩展分析
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php扩展分析相关的知识,希望对你有一定的参考价值。
<>调用堆栈
php_ext_test.dll!zif_confirm_test_compiled(int ht, _zval_struct * return_value, _zval_struct * * return_value_ptr, _zval_struct * this_ptr, int return_value_used) 行 60 C
php5.dll!zend_do_fcall_common_helper_SPEC(_zend_execute_data * execute_data) 行 558 C
php5.dll!execute_ex(_zend_execute_data * execute_data) 行 363 C
php5.dll!zend_execute(_zend_op_array * op_array) 行 388 C
php5.dll!zend_execute_scripts(int type, _zval_struct * * retval, int file_count, ...) 行 1341 C
php5.dll!php_execute_script(_zend_file_handle * primary_file) 行 2613 C
<>
PHP_FUNCTION(confirm_test_compiled)
{
char *arg = NULL;
int arg_len, len;
char *strg;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
return;
}
len = spprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "test", arg);
RETURN_STRINGL(strg, len, 0);
}
<>PHP_FUNCTION(confirm_test_compiled)
zif_confirm_test_compiled
void zif_confirm_test_compiled(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC)
<>zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE
zend_api.h
Boolean | b |
zend_bool |
Long | l |
long |
Double | d |
double |
String | s |
char*, int |
Resource | r |
zval* |
Array | a |
zval* |
Object | o |
zval* |
zval | z |
zval* |
类型指定符 |
对应的C类型 |
描述 |
l |
long |
符号整数 |
d |
double |
浮点数 |
s |
char *, int |
二进制字符串,长度 |
b |
zend_bool |
逻辑型(1或0) |
r |
zval * |
资源(文件指针,数据库连接等) |
a |
zval * |
联合数组 |
o |
zval * |
任何类型的对象 |
O |
zval * |
指定类型的对象。需要提供目标对象的类类型 |
z |
zval * |
无任何操作的zval |
RETURN_STRING
RETURN_LONG
RETURN_DOUBLE
RETURN_BOOL
RETURN_NULL
注意RETURN_STRING有两个参数
当你需要复制一份字符串时使用
RETURN_STRING("Hello World", 1);
否则使用
RETURN_STRING(str, 0);
zend_api.c
static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, int flags TSRMLS_DC) /* {{{ */
{
const char *spec_walk;
int c, i;
int min_num_args = -1;
int max_num_args = 0;
int post_varargs = 0;
zval **arg;
int arg_count;
int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
zend_bool have_varargs = 0;
zval ****varargs = NULL;
int *n_varargs = NULL;
for (spec_walk = type_spec; *spec_walk; spec_walk++) {
c = *spec_walk;
switch (c) {
case ‘l‘: case ‘d‘:
case ‘s‘: case ‘b‘:
case ‘r‘: case ‘a‘:
case ‘o‘: case ‘O‘:
case ‘z‘: case ‘Z‘:
case ‘C‘: case ‘h‘:
case ‘f‘: case ‘A‘:
case ‘H‘: case ‘p‘:
max_num_args++;
break;
case ‘|‘:
min_num_args = max_num_args;
break;
case ‘/‘:
case ‘!‘:
/* Pass */
break;
case ‘*‘:
case ‘+‘:
if (have_varargs) {
if (!quiet) {
zend_function *active_function = EG(current_execute_data)->function_state.function;
const char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
zend_error(E_WARNING, "%s%s%s(): only one varargs specifier (* or +) is permitted",
class_name,
class_name[0] ? "::" : "",
active_function->common.function_name);
}
return FAILURE;
}
have_varargs = 1;
/* we expect at least one parameter in varargs */
if (c == ‘+‘) {
max_num_args++;
}
/* mark the beginning of varargs */
post_varargs = max_num_args;
break;
default:
if (!quiet) {
zend_function *active_function = EG(current_execute_data)->function_state.function;
const char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters",
class_name,
class_name[0] ? "::" : "",
active_function->common.function_name);
}
return FAILURE;
}
}
if (min_num_args < 0) {
min_num_args = max_num_args;
}
if (have_varargs) {
/* calculate how many required args are at the end of the specifier list */
post_varargs = max_num_args - post_varargs;
max_num_args = -1;
}
if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) {
if (!quiet) {
zend_function *active_function = EG(current_execute_data)->function_state.function;
const char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given",
class_name,
class_name[0] ? "::" : "",
active_function->common.function_name,
min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
num_args < min_num_args ? min_num_args : max_num_args,
(num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
num_args);
}
return FAILURE;
}
arg_count = (int)(zend_uintptr_t) *(zend_vm_stack_top(TSRMLS_C) - 1);
if (num_args > arg_count) {
zend_error(E_WARNING, "%s(): could not obtain parameters for parsing",
get_active_function_name(TSRMLS_C));
return FAILURE;
}
i = 0;
while (num_args-- > 0) {
if (*type_spec == ‘|‘) {
type_spec++;
}
if (*type_spec == ‘*‘ || *type_spec == ‘+‘) {
int num_varargs = num_args + 1 - post_varargs;
/* eat up the passed in storage even if it won‘t be filled in with varargs */
varargs = va_arg(*va, zval ****);
n_varargs = va_arg(*va, int *);
type_spec++;
if (num_varargs > 0) {
int iv = 0;
zval **p = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - i));
*n_varargs = num_varargs;
/* allocate space for array and store args */
*varargs = safe_emalloc(num_varargs, sizeof(zval **), 0);
while (num_varargs-- > 0) {
(*varargs)[iv++] = p++;
}
/* adjust how many args we have left and restart loop */
num_args = num_args + 1 - iv;
i += iv;
continue;
} else {
*varargs = NULL;
*n_varargs = 0;
}
}
arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count-i));
if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) {
/* clean up varargs array if it was used */
if (varargs && *varargs) {
efree(*varargs);
*varargs = NULL;
}
return FAILURE;
}
i++;
}
return SUCCESS;
}
FAILURE
;
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht; /* hash table value */
zend_object_value obj;
zend_ast *ast;
} zvalue_value;
struct _zval_struct {
/* Variable information */
zvalue_value value; /* value */
zend_uint refcount__gc;
zend_uchar type; /* active type */
zend_uchar is_ref__gc;
};
/******/
typedef struct bucket {
ulong h; /* Used for numeric indexing */
uint nKeyLength;
void *pData;
void *pDataPtr;
struct bucket *pListNext;
struct bucket *pListLast;
struct bucket *pNext;
struct bucket *pLast;
const char *arKey;
} Bucket;
typedef struct _hashtable {
uint nTableSize;
uint nTableMask;
uint nNumOfElements;
ulong nNextFreeElement;
Bucket *pInternalPointer; /* Used for element traversal */
Bucket *pListHead;
Bucket *pListTail;
Bucket **arBuckets;
dtor_func_t pDestructor;
zend_bool persistent;
unsigned char nApplyCount;
zend_bool bApplyProtection;
#if ZEND_DEBUG
int inconsistent;
#endif
} HashTable;
typedef struct _zend_hash_key {
const char *arKey;
uint nKeyLength;
ulong h;
} zend_hash_key;
<>PHP_RINIT_FUNCTION 每次请求调的
PHP_RSHUTDOWN_FUNCTION 每次请求结束
PHP_MINIT_FUNCTION 模块加载调
以上是关于php扩展分析的主要内容,如果未能解决你的问题,请参考以下文章