Skip to content
Snippets Groups Projects
Commit b677f3ed authored by Kostyantyn Vorobyov's avatar Kostyantyn Vorobyov
Browse files

Reworked memory layout for shadowing

parent 35f5db4d
No related branches found
No related tags found
No related merge requests found
...@@ -136,21 +136,29 @@ static int initialized(void * ptr, size_t size) { ...@@ -136,21 +136,29 @@ static int initialized(void * ptr, size_t size) {
return 0; return 0;
} }
static size_t get_heap_size(void) { static size_t get_heap_allocation_size(void) {
return heap_size; return heap_allocation_size;
} }
static void memory_init(int *argc_ref, char *** argv_ref, size_t ptr_size) { static void memory_init(int *argc_ref, char *** argv_ref, size_t ptr_size) {
/** Verify that the given size of a pointer matches the one in the present
* architecture. This is a guard against Frama-C instrumentations using
* architectures different to the given one. */
arch_assert(ptr_size); arch_assert(ptr_size);
/* Initialize report file with debug logs (only in debug mode). */
initialize_report_file(argc_ref, argv_ref); initialize_report_file(argc_ref, argv_ref);
init_pgm_layout(argc_ref, argv_ref); /* Lift stack limit to account for extra stack memory overhead. */
increase_stack_limit(get_stack_size()*2);
/* Allocate and log shadow memory layout of the execution. */
init_memory_layout(argc_ref, argv_ref);
DEBUG_PRINT_LAYOUT;
/* Track program arguments. */
if (argc_ref && argv_ref) if (argc_ref && argv_ref)
argv_alloca(*argc_ref, *argv_ref); argv_alloca(*argc_ref, *argv_ref);
DEBUG_PRINT_LAYOUT;
} }
static void memory_clean(void) { static void memory_clean(void) {
clean_pgm_layout(); clean_memory_layout();
} }
/* API BINDINGS {{{ */ /* API BINDINGS {{{ */
...@@ -181,6 +189,6 @@ public_alias(full_init) ...@@ -181,6 +189,6 @@ public_alias(full_init)
public_alias(memory_clean) public_alias(memory_clean)
public_alias(memory_init) public_alias(memory_init)
/* Heap size */ /* Heap size */
public_alias(get_heap_size) public_alias(get_heap_allocation_size)
public_alias(heap_size) public_alias(heap_allocation_size)
/* }}} */ /* }}} */
...@@ -43,10 +43,10 @@ ...@@ -43,10 +43,10 @@
/*! \brief Size (in bytes) of a long block on the stack. */ /*! \brief Size (in bytes) of a long block on the stack. */
#define LONG_BLOCK 8 #define LONG_BLOCK 8
/*! \brief Bit offset in a short shadow byte that represents initialization. */ /*! \brief Bit offset in a primary shadow byte that represents initialization. */
#define INIT_BIT 0 #define INIT_BIT 0
/*! \brief Bit offset in a short shadow byte that represents read-only or /*! \brief Bit offset in a primary shadow byte that represents read-only or
* read-write access. * read-write access.
* *
* This is such that the value of 1 is read-only, and 0 is read/write */ * This is such that the value of 1 is read-only, and 0 is read/write */
...@@ -67,16 +67,16 @@ ...@@ -67,16 +67,16 @@
/*! \brief Short shadow of a long block consists of a 8-byte segment + a /*! \brief Short shadow of a long block consists of a 8-byte segment + a
* remainder. For instance, a 18-byte block is represented by two 8-byte * remainder. For instance, a 18-byte block is represented by two 8-byte
* segments + 2 bytes. Each byte of a segment stores an offset in the long * segments + 2 bytes. Each byte of a segment stores an offset in the secondary
* shadow. The offsets for each such segment can be expressed using the * shadow. The offsets for each such segment can be expressed using the
* following number obtained by compressing all eight bytes with offsets set * following number obtained by compressing all eight bytes with offsets set
* into a single block. */ * into a single block. */
#define LONG_BLOCK_MASK 15913703276567643328UL #define LONG_BLOCK_MASK 15913703276567643328UL
/*! \brief 6 higher bytes of a memory cell on stack that belongs to a long /*! \brief 6 higher bytes of a memory cell on stack that belongs to a long
* memory block store offsets relative to meta-data in long shadow. The offsets * memory block store offsets relative to meta-data in the secondary shadow. The
* start with the below number. E.g., if the bits store 51, then the offset at * offsets start with the below number. E.g., if the bits store 51, then the
* which to read meta-data is (51 - 48). */ * offset at which to read meta-data is (51 - 48). */
#define LONG_BLOCK_INDEX_START 48 #define LONG_BLOCK_INDEX_START 48
/*! \brief Increase the size to a multiple of a segment size. */ /*! \brief Increase the size to a multiple of a segment size. */
...@@ -211,7 +211,7 @@ static int freeable(void *ptr); ...@@ -211,7 +211,7 @@ static int freeable(void *ptr);
* This macro really belongs where static_allocated is defined, but * This macro really belongs where static_allocated is defined, but
* since it is used across this whole file it needs to be defined here. */ * since it is used across this whole file it needs to be defined here. */
#define static_allocated_one(addr, global) \ #define static_allocated_one(addr, global) \
((int)SHORT_SHADOW(addr, global)) ((int)PRIMARY_SHADOW(addr, global))
/* Runtime assertions */ /* Runtime assertions */
#define VALIDATE_ALIGNMENT(_addr) \ #define VALIDATE_ALIGNMENT(_addr) \
...@@ -221,7 +221,7 @@ static int freeable(void *ptr); ...@@ -221,7 +221,7 @@ static int freeable(void *ptr);
/* Debug-level macros for validating memory accesses and allocation */ /* Debug-level macros for validating memory accesses and allocation */
#ifdef E_ACSL_DEBUG #ifdef E_ACSL_DEBUG
# define DVALIDATE_SHADOW_LAYOUT \ # define DVALIDATE_SHADOW_LAYOUT \
DVASSERT(pgm_layout.initialized != 0, "Un-initialized shadow layout", NULL) DVASSERT(mem_layout.initialized != 0, "Un-initialized shadow layout", NULL)
# define DVALIDATE_HEAP_ACCESS(_addr, _size) \ # define DVALIDATE_HEAP_ACCESS(_addr, _size) \
DVALIDATE_SHADOW_LAYOUT; \ DVALIDATE_SHADOW_LAYOUT; \
...@@ -326,8 +326,8 @@ static uintptr_t predicate(uintptr_t addr, char p) { ...@@ -326,8 +326,8 @@ static uintptr_t predicate(uintptr_t addr, char p) {
* and then for a block of 5 bytes its base offset if 11 etc. */ * and then for a block of 5 bytes its base offset if 11 etc. */
static const char short_offsets_base [] = { 0, 1, 2, 4, 7, 11, 16, 22, 29 }; static const char short_offsets_base [] = { 0, 1, 2, 4, 7, 11, 16, 22, 29 };
/*! \brief Static (stack or global) memory-allocation. Record allocation of a /*! \brief Stack or global memory-allocation. Record allocation of a
* given memory block and update shadow regions. * given memory block and update shadows.
* *
* \param ptr - pointer to a base memory address of the stack memory block. * \param ptr - pointer to a base memory address of the stack memory block.
* \param size - size of the stack memory block. * \param size - size of the stack memory block.
...@@ -337,11 +337,11 @@ static void shadow_alloca(void *ptr, size_t size, int global) { ...@@ -337,11 +337,11 @@ static void shadow_alloca(void *ptr, size_t size, int global) {
DVALIDATE_SHADOW_LAYOUT; DVALIDATE_SHADOW_LAYOUT;
unsigned char *short_shadowed = unsigned char *short_shadowed =
(unsigned char*)SHORT_SHADOW((uintptr_t)ptr, global); (unsigned char*)PRIMARY_SHADOW(ptr, global);
uint64_t *short_shadowed_alt = uint64_t *short_shadowed_alt =
(uint64_t *)SHORT_SHADOW((uintptr_t)ptr, global); (uint64_t *)PRIMARY_SHADOW(ptr, global);
unsigned int *long_shadowed = unsigned int *long_shadowed =
(unsigned int*)LONG_SHADOW((uintptr_t)ptr, global); (unsigned int*)SECONDARY_SHADOW(ptr, global);
/* Flip read-only bit for zero-size blocks. That is, physically it exists /* Flip read-only bit for zero-size blocks. That is, physically it exists
* but one cannot write to it. Further, the flipped read-only bit will also * but one cannot write to it. Further, the flipped read-only bit will also
...@@ -391,8 +391,8 @@ static void static_shadow_freea(void *ptr, int global) { ...@@ -391,8 +391,8 @@ static void static_shadow_freea(void *ptr, int global) {
size_t size = block_length(ptr); size_t size = block_length(ptr);
memset((void*)SHORT_SHADOW(ptr, global), 0, size); memset((void*)PRIMARY_SHADOW(ptr, global), 0, size);
memset((void*)LONG_SHADOW(ptr, global), 0, size); memset((void*)SECONDARY_SHADOW(ptr, global), 0, size);
} }
/*! \brief Wrapper around ::static_shadow_freea for stack addresses */ /*! \brief Wrapper around ::static_shadow_freea for stack addresses */
...@@ -409,7 +409,7 @@ static void static_shadow_freea(void *ptr, int global) { ...@@ -409,7 +409,7 @@ static void static_shadow_freea(void *ptr, int global) {
* applied to a stack or global address. */ * applied to a stack or global address. */
static int static_allocated(uintptr_t addr, long size, int global) { static int static_allocated(uintptr_t addr, long size, int global) {
DVALIDATE_SHADOW_LAYOUT; DVALIDATE_SHADOW_LAYOUT;
unsigned char *short_shadowed = (unsigned char*)SHORT_SHADOW(addr, global); unsigned char *short_shadowed = (unsigned char*)PRIMARY_SHADOW(addr, global);
/* Unless the address belongs to tracked allocation 0 is returned */ /* Unless the address belongs to tracked allocation 0 is returned */
if (short_shadowed[0]) { if (short_shadowed[0]) {
unsigned int code = (short_shadowed[0] >> 2); unsigned int code = (short_shadowed[0] >> 2);
...@@ -418,7 +418,7 @@ static int static_allocated(uintptr_t addr, long size, int global) { ...@@ -418,7 +418,7 @@ static int static_allocated(uintptr_t addr, long size, int global) {
if (long_block) { if (long_block) {
offset = code - LONG_BLOCK_INDEX_START; offset = code - LONG_BLOCK_INDEX_START;
unsigned int *long_shadowed = unsigned int *long_shadowed =
(unsigned int*)LONG_SHADOW(addr - offset, global) ; (unsigned int*)SECONDARY_SHADOW(addr - offset, global) ;
length = long_shadowed[0]; length = long_shadowed[0];
offset = long_shadowed[1] + offset; offset = long_shadowed[1] + offset;
} else { } else {
...@@ -444,7 +444,7 @@ static int static_initialized(uintptr_t addr, long size, int global) { ...@@ -444,7 +444,7 @@ static int static_initialized(uintptr_t addr, long size, int global) {
DVALIDATE_STATIC_ACCESS(addr, size, global); DVALIDATE_STATIC_ACCESS(addr, size, global);
int result = 1; int result = 1;
uint64_t *shadow = (uint64_t*)SHORT_SHADOW(addr, global); uint64_t *shadow = (uint64_t*)PRIMARY_SHADOW(addr, global);
while (size > 0) { while (size > 0) {
int rem = (size >= ULONG_BYTES) ? ULONG_BYTES : size; int rem = (size >= ULONG_BYTES) ? ULONG_BYTES : size;
uint64_t mask = static_init_masks[rem]; uint64_t mask = static_init_masks[rem];
...@@ -471,7 +471,7 @@ static int static_initialized(uintptr_t addr, long size, int global) { ...@@ -471,7 +471,7 @@ static int static_initialized(uintptr_t addr, long size, int global) {
* read-only parts, that is to check whether the block has read-only access it * read-only parts, that is to check whether the block has read-only access it
* is sufficient to check any of its bytes. */ * is sufficient to check any of its bytes. */
#define global_readonly(_addr) \ #define global_readonly(_addr) \
checkbit(READONLY_BIT, (*(char*)SHORT_GLOBAL_SHADOW(addr))) checkbit(READONLY_BIT, (*(char*)PRIMARY_GLOBAL_SHADOW(addr)))
/*! \brief Querying information about a specific global or stack memory address /*! \brief Querying information about a specific global or stack memory address
* (based on the value of parameter `global'). The return value is interpreted * (based on the value of parameter `global'). The return value is interpreted
...@@ -490,7 +490,7 @@ static int static_initialized(uintptr_t addr, long size, int global) { ...@@ -490,7 +490,7 @@ static int static_initialized(uintptr_t addr, long size, int global) {
* unspecified. */ * unspecified. */
static uintptr_t static_info(uintptr_t addr, char type, int global) { static uintptr_t static_info(uintptr_t addr, char type, int global) {
DVALIDATE_STATIC_LOCATION(addr, global); DVALIDATE_STATIC_LOCATION(addr, global);
unsigned char *short_shadowed = (unsigned char*)SHORT_SHADOW(addr, global); unsigned char *short_shadowed = (unsigned char*)PRIMARY_SHADOW(addr, global);
/* Unless the address belongs to tracked allocation 0 is returned */ /* Unless the address belongs to tracked allocation 0 is returned */
if (short_shadowed[0]) { if (short_shadowed[0]) {
...@@ -499,7 +499,7 @@ static uintptr_t static_info(uintptr_t addr, char type, int global) { ...@@ -499,7 +499,7 @@ static uintptr_t static_info(uintptr_t addr, char type, int global) {
if (long_block) { if (long_block) {
unsigned int offset = code - LONG_BLOCK_INDEX_START; unsigned int offset = code - LONG_BLOCK_INDEX_START;
unsigned int *long_shadowed = unsigned int *long_shadowed =
(unsigned int*)LONG_SHADOW(addr - offset, global) ; (unsigned int*)SECONDARY_SHADOW(addr - offset, global) ;
switch(type) { switch(type) {
case 'B': /* Base address */ case 'B': /* Base address */
return addr - offset - long_shadowed[1]; return addr - offset - long_shadowed[1];
...@@ -567,7 +567,7 @@ static void initialize_static_region(uintptr_t addr, long size, int global) { ...@@ -567,7 +567,7 @@ static void initialize_static_region(uintptr_t addr, long size, int global) {
* That is, `*shadow |= static_init_masks[1]` will set only the least * That is, `*shadow |= static_init_masks[1]` will set only the least
* significant bit in *shadow. */ * significant bit in *shadow. */
uint64_t *shadow = (uint64_t*)SHORT_SHADOW(addr, global); uint64_t *shadow = (uint64_t*)PRIMARY_SHADOW(addr, global);
while (size > 0) { while (size > 0) {
int rem = (size >= ULONG_BYTES) ? ULONG_BYTES : size; int rem = (size >= ULONG_BYTES) ? ULONG_BYTES : size;
size -= ULONG_BYTES; size -= ULONG_BYTES;
...@@ -603,7 +603,7 @@ static void mark_readonly (uintptr_t addr, long size) { ...@@ -603,7 +603,7 @@ static void mark_readonly (uintptr_t addr, long size) {
size, addr, block_length(addr), base_addr(addr)); size, addr, block_length(addr), base_addr(addr));
/* See comments in ::initialize_static_region for details */ /* See comments in ::initialize_static_region for details */
uint64_t *shadow = (uint64_t*)SHORT_GLOBAL_SHADOW(addr); uint64_t *shadow = (uint64_t*)PRIMARY_GLOBAL_SHADOW(addr);
while (size > 0) { while (size > 0) {
int rem = (size >= ULONG_BYTES) ? ULONG_BYTES : size; int rem = (size >= ULONG_BYTES) ? ULONG_BYTES : size;
size -= ULONG_BYTES; size -= ULONG_BYTES;
...@@ -632,7 +632,7 @@ static void argv_alloca(int argc, char ** argv) { ...@@ -632,7 +632,7 @@ static void argv_alloca(int argc, char ** argv) {
/*! \brief Amount of heap memory allocated by the program. /*! \brief Amount of heap memory allocated by the program.
* Variable visible externally. */ * Variable visible externally. */
static size_t heap_size = 0; static size_t heap_allocation_size = 0;
/*! \brief Create a heap shadow for an allocated memory block starting at `ptr` /*! \brief Create a heap shadow for an allocated memory block starting at `ptr`
* and of length `size`. Optionally mark it as initialized if `init` * and of length `size`. Optionally mark it as initialized if `init`
...@@ -644,7 +644,7 @@ static void set_heap_segment(void *ptr, size_t size, size_t init) { ...@@ -644,7 +644,7 @@ static void set_heap_segment(void *ptr, size_t size, size_t init) {
return; return;
VALIDATE_ALIGNMENT(ptr); /* Make sure alignment is right */ VALIDATE_ALIGNMENT(ptr); /* Make sure alignment is right */
heap_size += size; /* Adjuct tracked allocation size */ heap_allocation_size += size; /* Adjuct tracked allocation size */
/* Get aligned size of the block, i.e., an actual size of the /* Get aligned size of the block, i.e., an actual size of the
* allocated block */ * allocated block */
...@@ -743,8 +743,8 @@ static void shadow_free(void *res) { ...@@ -743,8 +743,8 @@ static void shadow_free(void *res) {
void *meta_shadow = (void*)(HEAP_SHADOW(ptr) - HEAP_SEGMENT); void *meta_shadow = (void*)(HEAP_SHADOW(ptr) - HEAP_SEGMENT);
memset(meta_shadow, 0, HEAP_SHADOW_BLOCK_SIZE(size)); memset(meta_shadow, 0, HEAP_SHADOW_BLOCK_SIZE(size));
native_free(ptr - HEAP_SEGMENT); native_free(ptr - HEAP_SEGMENT);
/* Adjuct tracked allocation size carried via `__e_acsl_heap_size` */ /* Adjuct tracked allocation size carried via `__e_acsl_heap_allocation_size` */
heap_size -= size; heap_allocation_size -= size;
} else { } else {
vabort("Not a start of block (%a) in free\n", ptr); vabort("Not a start of block (%a) in free\n", ptr);
} }
...@@ -780,7 +780,7 @@ static void* shadow_realloc(void *p, size_t size) { ...@@ -780,7 +780,7 @@ static void* shadow_realloc(void *p, size_t size) {
/* Number of block segments in the new allocation */ /* Number of block segments in the new allocation */
size_t new_segments = BLOCK_SEGMENTS(size); size_t new_segments = BLOCK_SEGMENTS(size);
/* Adjuct tracked allocation size */ /* Adjuct tracked allocation size */
heap_size += -old_size + size; heap_allocation_size += -old_size + size;
/* Address of the meta-block in old allocation */ /* Address of the meta-block in old allocation */
uintptr_t *meta_shadow = (uintptr_t*)(HEAP_SHADOW(ptr) - HEAP_SEGMENT); uintptr_t *meta_shadow = (uintptr_t*)(HEAP_SHADOW(ptr) - HEAP_SEGMENT);
...@@ -1080,7 +1080,7 @@ static void initialize(void *ptr, size_t n) { ...@@ -1080,7 +1080,7 @@ static void initialize(void *ptr, size_t n) {
/* Internal state print {{{ */ /* Internal state print {{{ */
#ifdef E_ACSL_DEBUG #ifdef E_ACSL_DEBUG
/* ! \brief Print human-readable representation of a byte in a short (byte) /* ! \brief Print human-readable representation of a byte in a primary
* shadow */ * shadow */
static void printbyte(unsigned char c, char buf[]) { static void printbyte(unsigned char c, char buf[]) {
if (c >> 2 < LONG_BLOCK_INDEX_START) { if (c >> 2 < LONG_BLOCK_INDEX_START) {
...@@ -1095,13 +1095,13 @@ static void printbyte(unsigned char c, char buf[]) { ...@@ -1095,13 +1095,13 @@ static void printbyte(unsigned char c, char buf[]) {
} }
/*! \brief Print human-readable (well, ish) representation of a memory block /*! \brief Print human-readable (well, ish) representation of a memory block
* using short (byte) and long (block) shadow regions */ * using primary and secondary shadows. */
static void print_static_shadows(uintptr_t addr, size_t size, int global) { static void print_static_shadows(uintptr_t addr, size_t size, int global) {
char short_buf[256]; char short_buf[256];
char long_buf[256]; char long_buf[256];
unsigned char *short_shadowed = (unsigned char*)SHORT_SHADOW(addr, global); unsigned char *short_shadowed = (unsigned char*)PRIMARY_SHADOW(addr, global);
unsigned int *long_shadowed = (unsigned int*)LONG_SHADOW(addr, global); unsigned int *long_shadowed = (unsigned int*)SECONDARY_SHADOW(addr, global);
int i, j = 0; int i, j = 0;
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
...@@ -1152,60 +1152,27 @@ static void print_shadows(uintptr_t addr, size_t size) { ...@@ -1152,60 +1152,27 @@ static void print_shadows(uintptr_t addr, size_t size) {
print_heap_shadows(addr, size); print_heap_shadows(addr, size);
} }
static void print_pgm_layout() { static void print_memory_segment(struct memory_segment *seg, const char *name) {
DLOG("| --- Stack ------------------------------------\n"); DLOG(" --- %s ------------------------------------------\n", name);
DLOG("|Stack Shadow Size: %16lu MB\n", DLOG("%s Shadow Size: %16lu MB\n", name, MB_SZ(seg->shadow_size));
MB_SZ(pgm_layout.stack_shadow_size)); DLOG("%s Start: %19lu\n", name, seg->start);
DLOG("|Stack Start: %19lu\n", pgm_layout.stack_start); DLOG("%s End: %19lu\n", name, seg->end);
DLOG("|Stack End: %19lu\n", pgm_layout.stack_end); DLOG("%s Primary Shadow Offset: %19lu\n", name, seg->prim_offset);
DLOG("|Stack Soft Bound: %19lu\n", pgm_layout.stack_soft_bound); DLOG("%s Primary Shadow Start: %19lu\n", name, seg->prim_start);
DLOG("| --- Short Stack Shadow -----------------------\n"); DLOG("%s Primary Shadow End: %19lu\n", name, seg->prim_end);
DLOG("|Short Stack Shadow Offset: %19lu\n", if (seg->sec_start) {
pgm_layout.short_stack_shadow_offset); DLOG("%s Secondary Shadow Offset: %19lu\n", name, seg->sec_offset);
DLOG("|Short Stack Shadow Start: %19lu\n", DLOG("%s Secondary Shadow Start: %19lu\n", name, seg->sec_start);
pgm_layout.short_stack_shadow_start); DLOG("%s Secondary Shadow End: %19lu\n", name, seg->sec_end);
DLOG("|Short Stack Shadow End: %19lu\n", }
pgm_layout.short_stack_shadow_end); }
DLOG("| --- Long Stack Shadow ------------------------\n");
DLOG("|Long Stack Shadow Offset: %19lu\n", static void print_memory_layout() {
pgm_layout.long_stack_shadow_offset); print_memory_segment(&mem_layout.heap, "Heap");
DLOG("|Long Stack Shadow Start: %19lu\n", print_memory_segment(&mem_layout.stack, "Stack");
pgm_layout.long_stack_shadow_start); print_memory_segment(&mem_layout.global, "Global");
DLOG("|Long Stack Shadow End: %19lu\n", print_memory_segment(&mem_layout.tls, "TLS");
pgm_layout.long_stack_shadow_end); DLOG("-----------------------------------------------------\n");
DLOG("| --- Heap -------------------------------------\n");
DLOG("|Heap Shadow Size: %16lu MB\n",
MB_SZ(pgm_layout.heap_shadow_size));
DLOG("|Heap Shadow Offset: %19lu\n", pgm_layout.heap_shadow_offset);
DLOG("|Heap Start: %19lu\n", pgm_layout.heap_start);
DLOG("|Heap End: %19lu\n", pgm_layout.heap_end);
DLOG("|Heap Shadow Start: %19lu\n", pgm_layout.heap_shadow_start);
DLOG("|Heap Shadow End: %19lu\n", pgm_layout.heap_shadow_end);
DLOG("| --- Global -----------------------------------\n");
DLOG("|Global Shadow Size: %16lu MB\n", MB_SZ(pgm_layout.global_shadow_size));
DLOG("|Global Start: %19lu\n", pgm_layout.global_start);
DLOG("|Global End: %19lu\n", pgm_layout.global_end);
DLOG("| --- Short Global Shadow ----------------------\n");
DLOG("|Short Global Shadow Offset: %19lu\n", pgm_layout.short_global_shadow_offset);
DLOG("|Short Global Shadow Start: %19lu\n", pgm_layout.short_global_shadow_start);
DLOG("|Short Global Shadow End: %19lu\n", pgm_layout.short_global_shadow_end);
DLOG("| --- Long Global Shadow -----------------------\n");
DLOG("|Long Global Shadow Offset: %19lu\n", pgm_layout.long_global_shadow_offset);
DLOG("|Long Global Shadow Start: %19lu\n", pgm_layout.long_global_shadow_start);
DLOG("|Long Global Shadow End: %19lu\n", pgm_layout.long_global_shadow_end);
DLOG("| --- TLS -----------------------------------\n");
DLOG("|TLS Shadow Size: %16lu MB\n", MB_SZ(pgm_layout.tls_shadow_size));
DLOG("|TLS Start: %19lu\n", pgm_layout.tls_start);
DLOG("|TLS End: %19lu\n", pgm_layout.tls_end);
DLOG("| --- Short TLS Shadow ----------------------\n");
DLOG("|Short TLS Shadow Offset: %19lu\n", pgm_layout.short_tls_shadow_offset);
DLOG("|Short TLS Shadow Start: %19lu\n", pgm_layout.short_tls_shadow_start);
DLOG("|Short TLS Shadow End: %19lu\n", pgm_layout.short_tls_shadow_end);
DLOG("| --- Long TLS Shadow -----------------------\n");
DLOG("|Long TLS Shadow Offset: %19lu\n", pgm_layout.long_tls_shadow_offset);
DLOG("|Long TLS Shadow Start: %19lu\n", pgm_layout.long_tls_shadow_start);
DLOG("|Long TLS Shadow End: %19lu\n", pgm_layout.long_tls_shadow_end);
DLOG("------------------------------------------------\n");
} }
/*! \brief Output the shadow segment the address belongs to */ /*! \brief Output the shadow segment the address belongs to */
...@@ -1229,7 +1196,7 @@ static void which_segment(uintptr_t addr) { ...@@ -1229,7 +1196,7 @@ static void which_segment(uintptr_t addr) {
/*! \brief Print program layout. This function outputs start/end addresses of /*! \brief Print program layout. This function outputs start/end addresses of
* various program segments, their shadow counterparts and sizes of shadow * various program segments, their shadow counterparts and sizes of shadow
* regions used. */ * regions used. */
#define DEBUG_PRINT_LAYOUT print_pgm_layout() #define DEBUG_PRINT_LAYOUT print_memory_layout()
void ___e_acsl_debug_print_layout() { DEBUG_PRINT_LAYOUT; } void ___e_acsl_debug_print_layout() { DEBUG_PRINT_LAYOUT; }
/*! \brief Print the shadow segment address addr belongs to */ /*! \brief Print the shadow segment address addr belongs to */
......
...@@ -25,8 +25,7 @@ ...@@ -25,8 +25,7 @@
* \brief Setup for memory tracking using shadowing * \brief Setup for memory tracking using shadowing
***************************************************************************/ ***************************************************************************/
/*! \brief The first address past the end of the uninitialized data (BSS) /*! \brief The first address past the end of BSS segment */
* segment . */
extern char end; extern char end;
/* \cond */ /* \cond */
...@@ -49,15 +48,6 @@ char *strerror(int errnum); ...@@ -49,15 +48,6 @@ char *strerror(int errnum);
#define MB_SZ(_s) (_s/MB) //!< Convert bytes to megabytes #define MB_SZ(_s) (_s/MB) //!< Convert bytes to megabytes
#define GB_SZ(_s) (_s/GB) //!< Convert bytes to gigabytes #define GB_SZ(_s) (_s/GB) //!< Convert bytes to gigabytes
/*! \brief Size of the heap shadow */
#define HEAP_SHADOW_SIZE (1024 * MB)
/*! \brief Size of a stack shadow */
#define STACK_SHADOW_SIZE (72 * MB)
/*! \brief Size of the TLS shadow */
#define TLS_SHADOW_SIZE (64 * MB)
/*! \brief Pointer size (in bytes) for a given system */ /*! \brief Pointer size (in bytes) for a given system */
#define PTR_SZ sizeof(uintptr_t) #define PTR_SZ sizeof(uintptr_t)
...@@ -68,7 +58,15 @@ char *strerror(int errnum); ...@@ -68,7 +58,15 @@ char *strerror(int errnum);
#define ULONG_BYTES 8 #define ULONG_BYTES 8
#define ULONG_BITS 64 #define ULONG_BITS 64
/* Thread-local storage information {{{ */ /** Hardcoded sizes of tracked program segments {{{ */
/*! \brief Size of the heap segment */
#define PGM_HEAP_SIZE (256 * MB)
/*! \brief Size of the TLS segment */
#define PGM_TLS_SIZE (8 * MB)
/* }}} */
/** Thread-local storage information {{{ */
/*! Thread-local storage (TLS) keeps track of copies of per-thread variables. /*! Thread-local storage (TLS) keeps track of copies of per-thread variables.
* Even though at the present stage RTL of E-ACSL is not thread-safe, some * Even though at the present stage RTL of E-ACSL is not thread-safe, some
...@@ -90,32 +88,43 @@ char *strerror(int errnum); ...@@ -90,32 +88,43 @@ char *strerror(int errnum);
* start TLS address (&id_bss - TLS_SHADOW_SIZE/2) * start TLS address (&id_bss - TLS_SHADOW_SIZE/2)
*/ */
/*! Get byte-size of TLS segment */
static size_t get_tls_size() {
return PGM_TLS_SIZE;
}
static __thread int id_tdata = 1; static __thread int id_tdata = 1;
static __thread int id_tbss; static __thread int id_tbss;
/*! Set TLS size and its end and start addresses. */ /*! Set TLS size and its end and start addresses. */
static void set_tls_bounds(uintptr_t *tls_end, static uintptr_t get_tls_start() {
uintptr_t *tls_start, uintptr_t *tls_size) { size_t tls_size = get_tls_size();
uintptr_t uintptr_t data = (uintptr_t)&id_tdata,
data = (uintptr_t)&id_tdata, bss = (uintptr_t)&id_tbss;
bss = (uintptr_t)&id_tbss; return ((data > bss ? bss : data) - tls_size/2);
*tls_end = ((data > bss) ? data : bss) + TLS_SHADOW_SIZE/2;
*tls_start = ((data > bss) ? bss : data) - TLS_SHADOW_SIZE/2,
*tls_size = *tls_end - *tls_start;
} }
/* }}} */ /* }}} */
/* Program stack information {{{ */ /** Program stack information {{{ */
extern char ** environ; extern char ** environ;
/*! \brief Get the stack size (in bytes) as used by the program. The return
* value is the soft stack limit, i.e., it can be programmatically increased
* at runtime */
static size_t get_stack_size() {
struct rlimit rlim;
assert(!getrlimit(RLIMIT_STACK, &rlim));
return rlim.rlim_cur;
}
/*! \brief Return greatest (known) address on a program's stack. /*! \brief Return greatest (known) address on a program's stack.
* This function presently determines the address using the address of the * This function presently determines the address using the address of the
* last string in `environ`. That is, it assumes that argc and argv are * last string in `environ`. That is, it assumes that argc and argv are
* stored below environ, which holds for GCC/GLIBC but is not necessarily * stored below environ, which holds for GCC/GLIBC but is not necessarily
* true. In general, a reliable way of detecting the upper bound of a stack * true. In general, a reliable way of detecting the upper bound of a stack
* segment is needed. */ * segment is needed. */
static uintptr_t get_stack_end(int *argc_ref, char *** argv_ref) { static uintptr_t get_stack_start(int *argc_ref, char *** argv_ref) {
char **env = environ; char **env = environ;
while (env[1]) while (env[1])
env++; env++;
...@@ -126,16 +135,9 @@ static uintptr_t get_stack_end(int *argc_ref, char *** argv_ref) { ...@@ -126,16 +135,9 @@ static uintptr_t get_stack_end(int *argc_ref, char *** argv_ref) {
* to be able to set initialization and read-only bits ::ULONG_BITS * to be able to set initialization and read-only bits ::ULONG_BITS
* at a time. If not respected, this may cause a segfault in * at a time. If not respected, this may cause a segfault in
* ::argv_alloca. */ * ::argv_alloca. */
return addr + ULONG_BITS; uintptr_t stack_end = addr + ULONG_BITS;
} uintptr_t stack_start = stack_end - get_stack_size();
return stack_start;
/*! \brief Get the stack size (in bytes) as used by the program. The return
* value is the soft stack limit, i.e., it can be programmatically increased
* at runtime */
static size_t get_stack_size() {
struct rlimit rlim;
assert(!getrlimit(RLIMIT_STACK, &rlim));
return rlim.rlim_cur;
} }
/*! \brief Set a new stack limit /*! \brief Set a new stack limit
...@@ -156,6 +158,30 @@ static void increase_stack_limit(const size_t size) { ...@@ -156,6 +158,30 @@ static void increase_stack_limit(const size_t size) {
} }
/* }}} */ /* }}} */
/** Program heap information {{{ */
static uintptr_t get_heap_start() {
return (uintptr_t)sbrk(0);
}
static size_t get_heap_size() {
return PGM_HEAP_SIZE;
}
/** }}} */
/** Program global information {{{ */
static uintptr_t get_global_start() {
return (uintptr_t)(PTR_SZ*2);
}
/*! \brief Get byte-size of global segment */
static size_t get_global_size() {
/* In all likelihood it is reasonably safe to assume that first
* 2x*pointer-size bytes of the memory space will not be used. */
return ((uintptr_t)&end - get_global_start());
}
/** }}} */
/** MMAP allocation {{{ */ /** MMAP allocation {{{ */
/*! \brief Allocate a memory block of `size` bytes with `mmap` and return a /*! \brief Allocate a memory block of `size` bytes with `mmap` and return a
* pointer to its base address. Since this function is used to set-up shadowing * pointer to its base address. Since this function is used to set-up shadowing
...@@ -176,15 +202,12 @@ static void *do_mmap(size_t size) { ...@@ -176,15 +202,12 @@ static void *do_mmap(size_t size) {
* start address of a segment */ * start address of a segment */
static uintptr_t shadow_offset(void *shadow, uintptr_t start_addr) { static uintptr_t shadow_offset(void *shadow, uintptr_t start_addr) {
uintptr_t start_shadow = (uintptr_t)shadow; uintptr_t start_shadow = (uintptr_t)shadow;
return (start_shadow > start_addr) ? return (start_shadow > start_addr) ?
start_shadow - start_addr : start_addr - start_shadow; start_shadow - start_addr : start_addr - start_shadow;
} }
/* }}} */ /* }}} */
/* Program Layout {{{ */ /** Program Layout {{{ */
/***************************************************************************** /*****************************************************************************
* Memory Layout ************************************************************* * Memory Layout *************************************************************
***************************************************************************** *****************************************************************************
...@@ -227,197 +250,89 @@ NOTE: With mmap allocations heap does not necessarily grows from program break ...@@ -227,197 +250,89 @@ NOTE: With mmap allocations heap does not necessarily grows from program break
upwards from program break. upwards from program break.
*/ */
static struct program_layout pgm_layout; struct memory_segment {
uintptr_t start; //!< Least address
/*! \brief Structure for tracking shadow regions and boundaries of memory uintptr_t end; //!< Greatest address
* segments. */
struct program_layout { size_t shadow_size; //!< Byte-size of shadow
uintptr_t stack_start; //!< Least address in program stack
uintptr_t stack_end; //!< Greatest address in program stack. uintptr_t prim_start; //!< Least address in primary shadow
uintptr_t stack_soft_bound; /*!< \brief Address of the soft stack bound. uintptr_t prim_end; //!< Greatest address in primary shadow
A program using stack addresses beyond (i.e., less than) the soft bound uintptr_t prim_offset; //!< Primary shadow offset
runs into a stack overflow. */
size_t stack_shadow_size; /*!< \brief Size (in bytes) of a stack shadow. uintptr_t sec_start; //!< Least address in secondary shadow
Same size if used for short and long shadow regions. */ uintptr_t sec_end; //!< Greatest address in secondary shadow
uintptr_t sec_offset; //!< Secondary shadow offset
uintptr_t short_stack_shadow_start; //!< Least address in short shadow region
uintptr_t short_stack_shadow_end; //!< Greatest address in short shadow region
uintptr_t short_stack_shadow_offset; /*!< \brief Short shadow offset.
The offset is kept as a positive (unsigned) integer
relative to the stack shadow region situated below the stack. That is,
to get a shadow address from an actual one the offset needs to be
subtracted. */
uintptr_t long_stack_shadow_start; //!< Least address in long shadow region
uintptr_t long_stack_shadow_end; //!< Greatest address in long shadow region
uintptr_t long_stack_shadow_offset; /*!< \brief Long shadow offset. Similar
to #short_stack_shadow_offset */
uintptr_t heap_start; //!< Least address in a program's heap.
uintptr_t heap_end; //!< Greatest address in a program's heap.
uintptr_t heap_shadow_start; /*!< \brief Least address in a program's shadow
heap region. */
uintptr_t heap_shadow_end; /*!< \brief Greatest address in a program's
shadow heap region. */
size_t heap_shadow_size; //!< Size (in bytes) of the heap shadow region. */
uintptr_t heap_shadow_offset; /*!< \brief Short shadow offset.
* The offset is kept as a positive (unsigned) integer
* relative to the heap shadow region situated above the heap. That is,
* unlike stack shadow, to get a shadow address from an actual one the
* offset needs to be added. */
/* Same as `stack_...` but for shadowing globals */
uintptr_t global_end;
uintptr_t global_start;
size_t global_shadow_size;
uintptr_t short_global_shadow_end;
uintptr_t short_global_shadow_start;
uintptr_t short_global_shadow_offset;
uintptr_t long_global_shadow_end;
uintptr_t long_global_shadow_start;
uintptr_t long_global_shadow_offset;
/* Same as `global_...` but for shadowing thread-local storage */
uintptr_t tls_end;
uintptr_t tls_start;
size_t tls_shadow_size;
uintptr_t short_tls_shadow_end;
uintptr_t short_tls_shadow_start;
uintptr_t short_tls_shadow_offset;
uintptr_t long_tls_shadow_end;
uintptr_t long_tls_shadow_start;
uintptr_t long_tls_shadow_offset;
/*! Carries a non-zero value if shadow layout has been initialized and
* evaluates to zero otherwise. */
int initialized; int initialized;
}; };
/*! \brief Setting program layout for analysys, namely: static struct memory_layout mem_layout;
* - Detect boundaries of different program segments
* - Allocate shadow regions (1 heap region + 2 stack regions) struct memory_layout {
* - Compute shadow offsets struct memory_segment heap;
* struct memory_segment stack;
* *TODO*: This function should be a part of ::__e_acsl_memory_init visible struct memory_segment global;
* externally */ struct memory_segment tls;
static void init_pgm_layout(int *argc_ref, char ***argv_ref) { int initialized;
DLOG("<<< Initialize shadow layout >>>\n"); };
/* Setting up stack. Stack grows downwards starting from the stack end
* address initialization. */ static void set_shadow_segment(struct memory_segment *seg, uintptr_t start, uintptr_t size, int secondary) {
pgm_layout.stack_shadow_size = STACK_SHADOW_SIZE; seg->start = start;
pgm_layout.stack_end = get_stack_end(argc_ref, argv_ref); seg->end = seg->start + size;
pgm_layout.stack_start = seg->shadow_size = size;
pgm_layout.stack_end - pgm_layout.stack_shadow_size;
/* Soft bound can be increased programmatically, thus detecting void *prim_shadow = do_mmap(seg->shadow_size);
* stack overflows using this stack bound needs to take into account such seg->prim_start = (uintptr_t)prim_shadow;
* changes. Very approximate for the moment, */ seg->prim_end = seg->prim_start + seg->shadow_size;
pgm_layout.stack_soft_bound = pgm_layout.stack_end - get_stack_size(); seg->prim_offset = shadow_offset(prim_shadow, start);
/* Primary stack shadow region */ if (secondary) {
void * short_stack_shadow = do_mmap(pgm_layout.stack_shadow_size); void *sec_shadow = do_mmap(seg->shadow_size);
pgm_layout.short_stack_shadow_start = (uintptr_t)short_stack_shadow; seg->sec_start = (uintptr_t)sec_shadow;
pgm_layout.short_stack_shadow_end = seg->sec_end = seg->sec_start + seg->shadow_size;
(uintptr_t)short_stack_shadow + pgm_layout.stack_shadow_size; seg->sec_offset = shadow_offset(sec_shadow, seg->start);
pgm_layout.short_stack_shadow_offset = } else {
shadow_offset(short_stack_shadow, pgm_layout.stack_start); seg->sec_start = seg->sec_end = seg->sec_offset = 0;
}
/* Secondary stack shadow region */
void *long_stack_shadow = do_mmap(pgm_layout.stack_shadow_size);
pgm_layout.long_stack_shadow_start = (uintptr_t)long_stack_shadow;
pgm_layout.long_stack_shadow_end =
(uintptr_t)long_stack_shadow + pgm_layout.stack_shadow_size;
pgm_layout.long_stack_shadow_offset =
shadow_offset(long_stack_shadow, pgm_layout.stack_start);
/* Setting heap. Heap grows upwards starting from the current program break.
Alternative approach would be to use the end of BSS but in fact the end of
BSS and the current program break are not really close to each other, so
some space will be wasted. Another reason is that sbrk is likely to return
an aligned address which makes the access faster. */
pgm_layout.heap_start = (uintptr_t)sbrk(0);
pgm_layout.heap_shadow_size = HEAP_SHADOW_SIZE;
pgm_layout.heap_end = pgm_layout.heap_start + pgm_layout.heap_shadow_size;
void* heap_shadow = do_mmap(pgm_layout.heap_shadow_size);
pgm_layout.heap_shadow_start = (uintptr_t)heap_shadow;
pgm_layout.heap_shadow_end =
(uintptr_t)heap_shadow + pgm_layout.heap_shadow_size;
pgm_layout.heap_shadow_offset =
shadow_offset(heap_shadow, pgm_layout.heap_start);
/* Setting shadow for globals */
/* In all likelihood it is reasonably safe to assume that first
* 2x*pointer-size bytes of the memory space will not be used. */
pgm_layout.global_start = PTR_SZ*2;
pgm_layout.global_end = (uintptr_t)&end;
pgm_layout.global_shadow_size
= pgm_layout.global_end - pgm_layout.global_start;
/* Primary global shadow region */
void * short_global_shadow = do_mmap(pgm_layout.global_shadow_size);
pgm_layout.short_global_shadow_start = (uintptr_t)short_global_shadow;
pgm_layout.short_global_shadow_end =
(uintptr_t)short_global_shadow + pgm_layout.global_shadow_size;
pgm_layout.short_global_shadow_offset =
shadow_offset(short_global_shadow, pgm_layout.global_start);
/* Secondary global shadow */
void *long_global_shadow = do_mmap(pgm_layout.global_shadow_size);
pgm_layout.long_global_shadow_start = (uintptr_t)long_global_shadow;
pgm_layout.long_global_shadow_end =
(uintptr_t)long_global_shadow + pgm_layout.global_shadow_size;
pgm_layout.long_global_shadow_offset =
shadow_offset(long_global_shadow, pgm_layout.global_start);
/* Setting shadow for thread-local storage (TLS). */
set_tls_bounds(&pgm_layout.tls_end, &pgm_layout.tls_start,
&pgm_layout.tls_shadow_size);
/* Primary TLS shadow */
void * short_tls_shadow = do_mmap(pgm_layout.tls_shadow_size);
pgm_layout.short_tls_shadow_start = (uintptr_t)short_tls_shadow;
pgm_layout.short_tls_shadow_end =
(uintptr_t)short_tls_shadow + pgm_layout.tls_shadow_size;
pgm_layout.short_tls_shadow_offset =
shadow_offset(short_tls_shadow, pgm_layout.tls_start);
/* Secondary TLS shadow */
void *long_tls_shadow = do_mmap(pgm_layout.tls_shadow_size);
pgm_layout.long_tls_shadow_start = (uintptr_t)long_tls_shadow;
pgm_layout.long_tls_shadow_end =
(uintptr_t)long_tls_shadow + pgm_layout.tls_shadow_size;
pgm_layout.long_tls_shadow_offset =
shadow_offset(long_tls_shadow, pgm_layout.tls_start);
/* The shadow layout has been initialized */
pgm_layout.initialized = 1;
} }
/*! \brief Unmap (de-allocate) shadow regions used by runtime analysis */ static void init_memory_layout(int *argc_ref, char ***argv_ref) {
static void clean_pgm_layout() { DLOG("<<< Initialize heap shadow >>>\n");
struct memory_segment *heap = &mem_layout.heap;
set_shadow_segment(heap, get_heap_start(), get_heap_size(), 0);
DLOG("<<< Initialize stack shadow >>>\n");
struct memory_segment *stack = &mem_layout.stack;
set_shadow_segment(stack, get_stack_start(argc_ref, argv_ref), get_stack_size(), 1);
DLOG("<<< Initialize global shadow >>>\n");
struct memory_segment *global = &mem_layout.global;
set_shadow_segment(global, get_global_start(), get_global_size(), 1);
DLOG("<<< Initialize TLS shadow >>>\n");
struct memory_segment *tls = &mem_layout.tls;
set_shadow_segment(tls, get_tls_start(), get_tls_size(), 1);
mem_layout.initialized = 1;
}
/*! \brief Deallocate a shadow segment */
void clean_memory_segment(struct memory_segment *seg, int secondary) {
munmap((void*)seg->prim_start, seg->shadow_size);
if (secondary)
munmap((void*)seg->sec_start, seg->shadow_size);
}
/*! \brief Deallocate shadow regions used by runtime analysis */
static void clean_memory_layout() {
DLOG("<<< Clean shadow layout >>>\n"); DLOG("<<< Clean shadow layout >>>\n");
/* Unmap global shadows */ if (mem_layout.initialized) {
if (pgm_layout.long_global_shadow_start) clean_memory_segment(&mem_layout.heap, 0);
munmap((void*)pgm_layout.long_global_shadow_start, clean_memory_segment(&mem_layout.stack, 1);
pgm_layout.global_shadow_size); clean_memory_segment(&mem_layout.global, 1);
if (pgm_layout.short_global_shadow_start) clean_memory_segment(&mem_layout.tls, 1);
munmap((void*)pgm_layout.short_global_shadow_start, }
pgm_layout.global_shadow_size);
/* Unmap stack shadows */
if (pgm_layout.long_stack_shadow_start)
munmap((void*)pgm_layout.long_stack_shadow_start,
pgm_layout.stack_shadow_size);
if (pgm_layout.short_stack_shadow_start)
munmap((void*)pgm_layout.short_stack_shadow_start,
pgm_layout.stack_shadow_size);
/* Unmap heap shadow */
if (pgm_layout.heap_shadow_start)
munmap((void*)pgm_layout.heap_shadow_start, pgm_layout.heap_shadow_size);
} }
/* }}} */ /* }}} */
...@@ -437,60 +352,66 @@ static void clean_pgm_layout() { ...@@ -437,60 +352,66 @@ static void clean_pgm_layout() {
* are given using the following macros. * are given using the following macros.
*/ */
/*! \brief Convert a stack address into its short (byte) shadow counterpart */ /*! \brief Convert a stack address into its primary shadow counterpart */
#define SHORT_STACK_SHADOW(_addr) \ #define PRIMARY_STACK_SHADOW(_addr) \
((uintptr_t)((uintptr_t)_addr - pgm_layout.short_stack_shadow_offset)) ((uintptr_t)((uintptr_t)_addr - mem_layout.stack.prim_offset))
/*! \brief Convert a stack address into its long (block) shadow counterpart */ /*! \brief Convert a stack address into its secondary shadow counterpart */
#define LONG_STACK_SHADOW(_addr) \ #define SECONDARY_STACK_SHADOW(_addr) \
((uintptr_t)((uintptr_t)_addr - pgm_layout.long_stack_shadow_offset)) ((uintptr_t)((uintptr_t)_addr - mem_layout.stack.sec_offset))
/*! \brief Convert a global address into its short (byte) shadow counterpart */ /*! \brief Convert a global address into its primary shadow counterpart */
#define SHORT_GLOBAL_SHADOW(_addr) \ #define PRIMARY_GLOBAL_SHADOW(_addr) \
((uintptr_t)((uintptr_t)_addr + pgm_layout.short_global_shadow_offset)) ((uintptr_t)((uintptr_t)_addr + mem_layout.global.prim_offset))
/*! \brief Convert a global address into its long (block) shadow counterpart */ /*! \brief Convert a global address into its secondary shadow counterpart */
#define LONG_GLOBAL_SHADOW(_addr) \ #define SECONDARY_GLOBAL_SHADOW(_addr) \
((uintptr_t)((uintptr_t)_addr + pgm_layout.long_global_shadow_offset)) ((uintptr_t)((uintptr_t)_addr + mem_layout.global.sec_offset))
/*! \brief Select stack or global shadow based on the value of `_global` /*! \brief Select stack or global shadow based on the value of `_global`
* *
* - SHORT_SHADOW(_addr, 0) is equivalent to STACK_SHORT_SHADOW(_addr) * - PRIMARY_SHADOW(_addr, 0) is equivalent to PRIMARY_STACK_SHADOW(_addr)
* - SHORT_SHADOW(_addr, 1) is equivalent to GLOBAL_SHORT_SHADOW(_addr) */ * - PRIMARY_SHADOW(_addr, 1) is equivalent to PRIMARY_GLOBAL_SHADOW(_addr) */
#define SHORT_SHADOW(_addr, _global) \ #define PRIMARY_SHADOW(_addr, _global) \
(_global ? SHORT_GLOBAL_SHADOW(_addr) : SHORT_STACK_SHADOW(_addr)) (_global ? PRIMARY_GLOBAL_SHADOW(_addr) : PRIMARY_STACK_SHADOW(_addr))
/*! \brief Same as above but for long stack/global shadows */ /*! \brief Same as above but for secondary stack/global shadows */
#define LONG_SHADOW(_addr, _global) \ #define SECONDARY_SHADOW(_addr, _global) \
(_global ? LONG_GLOBAL_SHADOW(_addr) : LONG_STACK_SHADOW(_addr)) (_global ? SECONDARY_GLOBAL_SHADOW(_addr) : SECONDARY_STACK_SHADOW(_addr))
/*! \brief Convert a heap address into its shadow counterpart */ /*! \brief Convert a heap address into its shadow counterpart */
#define HEAP_SHADOW(_addr) \ #define HEAP_SHADOW(_addr) \
((uintptr_t)((uintptr_t)_addr + pgm_layout.heap_shadow_offset)) ((uintptr_t)((uintptr_t)_addr + mem_layout.heap.prim_offset))
/*! \brief Evaluate to a true value if a given address is a heap address */ /*! \brief Evaluate to a true value if a given address is a heap address */
#define IS_ON_HEAP(_addr) ( \ #define IS_ON_HEAP(_addr) ( \
((uintptr_t)_addr) >= pgm_layout.heap_start && \ ((uintptr_t)_addr) >= mem_layout.heap.start && \
((uintptr_t)_addr) <= pgm_layout.heap_end \ ((uintptr_t)_addr) <= mem_layout.heap.end \
) )
/*! \brief Evaluate to a true value if a given address is a stack address */ /*! \brief Evaluate to a true value if a given address is a stack address */
#define IS_ON_STACK(_addr) ( \ #define IS_ON_STACK(_addr) ( \
((uintptr_t)_addr) >= pgm_layout.stack_start && \ ((uintptr_t)_addr) >= mem_layout.stack.start && \
((uintptr_t)_addr) <= pgm_layout.stack_end \ ((uintptr_t)_addr) <= mem_layout.stack.end \
) )
/*! \brief Evaluate to a true value if a given address is a global address */ /*! \brief Evaluate to a true value if a given address is a global address */
#define IS_ON_GLOBAL(_addr) ( \ #define IS_ON_GLOBAL(_addr) ( \
((uintptr_t)_addr) >= pgm_layout.global_start && \ ((uintptr_t)_addr) >= mem_layout.global.start && \
((uintptr_t)_addr) <= pgm_layout.global_end \ ((uintptr_t)_addr) <= mem_layout.global.end \
)
/*! \brief Evaluate to a true value if a given address is a TLS address */
#define IS_ON_TLS(_addr) ( \
((uintptr_t)_addr) >= mem_layout.tls.start && \
((uintptr_t)_addr) <= mem_layout.tls.end \
) )
/*! \brief Shortcut for evaluating an address via ::IS_ON_STACK or /*! \brief Shortcut for evaluating an address via ::IS_ON_STACK or
* ::IS_ON_GLOBAL based on the valua of the second parameter */ * ::IS_ON_GLOBAL based on the value of the second parameter */
#define IS_ON_STATIC(_addr, _global) \ #define IS_ON_STATIC(_addr, _global) \
(_global ? IS_ON_GLOBAL(_addr) : IS_ON_STACK(_addr)) (_global ? IS_ON_GLOBAL(_addr) : IS_ON_STACK(_addr))
/*! \brief Evaluate to a true value if a given address belongs to tracked /*! \brief Evaluate to a true value if a given address belongs to tracked
* allocation (i.e., found within stack, heap oor globally) */ * allocation (i.e., found within stack, heap or globally) */
#define IS_ON_VALID(_addr) \ #define IS_ON_VALID(_addr) \
(IS_ON_STACK(_addr) || IS_ON_HEAP(_addr) || IS_ON_GLOBAL(_addr)) (IS_ON_STACK(_addr) || IS_ON_HEAP(_addr) || IS_ON_GLOBAL(_addr))
/* }}} */ /* }}} */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment