123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- #include "php.h"
- #include "Zend/zend_builtin_functions.h"
- #define TRACE_APPEND_CHR(chr) \
- *str = (char*)erealloc(*str, *len + 1 + 1); \
- (*str)[(*len)++] = chr
- #define TRACE_APPEND_STRL(val, vallen) \
- { \
- int l = vallen; \
- *str = (char*)erealloc(*str, *len + l + 1); \
- memcpy((*str) + *len, val, l); \
- *len += l; \
- }
- #define TRACE_APPEND_STR(val) \
- TRACE_APPEND_STRL(val, sizeof(val)-1)
- #define TRACE_APPEND_KEY(key) \
- if (zend_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
- TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); \
- }
- static int
- mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
- {
- char **str;
- int *len;
- str = va_arg(args, char**);
- len = va_arg(args, int*);
-
- switch (Z_TYPE_PP(arg)) {
- case IS_NULL:
- TRACE_APPEND_STR("NULL, ");
- break;
- case IS_STRING: {
- int l_added;
- TRACE_APPEND_CHR('\'');
- if (Z_STRLEN_PP(arg) > 15) {
- TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
- TRACE_APPEND_STR("...', ");
- l_added = 15 + 6 + 1;
- } else {
- l_added = Z_STRLEN_PP(arg);
- TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
- TRACE_APPEND_STR("', ");
- l_added += 3 + 1;
- }
- while (--l_added) {
- if ((*str)[*len - l_added] < 32) {
- (*str)[*len - l_added] = '?';
- }
- }
- break;
- }
- case IS_BOOL:
- if (Z_LVAL_PP(arg)) {
- TRACE_APPEND_STR("true, ");
- } else {
- TRACE_APPEND_STR("false, ");
- }
- break;
- case IS_RESOURCE:
- TRACE_APPEND_STR("Resource id #");
-
- case IS_LONG: {
- long lval = Z_LVAL_PP(arg);
- char s_tmp[MAX_LENGTH_OF_LONG + 1];
- int l_tmp = zend_sprintf(s_tmp, "%ld", lval);
- TRACE_APPEND_STRL(s_tmp, l_tmp);
- TRACE_APPEND_STR(", ");
- break;
- }
- case IS_DOUBLE: {
- double dval = Z_DVAL_PP(arg);
- char *s_tmp;
- int l_tmp;
- s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
- l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval);
- TRACE_APPEND_STRL(s_tmp, l_tmp);
-
- efree(s_tmp);
- TRACE_APPEND_STR(", ");
- break;
- }
- case IS_ARRAY:
- TRACE_APPEND_STR("Array, ");
- break;
- case IS_OBJECT: {
- char *class_name;
- zend_uint class_name_len;
- int dupl;
- TRACE_APPEND_STR("Object(");
- dupl = zend_get_object_classname(*arg, (const char **)&class_name, &class_name_len TSRMLS_CC);
- TRACE_APPEND_STRL(class_name, class_name_len);
- if (!dupl) {
- efree(class_name);
- }
- TRACE_APPEND_STR("), ");
- break;
- }
- default:
- break;
- }
- return ZEND_HASH_APPLY_KEEP;
- }
- static int
- mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
- {
- char *s_tmp, **str;
- int *len, *num;
- long line;
- HashTable *ht = Z_ARRVAL_PP(frame);
- zval **file, **tmp;
- uint * level;
- level = va_arg(args, uint *);
- str = va_arg(args, char**);
- len = va_arg(args, int*);
- num = va_arg(args, int*);
- if (!*level) {
- return ZEND_HASH_APPLY_KEEP;
- }
- --*level;
- s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
- sprintf(s_tmp, "#%d ", (*num)++);
- TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
- efree(s_tmp);
- if (zend_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
- if (zend_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
- line = Z_LVAL_PP(tmp);
- } else {
- line = 0;
- }
- s_tmp = emalloc(Z_STRLEN_PP(file) + MAX_LENGTH_OF_LONG + 4 + 1);
- sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_PP(file), line);
- TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
- efree(s_tmp);
- } else {
- TRACE_APPEND_STR("[internal function]: ");
- }
- TRACE_APPEND_KEY("class");
- TRACE_APPEND_KEY("type");
- TRACE_APPEND_KEY("function");
- TRACE_APPEND_CHR('(');
- if (zend_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
- int last_len = *len;
- zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len);
- if (last_len != *len) {
- *len -= 2;
- }
- }
- TRACE_APPEND_STR(")\n");
- return ZEND_HASH_APPLY_KEEP;
- }
- PHPAPI char *
- mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC)
- {
- zval *trace;
- char *res = estrdup(""), **str = &res, *s_tmp;
- int res_len = 0, *len = &res_len, num = 0;
- if (max_levels == 0) {
- max_levels = 99999;
- }
- MAKE_STD_ZVAL(trace);
- zend_fetch_debug_backtrace(trace, 0, 0, 0 TSRMLS_CC);
- zend_hash_apply_with_arguments(Z_ARRVAL_P(trace) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_string, 4, &max_levels, str, len, &num);
- zval_ptr_dtor(&trace);
- if (max_levels) {
- s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 7 + 1);
- sprintf(s_tmp, "#%d {main}", num);
- TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
- efree(s_tmp);
- }
- res[res_len] = '\0';
- *length = res_len;
- return res;
- }
|