Skip to content

Commit b156d49

Browse files
committed
draft update to MEMAUDIT support
Note: MEMAUDIT=0x3f crashes before libgmp can get started I need to take a closer look at that before going anywhere with this.
1 parent 55727d8 commit b156d49

2 files changed

Lines changed: 67 additions & 13 deletions

File tree

jsrc/j.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -676,12 +676,23 @@ struct jtimespec jmtfclk(void); //'fast clock'; maybe less inaccurate; intended
676676

677677
// Use MEMAUDIT to sniff out errant memory alloc/free
678678
#ifndef MEMAUDIT
679-
#define MEMAUDIT 0x00 // Bitmask for memory audits: 1=check headers 2=full audit of tpush/tpop 4=write garbage to memory before freeing it 8=write garbage to memory after getting it
679+
#define MEMAUDIT 0x00 // Bitmask for memory audits:
680+
// 1: make sure chains are valid (check headers)
681+
// 2: full audit of tpush/tpop
682+
// detect double-frees before they happen,
683+
// at the time of the erroneous tpush
684+
// 4: write garbage to memory before we free it (except reserved area)
685+
// 8: fill block with other garbage after we allocate it
686+
// 0x10: (or 16) audit freelist at every alloc/free
687+
// (starting after you have run 6!:5 (1) to turn it on)
688+
// 0x20: audit freelist at end of every sentence regardless of 6!:5
689+
// 0x40: enable guard blocks (libgmp mallocs only)
690+
//
691+
// Thus 1+4+8 (or 13 or 0xD) will verify that there are no blocks
692+
// being used after they are freed, or freed prematurely. If you
693+
// get a wild free, turn on bit 0x2. 2 will detect double-frees
694+
// before they happen, at the time of the erroneous tpush
680695
#endif
681-
// 16=audit freelist at every alloc/free (starting after you have run 6!:5 (1) to turn it on)
682-
// 0x20 audit freelist at end of every sentence regardless of 6!:5
683-
// 13 (0xD) will verify that there are no blocks being used after they are freed, or freed prematurely. If you get a wild free, turn on bit 0x2
684-
// 2 will detect double-frees before they happen, at the time of the erroneous tpush
685696
#define MEMAUDITPCALLENABLE 1 // expression for enabling stack auditing - enable auditing when true and enabled by MEMAUDIT&0x20 || jt->peekdata
686697
#ifndef AUDITEXECRESULTS
687698
#define AUDITEXECRESULTS 0 // When set, we go through all execution results to verify recursive and virtual bits are OK, and m nonzero if AC<0

jsrc/jgmpinit.c

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,16 +98,30 @@ static void (*jmp_set_memory_functions) (
9898

9999
long long gmpmallocs;
100100

101+
#if MEMAUDIT&0x40
102+
#define GUARDSIZE (CACHELINESIZE)
103+
#define GUARDsSIZE (2*CACHELINESIZE)
104+
C GUARDBLOCK[GUARDSIZE];
105+
#else
106+
#define GUARDSIZE 0
107+
#define GUARDsSIZE 0
108+
#endif
109+
101110
/*static*/void*jmalloc4gmp(size_t size){
102111
size_t avxsize= (size+7)&(-8); // libgmp's use of __strlen_avx2 segfaults when libgmp asks for size=2
103-
X z= malloc(avxsize+XHSZ);
104-
if(!z)SEGFAULT;
105-
if(!z)R0; // assert(z);// FIXME (but can't without replacing libgmp)
112+
C*m= malloc(avxsize+XHSZ+GUARDsSIZE);
113+
if(!m)SEGFAULT;
114+
if(!m)R0; // assert(z);// FIXME (but can't without replacing libgmp)
115+
#if MEMAUDIT&0x40
116+
memcpy(m, GUARDBLOCK, GUARDSIZE);
117+
memcpy(m+size+XHSZ+GUARDSIZE, GUARDBLOCK, GUARDSIZE);
118+
#endif
119+
X z= (X)(m+GUARDSIZE); // J header starts here
106120
AK(z)= XHSZ; // always rank 1
107121
AFLAG(z)= 0; // should be a safe value
108122
AT(z)= LIT; // matches significance of AN(z), simplifies 3!:1
109123
AC(z)= 1; // always 1 ref in libgmp
110-
AN(z)= avxsize; // track allocated memory
124+
AN(z)= size; // track amount of requested memory
111125
AR(z)= 1; // always rank 1
112126
AFHRH(z)= FHRHISGMP; // mark as a GMP psuedo-array
113127
/*
@@ -120,16 +134,30 @@ long long gmpmallocs;
120134
fprintf(stderr,"AR(z): %hhx (%hhu), ", AR(z), AR(z));
121135
fprintf(stderr,"AFHRH(z): %hx (%hi)\n", AFHRH(z), AFHRH(z));
122136
*/
137+
#if MEMAUDIT&8
138+
static I lfsr= 1;
139+
DO(size/SZI, lfsr= (lfsr<<1) ^ (lfsr<0 ?0x1b :0); if (i!=2&&i!=6)((I*)(XHSZ+(C*)z))[i]= lfsr;);
140+
#endif
123141
R CAV1(z);
124142
}
125143

126144
static void*jrealloc4gmp(void*ptr, size_t old, size_t new){
145+
size_t avxnew= (new+7)&(-8); // libgmp's use of __strlen_avx2 segfaults when libgmp asks for size=2
127146
X x= (X)(((C*)ptr)-XHSZ);
147+
C*m= (C*)x-GUARDSIZE;
148+
#if MEMAUDIT&0x40
149+
if (memcmp(m, GUARDBLOCK, GUARDSIZE)) SEGFAULT;
150+
if (memcmp(m+old+XHSZ+GUARDSIZE, GUARDBLOCK, GUARDSIZE)) SEGFAULT;
151+
#endif
128152
// assert(1==AC(x)); // must not have been exposed to J
129153
// assert(FHRHISGMP==AFHRH(x))
130-
X z= realloc(x, new+XHSZ);
131-
if(!z)SEGFAULT;
132-
if(!z)R0; // assert(z);// FIXME (but can't without replacing libgmp)
154+
m= realloc(m, avxnew+XHSZ+GUARDsSIZE);
155+
if(!m)SEGFAULT;
156+
if(!m)R0; // assert(m);// FIXME (but can't without replacing libgmp)
157+
#if MEMAUDIT&0x40
158+
memcpy(m+new+XHSZ+GUARDSIZE, GUARDBLOCK, GUARDSIZE);
159+
#endif
160+
X z= (X)(m+GUARDSIZE); // J header starts here
133161
AN(z)= new; // track allocated memory
134162
/*
135163
fprintf(stderr,"jrealloc4gmp z: %llx (size: %zx -> %zx), ", (UI)z, old, new);
@@ -141,6 +169,12 @@ static void*jrealloc4gmp(void*ptr, size_t old, size_t new){
141169
fprintf(stderr,"AR(z): %hhx (%hhu), ", AR(z), AR(z));
142170
fprintf(stderr,"AFHRH(z): %hx (%hi)\n", AFHRH(z), AFHRH(z));
143171
*/
172+
#if MEMAUDIT&8
173+
static I lfsr= 1;
174+
if (new > old) {
175+
DO((new-old)/SZI, lfsr= (lfsr<<1)^(lfsr<0 ?0x1b :0); if (i!=2&&i!=6)((I*)(old+XHSZ+(C*)z))[i]= lfsr;);
176+
}
177+
#endif
144178
R CAV1(z);
145179
}
146180

@@ -149,6 +183,11 @@ static void*jrealloc4gmp(void*ptr, size_t old, size_t new){
149183
// assert(FHRHISGMP=AT(x))
150184
X x= UNvoidAV1(ptr);
151185
if (ACPERMANENT&AC(x)) SEGFAULT;
186+
C* m= (C*)x-GUARDSIZE;
187+
#if MEMAUDIT&0x40
188+
if (memcmp(m, GUARDBLOCK, GUARDSIZE)) SEGFAULT;
189+
if (memcmp(m+n+XHSZ+GUARDSIZE, GUARDBLOCK, GUARDSIZE)) SEGFAULT;
190+
#endif
152191
/*
153192
fprintf(stderr,"\tjfree4gmp (%lli) x: %llx, ", gmpmallocs--, (UI)x);
154193
fprintf(stderr,"AK(x): %llx (%lli), ", AK(x), AK(x));
@@ -162,7 +201,7 @@ static void*jrealloc4gmp(void*ptr, size_t old, size_t new){
162201
#if MEMAUDIT&0x4
163202
AK(x)= AFLAG(x)= AM(x)= AT(x)= AC(x)= AN(x)= 0xdeadbeef;
164203
#endif
165-
free(x);
204+
free(m);
166205
}
167206

168207
// dehydrate fresh (mpz_t) as J (X)
@@ -249,6 +288,10 @@ void dldiag(){char*s=dlerror();if(s)fprintf(stderr,"%s\n",s);}
249288
// also in jgmp.h for global name declaration
250289
void jgmpinit() {
251290
if (SZI != sizeof (mp_limb_t)) SEGFAULT; // verify a fundamental assumption
291+
#if MEMAUDIT&0x40
292+
((UIL*)GUARDBLOCK)[0]= (UIL)0x1abe11ed1abe11edLL;
293+
memcpy(GUARDBLOCK+sizeof (UIL), GUARDBLOCK, GUARDSIZE-sizeof (UIL));
294+
#endif
252295
#ifndef IMPORTGMPLIB
253296
if (jmpz_init) return; // link with libgmp only once
254297
#endif

0 commit comments

Comments
 (0)