]> granicus.if.org Git - php/commitdiff
split mysqlnd_debug.c in 3 files
authorAndrey Hristov <andrey@php.net>
Fri, 18 Mar 2011 11:58:46 +0000 (11:58 +0000)
committerAndrey Hristov <andrey@php.net>
Fri, 18 Mar 2011 11:58:46 +0000 (11:58 +0000)
ext/mysqlnd/config.w32
ext/mysqlnd/config9.m4
ext/mysqlnd/mysqlnd_alloc.c [new file with mode: 0644]
ext/mysqlnd/mysqlnd_alloc.h [new file with mode: 0644]
ext/mysqlnd/mysqlnd_bt.c [new file with mode: 0644]
ext/mysqlnd/mysqlnd_debug.c
ext/mysqlnd/mysqlnd_debug.h

index 49da1ccafddca112170bac0edbe67bdb3aee4708..1c1ddec45cd7381d8cb3983bb5250921e6de8f76 100644 (file)
@@ -7,8 +7,10 @@ if (PHP_MYSQLND != "no") {
        if (CHECK_LIB("ws2_32.lib", "mysqlnd")) {
                mysqlnd_source = 
                        "mysqlnd.c " +
+                       "mysqlnd_alloc.c" +
                        "mysqlnd_auth.c " +
                        "mysqlnd_block_alloc.c " +
+                       "mysqlnd_bt.c" +
                        "mysqlnd_charset.c " +
                        "mysqlnd_debug.c " +
                        "mysqlnd_loaddata.c " +
index 9104a85889aac42bf8ef181616ffd0fd6eb870a0..46cdca74e7ec5d41ad1dee319b50376ff48646b3 100644 (file)
@@ -14,7 +14,7 @@ fi
 
 dnl If some extension uses mysqlnd it will get compiled in PHP core
 if test "$PHP_MYSQLND_ENABLED" = "yes"; then
-  mysqlnd_sources="mysqlnd.c mysqlnd_charset.c mysqlnd_wireprotocol.c \
+  mysqlnd_sources="mysqlnd.c mysqlnd_alloc.c mysqlnd_bt.c mysqlnd_charset.c mysqlnd_wireprotocol.c \
                    mysqlnd_ps.c mysqlnd_loaddata.c mysqlnd_net.c \
                    mysqlnd_ps_codec.c mysqlnd_statistics.c mysqlnd_auth.c \
                                   mysqlnd_result.c mysqlnd_result_meta.c mysqlnd_debug.c\
diff --git a/ext/mysqlnd/mysqlnd_alloc.c b/ext/mysqlnd/mysqlnd_alloc.c
new file mode 100644 (file)
index 0000000..808f3ae
--- /dev/null
@@ -0,0 +1,674 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 5                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2011 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.01 of the PHP license,      |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_01.txt                                  |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Authors: Georg Richter <georg@mysql.com>                             |
+  |          Andrey Hristov <andrey@mysql.com>                           |
+  |          Ulf Wendel <uwendel@mysql.com>                              |
+  +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd_debug.c 309303 2011-03-16 12:42:59Z andrey $ */
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_priv.h"
+#include "mysqlnd_debug.h"
+#include "mysqlnd_wireprotocol.h"
+#include "mysqlnd_statistics.h"
+
+
+static const char mysqlnd_emalloc_name[]       = "_mysqlnd_emalloc";
+static const char mysqlnd_pemalloc_name[]      = "_mysqlnd_pemalloc";
+static const char mysqlnd_ecalloc_name[]       = "_mysqlnd_ecalloc";
+static const char mysqlnd_pecalloc_name[]      = "_mysqlnd_pecalloc";
+static const char mysqlnd_erealloc_name[]      = "_mysqlnd_erealloc";
+static const char mysqlnd_perealloc_name[]     = "_mysqlnd_perealloc";
+static const char mysqlnd_efree_name[]         = "_mysqlnd_efree";
+static const char mysqlnd_pefree_name[]                = "_mysqlnd_pefree";
+static const char mysqlnd_malloc_name[]                = "_mysqlnd_malloc";
+static const char mysqlnd_calloc_name[]                = "_mysqlnd_calloc";
+static const char mysqlnd_realloc_name[]       = "_mysqlnd_realloc";
+static const char mysqlnd_free_name[]          = "_mysqlnd_free";
+static const char mysqlnd_pestrndup_name[]     = "_mysqlnd_pestrndup";
+static const char mysqlnd_pestrdup_name[]      = "_mysqlnd_pestrdup";
+
+const char * mysqlnd_debug_std_no_trace_funcs[] =
+{
+       mysqlnd_emalloc_name,
+       mysqlnd_ecalloc_name,
+       mysqlnd_efree_name,
+       mysqlnd_erealloc_name,
+       mysqlnd_pemalloc_name,
+       mysqlnd_pecalloc_name,
+       mysqlnd_pefree_name,
+       mysqlnd_perealloc_name,
+       mysqlnd_malloc_name,
+       mysqlnd_calloc_name,
+       mysqlnd_realloc_name,
+       mysqlnd_free_name,
+       mysqlnd_pestrndup_name,
+       mysqlnd_read_header_name,
+       mysqlnd_read_body_name,
+       NULL /* must be always last */
+};
+
+
+#if ZEND_DEBUG
+#else
+#define __zend_filename "/unknown/unknown"
+#define __zend_lineno   0
+#endif
+
+#define REAL_SIZE(s) (collect_memory_statistics? (s) + sizeof(size_t) : (s))
+#define REAL_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) - sizeof(size_t)) : (p))
+#define FAKE_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) + sizeof(size_t)) : (p))
+
+/* {{{ _mysqlnd_emalloc */
+void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D)
+{
+       void *ret;
+       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+       long * threshold = &MYSQLND_G(debug_emalloc_fail_threshold);
+       DBG_ENTER(mysqlnd_emalloc_name);
+
+       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+
+#if PHP_DEBUG
+       /* -1 is also "true" */
+       if (*threshold) {
+#endif
+               ret = emalloc(REAL_SIZE(size));
+#if PHP_DEBUG
+               --*threshold;
+       } else if (*threshold == 0) {
+               ret = NULL;
+       }
+#endif
+
+       DBG_INF_FMT("size=%lu ptr=%p", size, ret);
+
+       if (ret && collect_memory_statistics) {
+               *(size_t *) ret = size;
+               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EMALLOC_COUNT, 1, STAT_MEM_EMALLOC_AMOUNT, size);
+       }
+       DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_pemalloc */
+void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
+{
+       void *ret;
+       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+       long * threshold = persistent? &MYSQLND_G(debug_malloc_fail_threshold):&MYSQLND_G(debug_emalloc_fail_threshold);
+       DBG_ENTER(mysqlnd_pemalloc_name);
+       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+
+#if PHP_DEBUG
+       /* -1 is also "true" */
+       if (*threshold) {
+#endif
+               ret = pemalloc(REAL_SIZE(size), persistent);
+#if PHP_DEBUG
+               --*threshold;
+       } else if (*threshold == 0) {
+               ret = NULL;
+       }
+#endif
+
+       DBG_INF_FMT("size=%lu ptr=%p persistent=%u", size, ret, persistent);
+
+       if (ret && collect_memory_statistics) {
+               enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_MALLOC_COUNT:STAT_MEM_EMALLOC_COUNT;
+               enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_MALLOC_AMOUNT:STAT_MEM_EMALLOC_AMOUNT;
+               *(size_t *) ret = size;
+               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
+       }
+
+       DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_ecalloc */
+void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
+{
+       void *ret;
+       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+       long * threshold = &MYSQLND_G(debug_ecalloc_fail_threshold);
+       DBG_ENTER(mysqlnd_ecalloc_name);
+       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+       DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));
+
+#if PHP_DEBUG
+       /* -1 is also "true" */
+       if (*threshold) {
+#endif
+               ret = ecalloc(nmemb, REAL_SIZE(size));
+#if PHP_DEBUG
+               --*threshold;
+       } else if (*threshold == 0) {
+               ret = NULL;
+       }
+#endif
+
+       DBG_INF_FMT("after : %lu", zend_memory_usage(FALSE TSRMLS_CC));
+       DBG_INF_FMT("size=%lu ptr=%p", size, ret);
+       if (ret && collect_memory_statistics) {
+               *(size_t *) ret = size;
+               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_ECALLOC_COUNT, 1, STAT_MEM_ECALLOC_AMOUNT, size);
+       }
+       DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_pecalloc */
+void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)
+{
+       void *ret;
+       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+       long * threshold = persistent? &MYSQLND_G(debug_calloc_fail_threshold):&MYSQLND_G(debug_ecalloc_fail_threshold);
+       DBG_ENTER(mysqlnd_pecalloc_name);
+       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+
+#if PHP_DEBUG
+       /* -1 is also "true" */
+       if (*threshold) {
+#endif
+               ret = pecalloc(nmemb, REAL_SIZE(size), persistent);
+#if PHP_DEBUG
+               --*threshold;
+       } else if (*threshold == 0) {
+               ret = NULL;
+       }
+#endif
+
+       DBG_INF_FMT("size=%lu ptr=%p", size, ret);
+
+       if (ret && collect_memory_statistics) {
+               enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_CALLOC_COUNT:STAT_MEM_ECALLOC_COUNT;
+               enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_CALLOC_AMOUNT:STAT_MEM_ECALLOC_AMOUNT;
+               *(size_t *) ret = size;
+               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
+       }
+
+       DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_erealloc */
+void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
+{
+       void *ret;
+       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+       size_t old_size = collect_memory_statistics && ptr? *(size_t *) (((char*)ptr) - sizeof(size_t)) : 0;
+       long * threshold = &MYSQLND_G(debug_erealloc_fail_threshold);
+       DBG_ENTER(mysqlnd_erealloc_name);
+       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+       DBG_INF_FMT("ptr=%p old_size=%lu, new_size=%lu", ptr, old_size, new_size); 
+
+#if PHP_DEBUG
+       /* -1 is also "true" */
+       if (*threshold) {
+#endif
+               ret = erealloc(REAL_PTR(ptr), REAL_SIZE(new_size));
+#if PHP_DEBUG
+               --*threshold;
+       } else if (*threshold == 0) {
+               ret = NULL;
+       }
+#endif
+
+       DBG_INF_FMT("new_ptr=%p", (char*)ret);
+       if (ret && collect_memory_statistics) {
+               *(size_t *) ret = new_size;
+               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EREALLOC_COUNT, 1, STAT_MEM_EREALLOC_AMOUNT, new_size);
+       }
+       DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_perealloc */
+void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)
+{
+       void *ret;
+       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+       size_t old_size = collect_memory_statistics && ptr? *(size_t *) (((char*)ptr) - sizeof(size_t)) : 0;
+       long * threshold = persistent? &MYSQLND_G(debug_realloc_fail_threshold):&MYSQLND_G(debug_erealloc_fail_threshold);
+       DBG_ENTER(mysqlnd_perealloc_name);
+       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+       DBG_INF_FMT("ptr=%p old_size=%lu new_size=%lu persistent=%u", ptr, old_size, new_size, persistent); 
+
+#if PHP_DEBUG
+       /* -1 is also "true" */
+       if (*threshold) {
+#endif
+               ret = perealloc(REAL_PTR(ptr), REAL_SIZE(new_size), persistent);
+#if PHP_DEBUG
+               --*threshold;
+       } else if (*threshold == 0) {
+               ret = NULL;
+       }
+#endif
+
+       DBG_INF_FMT("new_ptr=%p", (char*)ret);
+
+       if (ret && collect_memory_statistics) {
+               enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_REALLOC_COUNT:STAT_MEM_EREALLOC_COUNT;
+               enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_REALLOC_AMOUNT:STAT_MEM_EREALLOC_AMOUNT;
+               *(size_t *) ret = new_size;
+               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, new_size);
+       }
+       DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_efree */
+void _mysqlnd_efree(void *ptr MYSQLND_MEM_D)
+{
+       size_t free_amount = 0;
+       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+       DBG_ENTER(mysqlnd_efree_name);
+       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+       DBG_INF_FMT("ptr=%p", ptr); 
+
+       if (ptr) {
+               if (collect_memory_statistics) {
+                       free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
+                       DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
+               }
+               efree(REAL_PTR(ptr));
+       }
+
+       if (collect_memory_statistics) {
+               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EFREE_COUNT, 1, STAT_MEM_EFREE_AMOUNT, free_amount);
+       }
+       DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_pefree */
+void _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D)
+{
+       size_t free_amount = 0;
+       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+       DBG_ENTER(mysqlnd_pefree_name);
+       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+       DBG_INF_FMT("ptr=%p persistent=%u", ptr, persistent); 
+
+       if (ptr) {
+               if (collect_memory_statistics) {
+                       free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
+                       DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
+               }
+               pefree(REAL_PTR(ptr), persistent);
+       }
+
+       if (collect_memory_statistics) {
+               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(persistent? STAT_MEM_FREE_COUNT:STAT_MEM_EFREE_COUNT, 1,
+                                                                                         persistent? STAT_MEM_FREE_AMOUNT:STAT_MEM_EFREE_AMOUNT, free_amount);
+       }
+       DBG_VOID_RETURN;
+}
+
+
+/* {{{ _mysqlnd_malloc */
+void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D)
+{
+       void *ret;
+       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+       long * threshold = &MYSQLND_G(debug_malloc_fail_threshold);
+       DBG_ENTER(mysqlnd_malloc_name);
+       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+
+#if PHP_DEBUG
+       /* -1 is also "true" */
+       if (*threshold) {
+#endif
+               ret = malloc(REAL_SIZE(size));
+#if PHP_DEBUG
+               --*threshold;
+       } else if (*threshold == 0) {
+               ret = NULL;
+       }
+#endif
+
+       DBG_INF_FMT("size=%lu ptr=%p", size, ret);
+       if (ret && collect_memory_statistics) {
+               *(size_t *) ret = size;
+               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_MALLOC_COUNT, 1, STAT_MEM_MALLOC_AMOUNT, size);
+       }
+       DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_calloc */
+void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
+{
+       void *ret;
+       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+       long * threshold = &MYSQLND_G(debug_calloc_fail_threshold);
+       DBG_ENTER(mysqlnd_calloc_name);
+       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+
+#if PHP_DEBUG
+       /* -1 is also "true" */
+       if (*threshold) {
+#endif
+               ret = calloc(nmemb, REAL_SIZE(size));
+#if PHP_DEBUG
+               --*threshold;
+       } else if (*threshold == 0) {
+               ret = NULL;
+       }
+#endif
+
+       DBG_INF_FMT("size=%lu ptr=%p", size, ret);
+       if (ret && collect_memory_statistics) {
+               *(size_t *) ret = size;
+               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_CALLOC_COUNT, 1, STAT_MEM_CALLOC_AMOUNT, size);
+       }
+       DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_realloc */
+void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D)
+{
+       void *ret;
+       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+       long * threshold = &MYSQLND_G(debug_realloc_fail_threshold);
+       DBG_ENTER(mysqlnd_realloc_name);
+       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+       DBG_INF_FMT("ptr=%p new_size=%lu ", new_size, ptr); 
+       DBG_INF_FMT("before: %lu", zend_memory_usage(TRUE TSRMLS_CC));
+
+#if PHP_DEBUG
+       /* -1 is also "true" */
+       if (*threshold) {
+#endif
+               ret = realloc(REAL_PTR(ptr), REAL_SIZE(new_size));
+#if PHP_DEBUG
+               --*threshold;
+       } else if (*threshold == 0) {
+               ret = NULL;
+       }
+#endif
+
+       DBG_INF_FMT("new_ptr=%p", (char*)ret);
+
+       if (ret && collect_memory_statistics) {
+               *(size_t *) ret = new_size;
+               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_REALLOC_COUNT, 1, STAT_MEM_REALLOC_AMOUNT, new_size);
+       }
+       DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_free */
+void _mysqlnd_free(void *ptr MYSQLND_MEM_D)
+{
+       size_t free_amount = 0;
+       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+       DBG_ENTER(mysqlnd_free_name);
+       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+       DBG_INF_FMT("ptr=%p", ptr); 
+
+       if (ptr) {
+               if (collect_memory_statistics) {
+                       free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
+                       DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
+               }
+               free(REAL_PTR(ptr));
+       }
+
+       if (collect_memory_statistics) {
+               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_FREE_COUNT, 1, STAT_MEM_FREE_AMOUNT, free_amount);
+       }
+       DBG_VOID_RETURN;
+}
+/* }}} */
+
+#define SMART_STR_START_SIZE 2048
+#define SMART_STR_PREALLOC 512
+#include "ext/standard/php_smart_str.h"
+
+
+/* {{{ _mysqlnd_pestrndup */
+char * _mysqlnd_pestrndup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)
+{
+       char * ret;
+       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+       DBG_ENTER(mysqlnd_pestrndup_name);
+       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+       DBG_INF_FMT("ptr=%p", ptr); 
+
+       ret = pemalloc(REAL_SIZE(length) + 1, persistent);
+       {
+               size_t l = length;
+               char * p = (char *) ptr;
+               char * dest = (char *) FAKE_PTR(ret);
+               while (*p && l--) {
+                       *dest++ = *p++;
+               }
+               *dest = '\0';
+       }
+
+       if (collect_memory_statistics) {
+               *(size_t *) ret = length;
+               MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRNDUP_COUNT : STAT_MEM_ESTRNDUP_COUNT);
+       }
+
+       DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_pestrdup */
+char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)
+{
+       char * ret;
+       smart_str tmp_str = {0, 0, 0};
+       const char * p = ptr;
+       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+       DBG_ENTER(mysqlnd_pestrdup_name);
+       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
+       DBG_INF_FMT("ptr=%p", ptr);
+       do {
+               smart_str_appendc(&tmp_str, *p);
+       } while (*p++);
+
+       ret = pemalloc(tmp_str.len + sizeof(size_t), persistent);
+       memcpy(FAKE_PTR(ret), tmp_str.c, tmp_str.len);
+
+       if (ret && collect_memory_statistics) {
+               *(size_t *) ret = tmp_str.len;
+               MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRDUP_COUNT : STAT_MEM_ESTRDUP_COUNT);
+       }
+       smart_str_free(&tmp_str);
+
+       DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+#define MYSQLND_DEBUG_MEMORY 1
+
+#if MYSQLND_DEBUG_MEMORY == 0
+
+/* {{{ mysqlnd_zend_mm_emalloc */
+static void * mysqlnd_zend_mm_emalloc(size_t size MYSQLND_MEM_D)
+{
+       return emalloc(size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_pemalloc */
+static void * mysqlnd_zend_mm_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
+{
+       return pemalloc(size, persistent);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_ecalloc */
+static void * mysqlnd_zend_mm_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
+{
+       return ecalloc(nmemb, size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_pecalloc */
+static void * mysqlnd_zend_mm_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)
+{
+       return pecalloc(nmemb, size, persistent);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_erealloc */
+static void * mysqlnd_zend_mm_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
+{
+       return erealloc(ptr, new_size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_perealloc */
+static void * mysqlnd_zend_mm_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)
+{
+       return perealloc(ptr, new_size, persistent);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_efree */
+static void mysqlnd_zend_mm_efree(void * ptr MYSQLND_MEM_D)
+{
+       efree(ptr);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_pefree */
+static void mysqlnd_zend_mm_pefree(void * ptr, zend_bool persistent MYSQLND_MEM_D)
+{
+       pefree(ptr, persistent);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_malloc */
+static void * mysqlnd_zend_mm_malloc(size_t size MYSQLND_MEM_D)
+{
+       return malloc(size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_calloc */
+static void * mysqlnd_zend_mm_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
+{
+       return calloc(nmemb, size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_realloc */
+static void * mysqlnd_zend_mm_realloc(void * ptr, size_t new_size MYSQLND_MEM_D)
+{
+       return realloc(ptr, new_size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_free */
+static void mysqlnd_zend_mm_free(void * ptr MYSQLND_MEM_D)
+{
+       free(ptr);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_pestrndup */
+static char * mysqlnd_zend_mm_pestrndup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)
+{
+       return pestrndup(ptr, length, persistent);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_pestrdup */
+static char * mysqlnd_zend_mm_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)
+{
+       return pestrdup(ptr, persistent);
+}
+/* }}} */
+
+#endif
+
+
+PHPAPI struct st_mysqlnd_allocator_methods mysqlnd_allocator = 
+{
+#if MYSQLND_DEBUG_MEMORY
+       _mysqlnd_emalloc,
+       _mysqlnd_pemalloc,
+       _mysqlnd_ecalloc,
+       _mysqlnd_pecalloc,
+       _mysqlnd_erealloc,
+       _mysqlnd_perealloc,
+       _mysqlnd_efree,
+       _mysqlnd_pefree,
+       _mysqlnd_malloc,
+       _mysqlnd_calloc,
+       _mysqlnd_realloc,
+       _mysqlnd_free,
+       _mysqlnd_pestrndup,
+       _mysqlnd_pestrdup
+#else
+       mysqlnd_zend_mm_emalloc,
+       mysqlnd_zend_mm_pemalloc,
+       mysqlnd_zend_mm_ecalloc,
+       mysqlnd_zend_mm_pecalloc,
+       mysqlnd_zend_mm_erealloc,
+       mysqlnd_zend_mm_perealloc,
+       mysqlnd_zend_mm_efree,
+       mysqlnd_zend_mm_pefree,
+       mysqlnd_zend_mm_malloc,
+       mysqlnd_zend_mm_calloc,
+       mysqlnd_zend_mm_realloc,
+       mysqlnd_zend_mm_free,
+       mysqlnd_zend_mm_pestrndup,
+       mysqlnd_zend_mm_pestrdup
+#endif
+};
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_alloc.h b/ext/mysqlnd/mysqlnd_alloc.h
new file mode 100644 (file)
index 0000000..b5fb862
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 5                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2011 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.01 of the PHP license,      |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_01.txt                                  |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Authors: Georg Richter <georg@mysql.com>                             |
+  |          Andrey Hristov <andrey@mysql.com>                           |
+  |          Ulf Wendel <uwendel@mysql.com>                              |
+  +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd_debug.h 306938 2011-01-01 02:17:06Z felipe $ */
+/* $Id: mysqlnd_debug.h 306938 2011-01-01 02:17:06Z felipe $ */
+
+#ifndef MYSQLND_ALLOC_H
+#define MYSQLND_ALLOC_H
+
+extern const char * mysqlnd_debug_std_no_trace_funcs[];
+
+#define MYSQLND_MEM_D  TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC
+#define MYSQLND_MEM_C  TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC
+
+struct st_mysqlnd_allocator_methods
+{
+       void *  (*m_emalloc)(size_t size MYSQLND_MEM_D);
+       void *  (*m_pemalloc)(size_t size, zend_bool persistent MYSQLND_MEM_D);
+       void *  (*m_ecalloc)(unsigned int nmemb, size_t size MYSQLND_MEM_D);
+       void *  (*m_pecalloc)(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D);
+       void *  (*m_erealloc)(void *ptr, size_t new_size MYSQLND_MEM_D);
+       void *  (*m_perealloc)(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D);
+       void    (*m_efree)(void *ptr MYSQLND_MEM_D);
+       void    (*m_pefree)(void *ptr, zend_bool persistent MYSQLND_MEM_D);
+       void *  (*m_malloc)(size_t size MYSQLND_MEM_D);
+       void *  (*m_calloc)(unsigned int nmemb, size_t size MYSQLND_MEM_D);
+       void *  (*m_realloc)(void *ptr, size_t new_size MYSQLND_MEM_D);
+       void    (*m_free)(void *ptr MYSQLND_MEM_D);
+       char *  (*m_pestrndup)(const char * const ptr, size_t size, zend_bool persistent MYSQLND_MEM_D);
+       char *  (*m_pestrdup)(const char * const ptr, zend_bool persistent MYSQLND_MEM_D);
+};
+
+PHPAPI extern struct st_mysqlnd_allocator_methods mysqlnd_allocator;
+
+PHPAPI void *  _mysqlnd_emalloc(size_t size MYSQLND_MEM_D);
+PHPAPI void *  _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI void *  _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D);
+PHPAPI void *  _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI void *  _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D);
+PHPAPI void *  _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI void            _mysqlnd_efree(void *ptr MYSQLND_MEM_D);
+PHPAPI void            _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI void *  _mysqlnd_malloc(size_t size MYSQLND_MEM_D);
+PHPAPI void *  _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D);
+PHPAPI void *  _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D);
+PHPAPI void            _mysqlnd_free(void *ptr MYSQLND_MEM_D);
+PHPAPI char *  _mysqlnd_pestrndup(const char * const ptr, size_t size, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI char *  _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D);
+
+
+#define mnd_emalloc(size)                              mysqlnd_allocator.m_emalloc((size) MYSQLND_MEM_C)
+#define mnd_pemalloc(size, pers)               mysqlnd_allocator.m_pemalloc((size), (pers) MYSQLND_MEM_C)
+#define mnd_ecalloc(nmemb, size)               mysqlnd_allocator.m_ecalloc((nmemb), (size) MYSQLND_MEM_C)
+#define mnd_pecalloc(nmemb, size, p)   mysqlnd_allocator.m_pecalloc((nmemb), (size), (p) MYSQLND_MEM_C)
+#define mnd_erealloc(ptr, new_size)            mysqlnd_allocator.m_erealloc((ptr), (new_size) MYSQLND_MEM_C)
+#define mnd_perealloc(ptr, new_size, p)        mysqlnd_allocator.m_perealloc((ptr), (new_size), (p) MYSQLND_MEM_C)
+#define mnd_efree(ptr)                                 mysqlnd_allocator.m_efree((ptr) MYSQLND_MEM_C)
+#define mnd_pefree(ptr, pers)                  mysqlnd_allocator.m_pefree((ptr), (pers) MYSQLND_MEM_C)
+#define mnd_malloc(size)                               mysqlnd_allocator.m_malloc((size) MYSQLND_MEM_C)
+#define mnd_calloc(nmemb, size)                        mysqlnd_allocator.m_calloc((nmemb), (size) MYSQLND_MEM_C)
+#define mnd_realloc(ptr, new_size)             mysqlnd_allocator.m_realloc((ptr), (new_size) MYSQLND_MEM_C)
+#define mnd_free(ptr)                                  mysqlnd_allocator.m_free((ptr) MYSQLND_MEM_C)
+#define mnd_pestrndup(ptr, size, pers) mysqlnd_allocator.m_pestrndup((ptr), (size), (pers) MYSQLND_MEM_C)
+#define mnd_pestrdup(ptr, pers)                        mysqlnd_allocator.m_pestrdup((ptr), (pers) MYSQLND_MEM_C)
+
+#endif /* MYSQLND_ALLOC_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_bt.c b/ext/mysqlnd/mysqlnd_bt.c
new file mode 100644 (file)
index 0000000..4863012
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 5                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006-2011 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.01 of the PHP license,      |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_01.txt                                  |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Authors: Georg Richter <georg@mysql.com>                             |
+  |          Andrey Hristov <andrey@mysql.com>                           |
+  |          Ulf Wendel <uwendel@mysql.com>                              |
+  +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd_debug.c 309303 2011-03-16 12:42:59Z andrey $ */
+
+#include "php.h"
+
+/* Follows code borrowed from zend_builtin_functions.c because the functions there are static */
+
+#if MYSQLND_UNICODE
+/* {{{ gettraceasstring() macros */
+#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_USTRL(val, vallen) \
+       { \
+               zval tmp, copy; \
+               int use_copy; \
+               ZVAL_UNICODEL(&tmp, val, vallen, 1); \
+               zend_make_printable_zval(&tmp, &copy, &use_copy); \
+               TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
+               zval_dtor(&copy); \
+               zval_dtor(&tmp); \
+       }
+
+#define TRACE_APPEND_ZVAL(zv) \
+       if (Z_TYPE_P((zv)) == IS_UNICODE) { \
+               zval copy; \
+               int use_copy; \
+               zend_make_printable_zval((zv), &copy, &use_copy); \
+               TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
+               zval_dtor(&copy); \
+       } else { \
+               TRACE_APPEND_STRL(Z_STRVAL_P((zv)), Z_STRLEN_P((zv))); \
+       }
+
+#define TRACE_APPEND_STR(val)                                            \
+       TRACE_APPEND_STRL(val, sizeof(val)-1)
+
+#define TRACE_APPEND_KEY(key)                                            \
+       if (zend_ascii_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
+               if (Z_TYPE_PP(tmp) == IS_UNICODE) { \
+                       zval copy; \
+                       int use_copy; \
+                       zend_make_printable_zval(*tmp, &copy, &use_copy); \
+                       TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
+                       zval_dtor(&copy); \
+               } else { \
+               TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));           \
+               } \
+       }
+/* }}} */
+
+
+/* {{{ mysqlnd_build_trace_args */
+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*);
+
+       /* the trivial way would be to do:
+        * conver_to_string_ex(arg);
+        * append it and kill the now tmp arg.
+        * but that could cause some E_NOTICE and also damn long lines.
+        */
+
+       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; /* +1 because of while (--l_added) */
+                       } 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 ((unsigned char)(*str)[*len - l_added] < 32) {
+                                       (*str)[*len - l_added] = '?';
+                               }
+                       }
+                       break;
+               }
+               case IS_UNICODE: {
+                       int l_added;
+
+                       /*
+                        * We do not want to apply current error mode here, since
+                        * zend_make_printable_zval() uses output encoding converter.
+                        * Temporarily set output encoding converter to escape offending
+                        * chars with \uXXXX notation.
+                        */
+                       zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, ZEND_CONV_ERROR_ESCAPE_JAVA);
+                       TRACE_APPEND_CHR('\'');
+                       if (Z_USTRLEN_PP(arg) > 15) {
+                               TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), 15);
+                               TRACE_APPEND_STR("...', ");
+                               l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
+                       } else {
+                               l_added = Z_USTRLEN_PP(arg);
+                               TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), l_added);
+                               TRACE_APPEND_STR("', ");
+                               l_added += 3 + 1;
+                       }
+                       /*
+                        * Reset output encoding converter error mode.
+                        */
+                       zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, UG(from_error_mode));
+                       while (--l_added) {
+                               if ((unsigned char)(*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 #");
+                       /* break; */
+               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);  /* SAFE */
+                       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);  /* SAFE */
+                       TRACE_APPEND_STRL(s_tmp, l_tmp);
+                       /* %G already handles removing trailing zeros from the fractional part, yay */
+                       efree(s_tmp);
+                       TRACE_APPEND_STR(", ");
+                       break;
+               }
+               case IS_ARRAY:
+                       TRACE_APPEND_STR("Array, ");
+                       break;
+               case IS_OBJECT: {
+                       zval tmp;
+                       zstr class_name;
+                       zend_uint class_name_len;
+                       int dup;
+
+                       TRACE_APPEND_STR("Object(");
+
+                       dup = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC);
+
+                       ZVAL_UNICODEL(&tmp, class_name.u, class_name_len, 1);
+                       convert_to_string_with_converter(&tmp, ZEND_U_CONVERTER(UG(output_encoding_conv)));
+                       TRACE_APPEND_STRL(Z_STRVAL(tmp), Z_STRLEN(tmp));
+                       zval_dtor(&tmp);
+
+                       if(!dup) {
+                               efree(class_name.v);
+                       }
+
+                       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_ascii_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
+               if (zend_ascii_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
+                       line = Z_LVAL_PP(tmp);
+               } else {
+                       line = 0;
+               }
+               TRACE_APPEND_ZVAL(*file);
+               s_tmp = emalloc(MAX_LENGTH_OF_LONG + 2 + 1);
+               sprintf(s_tmp, "(%ld): ", 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_ascii_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; /* remove last ', ' */
+               }
+       }
+       TRACE_APPEND_STR(")\n");
+       return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
+
+#else /* PHP 5*/
+
+
+/* {{{ gettraceasstring() macros */
+#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*);
+
+       /* the trivial way would be to do:
+        * conver_to_string_ex(arg);
+        * append it and kill the now tmp arg.
+        * but that could cause some E_NOTICE and also damn long lines.
+        */
+
+       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; /* +1 because of while (--l_added) */
+                       } 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 #");
+                       /* break; */
+               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);  /* SAFE */
+                       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);  /* SAFE */
+                       TRACE_APPEND_STRL(s_tmp, l_tmp);
+                       /* %G already handles removing trailing zeros from the fractional part, yay */
+                       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, &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; /* remove last ', ' */
+               }
+       }
+       TRACE_APPEND_STR(")\n");
+       return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+#endif
+
+
+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 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;
+}
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
index 21cd71c620c9127619dc46c4fd04306a71b7f07b..7d2da7e03ec41ef2a797cc32c7d163adce503574 100644 (file)
@@ -24,9 +24,6 @@
 #include "mysqlnd.h"
 #include "mysqlnd_priv.h"
 #include "mysqlnd_debug.h"
