Browse Source

Reimplemented ability to get debug info (C source file and line number) in phpdbg without hacks and ABI breaks.

Dmitry Stogov 11 years ago
parent
commit
162bf9e802
  1. 98
      Zend/zend_alloc.c
  2. 11
      Zend/zend_alloc.h
  3. 16
      Zend/zend_portability.h
  4. 61
      sapi/phpdbg/phpdbg.c
  5. 4
      sapi/phpdbg/phpdbg_watch.c

98
Zend/zend_alloc.c

@ -266,9 +266,18 @@ struct _zend_mm_heap {
int cached_chunks_count; /* number of cached chunks */ int cached_chunks_count; /* number of cached chunks */
double avg_chunks_count; /* average number of chunks allocated per request */ double avg_chunks_count; /* average number of chunks allocated per request */
#if ZEND_MM_CUSTOM #if ZEND_MM_CUSTOM
void *(*_malloc)(size_t);
void (*_free)(void*);
void *(*_realloc)(void*, size_t);
union {
struct {
void *(*_malloc)(size_t);
void (*_free)(void*);
void *(*_realloc)(void*, size_t);
} std;
struct {
void *(*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
void *(*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
} debug;
} custom_heap;
#endif #endif
}; };
@ -1810,7 +1819,7 @@ static zend_mm_heap *zend_mm_init(void)
heap->overflow = 0; heap->overflow = 0;
#endif #endif
#if ZEND_MM_CUSTOM #if ZEND_MM_CUSTOM
heap->use_custom_heap = 0;
heap->use_custom_heap = ZEND_MM_CUSTOM_HEAP_NONE;
#endif #endif
#if ZEND_MM_STORAGE #if ZEND_MM_STORAGE
heap->storage = NULL; heap->storage = NULL;
@ -2111,7 +2120,11 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent)
#if ZEND_MM_CUSTOM #if ZEND_MM_CUSTOM
if (heap->use_custom_heap) { if (heap->use_custom_heap) {
if (full) { if (full) {
heap->_free(heap);
if (ZEND_DEBUG && heap->use_custom_heap == ZEND_MM_CUSTOM_HEAP_DEBUG) {
heap->custom_heap.debug._free(heap ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
} else {
heap->custom_heap.std._free(heap);
}
} }
return; return;
} }
@ -2258,12 +2271,20 @@ ZEND_API int is_zend_mm(void)
#if ZEND_MM_CUSTOM #if ZEND_MM_CUSTOM
# define ZEND_MM_CUSTOM_ALLOCATOR(size) do { \ # define ZEND_MM_CUSTOM_ALLOCATOR(size) do { \
if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { \ if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { \
return AG(mm_heap)->_malloc(size); \
if (ZEND_DEBUG && AG(mm_heap)->use_custom_heap == ZEND_MM_CUSTOM_HEAP_DEBUG) { \
return AG(mm_heap)->custom_heap.debug._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
} else { \
return AG(mm_heap)->custom_heap.std._malloc(size); \
} \
} \ } \
} while (0) } while (0)
# define ZEND_MM_CUSTOM_DEALLOCATOR(ptr) do { \ # define ZEND_MM_CUSTOM_DEALLOCATOR(ptr) do { \
if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { \ if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { \
AG(mm_heap)->_free(ptr); \
if (ZEND_DEBUG && AG(mm_heap)->use_custom_heap == ZEND_MM_CUSTOM_HEAP_DEBUG) { \
AG(mm_heap)->custom_heap.debug._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
} else { \
AG(mm_heap)->custom_heap.std._free(ptr); \
} \
return; \ return; \
} \ } \
} while (0) } while (0)
@ -2353,7 +2374,11 @@ ZEND_API void* ZEND_FASTCALL _emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LI
#if ZEND_MM_CUSTOM #if ZEND_MM_CUSTOM
if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) {
return AG(mm_heap)->_malloc(size);
if (ZEND_DEBUG && AG(mm_heap)->use_custom_heap == ZEND_MM_CUSTOM_HEAP_DEBUG) {
return AG(mm_heap)->custom_heap.debug._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
} else {
return AG(mm_heap)->custom_heap.std._malloc(size);
}
} }
#endif #endif
return zend_mm_alloc_heap(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); return zend_mm_alloc_heap(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
@ -2364,7 +2389,11 @@ ZEND_API void ZEND_FASTCALL _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_OR
#if ZEND_MM_CUSTOM #if ZEND_MM_CUSTOM
if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) {
AG(mm_heap)->_free(ptr);
if (ZEND_DEBUG && AG(mm_heap)->use_custom_heap == ZEND_MM_CUSTOM_HEAP_DEBUG) {
AG(mm_heap)->custom_heap.debug._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
} else {
AG(mm_heap)->custom_heap.std._free(ptr);
}
return; return;
} }
#endif #endif
@ -2375,7 +2404,11 @@ ZEND_API void* ZEND_FASTCALL _erealloc(void *ptr, size_t size ZEND_FILE_LINE_DC
{ {
if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) {
return AG(mm_heap)->_realloc(ptr, size);
if (ZEND_DEBUG && AG(mm_heap)->use_custom_heap == ZEND_MM_CUSTOM_HEAP_DEBUG) {
return AG(mm_heap)->custom_heap.debug._realloc(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
} else {
return AG(mm_heap)->custom_heap.std._realloc(ptr, size);
}
} }
return zend_mm_realloc_heap(AG(mm_heap), ptr, size, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); return zend_mm_realloc_heap(AG(mm_heap), ptr, size, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
} }
@ -2384,7 +2417,11 @@ ZEND_API void* ZEND_FASTCALL _erealloc2(void *ptr, size_t size, size_t copy_size
{ {
if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) {
return AG(mm_heap)->_realloc(ptr, size);
if (ZEND_DEBUG && AG(mm_heap)->use_custom_heap == ZEND_MM_CUSTOM_HEAP_DEBUG) {
return AG(mm_heap)->custom_heap.debug._realloc(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
} else {
return AG(mm_heap)->custom_heap.std._realloc(ptr, size);
}
} }
return zend_mm_realloc_heap(AG(mm_heap), ptr, size, copy_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); return zend_mm_realloc_heap(AG(mm_heap), ptr, size, copy_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
} }
@ -2549,10 +2586,10 @@ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals)
if (tmp && !zend_atoi(tmp, 0)) { if (tmp && !zend_atoi(tmp, 0)) {
alloc_globals->mm_heap = malloc(sizeof(zend_mm_heap)); alloc_globals->mm_heap = malloc(sizeof(zend_mm_heap));
memset(alloc_globals->mm_heap, 0, sizeof(zend_mm_heap)); memset(alloc_globals->mm_heap, 0, sizeof(zend_mm_heap));
alloc_globals->mm_heap->use_custom_heap = 1;
alloc_globals->mm_heap->_malloc = malloc;
alloc_globals->mm_heap->_free = free;
alloc_globals->mm_heap->_realloc = realloc;
alloc_globals->mm_heap->use_custom_heap = ZEND_MM_CUSTOM_HEAP_STD;
alloc_globals->mm_heap->custom_heap.std._malloc = malloc;
alloc_globals->mm_heap->custom_heap.std._free = free;
alloc_globals->mm_heap->custom_heap.std._realloc = realloc;
return; return;
} }
#endif #endif
@ -2614,10 +2651,10 @@ ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
#if ZEND_MM_CUSTOM #if ZEND_MM_CUSTOM
zend_mm_heap *_heap = (zend_mm_heap*)heap; zend_mm_heap *_heap = (zend_mm_heap*)heap;
_heap->use_custom_heap = 1;
_heap->_malloc = _malloc;
_heap->_free = _free;
_heap->_realloc = _realloc;
_heap->use_custom_heap = ZEND_MM_CUSTOM_HEAP_STD;
_heap->custom_heap.std._malloc = _malloc;
_heap->custom_heap.std._free = _free;
_heap->custom_heap.std._realloc = _realloc;
#endif #endif
} }
@ -2630,9 +2667,9 @@ ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
zend_mm_heap *_heap = (zend_mm_heap*)heap; zend_mm_heap *_heap = (zend_mm_heap*)heap;
if (heap->use_custom_heap) { if (heap->use_custom_heap) {
*_malloc = _heap->_malloc;
*_free = _heap->_free;
*_realloc = _heap->_realloc;
*_malloc = _heap->custom_heap.std._malloc;
*_free = _heap->custom_heap.std._free;
*_realloc = _heap->custom_heap.std._realloc;
} else { } else {
*_malloc = NULL; *_malloc = NULL;
*_free = NULL; *_free = NULL;
@ -2645,6 +2682,23 @@ ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
#endif #endif
} }
#if ZEND_DEBUG
ZEND_API void zend_mm_set_custom_debug_handlers(zend_mm_heap *heap,
void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC))
{
#if ZEND_MM_CUSTOM
zend_mm_heap *_heap = (zend_mm_heap*)heap;
_heap->use_custom_heap = ZEND_MM_CUSTOM_HEAP_DEBUG;
_heap->custom_heap.debug._malloc = _malloc;
_heap->custom_heap.debug._free = _free;
_heap->custom_heap.debug._realloc = _realloc;
#endif
}
#endif
ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap) ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap)
{ {
#if ZEND_MM_STORAGE #if ZEND_MM_STORAGE

11
Zend/zend_alloc.h

@ -284,6 +284,10 @@ ZEND_API zend_mm_heap *zend_mm_get_heap(void);
ZEND_API size_t zend_mm_gc(zend_mm_heap *heap); ZEND_API size_t zend_mm_gc(zend_mm_heap *heap);
#define ZEND_MM_CUSTOM_HEAP_NONE 0
#define ZEND_MM_CUSTOM_HEAP_STD 1
#define ZEND_MM_CUSTOM_HEAP_DEBUG 2
ZEND_API int zend_mm_is_custom_heap(zend_mm_heap *new_heap); ZEND_API int zend_mm_is_custom_heap(zend_mm_heap *new_heap);
ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap, ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
void* (*_malloc)(size_t), void* (*_malloc)(size_t),
@ -294,6 +298,13 @@ ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
void (**_free)(void*), void (**_free)(void*),
void* (**_realloc)(void*, size_t)); void* (**_realloc)(void*, size_t));
#if ZEND_DEBUG
ZEND_API void zend_mm_set_custom_debug_handlers(zend_mm_heap *heap,
void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC));
#endif
typedef struct _zend_mm_storage zend_mm_storage; typedef struct _zend_mm_storage zend_mm_storage;
typedef void* (*zend_mm_chunk_alloc_t)(zend_mm_storage *storage, size_t size, size_t alignment); typedef void* (*zend_mm_chunk_alloc_t)(zend_mm_storage *storage, size_t size, size_t alignment);

