Add kernel heap allocation tracing debug facility.

This commit is contained in:
Jonas 'Sortie' Termansen 2022-04-25 23:36:10 +02:00
parent 89ca760722
commit bd7e8f93f9
19 changed files with 336 additions and 45 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2012, 2013, 2014 Jonas 'Sortie' Termansen. * Copyright (c) 2011, 2012, 2013, 2014, 2022 Jonas 'Sortie' Termansen.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -36,4 +36,35 @@ typedef uintptr_t addr_t;
#define CPU X64 #define CPU X64
#endif #endif
#ifdef __TRACE_ALLOCATION_SITES
struct kernel_allocation_site
{
struct __allocation_site allocation_site;
struct kernel_allocation_site* next;
bool registered;
};
extern struct kernel_allocation_site* first_kernel_allocation_site;
#undef ALLOCATION_SITE
#define ALLOCATION_SITE \
({ \
static struct kernel_allocation_site site = \
{ { __FILE__, __LINE__, __func__, 0, 0 }, NULL, false }; \
if ( !site.registered ) \
{ \
site.registered = true; \
site.next = first_kernel_allocation_site; \
first_kernel_allocation_site = &site; \
} \
&site.allocation_site; \
})
#include <stddef.h>
void* operator new(size_t size, struct __allocation_site* allocation_site);
void* operator new[](size_t size, struct __allocation_site* allocation_site);
#define new new (ALLOCATION_SITE)
#endif
#endif #endif

View File

@ -102,6 +102,8 @@
#include "x86-family/vbox.h" #include "x86-family/vbox.h"
#endif #endif
struct kernel_allocation_site* first_kernel_allocation_site = NULL;
// Keep the stack size aligned with $CPU/boot.s // Keep the stack size aligned with $CPU/boot.s
const size_t STACK_SIZE = 64*1024; const size_t STACK_SIZE = 64*1024;
extern "C" { __attribute__((aligned(16))) size_t stack[STACK_SIZE / sizeof(size_t)]; } extern "C" { __attribute__((aligned(16))) size_t stack[STACK_SIZE / sizeof(size_t)]; }

View File

@ -50,6 +50,51 @@ ssize_t sys_kernelinfo(const char* user_req, char* user_resp, size_t resplen)
char* req = GetStringFromUser(user_req); char* req = GetStringFromUser(user_req);
if ( !req ) if ( !req )
return -1; return -1;
#ifdef __TRACE_ALLOCATION_SITES
if ( !strcmp(req, "allocations") )
{
delete[] req;
bool exhausted = false;
size_t total_needed = 0;
for ( struct kernel_allocation_site* site = first_kernel_allocation_site;
site;
site = site->next )
{
char str[256];
snprintf(str, sizeof(str), "%20zu B %zu allocations %s:%zu %s %c",
site->allocation_site.current_size,
site->allocation_site.allocations,
site->allocation_site.file,
site->allocation_site.line,
site->allocation_site.function,
site->next ? '\n' : '\0');
size_t stringlen = strlen(str);
total_needed += stringlen;
if ( exhausted )
continue;
if ( resplen < stringlen )
{
exhausted = true;
continue;
}
if ( !CopyToUser(user_resp, str, sizeof(char) * stringlen) )
return -1;
user_resp += stringlen;
resplen -= stringlen;
}
if ( !exhausted && !resplen )
exhausted = true;
if ( !exhausted )
{
char zero = '\0';
if ( !CopyToUser(user_resp, &zero, 1) )
return -1;
}
if ( exhausted )
return errno = ERANGE, (ssize_t) total_needed;
return 0;
}
#endif
const char* str = KernelInfo(req); const char* str = KernelInfo(req);
delete[] req; delete[] req;
if ( !str ) if ( !str )

View File

