xref: /sqlite-3.40.0/ext/misc/memtrace.c (revision d46b6f57)
150b910a8Sdrh /*
250b910a8Sdrh ** 2019-01-21
350b910a8Sdrh **
450b910a8Sdrh ** The author disclaims copyright to this source code.  In place of
550b910a8Sdrh ** a legal notice, here is a blessing:
650b910a8Sdrh **
750b910a8Sdrh **    May you do good and not evil.
850b910a8Sdrh **    May you find forgiveness for yourself and forgive others.
950b910a8Sdrh **    May you share freely, never taking more than you give.
1050b910a8Sdrh **
1150b910a8Sdrh *************************************************************************
1250b910a8Sdrh **
1350b910a8Sdrh ** This file implements an extension that uses the SQLITE_CONFIG_MALLOC
1450b910a8Sdrh ** mechanism to add a tracing layer on top of SQLite.  If this extension
1550b910a8Sdrh ** is registered prior to sqlite3_initialize(), it will cause all memory
1650b910a8Sdrh ** allocation activities to be logged on standard output, or to some other
1750b910a8Sdrh ** FILE specified by the initializer.
1850b910a8Sdrh **
1950b910a8Sdrh ** This file needs to be compiled into the application that uses it.
2050b910a8Sdrh **
2150b910a8Sdrh ** This extension is used to implement the --memtrace option of the
2250b910a8Sdrh ** command-line shell.
2350b910a8Sdrh */
2450b910a8Sdrh #include <assert.h>
2550b910a8Sdrh #include <string.h>
2650b910a8Sdrh #include <stdio.h>
2750b910a8Sdrh 
2850b910a8Sdrh /* The original memory allocation routines */
2950b910a8Sdrh static sqlite3_mem_methods memtraceBase;
3050b910a8Sdrh static FILE *memtraceOut;
3150b910a8Sdrh 
3250b910a8Sdrh /* Methods that trace memory allocations */
memtraceMalloc(int n)3350b910a8Sdrh static void *memtraceMalloc(int n){
3450b910a8Sdrh   if( memtraceOut ){
3550b910a8Sdrh     fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n",
3650b910a8Sdrh             memtraceBase.xRoundup(n));
3750b910a8Sdrh   }
3850b910a8Sdrh   return memtraceBase.xMalloc(n);
3950b910a8Sdrh }
memtraceFree(void * p)4050b910a8Sdrh static void memtraceFree(void *p){
4150b910a8Sdrh   if( p==0 ) return;
4250b910a8Sdrh   if( memtraceOut ){
4350b910a8Sdrh     fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
4450b910a8Sdrh   }
4550b910a8Sdrh   memtraceBase.xFree(p);
4650b910a8Sdrh }
memtraceRealloc(void * p,int n)4750b910a8Sdrh static void *memtraceRealloc(void *p, int n){
4850b910a8Sdrh   if( p==0 ) return memtraceMalloc(n);
4950b910a8Sdrh   if( n==0 ){
5050b910a8Sdrh     memtraceFree(p);
5150b910a8Sdrh     return 0;
5250b910a8Sdrh   }
5350b910a8Sdrh   if( memtraceOut ){
5450b910a8Sdrh     fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
5550b910a8Sdrh             memtraceBase.xSize(p), memtraceBase.xRoundup(n));
5650b910a8Sdrh   }
5750b910a8Sdrh   return memtraceBase.xRealloc(p, n);
5850b910a8Sdrh }
memtraceSize(void * p)5950b910a8Sdrh static int memtraceSize(void *p){
6050b910a8Sdrh   return memtraceBase.xSize(p);
6150b910a8Sdrh }
memtraceRoundup(int n)6250b910a8Sdrh static int memtraceRoundup(int n){
6350b910a8Sdrh   return memtraceBase.xRoundup(n);
6450b910a8Sdrh }
memtraceInit(void * p)6550b910a8Sdrh static int memtraceInit(void *p){
6650b910a8Sdrh   return memtraceBase.xInit(p);
6750b910a8Sdrh }
memtraceShutdown(void * p)6850b910a8Sdrh static void memtraceShutdown(void *p){
6950b910a8Sdrh   memtraceBase.xShutdown(p);
7050b910a8Sdrh }
7150b910a8Sdrh 
7250b910a8Sdrh /* The substitute memory allocator */
7350b910a8Sdrh static sqlite3_mem_methods ersaztMethods = {
7450b910a8Sdrh   memtraceMalloc,
7550b910a8Sdrh   memtraceFree,
7650b910a8Sdrh   memtraceRealloc,
7750b910a8Sdrh   memtraceSize,
7850b910a8Sdrh   memtraceRoundup,
7950b910a8Sdrh   memtraceInit,
80*d46b6f57Sdrh   memtraceShutdown,
81*d46b6f57Sdrh   0
8250b910a8Sdrh };
8350b910a8Sdrh 
8450b910a8Sdrh /* Begin tracing memory allocations to out. */
sqlite3MemTraceActivate(FILE * out)8550b910a8Sdrh int sqlite3MemTraceActivate(FILE *out){
8650b910a8Sdrh   int rc = SQLITE_OK;
8750b910a8Sdrh   if( memtraceBase.xMalloc==0 ){
8850b910a8Sdrh     rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
8950b910a8Sdrh     if( rc==SQLITE_OK ){
9050b910a8Sdrh       rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
9150b910a8Sdrh     }
9250b910a8Sdrh   }
9350b910a8Sdrh   memtraceOut = out;
9450b910a8Sdrh   return rc;
9550b910a8Sdrh }
9650b910a8Sdrh 
9750b910a8Sdrh /* Deactivate memory tracing */
sqlite3MemTraceDeactivate(void)9850b910a8Sdrh int sqlite3MemTraceDeactivate(void){
9950b910a8Sdrh   int rc = SQLITE_OK;
10050b910a8Sdrh   if( memtraceBase.xMalloc!=0 ){
10150b910a8Sdrh     rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
10250b910a8Sdrh     if( rc==SQLITE_OK ){
10350b910a8Sdrh       memset(&memtraceBase, 0, sizeof(memtraceBase));
10450b910a8Sdrh     }
10550b910a8Sdrh   }
10650b910a8Sdrh   memtraceOut = 0;
10750b910a8Sdrh   return rc;
10850b910a8Sdrh }
109