16
Zend/zend_portability.h

@ -221,16 +221,12 @@ char *alloca();
# define ZEND_ATTRIBUTE_UNUSED_LABEL # define ZEND_ATTRIBUTE_UNUSED_LABEL
#endif #endif
#if !ZEND_DEBUG
# if defined(__GNUC__) && ZEND_GCC_VERSION >= 3004 && defined(__i386__)
# define ZEND_FASTCALL __attribute__((fastcall))
# elif defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER == 1700
# define ZEND_FASTCALL __fastcall
# elif defined(_MSC_VER) && _MSC_VER >= 1800 && !defined(__clang__)
# define ZEND_FASTCALL __vectorcall
# else
# define ZEND_FASTCALL
# endif
#if defined(__GNUC__) && ZEND_GCC_VERSION >= 3004 && defined(__i386__)
# define ZEND_FASTCALL __attribute__((fastcall))
#elif defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER == 1700
# define ZEND_FASTCALL __fastcall
#elif defined(_MSC_VER) && _MSC_VER >= 1800 && !defined(__clang__)
# define ZEND_FASTCALL __vectorcall
#else #else
# define ZEND_FASTCALL # define ZEND_FASTCALL
#endif #endif

61
sapi/phpdbg/phpdbg.c

@ -1225,48 +1225,12 @@ void phpdbg_signal_handler(int sig, siginfo_t *info, void *context) /* {{{ */
} /* }}} */ } /* }}} */
#endif #endif
/* A bit dark magic in order to have meaningful allocator adresses [ppc(64) may return bogus addresses here] */
#if ZEND_DEBUG && (__has_builtin(__builtin_frame_address) || ZEND_GCC_VERSION >= 3004) && !defined(__ppc__) && !defined(__ppc64__)
/* with gcc %rbp/%ebp for __builtin_frame_address() and clang returns the frame return address being at %ebp/%rbp + sizeof(void*) */
# ifdef __clang__
# define FETCH_PARENT_START() \
parent -= ZEND_MM_ALIGNED_SIZE(sizeof(void *));
# else
# define FETCH_PARENT_START()
# endif
# define FETCH_PARENT_FILELINE(argsize) \
char *__zend_filename, *__zend_orig_filename; \
uint __zend_lineno, __zend_orig_lineno; \
void *parent = __builtin_frame_address(1U); \
FETCH_PARENT_START() \
parent -= (argsize); /* size of first arguments */ \
parent -= sizeof(char *); /* filename */ \
__zend_filename = *(char **) parent; \
parent = (void *) ((intptr_t) parent & ZEND_MM_ALIGNMENT_MASK); /* realign */ \
parent -= sizeof(uint); /* lineno */ \
__zend_lineno = *(uint *) parent; \
parent = (void *) ((intptr_t) parent & ZEND_MM_ALIGNMENT_MASK); /* realign */ \
parent -= sizeof(char *); /* orig_filename */ \
__zend_orig_filename = *(char **) parent; \
parent = (void *) ((intptr_t) parent & ZEND_MM_ALIGNMENT_MASK); /* realign */ \
parent -= sizeof(uint); /* orig_lineno */ \
__zend_orig_lineno = *(uint *) parent;
#elif ZEND_DEBUG
# define FETCH_PARENT_FILELINE(argsize) \
char *__zend_filename = __FILE__, *__zend_orig_filename = NULL; \
uint __zend_lineno = __LINE__, __zend_orig_lineno = 0;
#else
# define FETCH_PARENT_FILELINE(argsize)
#endif
void *phpdbg_malloc_wrapper(size_t size) /* {{{ */
void *phpdbg_malloc_wrapper(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
{ {
FETCH_PARENT_FILELINE(ZEND_MM_ALIGNED_SIZE(sizeof(size)));
return _zend_mm_alloc(zend_mm_get_heap(), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); return _zend_mm_alloc(zend_mm_get_heap(), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
} /* }}} */ } /* }}} */
void phpdbg_free_wrapper(void *p) /* {{{ */
void phpdbg_free_wrapper(void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
{ {
zend_mm_heap *heap = zend_mm_get_heap(); zend_mm_heap *heap = zend_mm_get_heap();
if (UNEXPECTED(heap == p)) { if (UNEXPECTED(heap == p)) {
@ -1274,14 +1238,13 @@ void phpdbg_free_wrapper(void *p) /* {{{ */
* let's prevent it from segfault for now * let's prevent it from segfault for now
*/ */
} else { } else {
FETCH_PARENT_FILELINE(ZEND_MM_ALIGNED_SIZE(sizeof(p)));
phpdbg_watch_efree(p);
return _zend_mm_free(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); return _zend_mm_free(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
} }
} /* }}} */ } /* }}} */
void *phpdbg_realloc_wrapper(void *ptr, size_t size) /* {{{ */
void *phpdbg_realloc_wrapper(void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
{ {
FETCH_PARENT_FILELINE(ZEND_MM_ALIGNED_SIZE(sizeof(ptr)) + ZEND_MM_ALIGNED_SIZE(sizeof(size)));
return _zend_mm_realloc(zend_mm_get_heap(), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); return _zend_mm_realloc(zend_mm_get_heap(), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
} /* }}} */ } /* }}} */
@ -1633,18 +1596,20 @@ phpdbg_main:
use_mm_wrappers = !_malloc && !_realloc && !_free; use_mm_wrappers = !_malloc && !_realloc && !_free;
if (use_mm_wrappers) {
_malloc = phpdbg_malloc_wrapper;
_realloc = phpdbg_realloc_wrapper;
_free = phpdbg_free_wrapper;
}
phpdbg_init_list(); phpdbg_init_list();
PHPDBG_G(original_free_function) = _free; PHPDBG_G(original_free_function) = _free;
_free = phpdbg_watch_efree; _free = phpdbg_watch_efree;
zend_mm_set_custom_handlers(mm_heap, _malloc, _free, _realloc);
if (use_mm_wrappers) {
#if ZEND_DEBUG
zend_mm_set_custom_debug_handlers(mm_heap, phpdbg_malloc_wrapper, phpdbg_free_wrapper, phpdbg_realloc_wrapper);
#else
zend_mm_set_custom_handlers(mm_heap, phpdbg_malloc_wrapper, phpdbg_free_wrapper, phpdbg_realloc_wrapper);
#endif
} else {
zend_mm_set_custom_handlers(mm_heap, _malloc, _free, _realloc);
}
phpdbg_setup_watchpoints(); phpdbg_setup_watchpoints();

4
sapi/phpdbg/phpdbg_watch.c

@ -1133,5 +1133,7 @@ void phpdbg_watch_efree(void *ptr) {
} }
} }
PHPDBG_G(original_free_function)(ptr);
if (PHPDBG_G(original_free_function)) {
PHPDBG_G(original_free_function)(ptr);
}
} }
Loading…
Cancel
Save