root/ext/mysqlnd/mysqlnd_bt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mysqlnd_build_trace_args
  2. mysqlnd_build_trace_string
  3. mysqlnd_get_backtrace

   1 /*
   2   +----------------------------------------------------------------------+
   3   | PHP Version 5                                                        |
   4   +----------------------------------------------------------------------+
   5   | Copyright (c) 2006-2016 The PHP Group                                |
   6   +----------------------------------------------------------------------+
   7   | This source file is subject to version 3.01 of the PHP license,      |
   8   | that is bundled with this package in the file LICENSE, and is        |
   9   | available through the world-wide-web at the following url:           |
  10   | http://www.php.net/license/3_01.txt                                  |
  11   | If you did not receive a copy of the PHP license and are unable to   |
  12   | obtain it through the world-wide-web, please send a note to          |
  13   | license@php.net so we can mail you a copy immediately.               |
  14   +----------------------------------------------------------------------+
  15   | Authors: Georg Richter <georg@mysql.com>                             |
  16   |          Andrey Hristov <andrey@mysql.com>                           |
  17   |          Ulf Wendel <uwendel@mysql.com>                              |
  18   +----------------------------------------------------------------------+
  19 */
  20 
  21 /* $Id: mysqlnd_debug.c 309303 2011-03-16 12:42:59Z andrey $ */
  22 
  23 #include "php.h"
  24 #include "Zend/zend_builtin_functions.h"
  25 
  26 /* Follows code borrowed from zend_builtin_functions.c because the functions there are static */
  27 
  28 /* {{{ gettraceasstring() macros */
  29 #define TRACE_APPEND_CHR(chr)                                            \
  30         *str = (char*)erealloc(*str, *len + 1 + 1);                          \
  31         (*str)[(*len)++] = chr
  32 
  33 #define TRACE_APPEND_STRL(val, vallen)                                   \
  34         {                                                                    \
  35                 int l = vallen;                                                  \
  36                 *str = (char*)erealloc(*str, *len + l + 1);                      \
  37                 memcpy((*str) + *len, val, l);                                   \
  38                 *len += l;                                                       \
  39         }
  40 
  41 #define TRACE_APPEND_STR(val)                                            \
  42         TRACE_APPEND_STRL(val, sizeof(val)-1)
  43 
  44 #define TRACE_APPEND_KEY(key)                                            \
  45         if (zend_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
  46             TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));           \
  47         }
  48 
  49 /* }}} */
  50 
  51 
  52 static int
  53 mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
  54 {
  55         char **str;
  56         int *len;
  57 
  58         str = va_arg(args, char**);
  59         len = va_arg(args, int*);
  60 
  61         /* the trivial way would be to do:
  62          * conver_to_string_ex(arg);
  63          * append it and kill the now tmp arg.
  64          * but that could cause some E_NOTICE and also damn long lines.
  65          */
  66 
  67         switch (Z_TYPE_PP(arg)) {
  68                 case IS_NULL:
  69                         TRACE_APPEND_STR("NULL, ");
  70                         break;
  71                 case IS_STRING: {
  72                         int l_added;
  73                         TRACE_APPEND_CHR('\'');
  74                         if (Z_STRLEN_PP(arg) > 15) {
  75                                 TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
  76                                 TRACE_APPEND_STR("...', ");
  77                                 l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
  78                         } else {
  79                                 l_added = Z_STRLEN_PP(arg);
  80                                 TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
  81                                 TRACE_APPEND_STR("', ");
  82                                 l_added += 3 + 1;
  83                         }
  84                         while (--l_added) {
  85                                 if ((*str)[*len - l_added] < 32) {
  86                                         (*str)[*len - l_added] = '?';
  87                                 }
  88                         }
  89                         break;
  90                 }
  91                 case IS_BOOL:
  92                         if (Z_LVAL_PP(arg)) {
  93                                 TRACE_APPEND_STR("true, ");
  94                         } else {
  95                                 TRACE_APPEND_STR("false, ");
  96                         }
  97                         break;
  98                 case IS_RESOURCE:
  99                         TRACE_APPEND_STR("Resource id #");
 100                         /* break; */
 101                 case IS_LONG: {
 102                         long lval = Z_LVAL_PP(arg);
 103                         char s_tmp[MAX_LENGTH_OF_LONG + 1];
 104                         int l_tmp = zend_sprintf(s_tmp, "%ld", lval);  /* SAFE */
 105                         TRACE_APPEND_STRL(s_tmp, l_tmp);
 106                         TRACE_APPEND_STR(", ");
 107                         break;
 108                 }
 109                 case IS_DOUBLE: {
 110                         double dval = Z_DVAL_PP(arg);
 111                         char *s_tmp;
 112                         int l_tmp;
 113 
 114                         s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
 115                         l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval);  /* SAFE */
 116                         TRACE_APPEND_STRL(s_tmp, l_tmp);
 117                         /* %G already handles removing trailing zeros from the fractional part, yay */
 118                         efree(s_tmp);
 119                         TRACE_APPEND_STR(", ");
 120                         break;
 121                 }
 122                 case IS_ARRAY:
 123                         TRACE_APPEND_STR("Array, ");
 124                         break;
 125                 case IS_OBJECT: {
 126                         char *class_name;
 127                         zend_uint class_name_len;
 128                         int dupl;
 129 
 130                         TRACE_APPEND_STR("Object(");
 131 
 132                         dupl = zend_get_object_classname(*arg, (const char **)&class_name, &class_name_len TSRMLS_CC);
 133 
 134                         TRACE_APPEND_STRL(class_name, class_name_len);
 135                         if (!dupl) {
 136                                 efree(class_name);
 137                         }
 138 
 139                         TRACE_APPEND_STR("), ");
 140                         break;
 141                 }
 142                 default:
 143                         break;
 144         }
 145         return ZEND_HASH_APPLY_KEEP;
 146 }
 147 /* }}} */
 148 
 149 static int
 150 mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
 151 {
 152         char *s_tmp, **str;
 153         int *len, *num;
 154         long line;
 155         HashTable *ht = Z_ARRVAL_PP(frame);
 156         zval **file, **tmp;
 157         uint * level;
 158 
 159         level = va_arg(args, uint *);
 160         str = va_arg(args, char**);
 161         len = va_arg(args, int*);
 162         num = va_arg(args, int*);
 163 
 164         if (!*level) {
 165                 return ZEND_HASH_APPLY_KEEP;
 166         }
 167         --*level;
 168 
 169         s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
 170         sprintf(s_tmp, "#%d ", (*num)++);
 171         TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
 172         efree(s_tmp);
 173         if (zend_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
 174                 if (zend_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
 175                         line = Z_LVAL_PP(tmp);
 176                 } else {
 177                         line = 0;
 178                 }
 179                 s_tmp = emalloc(Z_STRLEN_PP(file) + MAX_LENGTH_OF_LONG + 4 + 1);
 180                 sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_PP(file), line);
 181                 TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
 182                 efree(s_tmp);
 183         } else {
 184                 TRACE_APPEND_STR("[internal function]: ");
 185         }
 186         TRACE_APPEND_KEY("class");
 187         TRACE_APPEND_KEY("type");
 188         TRACE_APPEND_KEY("function");
 189         TRACE_APPEND_CHR('(');
 190         if (zend_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
 191                 int last_len = *len;
 192                 zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len);
 193                 if (last_len != *len) {
 194                         *len -= 2; /* remove last ', ' */
 195                 }
 196         }
 197         TRACE_APPEND_STR(")\n");
 198         return ZEND_HASH_APPLY_KEEP;
 199 }
 200 /* }}} */
 201 
 202 
 203 PHPAPI char *
 204 mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC)
 205 {
 206         zval *trace;
 207         char *res = estrdup(""), **str = &res, *s_tmp;
 208         int res_len = 0, *len = &res_len, num = 0;
 209         if (max_levels == 0) {
 210                 max_levels = 99999;
 211         }
 212 
 213         MAKE_STD_ZVAL(trace);
 214         zend_fetch_debug_backtrace(trace, 0, 0, 0 TSRMLS_CC);
 215 
 216         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);
 217         zval_ptr_dtor(&trace);
 218 
 219         if (max_levels) {
 220                 s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 7 + 1);
 221                 sprintf(s_tmp, "#%d {main}", num);
 222                 TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
 223                 efree(s_tmp);
 224         }
 225 
 226         res[res_len] = '\0';
 227         *length = res_len;
 228 
 229         return res;
 230 }
 231 
 232 
 233 /*
 234  * Local variables:
 235  * tab-width: 4
 236  * c-basic-offset: 4
 237  * End:
 238  * vim600: noet sw=4 ts=4 fdm=marker
 239  * vim<600: noet sw=4 ts=4
 240  */

/* [<][>][^][v][top][bottom][index][help] */