@ -24,6 +24,19 @@
#warning "security: -fcheck-new might not work on clang" #warning "security: -fcheck-new might not work on clang"
#endif #endif
#ifdef __TRACE_ALLOCATION_SITES
#undef new
void* operator new(size_t size, struct __allocation_site* allocation_site)
{
return malloc_trace(allocation_site, size);
}
void* operator new[](size_t size, struct __allocation_site* allocation_site)
{
return malloc_trace(allocation_site, size);
}
#else
void* operator new(size_t size) void* operator new(size_t size)
{ {
return malloc(size); return malloc(size);
@ -33,6 +46,7 @@ void* operator new[](size_t size)
{ {
return malloc(size); return malloc(size);
} }
#endif
void operator delete(void* addr) void operator delete(void* addr)
{ {

View File

@ -60,20 +60,6 @@ malloc/__heap_verify.o \
netinet/if_ether/etheraddr_broadcast.o \ netinet/if_ether/etheraddr_broadcast.o \
netinet/in/in6addr_any.o \ netinet/in/in6addr_any.o \
netinet/in/in6addr_loopback.o \ netinet/in/in6addr_loopback.o \
regex/regcomp.o \
regex/regerror.o \
regex/regexec.o \
regex/regfree.o \
sha2/sha224hl.o \
sha2/sha224.o \
sha2/sha256hl.o \
sha2/sha256.o \
sha2/sha384hl.o \
sha2/sha384.o \
sha2/sha512_256hl.o \
sha2/sha512_256.o \
sha2/sha512hl.o \
sha2/sha512.o \
signal/sigaddset.o \ signal/sigaddset.o \
signal/sigandset.o \ signal/sigandset.o \
signal/sigdelset.o \ signal/sigdelset.o \
@ -86,7 +72,6 @@ signal/sigorset.o \
ssp/__stack_chk_fail.o \ ssp/__stack_chk_fail.o \
stdio/asprintf.o \ stdio/asprintf.o \
stdio/cbprintf.o \ stdio/cbprintf.o \
stdio/cbscanf.o \
stdio/clearerr.o \ stdio/clearerr.o \
stdio/clearerr_unlocked.o \ stdio/clearerr_unlocked.o \
stdio/dprintf.o \ stdio/dprintf.o \
@ -116,8 +101,6 @@ stdio/fgets.o \
stdio/fgets_unlocked.o \ stdio/fgets_unlocked.o \
stdio/fileno_unlocked.o \ stdio/fileno_unlocked.o \
stdio/flockfile.o \ stdio/flockfile.o \
stdio/fmemopen.o \
stdio/fnewfile.o \
stdio/fparsemode.o \ stdio/fparsemode.o \
stdio/fprintf_unlocked.o \ stdio/fprintf_unlocked.o \
stdio/fputc.o \ stdio/fputc.o \
@ -128,8 +111,6 @@ stdio/fread.o \
stdio/fread_unlocked.o \ stdio/fread_unlocked.o \
stdio/fregister.o \ stdio/fregister.o \
stdio/fresetfile.o \ stdio/fresetfile.o \
stdio/fscanf.o \
stdio/fscanf_unlocked.o \
stdio/fseek.o \ stdio/fseek.o \
stdio/fseeko.o \ stdio/fseeko.o \
stdio/fseeko_unlocked.o \ stdio/fseeko_unlocked.o \
@ -142,28 +123,20 @@ stdio/funlockfile.o \
stdio/funregister.o \ stdio/funregister.o \
stdio/fwrite.o \ stdio/fwrite.o \
stdio/fwrite_unlocked.o \ stdio/fwrite_unlocked.o \
stdio/getdelim.o \
stdio/getline.o \
stdio/open_memstream.o \
stdio/rewind.o \ stdio/rewind.o \
stdio/setbuf.o \ stdio/setbuf.o \
stdio/setvbuf.o \ stdio/setvbuf.o \
stdio/setvbuf_unlocked.o \ stdio/setvbuf_unlocked.o \
stdio/snprintf.o \ stdio/snprintf.o \
stdio/sprintf.o \ stdio/sprintf.o \
stdio/sscanf.o \
stdio/ungetc.o \ stdio/ungetc.o \
stdio/ungetc_unlocked.o \ stdio/ungetc_unlocked.o \
stdio/vasprintf.o \ stdio/vasprintf.o \
stdio/vcbprintf.o \ stdio/vcbprintf.o \
stdio/vdprintf.o \ stdio/vdprintf.o \
stdio/vfprintf_unlocked.o \ stdio/vfprintf_unlocked.o \
stdio/vfscanf.o \
stdio/vfscanf_unlocked.o \
stdio/vcbscanf.o \
stdio/vsnprintf.o \ stdio/vsnprintf.o \
stdio/vsprintf.o \ stdio/vsprintf.o \
stdio/vsscanf.o \
stdlib/abort.o \ stdlib/abort.o \
stdlib/abs.o \ stdlib/abs.o \
stdlib/arc4random_buf.o \ stdlib/arc4random_buf.o \
@ -278,7 +251,6 @@ wchar/wcscmp.o \
wchar/wcscoll.o \ wchar/wcscoll.o \
wchar/wcscpy.o \ wchar/wcscpy.o \
wchar/wcscspn.o \ wchar/wcscspn.o \
wchar/wcsdup.o \
wchar/wcsftime.o \ wchar/wcsftime.o \
wchar/wcslcat.o \ wchar/wcslcat.o \
wchar/wcslcpy.o \ wchar/wcslcpy.o \
@ -329,6 +301,34 @@ wctype/towupper.o \
wctype/wctype.o \ wctype/wctype.o \
HOSTEDOBJS=\ HOSTEDOBJS=\
regex/regcomp.o \
regex/regerror.o \
regex/regexec.o \
regex/regfree.o \
sha2/sha224hl.o \
sha2/sha224.o \
sha2/sha256hl.o \
sha2/sha256.o \
sha2/sha384hl.o \
sha2/sha384.o \
sha2/sha512_256hl.o \
sha2/sha512_256.o \
sha2/sha512hl.o \
sha2/sha512.o \
stdio/cbscanf.o \
stdio/fscanf.o \
stdio/fscanf_unlocked.o \
stdio/sscanf.o \
stdio/vfscanf.o \
stdio/vfscanf_unlocked.o \
stdio/vcbscanf.o \
stdio/vsscanf.o \
stdio/fmemopen.o \
stdio/open_memstream.o \
stdio/getdelim.o \
stdio/getline.o \
stdio/fnewfile.o \
wchar/wcsdup.o \
blf/blowfish.o \ blf/blowfish.o \
$(CPUDIR)/fork.o \ $(CPUDIR)/fork.o \
$(CPUDIR)/setjmp.o \ $(CPUDIR)/setjmp.o \

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen. * Copyright (c) 2012, 2013, 2014, 2015, 2016, 2022 Jonas 'Sortie' Termansen.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -117,6 +117,16 @@ struct heap_alloc
#warning "You need to implement HEAP_CHUNK_MAGIC for your native word width" #warning "You need to implement HEAP_CHUNK_MAGIC for your native word width"
#endif #endif
#ifdef __TRACE_ALLOCATION_SITES
#define MAGIC_IS_ALLOCATION_SITE(magic)( (((size_t) (magic)) & 0x3) == 0x2)
#define ALLOCATION_SITE_OF_MAGIC(magic) ((struct __allocation_site*) ((magic) & ~0x3UL))
#define MAGIC_OF_ALLOCATION_SITE(magic) (((size_t) (magic)) | 0x2)
#else
#define MAGIC_IS_ALLOCATION_SITE(magic) 0
#define ALLOCATION_SITE_OF_MAGIC(magic) NULL
#define MAGIC_OF_ALLOCATION_SITE(magic) NULL
#endif
/* The heap is split into a number of parts that each consists of a number of /* The heap is split into a number of parts that each consists of a number of
of chunks (used and unused). The heap normally is just a single part, but if of chunks (used and unused). The heap normally is just a single part, but if
the address space gets too fragmented, it may not be possible to extend the the address space gets too fragmented, it may not be possible to extend the
@ -346,7 +356,8 @@ bool heap_chunk_is_used(struct heap_chunk* chunk)
{ {
assert(HEAP_IS_POINTER_ALIGNED(chunk, chunk->chunk_size)); assert(HEAP_IS_POINTER_ALIGNED(chunk, chunk->chunk_size));
return chunk->chunk_magic == HEAP_CHUNK_MAGIC; return chunk->chunk_magic == HEAP_CHUNK_MAGIC ||
MAGIC_IS_ALLOCATION_SITE(chunk->chunk_magic);
} }
/* Returns the trailing structure following the given chunk. */ /* Returns the trailing structure following the given chunk. */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2012, 2013, 2014, 2015 Jonas 'Sortie' Termansen. * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2022 Jonas 'Sortie' Termansen.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -242,8 +242,14 @@ int vdprintf(int fildes, const char* __restrict format, __gnuc_va_list ap)
/* Functions copied from elsewhere. */ /* Functions copied from elsewhere. */
#if __USE_SORTIX #if __USE_SORTIX
#ifdef __TRACE_ALLOCATION_SITES
int asprintf_trace(struct __allocation_site*, char** __restrict, const char* __restrict, ...)
__attribute__((__format__ (printf, 3, 4)));
#define asprintf(a, ...) asprintf_trace(ALLOCATION_SITE, (a), __VA_ARGS__)
#else
int asprintf(char** __restrict, const char* __restrict, ...) int asprintf(char** __restrict, const char* __restrict, ...)
__attribute__((__format__ (printf, 2, 3))); __attribute__((__format__ (printf, 2, 3)));
#endif
void clearerr_unlocked(FILE* stream); void clearerr_unlocked(FILE* stream);
int feof_unlocked(FILE* stream); int feof_unlocked(FILE* stream);
int ferror_unlocked(FILE* stream); int ferror_unlocked(FILE* stream);
@ -255,9 +261,15 @@ int fputc_unlocked(int c, FILE* stream);
int fputs_unlocked(const char* __restrict, FILE* __restrict stream); int fputs_unlocked(const char* __restrict, FILE* __restrict stream);
size_t fread_unlocked(void* __restrict ptr, size_t size, size_t nitems, FILE* __restrict stream); size_t fread_unlocked(void* __restrict ptr, size_t size, size_t nitems, FILE* __restrict stream);
size_t fwrite_unlocked(const void* __restrict ptr, size_t size, size_t nitems, FILE* __restrict stream); size_t fwrite_unlocked(const void* __restrict ptr, size_t size, size_t nitems, FILE* __restrict stream);
#ifdef __TRACE_ALLOCATION_SITES
int vasprintf_trace(struct __allocation_site*, char** __restrict, const char* __restrict, __gnuc_va_list)
__attribute__((__format__ (printf, 3, 0)));
#define vasprintf(a, ...) vasprintf_trace(ALLOCATION_SITE, (a), __VA_ARGS__)
#else
int vasprintf(char** __restrict, const char* __restrict, __gnuc_va_list) int vasprintf(char** __restrict, const char* __restrict, __gnuc_va_list)
__attribute__((__format__ (printf, 2, 0))); __attribute__((__format__ (printf, 2, 0)));
#endif #endif
#endif
/* Functions that are Sortix extensions. */ /* Functions that are Sortix extensions. */
#if __USE_SORTIX #if __USE_SORTIX

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011-2017 Jonas 'Sortie' Termansen. * Copyright (c) 2011-2017, 2022 Jonas 'Sortie' Termansen.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -88,7 +88,12 @@ double atof(const char* value);
int atoi(const char*); int atoi(const char*);
long atol(const char*); long atol(const char*);
void* bsearch(const void*, const void*, size_t, size_t, int (*)(const void*, const void*)); void* bsearch(const void*, const void*, size_t, size_t, int (*)(const void*, const void*));
#ifdef __TRACE_ALLOCATION_SITES
void* calloc_trace(struct __allocation_site*, size_t, size_t);
#define calloc(a, b) calloc_trace(ALLOCATION_SITE, (a), (b))
#else
void* calloc(size_t, size_t); void* calloc(size_t, size_t);
#endif
char* canonicalize_file_name(const char* path); char* canonicalize_file_name(const char* path);
char* canonicalize_file_name_at(int dirfd, const char* path); char* canonicalize_file_name_at(int dirfd, const char* path);
int clearenv(void); int clearenv(void);
@ -99,7 +104,12 @@ void free(void*);
char* getenv(const char*); char* getenv(const char*);
long labs(long); long labs(long);
ldiv_t ldiv(long, long); ldiv_t ldiv(long, long);
#ifdef __TRACE_ALLOCATION_SITES
void* malloc_trace(struct __allocation_site*, size_t);
#define malloc(a) malloc_trace(ALLOCATION_SITE, (a))
#else
void* malloc(size_t); void* malloc(size_t);
#endif
int mblen(const char*, size_t); int mblen(const char*, size_t);
size_t mbstowcs(wchar_t* __restrict, const char* __restrict, size_t); size_t mbstowcs(wchar_t* __restrict, const char* __restrict, size_t);
int mbtowc(wchar_t *__restrict, const char* __restrict, size_t); int mbtowc(wchar_t *__restrict, const char* __restrict, size_t);
@ -116,7 +126,12 @@ void qsort_r(void*, size_t, size_t, int (*)(const void*, const void*, void*), vo
__attribute__((__warning__("rand() isn't random, use arc4random()"))) __attribute__((__warning__("rand() isn't random, use arc4random()")))
#endif #endif
int rand(void); int rand(void);
#ifdef __TRACE_ALLOCATION_SITES
void* realloc_trace(struct __allocation_site*, void*, size_t);
#define realloc(a, b) realloc_trace(ALLOCATION_SITE, (a), (b))
#else
void* realloc(void*, size_t); void* realloc(void*, size_t);
#endif
char* realpath(const char* __restrict, char* __restrict); char* realpath(const char* __restrict, char* __restrict);
int setenv(const char*, const char*, int); int setenv(const char*, const char*, int);
#if !defined(__is_sortix_libc) /* not a warning inside libc */ #if !defined(__is_sortix_libc) /* not a warning inside libc */
@ -189,7 +204,12 @@ int posix_openpt(int);
uint32_t arc4random(void); uint32_t arc4random(void);
void arc4random_buf(void*, size_t); void arc4random_buf(void*, size_t);
uint32_t arc4random_uniform(uint32_t); uint32_t arc4random_uniform(uint32_t);
#ifdef __TRACE_ALLOCATION_SITES
void* reallocarray_trace(struct __allocation_site*, void*, size_t, size_t);
#define reallocarray(a, b, c) reallocarray_trace(ALLOCATION_SITE, (a), (b), (c))
#else
void* reallocarray(void*, size_t, size_t); void* reallocarray(void*, size_t, size_t);
#endif
int ptsname_r(int, char*, size_t); int ptsname_r(int, char*, size_t);
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2012, 2013, 2014, 2017 Jonas 'Sortie' Termansen. * Copyright (c) 2011, 2012, 2013, 2014, 2017, 2022 Jonas 'Sortie' Termansen.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -91,8 +91,13 @@ void* memccpy(void* __restrict, const void* __restrict, int, size_t);
/* Functions from XOPEN 420 gone into POSIX 2008. */ /* Functions from XOPEN 420 gone into POSIX 2008. */
#if __USE_SORTIX || 420 <= __USE_XOPEN || 200809L <= __USE_POSIX #if __USE_SORTIX || 420 <= __USE_XOPEN || 200809L <= __USE_POSIX
#ifdef __TRACE_ALLOCATION_SITES
char* strdup_trace(struct __allocation_site*, const char*);
#define strdup(a) strdup_trace(ALLOCATION_SITE, (a))
#else
char* strdup(const char*); char* strdup(const char*);
#endif #endif
#endif
/* Functions from POSIX 2001. */ /* Functions from POSIX 2001. */
#if __USE_SORTIX || 200112L <= __USE_POSIX #if __USE_SORTIX || 200112L <= __USE_POSIX
@ -111,7 +116,12 @@ char* strtok_r(char* __restrict, const char* __restrict, char** __restrict);
char* stpcpy(char* __restrict, const char* __restrict); char* stpcpy(char* __restrict, const char* __restrict);
char* stpncpy(char* __restrict, const char* __restrict, size_t); char* stpncpy(char* __restrict, const char* __restrict, size_t);
int strcoll_l(const char*, const char*, locale_t); int strcoll_l(const char*, const char*, locale_t);
#ifdef __TRACE_ALLOCATION_SITES
char* strndup_trace(struct __allocation_site*, const char*, size_t);
#define strndup(a, b) strndup_trace(ALLOCATION_SITE, (a), (b))
#else
char* strndup(const char*, size_t); char* strndup(const char*, size_t);
#endif
size_t strnlen(const char*, size_t); size_t strnlen(const char*, size_t);
#if __USE_SORTIX && __SORTIX_STDLIB_REDIRECTS #if __USE_SORTIX && __SORTIX_STDLIB_REDIRECTS
const char* strsignal(int signum) __asm__ ("sortix_strsignal"); const char* strsignal(int signum) __asm__ ("sortix_strsignal");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2012, 2013, 2015 Jonas 'Sortie' Termansen. * Copyright (c) 2011, 2012, 2013, 2015, 2022 Jonas 'Sortie' Termansen.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -128,4 +128,24 @@
is updated to not rely on this macro. */ is updated to not rely on this macro. */
#undef __SORTIX_HAS_GETSERVBYNAME__ #undef __SORTIX_HAS_GETSERVBYNAME__
#if (defined(__is_sortix_libk) || defined(__is_sortix_kernel)) && \
defined(__TRACE_KMALLOC)
#undef __TRACE_ALLOCATION_SITES
#define __TRACE_ALLOCATION_SITES
#endif
#ifdef __TRACE_ALLOCATION_SITES
#include <stddef.h>
struct __allocation_site
{
const char* file;
size_t line;
const char* function;
size_t current_size;
size_t allocations;
};
#define __TRACE_ALLOCATION_SITES
#define ALLOCATION_SITE 0
#endif
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014 Jonas 'Sortie' Termansen. * Copyright (c) 2014, 2022 Jonas 'Sortie' Termansen.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -20,13 +20,24 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#ifdef __TRACE_ALLOCATION_SITES
int asprintf_trace(struct __allocation_site* allocation_site,
char** restrict result_ptr,
const char* restrict format,
...)
#else
int asprintf(char** restrict result_ptr, int asprintf(char** restrict result_ptr,
const char* restrict format, const char* restrict format,
...) ...)
#endif
{ {
va_list list; va_list list;
va_start(list, format); va_start(list, format);
#ifdef __TRACE_ALLOCATION_SITES
int result = vasprintf_trace(allocation_site, result_ptr, format, list);
#else
int result = vasprintf(result_ptr, format, list); int result = vasprintf(result_ptr, format, list);
#endif
va_end(list); va_end(list);
return result; return result;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2015 Jonas 'Sortie' Termansen. * Copyright (c) 2014, 2015, 2022 Jonas 'Sortie' Termansen.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -27,6 +27,9 @@ struct vasprintf
char* buffer; char* buffer;
size_t used; size_t used;
size_t size; size_t size;
#ifdef __TRACE_ALLOCATION_SITES
struct __allocation_site* allocation_site;
#endif
}; };
static size_t vasprintf_callback(void* ctx, const char* string, size_t length) static size_t vasprintf_callback(void* ctx, const char* string, size_t length)
@ -39,7 +42,12 @@ static size_t vasprintf_callback(void* ctx, const char* string, size_t length)
size_t new_size = 2 * state->size; size_t new_size = 2 * state->size;
if ( new_size < needed_size ) if ( new_size < needed_size )
new_size = needed_size; new_size = needed_size;
#ifdef __TRACE_ALLOCATION_SITES
char* new_buffer = (char*) realloc_trace(state->allocation_site,
state->buffer, new_size);
#else
char* new_buffer = (char*) realloc(state->buffer, new_size); char* new_buffer = (char*) realloc(state->buffer, new_size);
#endif
if ( !new_buffer ) if ( !new_buffer )
{ {
free(state->buffer); free(state->buffer);
@ -54,14 +62,26 @@ static size_t vasprintf_callback(void* ctx, const char* string, size_t length)
return length; return length;
} }
#ifdef __TRACE_ALLOCATION_SITES
int vasprintf_trace(struct __allocation_site* allocation_site,
char** restrict result_ptr,
const char* restrict format,
va_list list)
#else
int vasprintf(char** restrict result_ptr, int vasprintf(char** restrict result_ptr,
const char* restrict format, const char* restrict format,
va_list list) va_list list)
#endif
{ {
struct vasprintf state; struct vasprintf state;
state.used = 0; state.used = 0;
state.size = 32; state.size = 32;
#ifdef __TRACE_ALLOCATION_SITES
state.allocation_site = allocation_site;
if ( !(state.buffer = (char*) malloc_trace(allocation_site, state.size)) )
#else
if ( !(state.buffer = (char*) malloc(state.size)) ) if ( !(state.buffer = (char*) malloc(state.size)) )
#endif
return -1; return -1;
int result = vcbprintf(&state, vasprintf_callback, format, list); int result = vcbprintf(&state, vasprintf_callback, format, list);
if ( !state.buffer ) if ( !state.buffer )

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. * Copyright (c) 2011, 2012, 2014, 2022 Jonas 'Sortie' Termansen.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -22,12 +22,21 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef __TRACE_ALLOCATION_SITES
void* calloc_trace(struct __allocation_site* allocation_site,
size_t nmemb, size_t size)
#else
void* calloc(size_t nmemb, size_t size) void* calloc(size_t nmemb, size_t size)
#endif
{ {
if ( size && nmemb && SIZE_MAX / size < nmemb ) if ( size && nmemb && SIZE_MAX / size < nmemb )
return errno = ENOMEM, (void*) NULL; return errno = ENOMEM, (void*) NULL;
size_t total = nmemb * size; size_t total = nmemb * size;
#ifdef __TRACE_ALLOCATION_SITES
void* result = malloc_trace(allocation_site, total);
#else
void* result = malloc(total); void* result = malloc(total);
#endif
if ( !result ) if ( !result )
return NULL; return NULL;
memset(result, 0, total); memset(result, 0, total);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2012, 2013, 2014, 2015 Jonas 'Sortie' Termansen. * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2022 Jonas 'Sortie' Termansen.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -39,6 +39,16 @@ void free(void* addr)
// Retrieve the chunk that contains this allocation. // Retrieve the chunk that contains this allocation.
struct heap_chunk* chunk = heap_data_to_chunk((uint8_t*) addr); struct heap_chunk* chunk = heap_data_to_chunk((uint8_t*) addr);
#ifdef __TRACE_ALLOCATION_SITES
if ( MAGIC_IS_ALLOCATION_SITE(chunk->chunk_magic) )
{
struct __allocation_site* allocation_site =
ALLOCATION_SITE_OF_MAGIC(chunk->chunk_magic);
allocation_site->current_size -= chunk->chunk_size;
allocation_site->allocations--;
}
#endif
// Return the chunk to the heap. // Return the chunk to the heap.
heap_insert_chunk(chunk); heap_insert_chunk(chunk);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2012, 2013, 2014, 2015 Jonas 'Sortie' Termansen. * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2022 Jonas 'Sortie' Termansen.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -31,7 +31,12 @@
#if !defined(HEAP_GUARD_DEBUG) #if !defined(HEAP_GUARD_DEBUG)
#ifdef __TRACE_ALLOCATION_SITES
void* malloc_trace(struct __allocation_site* allocation_site,
size_t original_size)
#else
void* malloc(size_t original_size) void* malloc(size_t original_size)
#endif
{ {
if ( !heap_size_has_bin(original_size) ) if ( !heap_size_has_bin(original_size) )
return errno = ENOMEM, (void*) NULL; return errno = ENOMEM, (void*) NULL;
@ -89,6 +94,12 @@ void* malloc(size_t original_size)
if ( heap_can_split_chunk(result_chunk, chunk_size) ) if ( heap_can_split_chunk(result_chunk, chunk_size) )
heap_split_chunk(result_chunk, chunk_size); heap_split_chunk(result_chunk, chunk_size);
#ifdef __TRACE_ALLOCATION_SITES
allocation_site->current_size += result_chunk->chunk_size;
allocation_site->allocations++;
result_chunk->chunk_magic = MAGIC_OF_ALLOCATION_SITE(allocation_site);
#endif
__heap_verify(); __heap_verify();
__heap_unlock(); __heap_unlock();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2012, 2013, 2014, 2015 Jonas 'Sortie' Termansen. * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2022 Jonas 'Sortie' Termansen.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -31,10 +31,20 @@
#if !defined(HEAP_GUARD_DEBUG) #if !defined(HEAP_GUARD_DEBUG)
#ifdef __TRACE_ALLOCATION_SITES
void* realloc_trace(struct __allocation_site* new_allocation_site,
void* ptr,
size_t requested_size)
#else
void* realloc(void* ptr, size_t requested_size) void* realloc(void* ptr, size_t requested_size)
#endif
{ {
if ( !ptr ) if ( !ptr )
#ifdef __TRACE_ALLOCATION_SITES
return malloc_trace(new_allocation_site, requested_size);
#else
return malloc(requested_size); return malloc(requested_size);
#endif
if ( !heap_size_has_bin(requested_size) ) if ( !heap_size_has_bin(requested_size) )
return errno = ENOMEM, (void*) NULL; return errno = ENOMEM, (void*) NULL;
@ -55,7 +65,14 @@ void* realloc(void* ptr, size_t requested_size)
// Retrieve the chunk that contains this allocation. // Retrieve the chunk that contains this allocation.
struct heap_chunk* chunk = heap_data_to_chunk((uint8_t*) ptr); struct heap_chunk* chunk = heap_data_to_chunk((uint8_t*) ptr);
assert(chunk->chunk_magic == HEAP_CHUNK_MAGIC); #ifdef __TRACE_ALLOCATION_SITES
assert(MAGIC_IS_ALLOCATION_SITE(chunk->chunk_magic));
struct __allocation_site* allocation_site =
ALLOCATION_SITE_OF_MAGIC(chunk->chunk_magic);
#endif
assert(chunk->chunk_magic == HEAP_CHUNK_MAGIC ||
MAGIC_IS_ALLOCATION_SITE(chunk->chunk_magic));
assert(heap_chunk_to_post(chunk)->chunk_magic == HEAP_CHUNK_MAGIC); assert(heap_chunk_to_post(chunk)->chunk_magic == HEAP_CHUNK_MAGIC);
assert(heap_chunk_to_post(chunk)->chunk_size == chunk->chunk_size); assert(heap_chunk_to_post(chunk)->chunk_size == chunk->chunk_size);
@ -72,8 +89,17 @@ void* realloc(void* ptr, size_t requested_size)
if ( requested_chunk_size < chunk->chunk_size ) if ( requested_chunk_size < chunk->chunk_size )
{ {
assert(requested_chunk_size <= chunk->chunk_size); assert(requested_chunk_size <= chunk->chunk_size);
#ifdef __TRACE_ALLOCATION_SITES
allocation_site->current_size -= chunk->chunk_size;
allocation_site->allocations--;
#endif
if ( heap_can_split_chunk(chunk, requested_chunk_size) ) if ( heap_can_split_chunk(chunk, requested_chunk_size) )
heap_split_chunk(chunk, requested_chunk_size); heap_split_chunk(chunk, requested_chunk_size);
#ifdef __TRACE_ALLOCATION_SITES
allocation_site->current_size += chunk->chunk_size;
allocation_site->allocations++;
chunk->chunk_magic = MAGIC_OF_ALLOCATION_SITE(allocation_site);
#endif
__heap_verify(); __heap_verify();
__heap_unlock(); __heap_unlock();
return heap_chunk_to_data(chunk); return heap_chunk_to_data(chunk);
@ -88,11 +114,20 @@ void* realloc(void* ptr, size_t requested_size)
!heap_chunk_is_used(right) && !heap_chunk_is_used(right) &&
requested_chunk_size <= chunk->chunk_size + right->chunk_size ) requested_chunk_size <= chunk->chunk_size + right->chunk_size )
{ {
#ifdef __TRACE_ALLOCATION_SITES
allocation_site->current_size -= chunk->chunk_size;
allocation_site->allocations--;
#endif
heap_remove_chunk(right); heap_remove_chunk(right);
heap_chunk_format((uint8_t*) chunk, chunk->chunk_size + right->chunk_size); heap_chunk_format((uint8_t*) chunk, chunk->chunk_size + right->chunk_size);
assert(requested_chunk_size <= chunk->chunk_size); assert(requested_chunk_size <= chunk->chunk_size);
if ( heap_can_split_chunk(chunk, requested_chunk_size) ) if ( heap_can_split_chunk(chunk, requested_chunk_size) )
heap_split_chunk(chunk, requested_chunk_size); heap_split_chunk(chunk, requested_chunk_size);
#ifdef __TRACE_ALLOCATION_SITES
allocation_site->current_size += chunk->chunk_size;
allocation_site->allocations++;
chunk->chunk_magic = MAGIC_OF_ALLOCATION_SITE(allocation_site);
#endif
__heap_verify(); __heap_verify();
__heap_unlock(); __heap_unlock();
return heap_chunk_to_data(chunk); return heap_chunk_to_data(chunk);
@ -108,7 +143,11 @@ void* realloc(void* ptr, size_t requested_size)
assert(orignal_ptr_size < requested_size); assert(orignal_ptr_size < requested_size);
#ifdef __TRACE_ALLOCATION_SITES
void* result = malloc_trace(allocation_site, requested_size);
#else
void* result = malloc(requested_size); void* result = malloc(requested_size);
#endif
if ( !result ) if ( !result )
return (void*) NULL; return (void*) NULL;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014 Jonas 'Sortie' Termansen. * Copyright (c) 2014, 2022 Jonas 'Sortie' Termansen.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -21,9 +21,18 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef __TRACE_ALLOCATION_SITES
void* reallocarray_trace(struct __allocation_site* allocation_site,
void* ptr, size_t nmemb, size_t size)
#else
void* reallocarray(void* ptr, size_t nmemb, size_t size) void* reallocarray(void* ptr, size_t nmemb, size_t size)
#endif
{ {
if ( size && nmemb && SIZE_MAX / size < nmemb ) if ( size && nmemb && SIZE_MAX / size < nmemb )
return errno = ENOMEM, (void*) NULL; return errno = ENOMEM, (void*) NULL;
#ifdef __TRACE_ALLOCATION_SITES
return realloc_trace(allocation_site, ptr, nmemb * size);
#else
return realloc(ptr, nmemb * size); return realloc(ptr, nmemb * size);
#endif
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. * Copyright (c) 2011, 2012, 2014, 2022 Jonas 'Sortie' Termansen.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -20,10 +20,18 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef __TRACE_ALLOCATION_SITES
char* strdup_trace(struct __allocation_site* allocation_site, const char* input)
#else
char* strdup(const char* input) char* strdup(const char* input)
#endif
{ {
size_t input_length = strlen(input); size_t input_length = strlen(input);
#ifdef __TRACE_ALLOCATION_SITES
char* result = (char*) malloc_trace(allocation_site, input_length + 1);
#else
char* result = (char*) malloc(input_length + 1); char* result = (char*) malloc(input_length + 1);
#endif
if ( !result ) if ( !result )
return NULL; return NULL;
memcpy(result, input, input_length + 1); memcpy(result, input, input_length + 1);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2012, 2014 Jonas 'Sortie' Termansen. * Copyright (c) 2011, 2012, 2014, 2022 Jonas 'Sortie' Termansen.
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -20,10 +20,19 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef __TRACE_ALLOCATION_SITES
char* strndup_trace(struct __allocation_site* allocation_site,
const char* input, size_t n)
#else
char* strndup(const char* input, size_t n) char* strndup(const char* input, size_t n)
#endif
{ {
size_t input_size = strnlen(input, n); size_t input_size = strnlen(input, n);
#ifdef __TRACE_ALLOCATION_SITES
char* result = (char*) malloc_trace(allocation_site, input_size + 1);
#else
char* result = (char*) malloc(input_size + 1); char* result = (char*) malloc(input_size + 1);
#endif
if ( !result ) if ( !result )
return NULL; return NULL;
memcpy(result, input, input_size); memcpy(result, input, input_size);