-#include "mysqlnd_wireprotocol.h"
-#include "mysqlnd_statistics.h"
-#include "zend_builtin_functions.h"
 
 static const char * const mysqlnd_debug_default_trace_file = "/tmp/mysqlnd.trace";
 
@@ -36,41 +33,6 @@ static const char * const mysqlnd_debug_default_trace_file = "/tmp/mysqlnd.trace
 #define MYSQLND_ZTS(self)
 #endif
 
-static const char mysqlnd_emalloc_name[]       = "_mysqlnd_emalloc";
-static const char mysqlnd_pemalloc_name[]      = "_mysqlnd_pemalloc";
-static const char mysqlnd_ecalloc_name[]       = "_mysqlnd_ecalloc";
-static const char mysqlnd_pecalloc_name[]      = "_mysqlnd_pecalloc";
-static const char mysqlnd_erealloc_name[]      = "_mysqlnd_erealloc";
-static const char mysqlnd_perealloc_name[]     = "_mysqlnd_perealloc";
-static const char mysqlnd_efree_name[]         = "_mysqlnd_efree";
-static const char mysqlnd_pefree_name[]                = "_mysqlnd_pefree";
-static const char mysqlnd_malloc_name[]                = "_mysqlnd_malloc";
-static const char mysqlnd_calloc_name[]                = "_mysqlnd_calloc";
-static const char mysqlnd_realloc_name[]       = "_mysqlnd_realloc";
-static const char mysqlnd_free_name[]          = "_mysqlnd_free";
-static const char mysqlnd_pestrndup_name[]     = "_mysqlnd_pestrndup";
-static const char mysqlnd_pestrdup_name[]      = "_mysqlnd_pestrdup";
-
-const char * mysqlnd_debug_std_no_trace_funcs[] =
-{
-       mysqlnd_emalloc_name,
-       mysqlnd_ecalloc_name,
-       mysqlnd_efree_name,
-       mysqlnd_erealloc_name,
-       mysqlnd_pemalloc_name,
-       mysqlnd_pecalloc_name,
-       mysqlnd_pefree_name,
-       mysqlnd_perealloc_name,
-       mysqlnd_malloc_name,
-       mysqlnd_calloc_name,
-       mysqlnd_realloc_name,
-       mysqlnd_free_name,
-       mysqlnd_pestrndup_name,
-       mysqlnd_read_header_name,
-       mysqlnd_read_body_name,
-       NULL /* must be always last */
-};
-
 
 /* {{{ mysqlnd_debug::open */
 static enum_func_status
