mirror of
git://git.code.sf.net/p/zsh/code
synced 2026-01-02 08:21:09 +01:00
32789: --enable-zsh-valgrind allows analysis of heap allocation
This commit is contained in:
parent
0853bcfdd6
commit
920db696cb
5 changed files with 123 additions and 8 deletions
|
|
@ -1,3 +1,9 @@
|
|||
2014-06-24 Peter Stephenson <p.w.stephenson@ntlworld.com>
|
||||
|
||||
* 32789: Src/lex.c Src/mem.c Src/zsh_system.h configure.ac:
|
||||
--enable-zsh-valgrind allows valgrind to analyse heap
|
||||
allocations.
|
||||
|
||||
2014-06-16 Peter Stephenson <p.w.stephenson@ntlworld.com>
|
||||
|
||||
* Jun T: 32781: Doc/Zsh/options.yo: source builtin and path
|
||||
|
|
|
|||
10
Src/lex.c
10
Src/lex.c
|
|
@ -30,6 +30,8 @@
|
|||
#include "zsh.mdh"
|
||||
#include "lex.pro"
|
||||
|
||||
#define LEX_HEAP_SIZE (32)
|
||||
|
||||
/* tokens */
|
||||
|
||||
/**/
|
||||
|
|
@ -721,7 +723,7 @@ gettok(void)
|
|||
/* word includes the last character read and possibly \ before ! */
|
||||
if (dbparens) {
|
||||
len = 0;
|
||||
bptr = tokstr = (char *) hcalloc(bsiz = 32);
|
||||
bptr = tokstr = (char *) hcalloc(bsiz = LEX_HEAP_SIZE);
|
||||
hungetc(c);
|
||||
cmdpush(CS_MATH);
|
||||
c = dquote_parse(infor ? ';' : ')', 0);
|
||||
|
|
@ -775,7 +777,7 @@ gettok(void)
|
|||
|
||||
if (lexflags & LEXFLAGS_COMMENTS_KEEP) {
|
||||
len = 0;
|
||||
bptr = tokstr = (char *)hcalloc(bsiz = 32);
|
||||
bptr = tokstr = (char *)hcalloc(bsiz = LEX_HEAP_SIZE);
|
||||
add(c);
|
||||
}
|
||||
hwend();
|
||||
|
|
@ -877,7 +879,7 @@ gettok(void)
|
|||
}
|
||||
if (incmdpos || (isset(SHGLOB) && !isset(KSHGLOB))) {
|
||||
len = 0;
|
||||
bptr = tokstr = (char *) hcalloc(bsiz = 32);
|
||||
bptr = tokstr = (char *) hcalloc(bsiz = LEX_HEAP_SIZE);
|
||||
switch (cmd_or_math(CS_MATH)) {
|
||||
case 1:
|
||||
return DINPAR;
|
||||
|
|
@ -1027,7 +1029,7 @@ gettokstr(int c, int sub)
|
|||
peek = STRING;
|
||||
if (!sub) {
|
||||
len = 0;
|
||||
bptr = tokstr = (char *) hcalloc(bsiz = 32);
|
||||
bptr = tokstr = (char *) hcalloc(bsiz = LEX_HEAP_SIZE);
|
||||
}
|
||||
for (;;) {
|
||||
int act;
|
||||
|
|
|
|||
99
Src/mem.c
99
Src/mem.c
|
|
@ -225,6 +225,9 @@ old_heaps(Heap old)
|
|||
munmap((void *) h, h->size);
|
||||
#else
|
||||
zfree(h, HEAPSIZE);
|
||||
#endif
|
||||
#ifdef ZSH_VALGRIND
|
||||
VALGRIND_DESTROY_MEMPOOL((char *)h);
|
||||
#endif
|
||||
}
|
||||
heaps = old;
|
||||
|
|
@ -347,6 +350,10 @@ freeheap(void)
|
|||
hn = h->next;
|
||||
if (h->sp) {
|
||||
#ifdef ZSH_MEM_DEBUG
|
||||
#ifdef ZSH_VALGRIND
|
||||
VALGRIND_MAKE_MEM_UNDEFINED((char *)arena(h) + h->sp->used,
|
||||
h->used - h->sp->used);
|
||||
#endif
|
||||
memset(arena(h) + h->sp->used, 0xff, h->used - h->sp->used);
|
||||
#endif
|
||||
h->used = h->sp->used;
|
||||
|
|
@ -368,12 +375,18 @@ freeheap(void)
|
|||
}
|
||||
h->heap_id = new_id;
|
||||
}
|
||||
#endif
|
||||
#ifdef ZSH_VALGRIND
|
||||
VALGRIND_MEMPOOL_TRIM((char *)h, (char *)arena(h), h->used);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef USE_MMAP
|
||||
munmap((void *) h, h->size);
|
||||
#else
|
||||
zfree(h, HEAPSIZE);
|
||||
#endif
|
||||
#ifdef ZSH_VALGRIND
|
||||
VALGRIND_DESTROY_MEMPOOL((char *)h);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -406,6 +419,10 @@ popheap(void)
|
|||
if ((hs = h->sp)) {
|
||||
h->sp = hs->next;
|
||||
#ifdef ZSH_MEM_DEBUG
|
||||
#ifdef ZSH_VALGRIND
|
||||
VALGRIND_MAKE_MEM_UNDEFINED((char *)arena(h) + hs->used,
|
||||
h->used - hs->used);
|
||||
#endif
|
||||
memset(arena(h) + hs->used, 0xff, h->used - hs->used);
|
||||
#endif
|
||||
h->used = hs->used;
|
||||
|
|
@ -416,6 +433,9 @@ popheap(void)
|
|||
h->heap_id, hs->heap_id);
|
||||
}
|
||||
h->heap_id = hs->heap_id;
|
||||
#endif
|
||||
#ifdef ZSH_VALGRIND
|
||||
VALGRIND_MEMPOOL_TRIM((char *)h, (char *)arena(h), h->used);
|
||||
#endif
|
||||
if (!fheap && h->used < ARENA_SIZEOF(h))
|
||||
fheap = h;
|
||||
|
|
@ -427,6 +447,9 @@ popheap(void)
|
|||
munmap((void *) h, h->size);
|
||||
#else
|
||||
zfree(h, HEAPSIZE);
|
||||
#endif
|
||||
#ifdef ZSH_VALGRIND
|
||||
VALGRIND_DESTROY_MEMPOOL((char *)h);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -499,6 +522,12 @@ zhalloc(size_t size)
|
|||
{
|
||||
Heap h;
|
||||
size_t n;
|
||||
#ifdef ZSH_VALGRIND
|
||||
size_t req_size = size;
|
||||
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
size = (size + H_ISIZE - 1) & ~(H_ISIZE - 1);
|
||||
|
||||
|
|
@ -525,6 +554,9 @@ zhalloc(size_t size)
|
|||
fprintf(stderr, "HEAP DEBUG: allocated memory from heap "
|
||||
HEAPID_FMT ".\n", h->heap_id);
|
||||
}
|
||||
#endif
|
||||
#ifdef ZSH_VALGRIND
|
||||
VALGRIND_MEMPOOL_ALLOC((char *)h, (char *)ret, req_size);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -564,6 +596,12 @@ zhalloc(size_t size)
|
|||
h->heap_id);
|
||||
}
|
||||
#endif
|
||||
#ifdef ZSH_VALGRIND
|
||||
VALGRIND_CREATE_MEMPOOL((char *)h, 0, 0);
|
||||
VALGRIND_MAKE_MEM_NOACCESS((char *)arena(h),
|
||||
n - ((char *)arena(h)-(char *)h));
|
||||
VALGRIND_MEMPOOL_ALLOC((char *)h, (char *)arena(h), req_size);
|
||||
#endif
|
||||
|
||||
if (hp)
|
||||
hp->next = h;
|
||||
|
|
@ -589,13 +627,21 @@ hrealloc(char *p, size_t old, size_t new)
|
|||
{
|
||||
Heap h, ph;
|
||||
|
||||
#ifdef ZSH_VALGRIND
|
||||
size_t new_req = new;
|
||||
#endif
|
||||
|
||||
old = (old + H_ISIZE - 1) & ~(H_ISIZE - 1);
|
||||
new = (new + H_ISIZE - 1) & ~(H_ISIZE - 1);
|
||||
|
||||
if (old == new)
|
||||
return p;
|
||||
if (!old && !p)
|
||||
#ifdef ZSH_VALGRIND
|
||||
return zhalloc(new_req);
|
||||
#else
|
||||
return zhalloc(new);
|
||||
#endif
|
||||
|
||||
/* find the heap with p */
|
||||
|
||||
|
|
@ -618,14 +664,33 @@ hrealloc(char *p, size_t old, size_t new)
|
|||
*/
|
||||
if (p + old < arena(h) + h->used) {
|
||||
if (new > old) {
|
||||
#ifdef ZSH_VALGRIND
|
||||
char *ptr = (char *) zhalloc(new_req);
|
||||
#else
|
||||
char *ptr = (char *) zhalloc(new);
|
||||
#endif
|
||||
memcpy(ptr, p, old);
|
||||
#ifdef ZSH_MEM_DEBUG
|
||||
memset(p, 0xff, old);
|
||||
#endif
|
||||
#ifdef ZSH_VALGRIND
|
||||
VALGRIND_MEMPOOL_FREE((char *)h, (char *)p);
|
||||
/*
|
||||
* zhalloc() marked h,ptr,new as an allocation so we don't
|
||||
* need to do that here.
|
||||
*/
|
||||
#endif
|
||||
unqueue_signals();
|
||||
return ptr;
|
||||
} else {
|
||||
#ifdef ZSH_VALGRIND
|
||||
VALGRIND_MEMPOOL_FREE((char *)h, (char *)p);
|
||||
if (p) {
|
||||
VALGRIND_MEMPOOL_ALLOC((char *)h, (char *)p,
|
||||
new_req);
|
||||
VALGRIND_MAKE_MEM_DEFINED((char *)h, (char *)p);
|
||||
}
|
||||
#endif
|
||||
unqueue_signals();
|
||||
return new ? p : NULL;
|
||||
}
|
||||
|
|
@ -659,11 +724,15 @@ hrealloc(char *p, size_t old, size_t new)
|
|||
munmap((void *) h, h->size);
|
||||
#else
|
||||
zfree(h, HEAPSIZE);
|
||||
#endif
|
||||
#ifdef ZSH_VALGRIND
|
||||
VALGRIND_DESTROY_MEMPOOL((char *)h);
|
||||
#endif
|
||||
unqueue_signals();
|
||||
return NULL;
|
||||
}
|
||||
if (new > ARENA_SIZEOF(h)) {
|
||||
Heap hnew;
|
||||
/*
|
||||
* Not enough memory in this heap. Allocate a new
|
||||
* one of sufficient size.
|
||||
|
|
@ -685,17 +754,23 @@ hrealloc(char *p, size_t old, size_t new)
|
|||
* a mmap'd segment be extended, so simply allocate
|
||||
* a new one and copy.
|
||||
*/
|
||||
Heap hnew;
|
||||
|
||||
hnew = mmap_heap_alloc(&n);
|
||||
/* Copy the entire heap, header (with next pointer) included */
|
||||
memcpy(hnew, h, h->size);
|
||||
munmap((void *)h, h->size);
|
||||
h = hnew;
|
||||
}
|
||||
#else
|
||||
h = (Heap) realloc(h, n);
|
||||
hnew = (Heap) realloc(h, n);
|
||||
#endif
|
||||
#ifdef ZSH_VALGRIND
|
||||
VALGRIND_MEMPOOL_FREE((char *)h, p);
|
||||
VALGRIND_DESTROY_MEMPOOL((char *)h);
|
||||
VALGRIND_CREATE_MEMPOOL((char *)hnew, 0, 0);
|
||||
VALGRIND_MEMPOOL_ALLOC((char *)hnew, (char *)arena(hnew),
|
||||
new_req);
|
||||
VALGRIND_MAKE_MEM_DEFINED((char *)hnew, (char *)arena(hnew));
|
||||
#endif
|
||||
h = hnew;
|
||||
|
||||
h->size = n;
|
||||
if (ph)
|
||||
|
|
@ -703,6 +778,13 @@ hrealloc(char *p, size_t old, size_t new)
|
|||
else
|
||||
heaps = h;
|
||||
}
|
||||
#ifdef ZSH_VALGRIND
|
||||
else {
|
||||
VALGRIND_MEMPOOL_FREE((char *)h, (char *)p);
|
||||
VALGRIND_MEMPOOL_ALLOC((char *)h, (char *)p, new_req);
|
||||
VALGRIND_MAKE_MEM_DEFINED((char *)h, (char *)p);
|
||||
}
|
||||
#endif
|
||||
h->used = new;
|
||||
#ifdef ZSH_HEAP_DEBUG
|
||||
h->heap_id = heap_id;
|
||||
|
|
@ -716,6 +798,11 @@ hrealloc(char *p, size_t old, size_t new)
|
|||
if (h->used + (new - old) <= ARENA_SIZEOF(h)) {
|
||||
h->used += new - old;
|
||||
unqueue_signals();
|
||||
#ifdef ZSH_VALGRIND
|
||||
VALGRIND_MEMPOOL_FREE((char *)h, (char *)p);
|
||||
VALGRIND_MEMPOOL_ALLOC((char *)h, (char *)p, new_req);
|
||||
VALGRIND_MAKE_MEM_DEFINED((char *)h, (char *)p);
|
||||
#endif
|
||||
return p;
|
||||
} else {
|
||||
char *t = zhalloc(new);
|
||||
|
|
@ -723,6 +810,10 @@ hrealloc(char *p, size_t old, size_t new)
|
|||
h->used -= old;
|
||||
#ifdef ZSH_MEM_DEBUG
|
||||
memset(p, 0xff, old);
|
||||
#endif
|
||||
#ifdef ZSH_VALGRIND
|
||||
VALGRIND_MEMPOOL_FREE((char *)h, (char *)p);
|
||||
/* t already marked as allocated by zhalloc() */
|
||||
#endif
|
||||
unqueue_signals();
|
||||
return t;
|
||||
|
|
|
|||
|
|
@ -877,3 +877,8 @@ extern short ospeed;
|
|||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef ZSH_VALGRIND
|
||||
# include "valgrind/valgrind.h"
|
||||
# include "valgrind/memcheck.h"
|
||||
#endif
|
||||
|
|
|
|||
11
configure.ac
11
configure.ac
|
|
@ -117,6 +117,17 @@ AC_HELP_STRING([--enable-zsh-heap-debug],
|
|||
AC_DEFINE(ZSH_HEAP_DEBUG)
|
||||
fi])
|
||||
|
||||
dnl Do you want to allow Valgrind to debug heap allocation?
|
||||
ifdef([zsh-valgrind],[undefine([zsh-valgrind])])dnl
|
||||
AH_TEMPLATE([ZSH_VALGRIND],
|
||||
[Define to 1 if you want to add code for valgrind to debug heap memory.])
|
||||
AC_ARG_ENABLE(zsh-valgrind,
|
||||
AC_HELP_STRING([--enable-zsh-valgrind],
|
||||
[turn on support for valgrind debugging of heap memory]),
|
||||
[if test x$enableval = xyes; then
|
||||
AC_DEFINE(ZSH_VALGRIND)
|
||||
fi])
|
||||
|
||||
dnl Do you want debugging information on internal hash tables.
|
||||
dnl This turns on the `hashinfo' builtin command.
|
||||
ifdef([zsh-hash-debug],[undefine([zsh-hash-debug])])dnl
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue