summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2011-05-17 22:33:15 +0100
committerRobin Watts <Robin.Watts@artifex.com>2011-05-17 22:38:09 +0100
commit8d9bc767c0c59a7effa7652cbcbde14ab82de249 (patch)
tree3e827a8d3ba75b730786c1bc80f5286b1562ce91
parentcbe9dcfc93812aae26ffd5c2bebbe5b2dc1a4623 (diff)
Make Memento work with valgrind, plus fix unix build issues.
Various fixes for Memento, most especially to ensure it works with Valgrind (lots of valgrind calls to make memory readable/hide it again). No cluster differences expected.
-rw-r--r--gs/base/lib.mak2
-rw-r--r--gs/base/memento.c258
-rw-r--r--gs/base/memento.h36
-rw-r--r--gs/base/unix-aux.mak2
4 files changed, 200 insertions, 98 deletions
diff --git a/gs/base/lib.mak b/gs/base/lib.mak
index ae1043a37..2f3f1fff9 100644
--- a/gs/base/lib.mak
+++ b/gs/base/lib.mak
@@ -261,7 +261,7 @@ $(GLOBJ)gsargs.$(OBJ) : $(GLSRC)gsargs.c\
$(GLCC) $(GLO_)gsargs.$(OBJ) $(C_) $(GLSRC)gsargs.c
$(GLOBJ)gsmisc.$(OBJ) : $(GLSRC)gsmisc.c $(GXERR)\
- $(vmsmath_h)\
+ $(vmsmath_h) $(memento_h)\
$(ctype__h) $(malloc__h) $(math__h) $(memory__h) $(string__h)\
$(gpcheck_h) $(gserror_h) $(gxfarith_h) $(gxfixed_h) $(stdint__h) $(stdio__h)
$(GLCC) $(GLO_)gsmisc.$(OBJ) $(C_) $(GLSRC)gsmisc.c
diff --git a/gs/base/memento.c b/gs/base/memento.c
index 014484a75..92bf0ca27 100644
--- a/gs/base/memento.c
+++ b/gs/base/memento.c
@@ -22,8 +22,17 @@ void MEMENTO_UNDERLYING_FREE(void *);
void *MEMENTO_UNDERLYING_REALLOC(void *,size_t);
void *MEMENTO_UNDERLYING_CALLOC(size_t,size_t);
+/* And some other standard functions we use. We don't include the header
+ * files, just in case they pull in unexpected others. */
+int atoi(const char *);
+char *getenv(const char *);
+void *memset(void *,unsigned char,size_t);
+int atexit(void (*)(void));
+
#ifdef MEMENTO
+#include "valgrind.h"
+
enum {
Memento_PreSize = 16,
Memento_PostSize = 16
@@ -60,6 +69,8 @@ static struct {
int countdown;
int lastChecked;
int breakAt;
+ int failAt;
+ int failing;
size_t alloc;
size_t peakAlloc;
size_t totalAlloc;
@@ -93,12 +104,21 @@ void Memento_breakpoint(void)
#endif
}
-static void Memento_addBlock(Memento_Blocks *blks, Memento_BlkHeader *b)
+static void Memento_addBlock(Memento_Blocks *blks,
+ Memento_BlkHeader *b,
+ int type)
{
b->next = blks->head;
blks->head = b;
memset(b->preblk, MEMENTO_PREFILL, Memento_PreSize);
memset(MEMBLK_POSTPTR(b), MEMENTO_POSTFILL, Memento_PostSize);
+ VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(b), Memento_PostSize);
+ if (type == 0) { /* malloc */
+ VALGRIND_MAKE_MEM_UNDEFINED(MEMBLK_TOBLK(b), b->rawsize);
+ } else if (type == 1) { /* free */
+ VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_TOBLK(b), b->rawsize);
+ }
+ VALGRIND_MAKE_MEM_NOACCESS(b, sizeof(Memento_BlkHeader));
}
typedef struct BlkCheckData {
@@ -115,7 +135,6 @@ static int Memento_Internal_checkAllocedBlock(Memento_BlkHeader *b, void *arg)
char *p;
int corrupt = 0;
BlkCheckData *data = (BlkCheckData *)arg;
- int res = 0;
p = b->preblk;
i = Memento_PreSize;
@@ -163,38 +182,34 @@ static void Memento_removeBlock(Memento_Blocks *blks,
const char *listName,
Memento_BlkHeader *b)
{
- Memento_BlkHeader **head = &blks->head;
- while ((*head) && (*head != b)) {
- head = &(*head)->next;
- }
- if (*head == NULL) {
- /* FAIL! Will have been reported to user earlier, so just exit. */
- return;
- }
- (*head) = (*head)->next;
-}
-
-static void Memento_touchBlock(Memento_Blocks *blks,
- const char *listName,
- Memento_BlkHeader *b)
-{
Memento_BlkHeader *head = blks->head;
- while (head && (head != b)) {
- head = head->next;
+ Memento_BlkHeader *prev = NULL;
+ while ((head) && (head != b)) {
+ VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head));
+ prev = head;
+ head = head->next;
+ VALGRIND_MAKE_MEM_NOACCESS(prev, sizeof(*prev));
}
if (head == NULL) {
- /* FAIL! */
- /* FIXME: Check the free list */
- fprintf(stderr, "Block %x not in %s list!\n", MEMBLK_TOBLK(b), listName);
- Memento_breakpoint();
+ /* FAIL! Will have been reported to user earlier, so just exit. */
return;
}
- Memento_Internal_checkBlock(b, NULL);
+ if (prev == NULL) {
+ VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head));
+ blks->head = head->next;
+ VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(*head));
+ } else {
+ VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head));
+ VALGRIND_MAKE_MEM_DEFINED(prev, sizeof(*prev));
+ prev->next = head->next;
+ VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(*head));
+ VALGRIND_MAKE_MEM_NOACCESS(prev, sizeof(*prev));
+ }
}
static int Memento_Internal_makeSpace(size_t space)
{
- Memento_BlkHeader **head, **next;
+ Memento_BlkHeader *head, *prev;
size_t listSize = globals.freeListSize;
/* If too big, it can never go on the freelist */
if (space > MEMENTO_FREELIST_MAX)
@@ -207,21 +222,32 @@ static int Memento_Internal_makeSpace(size_t space)
}
/* We need to bin some entries from the list */
listSize = MEMENTO_FREELIST_MAX-space;
- head = &globals.free.head;
- while (*head && listSize != 0) {
- if (listSize < MEMBLK_SIZE((*head)->rawsize)) {
+ head = globals.free.head;
+ prev = NULL;
+ while (head && listSize != 0) {
+ VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head));
+ if (listSize < MEMBLK_SIZE(head->rawsize)) {
break;
}
- listSize -= MEMBLK_SIZE((*head)->rawsize);
- head = &(*head)->next;
+ listSize -= MEMBLK_SIZE(head->rawsize);
+ prev = head;
+ head = head->next;
+ VALGRIND_MAKE_MEM_NOACCESS(prev, sizeof(*prev));
}
/* Free all blocks forwards from here */
- *head = NULL;
- while (*head) {
- next = &(*head)->next;
- globals.freeListSize -= MEMBLK_SIZE((*head)->rawsize);
- MEMENTO_UNDERLYING_FREE((*head));
- head = next;
+ if (prev == NULL) {
+ globals.free.head = NULL;
+ } else {
+ VALGRIND_MAKE_MEM_DEFINED(prev, sizeof(*prev));
+ prev->next = NULL;
+ VALGRIND_MAKE_MEM_NOACCESS(prev, sizeof(*prev));
+ }
+ while (head) {
+ VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head));
+ prev = head;
+ head = prev->next;
+ globals.freeListSize -= MEMBLK_SIZE(prev->rawsize);
+ MEMENTO_UNDERLYING_FREE(prev);
}
return 1;
}
@@ -232,12 +258,19 @@ static int Memento_appBlocks(Memento_Blocks *blks,
void *arg)
{
Memento_BlkHeader *head = blks->head;
+ Memento_BlkHeader *next;
int result;
while (head) {
+ VALGRIND_MAKE_MEM_DEFINED(head, sizeof(Memento_BlkHeader));
+ VALGRIND_MAKE_MEM_DEFINED(MEMBLK_TOBLK(head),
+ head->rawsize + Memento_PostSize);
result = app(head, arg);
+ next = head->next;
+ VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(head), Memento_PostSize);
+ VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(Memento_BlkHeader));
if (result)
return result;
- head = head->next;
+ head = next;
}
return 0;
}
@@ -249,12 +282,22 @@ static int Memento_appBlock(Memento_Blocks *blks,
Memento_BlkHeader *b)
{
Memento_BlkHeader *head = blks->head;
+ Memento_BlkHeader *next;
int result;
while (head && head != b) {
- head = head->next;
+ VALGRIND_MAKE_MEM_DEFINED(head, sizeof(Memento_BlkHeader));
+ next = head->next;
+ VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(head), Memento_PostSize);
+ head = next;
}
if (head == b) {
- return app(head, arg);
+ VALGRIND_MAKE_MEM_DEFINED(head, sizeof(Memento_BlkHeader));
+ VALGRIND_MAKE_MEM_DEFINED(MEMBLK_TOBLK(head),
+ head->rawsize + Memento_PostSize);
+ result = app(head, arg);
+ VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(head), Memento_PostSize);
+ VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(Memento_BlkHeader));
+ return result;
}
return 0;
}
@@ -270,7 +313,7 @@ static int Memento_listBlock(Memento_BlkHeader *b,
return 0;
}
-void Memento_listBlocks(void) {
+static void Memento_listBlocks(void) {
int counts[2];
counts[0] = 0;
counts[1] = 0;
@@ -282,6 +325,7 @@ void Memento_listBlocks(void) {
static void Memento_fin(void)
{
+ Memento_checkAllMemory();
fprintf(stderr, "Total memory malloced = %d bytes\n", globals.totalAlloc);
fprintf(stderr, "Peak memory malloced = %d bytes\n", globals.peakAlloc);
fprintf(stderr, "%d mallocs, %d frees, %d reallocs\n", globals.numMallocs,
@@ -296,13 +340,25 @@ static void Memento_fin(void)
static void Memento_init(void)
{
+ char *env;
memset(&globals, 0, sizeof(globals));
globals.inited = 1;
globals.used.head = NULL;
globals.free.head = NULL;
globals.sequence = 1;
- globals.paranoia = 1024;
globals.countdown = 1024;
+
+ env = getenv("MEMENTO_FAILAT");
+ globals.failAt = (env ? atoi(env) : 0);
+
+ env = getenv("MEMENTO_PARANOIA");
+ globals.paranoia = (env ? atoi(env) : 0);
+ if (globals.paranoia == 0)
+ globals.paranoia = 1024;
+
+ env = getenv("MEMENTO_PARANOIDAT");
+ globals.paranoidAt = (env ? atoi(env) : 0);
+
atexit(Memento_fin);
}
@@ -313,6 +369,10 @@ static void Memento_event(void)
globals.paranoia = 1;
globals.countdown = 1;
}
+ if ((globals.sequence == globals.failAt) &&
+ (globals.sequence != 0)) {
+ globals.failing = 1;
+ }
if (--globals.countdown == 0) {
Memento_checkAllMemory();
@@ -324,15 +384,15 @@ static void Memento_event(void)
Memento_breakpoint();
}
-void Memento_breakAt(int event)
+int Memento_breakAt(int event)
{
globals.breakAt = event;
+ return event;
}
void *Memento_malloc(size_t s)
{
Memento_BlkHeader *memblk;
- int *blk;
size_t smem = MEMBLK_SIZE(s);
if (!globals.inited)
@@ -340,6 +400,9 @@ void *Memento_malloc(size_t s)
Memento_event();
+ if (globals.failing)
+ return NULL;
+
if (s == 0)
return NULL;
@@ -356,7 +419,7 @@ void *Memento_malloc(size_t s)
memblk->rawsize = s;
memblk->sequence = globals.sequence;
memblk->lastCheckedOK = memblk->sequence;
- Memento_addBlock(&globals.used, memblk);
+ Memento_addBlock(&globals.used, memblk, 0);
return MEMBLK_TOBLK(memblk);
}
@@ -402,7 +465,6 @@ static int checkBlock(Memento_BlkHeader *memblk, const char *action)
void Memento_free(void *blk)
{
Memento_BlkHeader *memblk;
- int res;
if (!globals.inited)
Memento_init();
@@ -413,18 +475,23 @@ void Memento_free(void *blk)
return;
memblk = MEMBLK_FROMBLK(blk);
-
+ VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
if (checkBlock(memblk, "free"))
return;
+ VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
globals.alloc -= memblk->rawsize;
globals.numFrees++;
Memento_removeBlock(&globals.used, "allocated", memblk);
+ VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
if (Memento_Internal_makeSpace(MEMBLK_SIZE(memblk->rawsize))) {
- Memento_addBlock(&globals.free, memblk);
+ VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
+ VALGRIND_MAKE_MEM_DEFINED(MEMBLK_TOBLK(memblk),
+ memblk->rawsize + Memento_PostSize);
memset(MEMBLK_TOBLK(memblk), MEMENTO_FREEFILL, memblk->rawsize);
+ Memento_addBlock(&globals.free, memblk, 1);
} else {
MEMENTO_UNDERLYING_FREE(memblk);
}
@@ -444,6 +511,8 @@ void *Memento_realloc(void *blk, size_t newsize)
Memento_free(blk);
return NULL;
}
+ if (globals.failing)
+ return NULL;
memblk = MEMBLK_FROMBLK(blk);
@@ -458,7 +527,7 @@ void *Memento_realloc(void *blk, size_t newsize)
newmemblk = MEMENTO_UNDERLYING_REALLOC(memblk, newsizemem);
if (newmemblk == NULL)
{
- Memento_addBlock(&globals.used, memblk);
+ Memento_addBlock(&globals.used, memblk, 2);
return NULL;
}
globals.numReallocs++;
@@ -467,25 +536,26 @@ void *Memento_realloc(void *blk, size_t newsize)
globals.alloc += newsize;
if (globals.peakAlloc < globals.alloc)
globals.peakAlloc = globals.alloc;
- if (newmemblk->rawsize < newsize)
- memset(((char *)MEMBLK_TOBLK(newmemblk))+newmemblk->rawsize,
- MEMENTO_ALLOCFILL, newsize - newmemblk->rawsize);
+ if (newmemblk->rawsize < newsize) {
+ char *newbytes = ((char *)MEMBLK_TOBLK(newmemblk))+newmemblk->rawsize;
+ memset(newbytes, MEMENTO_ALLOCFILL, newsize - newmemblk->rawsize);
+ VALGRIND_MAKE_MEM_UNDEFINED(newbytes, newsize - newmemblk->rawsize);
+ }
newmemblk->rawsize = newsize;
- Memento_addBlock(&globals.used, newmemblk);
memset(newmemblk->preblk, MEMENTO_PREFILL, Memento_PreSize);
memset(MEMBLK_POSTPTR(newmemblk), MEMENTO_POSTFILL, Memento_PostSize);
+ Memento_addBlock(&globals.used, newmemblk, 2);
return MEMBLK_TOBLK(newmemblk);
}
-void Memento_checkBlock(void *blk)
+int Memento_checkBlock(void *blk)
{
Memento_BlkHeader *memblk;
if (blk == NULL)
- return;
+ return 0;
memblk = MEMBLK_FROMBLK(blk);
- if (checkBlock(memblk, "check"))
- return;
+ return checkBlock(memblk, "check");
}
static int Memento_Internal_checkAllAlloced(Memento_BlkHeader *memblk, void *arg)
@@ -556,25 +626,30 @@ static int Memento_Internal_checkAllFreed(Memento_BlkHeader *memblk, void *arg)
return 0;
}
-void Memento_checkAllMemory(void)
+int Memento_checkAllMemory(void)
{
BlkCheckData data;
memset(&data, 0, sizeof(data));
Memento_appBlocks(&globals.used, Memento_Internal_checkAllAlloced, &data);
Memento_appBlocks(&globals.free, Memento_Internal_checkAllFreed, &data);
- if (data.found & 6)
+ if (data.found & 6) {
Memento_breakpoint();
+ return 1;
+ }
+ return 0;
}
-void Memento_setParanoia(int i)
+int Memento_setParanoia(int i)
{
globals.paranoia = i;
+ return i;
}
-void Memento_paranoidAt(int i)
+int Memento_paranoidAt(int i)
{
globals.paranoidAt = i;
+ return i;
}
int Memento_getBlockNum(void *b)
@@ -586,11 +661,14 @@ int Memento_getBlockNum(void *b)
return (memblk->sequence);
}
-void Memento_check(void)
+int Memento_check(void)
{
+ int result;
+
fprintf(stderr, "Checking memory\n");
- Memento_checkAllMemory();
+ result = Memento_checkAllMemory();
fprintf(stderr, "Memory checked!\n");
+ return result;
}
typedef struct findBlkData {
@@ -605,7 +683,7 @@ static int Memento_containsAddr(Memento_BlkHeader *b,
findBlkData *data = (findBlkData *)arg;
char *blkend = &((char *)MEMBLK_TOBLK(b))[b->rawsize];
if ((MEMBLK_TOBLK(b) <= data->addr) &&
- (blkend > data->addr)) {
+ ((void *)blkend > data->addr)) {
data->blk = b;
data->flags = 1;
return 1;
@@ -616,8 +694,8 @@ static int Memento_containsAddr(Memento_BlkHeader *b,
data->flags = 2;
return 1;
}
- if ((blkend <= data->addr) &&
- (blkend + Memento_PostSize > data->addr)) {
+ if (((void *)blkend <= data->addr) &&
+ ((void *)(blkend + Memento_PostSize) > data->addr)) {
data->blk = b;
data->flags = 3;
return 1;
@@ -625,7 +703,7 @@ static int Memento_containsAddr(Memento_BlkHeader *b,
return 0;
}
-void Memento_find(void *a)
+int Memento_find(void *a)
{
findBlkData data;
@@ -634,24 +712,34 @@ void Memento_find(void *a)
data.flags = 0;
Memento_appBlocks(&globals.used, Memento_containsAddr, &data);
if (data.blk != NULL) {
- fprintf(stderr, "Address %x is in %sallocated block %x(%d)\n",
+ fprintf(stderr, "Address %x is in %sallocated block %x(size=%d,num=%d)\n",
data.addr,
(data.flags == 1 ? "" : (data.flags == 2 ?
"preguard of " : "postguard of ")),
- data.blk, data.blk->rawsize);
- return;
+ MEMBLK_TOBLK(data.blk), data.blk->rawsize, data.blk->sequence);
+ return data.blk->sequence;
}
data.blk = NULL;
data.flags = 0;
Memento_appBlocks(&globals.free, Memento_containsAddr, &data);
if (data.blk != NULL) {
- fprintf(stderr, "Address %x is in %sfreed block %x(%d)\n",
+ fprintf(stderr, "Address %x is in %sfreed block %x(size=%d,num=%d)\n",
data.addr,
(data.flags == 1 ? "" : (data.flags == 2 ?
"preguard of " : "postguard of ")),
- data.blk, data.blk->rawsize);
- return;
+ MEMBLK_TOBLK(data.blk), data.blk->rawsize, data.blk->sequence);
+ return data.blk->sequence;
}
+ return 0;
+}
+
+int Memento_failAt(int i)
+{
+ globals.failAt = i;
+ if ((globals.sequence > globals.failAt) &&
+ (globals.failing != 0))
+ globals.failing = 1;
+ return i;
}
#else
@@ -661,28 +749,34 @@ void (Memento_breakpoint)(void)
{
}
-void (Memento_checkBlock)(void *b)
+int (Memento_checkBlock)(void *b)
{
+ return 0;
}
-void (Memento_checkAllMemory)(void)
+int (Memento_checkAllMemory)(void)
{
+ return 0;
}
-void (Memento_check)(void)
+int (Memento_check)(void)
{
+ return 0;
}
-void (Memento_setParanoia)(int i)
+int (Memento_setParanoia)(int i)
{
+ return 0;
}
-void (Memento_paranoidAt)(int i)
+int (Memento_paranoidAt)(int i)
{
+ return 0;
}
-void (Memento_breakAt)(int i)
+int (Memento_breakAt)(int i)
{
+ return 0;
}
int (Memento_getBlockNum)(void *i)
@@ -690,8 +784,14 @@ int (Memento_getBlockNum)(void *i)
return 0;
}
-void (Memento_find)(void *a)
+int (Memento_find)(void *a)
{
+ return 0;
+}
+
+int (Memento_failAt)(int i)
+{
+ return 0;
}
#undef Memento_malloc
diff --git a/gs/base/memento.h b/gs/base/memento.h
index bf6462385..7133c933a 100644
--- a/gs/base/memento.h
+++ b/gs/base/memento.h
@@ -99,16 +99,17 @@
#define MEMENTO_FREELIST_MAX 0x2000000
-void Memento_checkBlock(void *);
-void Memento_checkAllMemory(void);
-void Memento_check(void);
-
-void Memento_setParanoia(int);
-void Memento_paranoidAt(int);
-void Memento_breakAt(int);
-int Memento_getBlockNum(void *);
-void Memento_find(void *a);
+int Memento_checkBlock(void *);
+int Memento_checkAllMemory(void);
+int Memento_check(void);
+
+int Memento_setParanoia(int);
+int Memento_paranoidAt(int);
+int Memento_breakAt(int);
+int Memento_getBlockNum(void *);
+int Memento_find(void *a);
void Memento_breakpoint(void);
+int Memento_failAt(int);
void *Memento_malloc(size_t s);
void *Memento_realloc(void *, size_t s);
@@ -131,15 +132,16 @@ void *Memento_calloc(size_t, size_t);
#define Memento_realloc MEMENTO_UNDERLYING_REALLOC
#define Memento_calloc MEMENTO_UNDERLYING_CALLOC
-#define Memento_checkBlock(A) do {} while (0)
-#define Memento_checkAllMemory() do {} while (0)
-#define Memento_check() do {} while (0)
-#define Memento_setParanoia(A) do {} while (0)
-#define Memento_paranoidAt(A) do {} while (0)
-#define Memento_breakAt(A) do {} while (0)
+#define Memento_checkBlock(A) 0
+#define Memento_checkAllMemory() 0
+#define Memento_check() 0
+#define Memento_setParanoia(A) 0
+#define Memento_paranoidAt(A) 0
+#define Memento_breakAt(A) 0
#define Memento_getBlockNum(A) 0
-#define Memento_find(A) do {} while (0)
-#define Memento_breakpoint(void) do {} while (0)
+#define Memento_find(A) 0
+#define Memento_breakpoint() do {} while (0)
+#define Memento_failAt(A) 0
#endif /* MEMENTO */
diff --git a/gs/base/unix-aux.mak b/gs/base/unix-aux.mak
index 58599705f..e56c2f403 100644
--- a/gs/base/unix-aux.mak
+++ b/gs/base/unix-aux.mak
@@ -80,7 +80,7 @@ $(GENHT_XE): $(GLSRC)genht.c $(AK) $(GENHT_DEPS)
MKROMFS_OBJS_0=$(MKROMFS_ZLIB_OBJS) $(GLOBJ)gscdefs.$(OBJ) $(GLOBJ)gsmisc.$(OBJ) \
$(GLOBJ)gpmisc.$(OBJ) $(GLOBJ)gslibctx.$(OBJ) $(GLOBJ)gp_getnv.$(OBJ) \
$(GLOBJ)gp_unix.$(OBJ) $(GLOBJ)gp_unifs.$(OBJ) $(GLOBJ)gp_unifn.$(OBJ) \
- $(GLOBJ)gp_stdia.$(OBJ) $(GLOBJ)gsutil.$(OBJ)
+ $(GLOBJ)gp_stdia.$(OBJ) $(GLOBJ)gsutil.$(OBJ) $(GLOBJ)memento.$(OBJ)
$(MKROMFS_XE)_0: $(GLSRC)mkromfs.c $(MKROMFS_COMMON_DEPS) $(MKROMFS_OBJS_0)
$(CCAUX) $(GENOPT) $(CFLAGS) $(I_)$(GLSRCDIR)$(_I) $(I_)$(GLOBJ)$(_I) $(I_)$(ZSRCDIR)$(_I) $(GLSRC)mkromfs.c $(O_)$(MKROMFS_XE)_0 $(MKROMFS_OBJS_0) -lm $(EXTRALIBS)