@@ -805,1058 +767,6 @@ PHPAPI void _mysqlnd_debug(const char * mode TSRMLS_DC)
 /* }}} */
 
 
-#if ZEND_DEBUG
-#else
-#define __zend_filename "/unknown/unknown"
-#define __zend_lineno   0
-#endif
-
-#define REAL_SIZE(s) (collect_memory_statistics? (s) + sizeof(size_t) : (s))
-#define REAL_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) - sizeof(size_t)) : (p))
-#define FAKE_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) + sizeof(size_t)) : (p))
-
-/* {{{ _mysqlnd_emalloc */
-void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D)
-{
-       void *ret;
-       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
-       long * threshold = &MYSQLND_G(debug_emalloc_fail_threshold);
-       DBG_ENTER(mysqlnd_emalloc_name);
-
-       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-
-#if PHP_DEBUG
-       /* -1 is also "true" */
-       if (*threshold) {
-#endif
-               ret = emalloc(REAL_SIZE(size));
-#if PHP_DEBUG
-               --*threshold;
-       } else if (*threshold == 0) {
-               ret = NULL;
-       }
-#endif
-
-       DBG_INF_FMT("size=%lu ptr=%p", size, ret);
-
-       if (ret && collect_memory_statistics) {
-               *(size_t *) ret = size;
-               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EMALLOC_COUNT, 1, STAT_MEM_EMALLOC_AMOUNT, size);
-       }
-       DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_pemalloc */
-void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
-{
-       void *ret;
-       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
-       long * threshold = persistent? &MYSQLND_G(debug_malloc_fail_threshold):&MYSQLND_G(debug_emalloc_fail_threshold);
-       DBG_ENTER(mysqlnd_pemalloc_name);
-       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-
-#if PHP_DEBUG
-       /* -1 is also "true" */
-       if (*threshold) {
-#endif
-               ret = pemalloc(REAL_SIZE(size), persistent);
-#if PHP_DEBUG
-               --*threshold;
-       } else if (*threshold == 0) {
-               ret = NULL;
-       }
-#endif
-
-       DBG_INF_FMT("size=%lu ptr=%p persistent=%u", size, ret, persistent);
-
-       if (ret && collect_memory_statistics) {
-               enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_MALLOC_COUNT:STAT_MEM_EMALLOC_COUNT;
-               enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_MALLOC_AMOUNT:STAT_MEM_EMALLOC_AMOUNT;
-               *(size_t *) ret = size;
-               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
-       }
-
-       DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_ecalloc */
-void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
-{
-       void *ret;
-       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
-       long * threshold = &MYSQLND_G(debug_ecalloc_fail_threshold);
-       DBG_ENTER(mysqlnd_ecalloc_name);
-       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-       DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));
-
-#if PHP_DEBUG
-       /* -1 is also "true" */
-       if (*threshold) {
-#endif
-               ret = ecalloc(nmemb, REAL_SIZE(size));
-#if PHP_DEBUG
-               --*threshold;
-       } else if (*threshold == 0) {
-               ret = NULL;
-       }
-#endif
-
-       DBG_INF_FMT("after : %lu", zend_memory_usage(FALSE TSRMLS_CC));
-       DBG_INF_FMT("size=%lu ptr=%p", size, ret);
-       if (ret && collect_memory_statistics) {
-               *(size_t *) ret = size;
-               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_ECALLOC_COUNT, 1, STAT_MEM_ECALLOC_AMOUNT, size);
-       }
-       DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_pecalloc */
-void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)
-{
-       void *ret;
-       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
-       long * threshold = persistent? &MYSQLND_G(debug_calloc_fail_threshold):&MYSQLND_G(debug_ecalloc_fail_threshold);
-       DBG_ENTER(mysqlnd_pecalloc_name);
-       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-
-#if PHP_DEBUG
-       /* -1 is also "true" */
-       if (*threshold) {
-#endif
-               ret = pecalloc(nmemb, REAL_SIZE(size), persistent);
-#if PHP_DEBUG
-               --*threshold;
-       } else if (*threshold == 0) {
-               ret = NULL;
-       }
-#endif
-
-       DBG_INF_FMT("size=%lu ptr=%p", size, ret);
-
-       if (ret && collect_memory_statistics) {
-               enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_CALLOC_COUNT:STAT_MEM_ECALLOC_COUNT;
-               enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_CALLOC_AMOUNT:STAT_MEM_ECALLOC_AMOUNT;
-               *(size_t *) ret = size;
-               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
-       }
-
-       DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_erealloc */
-void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
-{
-       void *ret;
-       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
-       size_t old_size = collect_memory_statistics && ptr? *(size_t *) (((char*)ptr) - sizeof(size_t)) : 0;
-       long * threshold = &MYSQLND_G(debug_erealloc_fail_threshold);
-       DBG_ENTER(mysqlnd_erealloc_name);
-       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-       DBG_INF_FMT("ptr=%p old_size=%lu, new_size=%lu", ptr, old_size, new_size); 
-
-#if PHP_DEBUG
-       /* -1 is also "true" */
-       if (*threshold) {
-#endif
-               ret = erealloc(REAL_PTR(ptr), REAL_SIZE(new_size));
-#if PHP_DEBUG
-               --*threshold;
-       } else if (*threshold == 0) {
-               ret = NULL;
-       }
-#endif
-
-       DBG_INF_FMT("new_ptr=%p", (char*)ret);
-       if (ret && collect_memory_statistics) {
-               *(size_t *) ret = new_size;
-               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EREALLOC_COUNT, 1, STAT_MEM_EREALLOC_AMOUNT, new_size);
-       }
-       DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_perealloc */
-void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)
-{
-       void *ret;
-       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
-       size_t old_size = collect_memory_statistics && ptr? *(size_t *) (((char*)ptr) - sizeof(size_t)) : 0;
-       long * threshold = persistent? &MYSQLND_G(debug_realloc_fail_threshold):&MYSQLND_G(debug_erealloc_fail_threshold);
-       DBG_ENTER(mysqlnd_perealloc_name);
-       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-       DBG_INF_FMT("ptr=%p old_size=%lu new_size=%lu persistent=%u", ptr, old_size, new_size, persistent); 
-
-#if PHP_DEBUG
-       /* -1 is also "true" */
-       if (*threshold) {
-#endif
-               ret = perealloc(REAL_PTR(ptr), REAL_SIZE(new_size), persistent);
-#if PHP_DEBUG
-               --*threshold;
-       } else if (*threshold == 0) {
-               ret = NULL;
-       }
-#endif
-
-       DBG_INF_FMT("new_ptr=%p", (char*)ret);
-
-       if (ret && collect_memory_statistics) {
-               enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_REALLOC_COUNT:STAT_MEM_EREALLOC_COUNT;
-               enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_REALLOC_AMOUNT:STAT_MEM_EREALLOC_AMOUNT;
-               *(size_t *) ret = new_size;
-               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, new_size);
-       }
-       DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_efree */
-void _mysqlnd_efree(void *ptr MYSQLND_MEM_D)
-{
-       size_t free_amount = 0;
-       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
-       DBG_ENTER(mysqlnd_efree_name);
-       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-       DBG_INF_FMT("ptr=%p", ptr); 
-
-       if (ptr) {
-               if (collect_memory_statistics) {
-                       free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
-                       DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
-               }
-               efree(REAL_PTR(ptr));
-       }
-
-       if (collect_memory_statistics) {
-               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EFREE_COUNT, 1, STAT_MEM_EFREE_AMOUNT, free_amount);
-       }
-       DBG_VOID_RETURN;
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_pefree */
-void _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D)
-{
-       size_t free_amount = 0;
-       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
-       DBG_ENTER(mysqlnd_pefree_name);
-       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-       DBG_INF_FMT("ptr=%p persistent=%u", ptr, persistent); 
-
-       if (ptr) {
-               if (collect_memory_statistics) {
-                       free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
-                       DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
-               }
-               pefree(REAL_PTR(ptr), persistent);
-       }
-
-       if (collect_memory_statistics) {
-               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(persistent? STAT_MEM_FREE_COUNT:STAT_MEM_EFREE_COUNT, 1,
-                                                                                         persistent? STAT_MEM_FREE_AMOUNT:STAT_MEM_EFREE_AMOUNT, free_amount);
-       }
-       DBG_VOID_RETURN;
-}
-
-
-/* {{{ _mysqlnd_malloc */
-void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D)
-{
-       void *ret;
-       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
-       long * threshold = &MYSQLND_G(debug_malloc_fail_threshold);
-       DBG_ENTER(mysqlnd_malloc_name);
-       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-
-#if PHP_DEBUG
-       /* -1 is also "true" */
-       if (*threshold) {
-#endif
-               ret = malloc(REAL_SIZE(size));
-#if PHP_DEBUG
-               --*threshold;
-       } else if (*threshold == 0) {
-               ret = NULL;
-       }
-#endif
-
-       DBG_INF_FMT("size=%lu ptr=%p", size, ret);
-       if (ret && collect_memory_statistics) {
-               *(size_t *) ret = size;
-               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_MALLOC_COUNT, 1, STAT_MEM_MALLOC_AMOUNT, size);
-       }
-       DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_calloc */
-void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
-{
-       void *ret;
-       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
-       long * threshold = &MYSQLND_G(debug_calloc_fail_threshold);
-       DBG_ENTER(mysqlnd_calloc_name);
-       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-
-#if PHP_DEBUG
-       /* -1 is also "true" */
-       if (*threshold) {
-#endif
-               ret = calloc(nmemb, REAL_SIZE(size));
-#if PHP_DEBUG
-               --*threshold;
-       } else if (*threshold == 0) {
-               ret = NULL;
-       }
-#endif
-
-       DBG_INF_FMT("size=%lu ptr=%p", size, ret);
-       if (ret && collect_memory_statistics) {
-               *(size_t *) ret = size;
-               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_CALLOC_COUNT, 1, STAT_MEM_CALLOC_AMOUNT, size);
-       }
-       DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_realloc */
-void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D)
-{
-       void *ret;
-       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
-       long * threshold = &MYSQLND_G(debug_realloc_fail_threshold);
-       DBG_ENTER(mysqlnd_realloc_name);
-       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-       DBG_INF_FMT("ptr=%p new_size=%lu ", new_size, ptr); 
-       DBG_INF_FMT("before: %lu", zend_memory_usage(TRUE TSRMLS_CC));
-
-#if PHP_DEBUG
-       /* -1 is also "true" */
-       if (*threshold) {
-#endif
-               ret = realloc(REAL_PTR(ptr), REAL_SIZE(new_size));
-#if PHP_DEBUG
-               --*threshold;
-       } else if (*threshold == 0) {
-               ret = NULL;
-       }
-#endif
-
-       DBG_INF_FMT("new_ptr=%p", (char*)ret);
-
-       if (ret && collect_memory_statistics) {
-               *(size_t *) ret = new_size;
-               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_REALLOC_COUNT, 1, STAT_MEM_REALLOC_AMOUNT, new_size);
-       }
-       DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_free */
-void _mysqlnd_free(void *ptr MYSQLND_MEM_D)
-{
-       size_t free_amount = 0;
-       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
-       DBG_ENTER(mysqlnd_free_name);
-       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-       DBG_INF_FMT("ptr=%p", ptr); 
-
-       if (ptr) {
-               if (collect_memory_statistics) {
-                       free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
-                       DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
-               }
-               free(REAL_PTR(ptr));
-       }
-
-       if (collect_memory_statistics) {
-               MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_FREE_COUNT, 1, STAT_MEM_FREE_AMOUNT, free_amount);
-       }
-       DBG_VOID_RETURN;
-}
-/* }}} */
-
-#define SMART_STR_START_SIZE 2048
-#define SMART_STR_PREALLOC 512
-#include "ext/standard/php_smart_str.h"
-
-
-/* {{{ _mysqlnd_pestrndup */
-char * _mysqlnd_pestrndup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)
-{
-       char * ret;
-       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
-       DBG_ENTER(mysqlnd_pestrndup_name);
-       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-       DBG_INF_FMT("ptr=%p", ptr); 
-
-       ret = pemalloc(REAL_SIZE(length) + 1, persistent);
-       {
-               size_t l = length;
-               char * p = (char *) ptr;
-               char * dest = (char *) FAKE_PTR(ret);
-               while (*p && l--) {
-                       *dest++ = *p++;
-               }
-               *dest = '\0';
-       }
-
-       if (collect_memory_statistics) {
-               *(size_t *) ret = length;
-               MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRNDUP_COUNT : STAT_MEM_ESTRNDUP_COUNT);
-       }
-
-       DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_pestrdup */
-char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)
-{
-       char * ret;
-       smart_str tmp_str = {0, 0, 0};
-       const char * p = ptr;
-       zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
-       DBG_ENTER(mysqlnd_pestrdup_name);
-       DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-       DBG_INF_FMT("ptr=%p", ptr);
-       do {
-               smart_str_appendc(&tmp_str, *p);
-       } while (*p++);
-
-       ret = pemalloc(tmp_str.len + sizeof(size_t), persistent);
-       memcpy(FAKE_PTR(ret), tmp_str.c, tmp_str.len);
-
-       if (ret && collect_memory_statistics) {
-               *(size_t *) ret = tmp_str.len;
-               MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRDUP_COUNT : STAT_MEM_ESTRDUP_COUNT);
-       }
-       smart_str_free(&tmp_str);
-
-       DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-#define MYSQLND_DEBUG_MEMORY 1
-
-#if MYSQLND_DEBUG_MEMORY == 0
-
-/* {{{ mysqlnd_zend_mm_emalloc */
-static void * mysqlnd_zend_mm_emalloc(size_t size MYSQLND_MEM_D)
-{
-       return emalloc(size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_pemalloc */
-static void * mysqlnd_zend_mm_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
-{
-       return pemalloc(size, persistent);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_ecalloc */
-static void * mysqlnd_zend_mm_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
-{
-       return ecalloc(nmemb, size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_pecalloc */
-static void * mysqlnd_zend_mm_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)
-{
-       return pecalloc(nmemb, size, persistent);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_erealloc */
-static void * mysqlnd_zend_mm_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
-{
-       return erealloc(ptr, new_size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_perealloc */
-static void * mysqlnd_zend_mm_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)
-{
-       return perealloc(ptr, new_size, persistent);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_efree */
-static void mysqlnd_zend_mm_efree(void * ptr MYSQLND_MEM_D)
-{
-       efree(ptr);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_pefree */
-static void mysqlnd_zend_mm_pefree(void * ptr, zend_bool persistent MYSQLND_MEM_D)
-{
-       pefree(ptr, persistent);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_malloc */
-static void * mysqlnd_zend_mm_malloc(size_t size MYSQLND_MEM_D)
-{
-       return malloc(size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_calloc */
-static void * mysqlnd_zend_mm_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
-{
-       return calloc(nmemb, size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_realloc */
-static void * mysqlnd_zend_mm_realloc(void * ptr, size_t new_size MYSQLND_MEM_D)
-{
-       return realloc(ptr, new_size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_free */
-static void mysqlnd_zend_mm_free(void * ptr MYSQLND_MEM_D)
-{
-       free(ptr);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_pestrndup */
-static char * mysqlnd_zend_mm_pestrndup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)
-{
-       return pestrndup(ptr, length, persistent);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_pestrdup */
-static char * mysqlnd_zend_mm_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)
-{
-       return pestrdup(ptr, persistent);
-}
-/* }}} */
-
-#endif
-
-
-PHPAPI struct st_mysqlnd_allocator_methods mysqlnd_allocator = 
-{
-#if MYSQLND_DEBUG_MEMORY
-       _mysqlnd_emalloc,
-       _mysqlnd_pemalloc,
-       _mysqlnd_ecalloc,
-       _mysqlnd_pecalloc,
-       _mysqlnd_erealloc,
-       _mysqlnd_perealloc,
-       _mysqlnd_efree,
-       _mysqlnd_pefree,
-       _mysqlnd_malloc,
-       _mysqlnd_calloc,
-       _mysqlnd_realloc,
-       _mysqlnd_free,
-       _mysqlnd_pestrndup,
-       _mysqlnd_pestrdup
-#else
-       mysqlnd_zend_mm_emalloc,
-       mysqlnd_zend_mm_pemalloc,
-       mysqlnd_zend_mm_ecalloc,
-       mysqlnd_zend_mm_pecalloc,
-       mysqlnd_zend_mm_erealloc,
-       mysqlnd_zend_mm_perealloc,
-       mysqlnd_zend_mm_efree,
-       mysqlnd_zend_mm_pefree,
-       mysqlnd_zend_mm_malloc,
-       mysqlnd_zend_mm_calloc,
-       mysqlnd_zend_mm_realloc,
-       mysqlnd_zend_mm_free,
-       mysqlnd_zend_mm_pestrndup,
-       mysqlnd_zend_mm_pestrdup
-#endif
-};
-
-
-
-/* Follows code borrowed from zend_builtin_functions.c because the functions there are static */
-
-#if MYSQLND_UNICODE
-/* {{{ gettraceasstring() macros */
-#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_USTRL(val, vallen) \
-       { \
-               zval tmp, copy; \
-               int use_copy; \
-               ZVAL_UNICODEL(&tmp, val, vallen, 1); \
-               zend_make_printable_zval(&tmp, &copy, &use_copy); \
-               TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
-               zval_dtor(&copy); \
-               zval_dtor(&tmp); \
-       }
-
-#define TRACE_APPEND_ZVAL(zv) \
-       if (Z_TYPE_P((zv)) == IS_UNICODE) { \
-               zval copy; \
-               int use_copy; \
-               zend_make_printable_zval((zv), &copy, &use_copy); \
-               TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
-               zval_dtor(&copy); \
-       } else { \
-               TRACE_APPEND_STRL(Z_STRVAL_P((zv)), Z_STRLEN_P((zv))); \
-       }
-
-#define TRACE_APPEND_STR(val)                                            \
-       TRACE_APPEND_STRL(val, sizeof(val)-1)
-
-#define TRACE_APPEND_KEY(key)                                            \
-       if (zend_ascii_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
-               if (Z_TYPE_PP(tmp) == IS_UNICODE) { \
-                       zval copy; \
-                       int use_copy; \
-                       zend_make_printable_zval(*tmp, &copy, &use_copy); \
-                       TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
-                       zval_dtor(&copy); \
-               } else { \
-               TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));           \
-               } \
-       }
-/* }}} */
-
-/* {{{ mysqlnd_build_trace_args */
-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*);
-
-       /* the trivial way would be to do:
-        * conver_to_string_ex(arg);
-        * append it and kill the now tmp arg.
-        * but that could cause some E_NOTICE and also damn long lines.
-        */
-
-       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; /* +1 because of while (--l_added) */
-                       } 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 ((unsigned char)(*str)[*len - l_added] < 32) {
-                                       (*str)[*len - l_added] = '?';
-                               }
-                       }
-                       break;
-               }
-               case IS_UNICODE: {
-                       int l_added;
-
-                       /*
-                        * We do not want to apply current error mode here, since
-                        * zend_make_printable_zval() uses output encoding converter.
-                        * Temporarily set output encoding converter to escape offending
-                        * chars with \uXXXX notation.
-                        */
-                       zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, ZEND_CONV_ERROR_ESCAPE_JAVA);
-                       TRACE_APPEND_CHR('\'');
-                       if (Z_USTRLEN_PP(arg) > 15) {
-                               TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), 15);
-                               TRACE_APPEND_STR("...', ");
-                               l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
-                       } else {
-                               l_added = Z_USTRLEN_PP(arg);
-                               TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), l_added);
-                               TRACE_APPEND_STR("', ");
-                               l_added += 3 + 1;
-                       }
-                       /*
-                        * Reset output encoding converter error mode.
-                        */
-                       zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, UG(from_error_mode));
-                       while (--l_added) {
-                               if ((unsigned char)(*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 #");
-                       /* break; */
-               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);  /* SAFE */
-                       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);  /* SAFE */
-                       TRACE_APPEND_STRL(s_tmp, l_tmp);
-                       /* %G already handles removing trailing zeros from the fractional part, yay */
-                       efree(s_tmp);
-                       TRACE_APPEND_STR(", ");
-                       break;
-               }
-               case IS_ARRAY:
-                       TRACE_APPEND_STR("Array, ");
-                       break;
-               case IS_OBJECT: {
-                       zval tmp;
-                       zstr class_name;
-                       zend_uint class_name_len;
-                       int dup;
-
-                       TRACE_APPEND_STR("Object(");
-
-                       dup = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC);
-
-                       ZVAL_UNICODEL(&tmp, class_name.u, class_name_len, 1);
-                       convert_to_string_with_converter(&tmp, ZEND_U_CONVERTER(UG(output_encoding_conv)));
-                       TRACE_APPEND_STRL(Z_STRVAL(tmp), Z_STRLEN(tmp));
-                       zval_dtor(&tmp);
-
-                       if(!dup) {
-                               efree(class_name.v);
-                       }
-
-                       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_ascii_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
-               if (zend_ascii_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
-                       line = Z_LVAL_PP(tmp);
-               } else {
-                       line = 0;
-               }
-               TRACE_APPEND_ZVAL(*file);
-               s_tmp = emalloc(MAX_LENGTH_OF_LONG + 2 + 1);
-               sprintf(s_tmp, "(%ld): ", 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_ascii_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; /* remove last ', ' */
-               }
-       }
-       TRACE_APPEND_STR(")\n");
-       return ZEND_HASH_APPLY_KEEP;
-}
-/* }}} */
-
-
-#else /* PHP 5*/
-
-
-/* {{{ gettraceasstring() macros */
-#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*);
-
-       /* the trivial way would be to do:
-        * conver_to_string_ex(arg);
-        * append it and kill the now tmp arg.
-        * but that could cause some E_NOTICE and also damn long lines.
-        */
-
-       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; /* +1 because of while (--l_added) */
-                       } 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 #");
-                       /* break; */
-               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);  /* SAFE */
-                       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);  /* SAFE */
-                       TRACE_APPEND_STRL(s_tmp, l_tmp);
-                       /* %G already handles removing trailing zeros from the fractional part, yay */
-                       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, &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; /* remove last ', ' */
-               }
-       }
-       TRACE_APPEND_STR(")\n");
-       return ZEND_HASH_APPLY_KEEP;
-}
-/* }}} */
-#endif
-
-
-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 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;
-}
-
-
 static struct st_mysqlnd_plugin_trace_log mysqlnd_plugin_trace_log_plugin =
 {
        {
@@ -1880,6 +790,7 @@ static struct st_mysqlnd_plugin_trace_log mysqlnd_plugin_trace_log_plugin =
        }
 };
 
+
 /* {{{ mysqlnd_debug_trace_plugin_register */
 void
 mysqlnd_debug_trace_plugin_register(TSRMLS_D)
index 65560e5e5f3c48201f0fa02c92bc65e1d192b064..ff96d1e7c0bdf45160f2ec873ca2d05b2d9c5bd7 100644 (file)
@@ -23,6 +23,7 @@
 #ifndef MYSQLND_DEBUG_H
 #define MYSQLND_DEBUG_H
 
+#include "mysqlnd_alloc.h"
 #include "zend_stack.h"
 
 struct st_mysqlnd_debug_methods
@@ -71,11 +72,9 @@ struct st_mysqlnd_plugin_trace_log
 
 void mysqlnd_debug_trace_plugin_register(TSRMLS_D);
 
-PHPAPI extern const char * mysqlnd_debug_std_no_trace_funcs[];
-
 PHPAPI MYSQLND_DEBUG * mysqlnd_debug_init(const char * skip_functions[] TSRMLS_DC);
 
-PHPAPI char *  mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC);
+PHPAPI char * mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC);
 
 #if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 1400))
 #ifdef PHP_WIN32
@@ -162,8 +161,6 @@ static inline void DBG_ENTER_EX(MYSQLND_DEBUG * dbg_obj, const char * const func
 
 #elif MYSQLND_DBG_ENABLED == 0
 
-
-
 static inline void DBG_INF(const char * const msg) {}
 static inline void DBG_ERR(const char * const msg) {}
 static inline void DBG_INF_FMT(const char * const format, ...) {}
@@ -174,62 +171,6 @@ static inline void DBG_ENTER(const char * const func_name) {}
 
 #endif
 
-
-#define MYSQLND_MEM_D  TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC
-#define MYSQLND_MEM_C  TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC
-
-struct st_mysqlnd_allocator_methods
-{
-       void *  (*m_emalloc)(size_t size MYSQLND_MEM_D);
-       void *  (*m_pemalloc)(size_t size, zend_bool persistent MYSQLND_MEM_D);
-       void *  (*m_ecalloc)(unsigned int nmemb, size_t size MYSQLND_MEM_D);
-       void *  (*m_pecalloc)(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D);
-       void *  (*m_erealloc)(void *ptr, size_t new_size MYSQLND_MEM_D);
-       void *  (*m_perealloc)(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D);
-       void    (*m_efree)(void *ptr MYSQLND_MEM_D);
-       void    (*m_pefree)(void *ptr, zend_bool persistent MYSQLND_MEM_D);
-       void *  (*m_malloc)(size_t size MYSQLND_MEM_D);
-       void *  (*m_calloc)(unsigned int nmemb, size_t size MYSQLND_MEM_D);
-       void *  (*m_realloc)(void *ptr, size_t new_size MYSQLND_MEM_D);
-       void    (*m_free)(void *ptr MYSQLND_MEM_D);
-       char *  (*m_pestrndup)(const char * const ptr, size_t size, zend_bool persistent MYSQLND_MEM_D);
-       char *  (*m_pestrdup)(const char * const ptr, zend_bool persistent MYSQLND_MEM_D);
-};
-
-PHPAPI extern struct st_mysqlnd_allocator_methods mysqlnd_allocator;
-
-
-PHPAPI void *  _mysqlnd_emalloc(size_t size MYSQLND_MEM_D);
-PHPAPI void *  _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D);
-PHPAPI void *  _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D);
-PHPAPI void *  _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D);
-PHPAPI void *  _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D);
-PHPAPI void *  _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D);
-PHPAPI void            _mysqlnd_efree(void *ptr MYSQLND_MEM_D);
-PHPAPI void            _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D);
-PHPAPI void *  _mysqlnd_malloc(size_t size MYSQLND_MEM_D);
-PHPAPI void *  _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D);
-PHPAPI void *  _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D);
-PHPAPI void            _mysqlnd_free(void *ptr MYSQLND_MEM_D);
-PHPAPI char *  _mysqlnd_pestrndup(const char * const ptr, size_t size, zend_bool persistent MYSQLND_MEM_D);
-PHPAPI char *  _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D);
-
-
-#define mnd_emalloc(size)                              mysqlnd_allocator.m_emalloc((size) MYSQLND_MEM_C)
-#define mnd_pemalloc(size, pers)               mysqlnd_allocator.m_pemalloc((size), (pers) MYSQLND_MEM_C)
-#define mnd_ecalloc(nmemb, size)               mysqlnd_allocator.m_ecalloc((nmemb), (size) MYSQLND_MEM_C)
-#define mnd_pecalloc(nmemb, size, p)   mysqlnd_allocator.m_pecalloc((nmemb), (size), (p) MYSQLND_MEM_C)
-#define mnd_erealloc(ptr, new_size)            mysqlnd_allocator.m_erealloc((ptr), (new_size) MYSQLND_MEM_C)
-#define mnd_perealloc(ptr, new_size, p)        mysqlnd_allocator.m_perealloc((ptr), (new_size), (p) MYSQLND_MEM_C)
-#define mnd_efree(ptr)                                 mysqlnd_allocator.m_efree((ptr) MYSQLND_MEM_C)
-#define mnd_pefree(ptr, pers)                  mysqlnd_allocator.m_pefree((ptr), (pers) MYSQLND_MEM_C)
-#define mnd_malloc(size)                               mysqlnd_allocator.m_malloc((size) MYSQLND_MEM_C)
-#define mnd_calloc(nmemb, size)                        mysqlnd_allocator.m_calloc((nmemb), (size) MYSQLND_MEM_C)
-#define mnd_realloc(ptr, new_size)             mysqlnd_allocator.m_realloc((ptr), (new_size) MYSQLND_MEM_C)
-#define mnd_free(ptr)                                  mysqlnd_allocator.m_free((ptr) MYSQLND_MEM_C)
-#define mnd_pestrndup(ptr, size, pers) mysqlnd_allocator.m_pestrndup((ptr), (size), (pers) MYSQLND_MEM_C)
-#define mnd_pestrdup(ptr, pers)                        mysqlnd_allocator.m_pestrdup((ptr), (pers) MYSQLND_MEM_C)
-
 #endif /* MYSQLND_DEBUG_H */
 
 /*