da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1985-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern int atexit(void(*)(void));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern char* getenv(const char*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * define _AST_std_malloc=1 to force the standard malloc
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if _map_malloc is also defined then _ast_malloc etc.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * will simply call malloc etc.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner/* malloc compatibility functions
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** These are aware of debugging/profiling and are driven by the
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** VMALLOC_OPTIONS environment variable which is a space-separated
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** list of [no]name[=value] options:
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** abort if Vmregion==Vmdebug then VM_DBABORT is set,
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** otherwise _BLD_debug enabled assertions abort()
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** check if Vmregion==Vmbest then the region is checked every op
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** method=m sets Vmregion=m if not defined, m (Vm prefix optional)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** may be one of { best debug last profile }
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** mmap prefer mmap() over brk() for region allocation
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** period=n sets Vmregion=Vmdebug if not defined, if
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** Vmregion==Vmdebug the region is checked every n ops
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** profile=f sets Vmregion=Vmprofile if not set, if
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** Vmregion==Vmprofile then profile info printed to file f
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** region if Vmregion==Vmbest then block free verifies
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** that the block belongs to the region
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** start=n sets Vmregion=Vmdebug if not defined, if
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** Vmregion==Vmdebug region checking starts after n ops
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** trace=f enables tracing to file f
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** warn=f sets Vmregion=Vmdebug if not defined, if
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** Vmregion==Vmdebug then warnings printed to file f
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** watch=a sets Vmregion=Vmdebug if not defined, if
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** Vmregion==Vmdebug then address a is watched
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** Output files are created if they don't exist. &n and /dev/fd/n name
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** the file descriptor n which must be open for writing. The pattern %p
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** in a file name is replaced by the process ID.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** VMALLOC_OPTIONS combines the features of these previously used env vars:
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner** { VMDEBUG VMETHOD VMPROFILE VMTRACE }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#if ( !_std_malloc || !_BLD_ast ) && !_AST_std_malloc
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern int _sigblock(void);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern void _sigunblock(int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned long v = ((unsigned long)p)>>16;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(n = GetEnvironmentVariable(s, buf, sizeof(buf))) || n > sizeof(buf))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* _UWIN */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* _WINIX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define extern extern __EXPORT__
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if((_Vmdbtime += 1) < _Vmdbstart) _Vmdbtime = _Vmdbstart; \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(_Vmdbtime >= _Vmdbstart && (_Vmdbtime % _Vmdbcheck) == 0 && \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int vmflinit()
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* this must be done now to avoid any inadvertent recursion (more below) */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner /* if getenv() calls malloc(), the options may not affect the eventual region */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* reset file and line number to correct values for the call */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* calloc(reg size_t n_obj, reg size_t s_obj)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return VMRECORD((*Vmregion->meth.resizef)(Vmregion,NIL(Void_t*),n_obj*s_obj,VM_RSZERO));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return VMRECORD((*Vmregion->meth.allocf)(Vmregion,size));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* realloc(reg Void_t* data, reg size_t size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((newdata = (*Vmregion->meth.allocf)(Vmregion,size)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (newdata = (*Vmregion->meth.resizef)(Vmregion,data,size,VM_RSCOPY|VM_RSMOVE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return VMRECORD((*Vmregion->meth.resizef)(Vmregion,data,size,VM_RSCOPY|VM_RSMOVE));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin extern void free();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* memalign(reg size_t align, reg size_t size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin addr = VMRECORD((*Vmregion->meth.alignf)(Vmregion,size,align));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzextern int posix_memalign(reg Void_t **memptr, reg size_t align, reg size_t size)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(align == 0 || (align%sizeof(Void_t*)) != 0 || ((align-1)&align) != 0 )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return VMRECORD((*Vmregion->meth.alignf)(Vmregion,size,_Vmpagesize));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return VMRECORD((*Vmregion->meth.alignf)(Vmregion,ROUND(size,_Vmpagesize),_Vmpagesize));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return NIL(char*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* _PACKAGE_ast */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(( _stk_down && &array[0] > Frame->head.head.addr) ||
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f = (Alloca_t*)(*Vmregion->meth.allocf)(Vmregion,size+sizeof(Alloca_t)-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*!_lib_alloca || _mal_alloca*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* not sure of all the implications -- 0 is conservative for now */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define USE_NATIVE 0 /* native free/realloc on non-vmalloc ptrs */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* intercept _* __* __libc_* variants */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F2(_calloc, size_t,n, size_t,m) { return calloc(n, m); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F1(_malloc, size_t,n) { return malloc(n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F2(_memalign, size_t,a, size_t,n) { return memalign(a, n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F1(_pvalloc, size_t,n) { return pvalloc(n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F2(_realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F1(_valloc, size_t,n) { return valloc(n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F2(__calloc, size_t,n, size_t,m) { return calloc(n, m); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F1(__malloc, size_t,n) { return malloc(n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F2(__memalign, size_t,a, size_t,n) { return memalign(a, n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F1(__pvalloc, size_t,n) { return pvalloc(n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F2(__realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F1(__valloc, size_t,n) { return valloc(n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F2(__libc_calloc, size_t,n, size_t,m) { return calloc(n, m); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F1(__libc_malloc, size_t,n) { return malloc(n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F2(__libc_memalign, size_t,a, size_t,n) { return memalign(a, n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F1(__libc_pvalloc, size_t,n) { return pvalloc(n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F2(__libc_realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F1(__libc_valloc, size_t,n) { return valloc(n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* _map_malloc */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _hdr_malloc /* need the mallint interface for statistics, etc. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define extern __EXPORT__
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*_lib_mallopt*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* _lib_mallinfo */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*_lib_mstats*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif/*_hdr_malloc*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * even though there is no malloc override, still provide
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * _ast_* counterparts for object compatibility
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define extern __EXPORT__
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F2(_ast_calloc, size_t,n, size_t,m) { return calloc(n, m); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F1(_ast_malloc, size_t,n) { return malloc(n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F2(_ast_memalign, size_t,a, size_t,n) { return memalign(a, n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F1(_ast_pvalloc, size_t,n) { return pvalloc(n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F2(_ast_realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Void_t* F1(_ast_valloc, size_t,n) { return valloc(n); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define extern __EXPORT__
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern int F2(_ast_mallopt, int,cmd, int,value) { return mallopt(cmd, value); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Mallinfo_t F0(_ast_mallinfo, void) { return mallinfo(); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern Mstats_t F0(_ast_mstats, void) { return mstats(); }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*_hdr_malloc*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*!_std_malloc*/
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X') )
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner { for(s += 2; *s; ++s)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner { for(; *s; ++s)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerstatic char* insertpid(char* begs, char* ends)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner return NIL(char*);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner return NIL(char*);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if (*file == '&' && *(file += 1) || strncmp(file, "/dev/fd/", 8) == 0 && *(file += 8))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner fd = open(file, O_WRONLY|O_CREAT|O_TRUNC, CREAT_MODE);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * initialize runtime options from the VMALLOC_OPTIONS env var
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#define COPY(t,e,f) while ((*t = *f++) && t < e) t++
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#if 1 /* backwards compatibility until 2011 */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if (*s-- == 'x')
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner p = " watch=";
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner /*FALLTHROUGH*/
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner p = " period=";
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner p = " method=";
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner p = " profile=";
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner p = " trace=";
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if (!*(t = s))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner else if (!v && *s == '=')
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if (!*(v = s))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if ((v[0] == 'V' || v[0] == 'v') && (v[1] == 'M' || v[1] == 'm'))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if (v && vm && vm->meth.meth == VM_MTPROFILE)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if (v && vm && vm->meth.meth == VM_MTDEBUG)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if (v && vm && vm->meth.meth == VM_MTDEBUG && (fd = createfile(v)) >= 0)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if (v && vm && vm->meth.meth == VM_MTDEBUG && (n = atou(&v)) >= 0)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner /* slip in the new region now so that malloc() will work fine */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner /* enable tracing */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if (trace && (fd = createfile(trace)) >= 0)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner /* make sure that profile data is output upon exiting */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner /* this may wind up calling malloc(), but region is ok now */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner else if (_Vmpffd >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*_UWIN*/