xref: /minix3/minix/lib/libmagicrt/magic_mem.c (revision b2ed49a5d83e311ee0fa9e5ff613639b1bf77aaf)
1*b2ed49a5SDavid van Moolenbroek 
2*b2ed49a5SDavid van Moolenbroek #ifdef _FILE_OFFSET_BITS
3*b2ed49a5SDavid van Moolenbroek #undef _FILE_OFFSET_BITS
4*b2ed49a5SDavid van Moolenbroek #endif
5*b2ed49a5SDavid van Moolenbroek #define _FILE_OFFSET_BITS 64
6*b2ed49a5SDavid van Moolenbroek 
7*b2ed49a5SDavid van Moolenbroek #include <magic_mem.h>
8*b2ed49a5SDavid van Moolenbroek #include <stdio.h>
9*b2ed49a5SDavid van Moolenbroek #include <errno.h>
10*b2ed49a5SDavid van Moolenbroek #include <stdarg.h>
11*b2ed49a5SDavid van Moolenbroek #include <magic_asr.h>
12*b2ed49a5SDavid van Moolenbroek 
13*b2ed49a5SDavid van Moolenbroek #ifdef __MINIX
14*b2ed49a5SDavid van Moolenbroek #define util_time_tsc_read_ns(x) 0
15*b2ed49a5SDavid van Moolenbroek #define util_strhash(x, y) 0
16*b2ed49a5SDavid van Moolenbroek #define util_stacktrace_hash() 0
17*b2ed49a5SDavid van Moolenbroek #define util_stacktrace_print_custom(x)
18*b2ed49a5SDavid van Moolenbroek #define util_stacktrace_hash_skip(x) 0
19*b2ed49a5SDavid van Moolenbroek #else
20*b2ed49a5SDavid van Moolenbroek #include <common/util/stacktrace.h>
21*b2ed49a5SDavid van Moolenbroek #include <common/util/time.h>
22*b2ed49a5SDavid van Moolenbroek #include <common/util/string.h>
23*b2ed49a5SDavid van Moolenbroek #endif
24*b2ed49a5SDavid van Moolenbroek 
25*b2ed49a5SDavid van Moolenbroek #define DEBUG                           MAGIC_DEBUG_SET(0)
26*b2ed49a5SDavid van Moolenbroek #define DEBUG_TYPE_SIZE_MISMATCH        MAGIC_DEBUG_SET(0)
27*b2ed49a5SDavid van Moolenbroek 
28*b2ed49a5SDavid van Moolenbroek #if DEBUG
29*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_PRINTF _magic_printf
30*b2ed49a5SDavid van Moolenbroek #else
31*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_PRINTF magic_null_printf
32*b2ed49a5SDavid van Moolenbroek #endif
33*b2ed49a5SDavid van Moolenbroek 
34*b2ed49a5SDavid van Moolenbroek /* CPU frequency (used for timestamp logging) */
35*b2ed49a5SDavid van Moolenbroek PUBLIC double magic_cycles_per_ns = 0;
36*b2ed49a5SDavid van Moolenbroek 
37*b2ed49a5SDavid van Moolenbroek /*
38*b2ed49a5SDavid van Moolenbroek  * External callbacks.
39*b2ed49a5SDavid van Moolenbroek  */
40*b2ed49a5SDavid van Moolenbroek PUBLIC magic_mem_heap_alloc_cb_t magic_mem_heap_alloc_cb = NULL;
41*b2ed49a5SDavid van Moolenbroek PUBLIC magic_mem_create_dsentry_cb_t magic_mem_create_dsentry_cb = NULL;
42*b2ed49a5SDavid van Moolenbroek PUBLIC magic_mem_heap_free_cb_t magic_mem_heap_free_cb = NULL;
43*b2ed49a5SDavid van Moolenbroek 
44*b2ed49a5SDavid van Moolenbroek PUBLIC short magic_mem_create_dsentry_site_id = 0;
45*b2ed49a5SDavid van Moolenbroek PUBLIC THREAD_LOCAL short magic_mem_wrapper_active = 0;
46*b2ed49a5SDavid van Moolenbroek PUBLIC THREAD_LOCAL short magic_mempool_mgmt_active_level = 0;
47*b2ed49a5SDavid van Moolenbroek PUBLIC THREAD_LOCAL short magic_mempool_ids[MAGIC_MEMPOOL_MAX_FUNC_RECURSIONS];
48*b2ed49a5SDavid van Moolenbroek 
49*b2ed49a5SDavid van Moolenbroek const char* const MAGIC_MEMPOOL_NAME_UNKNOWN = "_magic_mempool_unknown#";
50*b2ed49a5SDavid van Moolenbroek const char* const MAGIC_MEMPOOL_NAME_DETACHED = "_magic_mempool_detached#";
51*b2ed49a5SDavid van Moolenbroek 
52*b2ed49a5SDavid van Moolenbroek __attribute__((weak)) int magic_mempool_allow_reset = 1;
53*b2ed49a5SDavid van Moolenbroek __attribute__((weak)) int magic_mempool_allow_reuse = 1;
54*b2ed49a5SDavid van Moolenbroek __attribute__((weak)) int magic_mempool_allow_external_alloc = 0;
55*b2ed49a5SDavid van Moolenbroek 
56*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_FAILED    ((void*) -1)
57*b2ed49a5SDavid van Moolenbroek 
58*b2ed49a5SDavid van Moolenbroek #ifndef SHM_REMAP
59*b2ed49a5SDavid van Moolenbroek #define SHM_REMAP 0
60*b2ed49a5SDavid van Moolenbroek #endif
61*b2ed49a5SDavid van Moolenbroek 
62*b2ed49a5SDavid van Moolenbroek EXTERN char **environ;
63*b2ed49a5SDavid van Moolenbroek 
64*b2ed49a5SDavid van Moolenbroek PRIVATE magic_dsentry_cb_t magic_destroy_dsentry_ext_cb = NULL;
65*b2ed49a5SDavid van Moolenbroek 
66*b2ed49a5SDavid van Moolenbroek /* Magic real mem function definitions. */
67*b2ed49a5SDavid van Moolenbroek PUBLIC void *(*magic_real_malloc)(size_t size) = &malloc;
68*b2ed49a5SDavid van Moolenbroek PUBLIC void *(*magic_real_calloc)(size_t nmemb, size_t size) = &calloc;
69*b2ed49a5SDavid van Moolenbroek PUBLIC void  (*magic_real_free)(void *ptr) = &free;
70*b2ed49a5SDavid van Moolenbroek PUBLIC void *(*magic_real_realloc)(void *ptr, size_t size) = &realloc;
71*b2ed49a5SDavid van Moolenbroek 
72*b2ed49a5SDavid van Moolenbroek PUBLIC int (*magic_real_posix_memalign)(void **memptr, size_t alignment, size_t size) = &posix_memalign;
73*b2ed49a5SDavid van Moolenbroek 
74*b2ed49a5SDavid van Moolenbroek #ifndef __MINIX
75*b2ed49a5SDavid van Moolenbroek PUBLIC void *(*magic_real_valloc)(size_t size) = &valloc;
76*b2ed49a5SDavid van Moolenbroek PUBLIC void *(*magic_real_memalign)(size_t boundary, size_t size) = &memalign;
77*b2ed49a5SDavid van Moolenbroek #endif
78*b2ed49a5SDavid van Moolenbroek 
79*b2ed49a5SDavid van Moolenbroek PUBLIC void *(*magic_real_mmap)(void *start, size_t length, int prot, int flags,
80*b2ed49a5SDavid van Moolenbroek     int fd, off_t offset) = &mmap;
81*b2ed49a5SDavid van Moolenbroek PUBLIC int (*magic_real_munmap)(void *start, size_t length) = &munmap;
82*b2ed49a5SDavid van Moolenbroek 
83*b2ed49a5SDavid van Moolenbroek PUBLIC int (*magic_real_brk)(void *addr) = &brk;
84*b2ed49a5SDavid van Moolenbroek PUBLIC void *(*magic_real_sbrk)(intptr_t increment) = &sbrk;
85*b2ed49a5SDavid van Moolenbroek 
86*b2ed49a5SDavid van Moolenbroek #ifndef __MINIX
87*b2ed49a5SDavid van Moolenbroek PUBLIC void *(*magic_real_shmat)(int shmid, const void *shmaddr, int shmflg) = &shmat;
88*b2ed49a5SDavid van Moolenbroek PUBLIC int (*magic_real_shmdt)(const void *shmaddr) = &shmdt;
89*b2ed49a5SDavid van Moolenbroek 
90*b2ed49a5SDavid van Moolenbroek PUBLIC void *(*magic_real_mmap64)(void *start, size_t length, int prot, int flags,
91*b2ed49a5SDavid van Moolenbroek     int fd, off_t pgoffset) = &mmap64;
92*b2ed49a5SDavid van Moolenbroek #else
93*b2ed49a5SDavid van Moolenbroek PUBLIC void *(*magic_real_vm_map_cacheblock)(dev_t dev, off_t dev_offset,
94*b2ed49a5SDavid van Moolenbroek     ino_t ino, off_t ino_offset, u32_t *flags, int blocksize) = &vm_map_cacheblock;
95*b2ed49a5SDavid van Moolenbroek #endif
96*b2ed49a5SDavid van Moolenbroek 
97*b2ed49a5SDavid van Moolenbroek /* Use magic_real* functions in the rest of the file. */
98*b2ed49a5SDavid van Moolenbroek #include <magic_real_mem.h>
99*b2ed49a5SDavid van Moolenbroek 
100*b2ed49a5SDavid van Moolenbroek /* Macros for memory usage logging. */
101*b2ed49a5SDavid van Moolenbroek #if MAGIC_MEM_USAGE_OUTPUT_CTL
102*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_DEBUG_PREFIX "MEM_USAGE: "
103*b2ed49a5SDavid van Moolenbroek #define TIMESTAMP_STR "%llu"
104*b2ed49a5SDavid van Moolenbroek #define TIMESTAMP_ARG (util_time_tsc_read_ns(magic_cycles_per_ns))
105*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_DEBUG_EVENT(EVENT, FORMAT, ...) \
106*b2ed49a5SDavid van Moolenbroek 	_magic_printf(MAGIC_MEM_DEBUG_PREFIX TIMESTAMP_STR " " #EVENT " " FORMAT "\n", TIMESTAMP_ARG, __VA_ARGS__)
107*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_DEBUG_EVENT_1(event, ptr)                 MAGIC_MEM_DEBUG_EVENT(event, "%u", (unsigned) ptr)
108*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_DEBUG_EVENT_2(event, ptr, type)           MAGIC_MEM_DEBUG_EVENT(event, "%u %lu", (unsigned) ptr, type)
109*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_DEBUG_EVENT_3(event, ptr, type, size)     MAGIC_MEM_DEBUG_EVENT(event, "%u %lu %d", (unsigned) ptr, type, size)
110*b2ed49a5SDavid van Moolenbroek 
111*b2ed49a5SDavid van Moolenbroek #if (MAGIC_MEM_USAGE_OUTPUT_CTL == 1)
112*b2ed49a5SDavid van Moolenbroek /* use the hash of the name (extended with line number & file name) as dynamic type */
113*b2ed49a5SDavid van Moolenbroek #define	MAGIC_MEM_GET_DTYPE() util_strhash(0, name)
114*b2ed49a5SDavid van Moolenbroek #elif (MAGIC_MEM_USAGE_OUTPUT_CTL == 2)
115*b2ed49a5SDavid van Moolenbroek /* use the hash of the stacktrace as a dynamic type */
116*b2ed49a5SDavid van Moolenbroek #define	MAGIC_MEM_GET_DTYPE() util_stacktrace_hash()
117*b2ed49a5SDavid van Moolenbroek #endif
118*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_DEBUG_ALLOC(ptr, size)            MAGIC_MEM_DEBUG_EVENT_3(alloc, ptr, (MAGIC_MEMPOOL_MGMT_IS_ACTIVE() ? MAGIC_MEMPOOL_GET_DTYPE() : MAGIC_MEM_GET_DTYPE()), size)
119*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_DEBUG_FREE(ptr)                   MAGIC_MEM_DEBUG_EVENT_1(dealloc, ptr)
120*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_DEBUG_RESET(ptr)                  MAGIC_MEM_DEBUG_EVENT_1(reset, ptr)
121*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_DEBUG_REUSE(ptr, type)            MAGIC_MEM_DEBUG_EVENT_2(reuse, ptr, type)
122*b2ed49a5SDavid van Moolenbroek #else
123*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_GET_DTYPE() 0
124*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_DEBUG_ALLOC(ptr, size)
125*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_DEBUG_FREE(ptr)
126*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_DEBUG_RESET(ptr)
127*b2ed49a5SDavid van Moolenbroek #define MAGIC_MEM_DEBUG_REUSE(ptr, type)
128*b2ed49a5SDavid van Moolenbroek #endif
129*b2ed49a5SDavid van Moolenbroek 
130*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
131*b2ed49a5SDavid van Moolenbroek  *                       magic_mempool_alloc_id                              *
132*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_mempool_alloc_id(void)133*b2ed49a5SDavid van Moolenbroek MAGIC_MACRO_FUNC short magic_mempool_alloc_id(void)
134*b2ed49a5SDavid van Moolenbroek {
135*b2ed49a5SDavid van Moolenbroek     short i, id = -1;
136*b2ed49a5SDavid van Moolenbroek 
137*b2ed49a5SDavid van Moolenbroek     MAGIC_MPDESC_LOCK();
138*b2ed49a5SDavid van Moolenbroek 
139*b2ed49a5SDavid van Moolenbroek     /* Find a free slot. */
140*b2ed49a5SDavid van Moolenbroek     for(i = 0; i < MAGIC_MAX_MEMPOOLS; i++) {
141*b2ed49a5SDavid van Moolenbroek         if(MAGIC_MPDESC_IS_FREE(&_magic_mpdescs[i])) {
142*b2ed49a5SDavid van Moolenbroek             MAGIC_MPDESC_ALLOC(&_magic_mpdescs[i]);
143*b2ed49a5SDavid van Moolenbroek             id = i + 1;
144*b2ed49a5SDavid van Moolenbroek             break;
145*b2ed49a5SDavid van Moolenbroek         }
146*b2ed49a5SDavid van Moolenbroek     }
147*b2ed49a5SDavid van Moolenbroek 
148*b2ed49a5SDavid van Moolenbroek     MAGIC_MPDESC_UNLOCK();
149*b2ed49a5SDavid van Moolenbroek 
150*b2ed49a5SDavid van Moolenbroek     assert((id > 0) && (id <= MAGIC_MAX_MEMPOOLS) && "Ran out of memory pool descriptors!");
151*b2ed49a5SDavid van Moolenbroek 
152*b2ed49a5SDavid van Moolenbroek     return id;
153*b2ed49a5SDavid van Moolenbroek }
154*b2ed49a5SDavid van Moolenbroek 
155*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
156*b2ed49a5SDavid van Moolenbroek  *                       magic_mempool_create_begin                          *
157*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_mempool_create_begin(__MDEBUG_ARGS__)158*b2ed49a5SDavid van Moolenbroek MAGIC_HOOK void magic_mempool_create_begin(__MDEBUG_ARGS__)
159*b2ed49a5SDavid van Moolenbroek {
160*b2ed49a5SDavid van Moolenbroek     MAGIC_MEMPOOL_MGMT_SET_ACTIVE();
161*b2ed49a5SDavid van Moolenbroek     assert(MAGIC_MEMPOOL_MGMT_IS_ACTIVE());
162*b2ed49a5SDavid van Moolenbroek     MAGIC_MEMPOOL_SET_ID(magic_mempool_alloc_id());
163*b2ed49a5SDavid van Moolenbroek     MAGIC_MEMPOOL_SET_DTYPE(MAGIC_MEM_GET_DTYPE());
164*b2ed49a5SDavid van Moolenbroek }
165*b2ed49a5SDavid van Moolenbroek 
166*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
167*b2ed49a5SDavid van Moolenbroek  *                       magic_mempool_create_end                            *
168*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_mempool_create_end(void * addr,int indirection)169*b2ed49a5SDavid van Moolenbroek MAGIC_HOOK void magic_mempool_create_end(void* addr, int indirection)
170*b2ed49a5SDavid van Moolenbroek {
171*b2ed49a5SDavid van Moolenbroek     void* pool;
172*b2ed49a5SDavid van Moolenbroek     pool = (indirection && addr) ? *((void**)addr) : addr;
173*b2ed49a5SDavid van Moolenbroek     assert(pool && "Cannot have a NULL pool pointer.");
174*b2ed49a5SDavid van Moolenbroek     _magic_mpdescs[MAGIC_MEMPOOL_GET_ID() - 1].addr = pool;
175*b2ed49a5SDavid van Moolenbroek     magic_mempool_mgmt_end();
176*b2ed49a5SDavid van Moolenbroek }
177*b2ed49a5SDavid van Moolenbroek 
178*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
179*b2ed49a5SDavid van Moolenbroek  *                       magic_mempool_lookup_by_addr                        *
180*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_mempool_lookup_by_addr(void * addr)181*b2ed49a5SDavid van Moolenbroek MAGIC_MACRO_FUNC short magic_mempool_lookup_by_addr(void* addr)
182*b2ed49a5SDavid van Moolenbroek {
183*b2ed49a5SDavid van Moolenbroek     short i, id = MAGIC_MEMPOOL_ID_UNKNOWN;
184*b2ed49a5SDavid van Moolenbroek 
185*b2ed49a5SDavid van Moolenbroek     if (addr) {
186*b2ed49a5SDavid van Moolenbroek         for(i = 0; i < MAGIC_MAX_MEMPOOLS; i++) {
187*b2ed49a5SDavid van Moolenbroek             if(_magic_mpdescs[i].addr == addr) {
188*b2ed49a5SDavid van Moolenbroek                 id = i + 1;
189*b2ed49a5SDavid van Moolenbroek                 break;
190*b2ed49a5SDavid van Moolenbroek             }
191*b2ed49a5SDavid van Moolenbroek         }
192*b2ed49a5SDavid van Moolenbroek     }
193*b2ed49a5SDavid van Moolenbroek 
194*b2ed49a5SDavid van Moolenbroek     return id;
195*b2ed49a5SDavid van Moolenbroek }
196*b2ed49a5SDavid van Moolenbroek 
197*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
198*b2ed49a5SDavid van Moolenbroek  *                       magic_mempool_reset                                 *
199*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_mempool_reset(const char * mempool_name,int reset_name)200*b2ed49a5SDavid van Moolenbroek MAGIC_MACRO_FUNC void magic_mempool_reset(const char* mempool_name, int reset_name)
201*b2ed49a5SDavid van Moolenbroek {
202*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *prev_dsentry, *dsentry, *block_dsentry;
203*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry* sentry;
204*b2ed49a5SDavid van Moolenbroek 
205*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_LOCK();
206*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_MEMPOOL_ALIVE_ITER(_magic_first_mempool_dsentry, prev_dsentry, dsentry, sentry,
207*b2ed49a5SDavid van Moolenbroek         if (sentry->name == mempool_name) {
208*b2ed49a5SDavid van Moolenbroek             block_dsentry = MAGIC_DSENTRY_NEXT_MEMBLOCK(dsentry);
209*b2ed49a5SDavid van Moolenbroek             if (block_dsentry != NULL) {
210*b2ed49a5SDavid van Moolenbroek                 struct _magic_dsentry *tmp_block_dsentry =
211*b2ed49a5SDavid van Moolenbroek                   MAGIC_PCAS(&MAGIC_DSENTRY_NEXT_MEMBLOCK(dsentry), block_dsentry, NULL);
212*b2ed49a5SDavid van Moolenbroek                 assert(tmp_block_dsentry == block_dsentry && "New blocks have been allocated from a reseted mempool!");
213*b2ed49a5SDavid van Moolenbroek             }
214*b2ed49a5SDavid van Moolenbroek             if (reset_name) {
215*b2ed49a5SDavid van Moolenbroek                 const char *tmp_name =
216*b2ed49a5SDavid van Moolenbroek                   MAGIC_PCAS(&sentry->name, mempool_name, MAGIC_MEMPOOL_NAME_UNKNOWN);
217*b2ed49a5SDavid van Moolenbroek                 assert(tmp_name == mempool_name && "The name of the mempool has changed while being reseted!");
218*b2ed49a5SDavid van Moolenbroek             }
219*b2ed49a5SDavid van Moolenbroek             MAGIC_MEM_DEBUG_RESET((char*)dsentry);
220*b2ed49a5SDavid van Moolenbroek         }
221*b2ed49a5SDavid van Moolenbroek     );
222*b2ed49a5SDavid van Moolenbroek 
223*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_UNLOCK();
224*b2ed49a5SDavid van Moolenbroek }
225*b2ed49a5SDavid van Moolenbroek 
226*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
227*b2ed49a5SDavid van Moolenbroek  *                       magic_mempool_destroy_begin                         *
228*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_mempool_destroy_begin(void * addr,int memory_reuse)229*b2ed49a5SDavid van Moolenbroek MAGIC_HOOK void magic_mempool_destroy_begin(void* addr, int memory_reuse)
230*b2ed49a5SDavid van Moolenbroek {
231*b2ed49a5SDavid van Moolenbroek     magic_mempool_mgmt_begin(addr);
232*b2ed49a5SDavid van Moolenbroek     if (addr && memory_reuse) {
233*b2ed49a5SDavid van Moolenbroek         assert(MAGIC_MEMPOOL_ID_IS_SET() && "Cannot destroy a pool with an unknown id.");
234*b2ed49a5SDavid van Moolenbroek         magic_mempool_reset(MAGIC_MEMPOOL_GET_NAME(), TRUE);
235*b2ed49a5SDavid van Moolenbroek     }
236*b2ed49a5SDavid van Moolenbroek }
237*b2ed49a5SDavid van Moolenbroek 
238*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
239*b2ed49a5SDavid van Moolenbroek  *                       magic_mempool_destroy_end                           *
240*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_mempool_destroy_end()241*b2ed49a5SDavid van Moolenbroek MAGIC_HOOK void magic_mempool_destroy_end()
242*b2ed49a5SDavid van Moolenbroek {
243*b2ed49a5SDavid van Moolenbroek     MAGIC_MPDESC_LOCK();
244*b2ed49a5SDavid van Moolenbroek 
245*b2ed49a5SDavid van Moolenbroek     MAGIC_MPDESC_FREE(&_magic_mpdescs[MAGIC_MEMPOOL_GET_ID() - 1]);
246*b2ed49a5SDavid van Moolenbroek 
247*b2ed49a5SDavid van Moolenbroek     MAGIC_MPDESC_UNLOCK();
248*b2ed49a5SDavid van Moolenbroek 
249*b2ed49a5SDavid van Moolenbroek     magic_mempool_mgmt_end();
250*b2ed49a5SDavid van Moolenbroek }
251*b2ed49a5SDavid van Moolenbroek 
252*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
253*b2ed49a5SDavid van Moolenbroek  *                       magic_mempool_mgmt_begin                            *
254*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_mempool_mgmt_begin(void * addr)255*b2ed49a5SDavid van Moolenbroek MAGIC_HOOK void  magic_mempool_mgmt_begin(void* addr)
256*b2ed49a5SDavid van Moolenbroek {
257*b2ed49a5SDavid van Moolenbroek     short id;
258*b2ed49a5SDavid van Moolenbroek 
259*b2ed49a5SDavid van Moolenbroek     MAGIC_MEMPOOL_MGMT_SET_ACTIVE();
260*b2ed49a5SDavid van Moolenbroek     assert(MAGIC_MEMPOOL_MGMT_IS_ACTIVE());
261*b2ed49a5SDavid van Moolenbroek 
262*b2ed49a5SDavid van Moolenbroek     id = magic_mempool_lookup_by_addr(addr);
263*b2ed49a5SDavid van Moolenbroek     /* For some reason, this mempool has not been registered yet, reserve a new slot in the mempool array. */
264*b2ed49a5SDavid van Moolenbroek     if (addr && (id == MAGIC_MEMPOOL_ID_UNKNOWN)) {
265*b2ed49a5SDavid van Moolenbroek         id = magic_mempool_alloc_id();
266*b2ed49a5SDavid van Moolenbroek         _magic_mpdescs[id - 1].addr = addr;
267*b2ed49a5SDavid van Moolenbroek     }
268*b2ed49a5SDavid van Moolenbroek     MAGIC_MEMPOOL_SET_ID(id);
269*b2ed49a5SDavid van Moolenbroek }
270*b2ed49a5SDavid van Moolenbroek 
271*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
272*b2ed49a5SDavid van Moolenbroek  *                       magic_mempool_mgmt_end                              *
273*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_mempool_mgmt_end()274*b2ed49a5SDavid van Moolenbroek MAGIC_HOOK void magic_mempool_mgmt_end()
275*b2ed49a5SDavid van Moolenbroek {
276*b2ed49a5SDavid van Moolenbroek     MAGIC_MEMPOOL_SET_ID(MAGIC_MEMPOOL_ID_UNKNOWN);
277*b2ed49a5SDavid van Moolenbroek     assert(MAGIC_MEMPOOL_MGMT_IS_ACTIVE());
278*b2ed49a5SDavid van Moolenbroek     MAGIC_MEMPOOL_MGMT_UNSET_ACTIVE();
279*b2ed49a5SDavid van Moolenbroek }
280*b2ed49a5SDavid van Moolenbroek 
281*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
282*b2ed49a5SDavid van Moolenbroek  *                       magic_mempool_reset_begin                           *
283*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_mempool_reset_begin(void * addr)284*b2ed49a5SDavid van Moolenbroek MAGIC_HOOK void magic_mempool_reset_begin(void* addr)
285*b2ed49a5SDavid van Moolenbroek {
286*b2ed49a5SDavid van Moolenbroek     magic_mempool_mgmt_begin(addr);
287*b2ed49a5SDavid van Moolenbroek     /* skip reset when it has been disabled by the application. */
288*b2ed49a5SDavid van Moolenbroek     if (magic_mempool_allow_reset) {
289*b2ed49a5SDavid van Moolenbroek         if (addr != NULL) {
290*b2ed49a5SDavid van Moolenbroek             assert(MAGIC_MEMPOOL_ID_IS_SET() && "Cannot reset a pool with an unknown id.");
291*b2ed49a5SDavid van Moolenbroek             magic_mempool_reset(MAGIC_MEMPOOL_GET_NAME(), TRUE);
292*b2ed49a5SDavid van Moolenbroek         }
293*b2ed49a5SDavid van Moolenbroek     }
294*b2ed49a5SDavid van Moolenbroek }
295*b2ed49a5SDavid van Moolenbroek 
296*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
297*b2ed49a5SDavid van Moolenbroek  *                       magic_mempool_dsentry_set_name                      *
298*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_mempool_dsentry_set_name(struct _magic_dsentry * dsentry,const char * name)299*b2ed49a5SDavid van Moolenbroek MAGIC_MACRO_FUNC void magic_mempool_dsentry_set_name(struct _magic_dsentry* dsentry,
300*b2ed49a5SDavid van Moolenbroek 	const char* name)
301*b2ed49a5SDavid van Moolenbroek {
302*b2ed49a5SDavid van Moolenbroek     const char *old_name, *ret;
303*b2ed49a5SDavid van Moolenbroek 
304*b2ed49a5SDavid van Moolenbroek     if ((name == MAGIC_MEMPOOL_NAME_UNKNOWN) || (name == MAGIC_MEMPOOL_NAME_DETACHED)) {
305*b2ed49a5SDavid van Moolenbroek         do {
306*b2ed49a5SDavid van Moolenbroek             old_name = MAGIC_DSENTRY_TO_SENTRY(dsentry)->name;
307*b2ed49a5SDavid van Moolenbroek         } while (MAGIC_CAS(&MAGIC_DSENTRY_TO_SENTRY(dsentry)->name, old_name, name) != old_name && old_name != name);
308*b2ed49a5SDavid van Moolenbroek     } else {
309*b2ed49a5SDavid van Moolenbroek         old_name = MAGIC_DSENTRY_TO_SENTRY(dsentry)->name;
310*b2ed49a5SDavid van Moolenbroek         if (old_name != name) {
311*b2ed49a5SDavid van Moolenbroek             if (!strncmp(old_name, MAGIC_MEMPOOL_NAME_PREFIX, strlen(MAGIC_MEMPOOL_NAME_PREFIX))) {
312*b2ed49a5SDavid van Moolenbroek                 assert(((old_name == MAGIC_MEMPOOL_NAME_UNKNOWN) || (old_name == MAGIC_MEMPOOL_NAME_DETACHED))
313*b2ed49a5SDavid van Moolenbroek                         && "Cannot overwrite an already existing valid memory pool name!");
314*b2ed49a5SDavid van Moolenbroek             }
315*b2ed49a5SDavid van Moolenbroek             ret = MAGIC_CAS(&MAGIC_DSENTRY_TO_SENTRY(dsentry)->name, old_name, name);
316*b2ed49a5SDavid van Moolenbroek             assert((ret == old_name || ret == name) && "Cannot overwrite an already existing valid memory pool name!");
317*b2ed49a5SDavid van Moolenbroek         }
318*b2ed49a5SDavid van Moolenbroek     }
319*b2ed49a5SDavid van Moolenbroek }
320*b2ed49a5SDavid van Moolenbroek 
321*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
322*b2ed49a5SDavid van Moolenbroek  *                       magic_mempool_dsentry_update                        *
323*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_mempool_dsentry_update(struct _magic_dsentry * dsentry,const char * name)324*b2ed49a5SDavid van Moolenbroek MAGIC_MACRO_FUNC void magic_mempool_dsentry_update(struct _magic_dsentry* dsentry,
325*b2ed49a5SDavid van Moolenbroek 	const char* name)
326*b2ed49a5SDavid van Moolenbroek {
327*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry* sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry);
328*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry* next_mempool_dsentry;
329*b2ed49a5SDavid van Moolenbroek     int flags;
330*b2ed49a5SDavid van Moolenbroek     /* set the magic state mempool flag atomically */
331*b2ed49a5SDavid van Moolenbroek     do {
332*b2ed49a5SDavid van Moolenbroek         flags = sentry->flags;
333*b2ed49a5SDavid van Moolenbroek     } while (MAGIC_CAS(&sentry->flags, flags, flags | MAGIC_STATE_MEMPOOL) != flags && !(flags & MAGIC_STATE_MEMPOOL));
334*b2ed49a5SDavid van Moolenbroek     magic_mempool_dsentry_set_name(dsentry, name);
335*b2ed49a5SDavid van Moolenbroek     /* the thread that updates the id adds the dsentry to the mempool dsentry list */
336*b2ed49a5SDavid van Moolenbroek     if (!(flags & MAGIC_STATE_MEMPOOL)) {
337*b2ed49a5SDavid van Moolenbroek         /* Add the new dsentry before the first dsentry atomically. */
338*b2ed49a5SDavid van Moolenbroek         do {
339*b2ed49a5SDavid van Moolenbroek             next_mempool_dsentry = _magic_first_mempool_dsentry;
340*b2ed49a5SDavid van Moolenbroek             MAGIC_DSENTRY_NEXT_MEMPOOL(dsentry) = next_mempool_dsentry;
341*b2ed49a5SDavid van Moolenbroek         } while(MAGIC_CAS(&_magic_first_mempool_dsentry, next_mempool_dsentry, dsentry) != next_mempool_dsentry);
342*b2ed49a5SDavid van Moolenbroek     }
343*b2ed49a5SDavid van Moolenbroek }
344*b2ed49a5SDavid van Moolenbroek 
345*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
346*b2ed49a5SDavid van Moolenbroek  *                       mempool_block_alloc_template                        *
347*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
mempool_block_alloc_template(void * addr,size_t size)348*b2ed49a5SDavid van Moolenbroek MAGIC_FUNC void *mempool_block_alloc_template(void* addr, size_t size)
349*b2ed49a5SDavid van Moolenbroek {
350*b2ed49a5SDavid van Moolenbroek     return NULL;
351*b2ed49a5SDavid van Moolenbroek }
352*b2ed49a5SDavid van Moolenbroek 
353*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
354*b2ed49a5SDavid van Moolenbroek  *                       magic_mempool_block_alloc_template                  *
355*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_mempool_block_alloc_template(__MA_ARGS__ void * addr,size_t size)356*b2ed49a5SDavid van Moolenbroek PUBLIC void *magic_mempool_block_alloc_template(__MA_ARGS__ void* addr, size_t size)
357*b2ed49a5SDavid van Moolenbroek {
358*b2ed49a5SDavid van Moolenbroek     void *ptr, *data_ptr;
359*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry* mempool_sentry;
360*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry* mempool_dsentry, *next_block_dsentry;
361*b2ed49a5SDavid van Moolenbroek 
362*b2ed49a5SDavid van Moolenbroek     magic_mempool_mgmt_begin(addr);
363*b2ed49a5SDavid van Moolenbroek     /* don't set the memory wrapper flag, this function is supposed to allocate memory from a pool
364*b2ed49a5SDavid van Moolenbroek      and not using the standard allocators. it might also call other memory pool management functions */
365*b2ed49a5SDavid van Moolenbroek     if(size > 0) {
366*b2ed49a5SDavid van Moolenbroek         /* this call should be replaced with a call to a "real" block allocation function, when generating custom wrappers */
367*b2ed49a5SDavid van Moolenbroek         ptr = mempool_block_alloc_template(addr, MAGIC_SIZE_TO_REAL(size) + magic_asr_get_padding_size(MAGIC_STATE_HEAP));
368*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_PRINTF("%s: ptr = malloc(size) <-> 0x%08x = malloc(%d)\n", __FUNCTION__,(unsigned) ptr, MAGIC_SIZE_TO_REAL(size));
369*b2ed49a5SDavid van Moolenbroek         data_ptr = magic_alloc(__MA_VALUES__ ptr, size, MAGIC_STATE_HEAP | MAGIC_STATE_MEMBLOCK);
370*b2ed49a5SDavid van Moolenbroek         if(data_ptr == MAGIC_MEM_FAILED) {
371*b2ed49a5SDavid van Moolenbroek             /* cannot free individual blocks inside the pool */
372*b2ed49a5SDavid van Moolenbroek             data_ptr = NULL;
373*b2ed49a5SDavid van Moolenbroek             errno = ENOMEM;
374*b2ed49a5SDavid van Moolenbroek         } else if (ptr) {
375*b2ed49a5SDavid van Moolenbroek             /* lookup the pool buffer dsentry from which this block was allocated */
376*b2ed49a5SDavid van Moolenbroek             mempool_sentry = magic_mempool_sentry_lookup_by_range(ptr, NULL);
377*b2ed49a5SDavid van Moolenbroek             if (!mempool_sentry && magic_mempool_allow_external_alloc) {
378*b2ed49a5SDavid van Moolenbroek                 mempool_sentry = magic_sentry_lookup_by_range(ptr, NULL);
379*b2ed49a5SDavid van Moolenbroek                 if (mempool_sentry) {
380*b2ed49a5SDavid van Moolenbroek                     magic_mempool_dsentry_update(MAGIC_DSENTRY_FROM_SENTRY(mempool_sentry), MAGIC_MEMPOOL_GET_NAME());
381*b2ed49a5SDavid van Moolenbroek                 }
382*b2ed49a5SDavid van Moolenbroek             }
383*b2ed49a5SDavid van Moolenbroek 
384*b2ed49a5SDavid van Moolenbroek             assert(mempool_sentry && "XXX Mempool dsentry not found for this memblock dsentry: memory not allocated from a memory pool management function?");
385*b2ed49a5SDavid van Moolenbroek             mempool_dsentry = MAGIC_DSENTRY_FROM_SENTRY(mempool_sentry);
386*b2ed49a5SDavid van Moolenbroek 
387*b2ed49a5SDavid van Moolenbroek             /* Reuse of buffers across pools - propagate the new pool name */
388*b2ed49a5SDavid van Moolenbroek             if (MAGIC_MEMPOOL_ID_IS_SET() && (mempool_sentry->name != MAGIC_MEMPOOL_GET_NAME())) {
389*b2ed49a5SDavid van Moolenbroek                 assert(magic_mempool_allow_reuse && "Pool memory reuse is disabled!");
390*b2ed49a5SDavid van Moolenbroek                 magic_mempool_dsentry_set_name(mempool_dsentry, MAGIC_MEMPOOL_GET_NAME());
391*b2ed49a5SDavid van Moolenbroek             }
392*b2ed49a5SDavid van Moolenbroek             MAGIC_DSENTRY_TO_SENTRY(MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr)))->name = mempool_sentry->name;
393*b2ed49a5SDavid van Moolenbroek 
394*b2ed49a5SDavid van Moolenbroek             /* Add the new dsentry before the first block dsentry chained to the memory pool dsentry, atomically.
395*b2ed49a5SDavid van Moolenbroek              The list should be circular - the last block dsentry (first one added) points to the memory pool dsentry. */
396*b2ed49a5SDavid van Moolenbroek             do {
397*b2ed49a5SDavid van Moolenbroek                 next_block_dsentry = MAGIC_DSENTRY_NEXT_MEMBLOCK(mempool_dsentry);
398*b2ed49a5SDavid van Moolenbroek                 MAGIC_DSENTRY_NEXT_MEMBLOCK(MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))) = next_block_dsentry ? next_block_dsentry : mempool_dsentry;
399*b2ed49a5SDavid van Moolenbroek             }while(MAGIC_CAS(&(MAGIC_DSENTRY_NEXT_MEMBLOCK(mempool_dsentry)), next_block_dsentry, MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))) != next_block_dsentry);
400*b2ed49a5SDavid van Moolenbroek 
401*b2ed49a5SDavid van Moolenbroek             /* First write to this pool buffer, potential reuse */
402*b2ed49a5SDavid van Moolenbroek             if (next_block_dsentry == NULL) {
403*b2ed49a5SDavid van Moolenbroek             	MAGIC_MEM_DEBUG_REUSE((char*)mempool_dsentry, MAGIC_MEMPOOL_GET_DTYPE());
404*b2ed49a5SDavid van Moolenbroek             }
405*b2ed49a5SDavid van Moolenbroek         }
406*b2ed49a5SDavid van Moolenbroek     }
407*b2ed49a5SDavid van Moolenbroek     else {
408*b2ed49a5SDavid van Moolenbroek         /* Some applications return a valid pointer even if size is 0... */
409*b2ed49a5SDavid van Moolenbroek         data_ptr = mempool_block_alloc_template(addr, size);
410*b2ed49a5SDavid van Moolenbroek     }
411*b2ed49a5SDavid van Moolenbroek     magic_mempool_mgmt_end();
412*b2ed49a5SDavid van Moolenbroek 
413*b2ed49a5SDavid van Moolenbroek     return data_ptr;
414*b2ed49a5SDavid van Moolenbroek }
415*b2ed49a5SDavid van Moolenbroek 
416*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
417*b2ed49a5SDavid van Moolenbroek  *                       magic_create_dsentry                                *
418*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_create_dsentry(struct _magic_dsentry * dsentry,void * data_ptr,struct _magic_type * type,size_t size,int flags,const char * name,const char * parent_name)419*b2ed49a5SDavid van Moolenbroek PUBLIC int magic_create_dsentry(struct _magic_dsentry *dsentry,
420*b2ed49a5SDavid van Moolenbroek     void *data_ptr, struct _magic_type *type, size_t size, int flags,
421*b2ed49a5SDavid van Moolenbroek     const char *name, const char *parent_name)
422*b2ed49a5SDavid van Moolenbroek {
423*b2ed49a5SDavid van Moolenbroek     /* This function does not require any dsentry locking. */
424*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry);
425*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *next_dsentry, *next_mempool_dsentry;
426*b2ed49a5SDavid van Moolenbroek     size_t type_size;
427*b2ed49a5SDavid van Moolenbroek     int is_varsized = 0;
428*b2ed49a5SDavid van Moolenbroek     int num_vsa_elements = 0;
429*b2ed49a5SDavid van Moolenbroek 
430*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *saved_next = dsentry->next;
431*b2ed49a5SDavid van Moolenbroek     int save_linkage = ((flags & MAGIC_STATE_HEAP) && _magic_vars->fake_malloc);
432*b2ed49a5SDavid van Moolenbroek 
433*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_PRINTF("Dsentry created from stacktrace:\n");
434*b2ed49a5SDavid van Moolenbroek     if (MAGIC_MEM_PRINTF != magic_null_printf) {
435*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_WRAPPER_BEGIN();
436*b2ed49a5SDavid van Moolenbroek         util_stacktrace_print_custom(MAGIC_MEM_PRINTF);
437*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_WRAPPER_END();
438*b2ed49a5SDavid van Moolenbroek     }
439*b2ed49a5SDavid van Moolenbroek 
440*b2ed49a5SDavid van Moolenbroek     if (!type) {
441*b2ed49a5SDavid van Moolenbroek         type = MAGIC_VOID_TYPE;
442*b2ed49a5SDavid van Moolenbroek     }
443*b2ed49a5SDavid van Moolenbroek     type_size = type->size;
444*b2ed49a5SDavid van Moolenbroek     assert(size > 0);
445*b2ed49a5SDavid van Moolenbroek 
446*b2ed49a5SDavid van Moolenbroek     memcpy(dsentry, &magic_default_dsentry, sizeof(struct _magic_dsentry));
447*b2ed49a5SDavid van Moolenbroek 
448*b2ed49a5SDavid van Moolenbroek     /* Catch variable-sized struct allocation. */
449*b2ed49a5SDavid van Moolenbroek     if (magic_type_alloc_needs_varsized_array(type, size, &num_vsa_elements)) {
450*b2ed49a5SDavid van Moolenbroek         is_varsized = 1;
451*b2ed49a5SDavid van Moolenbroek     }
452*b2ed49a5SDavid van Moolenbroek 
453*b2ed49a5SDavid van Moolenbroek     if (size % type_size != 0 && !is_varsized) {
454*b2ed49a5SDavid van Moolenbroek         /* This should only happen for uncaught variable-sized struct allocations. */
455*b2ed49a5SDavid van Moolenbroek #if DEBUG_TYPE_SIZE_MISMATCH
456*b2ed49a5SDavid van Moolenbroek         _magic_printf("magic_create_dsentry: type <-> size mismatch, reverting to void type: size=%d, type=", size);
457*b2ed49a5SDavid van Moolenbroek         MAGIC_TYPE_PRINT(type, MAGIC_EXPAND_TYPE_STR);
458*b2ed49a5SDavid van Moolenbroek         _magic_printf("\n");
459*b2ed49a5SDavid van Moolenbroek #endif
460*b2ed49a5SDavid van Moolenbroek         type = MAGIC_VOID_TYPE;
461*b2ed49a5SDavid van Moolenbroek         type_size = type->size;
462*b2ed49a5SDavid van Moolenbroek         flags |= MAGIC_STATE_TYPE_SIZE_MISMATCH;
463*b2ed49a5SDavid van Moolenbroek     }
464*b2ed49a5SDavid van Moolenbroek 
465*b2ed49a5SDavid van Moolenbroek     if (size == type_size && !is_varsized) {
466*b2ed49a5SDavid van Moolenbroek         sentry->type = type;
467*b2ed49a5SDavid van Moolenbroek     }
468*b2ed49a5SDavid van Moolenbroek     else {
469*b2ed49a5SDavid van Moolenbroek         struct _magic_type *array_type = &(dsentry->type);
470*b2ed49a5SDavid van Moolenbroek         MAGIC_TYPE_ARRAY_CREATE_FROM_SIZE(array_type, type,
471*b2ed49a5SDavid van Moolenbroek             MAGIC_DSENTRY_TO_TYPE_ARR(dsentry), size, num_vsa_elements);
472*b2ed49a5SDavid van Moolenbroek         array_type->id = MAGIC_FAA(&_magic_types_next_id, 1);
473*b2ed49a5SDavid van Moolenbroek         assert(_magic_types_next_id < MAGIC_ID_MAX);
474*b2ed49a5SDavid van Moolenbroek         sentry->type = array_type;
475*b2ed49a5SDavid van Moolenbroek     }
476*b2ed49a5SDavid van Moolenbroek 
477*b2ed49a5SDavid van Moolenbroek     sentry->flags |= flags;
478*b2ed49a5SDavid van Moolenbroek     sentry->address = data_ptr;
479*b2ed49a5SDavid van Moolenbroek 
480*b2ed49a5SDavid van Moolenbroek     if (name) {
481*b2ed49a5SDavid van Moolenbroek         sentry->name = name;
482*b2ed49a5SDavid van Moolenbroek     }
483*b2ed49a5SDavid van Moolenbroek     if (parent_name) {
484*b2ed49a5SDavid van Moolenbroek         dsentry->parent_name = parent_name;
485*b2ed49a5SDavid van Moolenbroek     }
486*b2ed49a5SDavid van Moolenbroek     sentry->id = MAGIC_FAA(&_magic_sentries_next_id, 1);
487*b2ed49a5SDavid van Moolenbroek     assert(_magic_sentries_next_id < MAGIC_ID_MAX);
488*b2ed49a5SDavid van Moolenbroek 
489*b2ed49a5SDavid van Moolenbroek     /*
490*b2ed49a5SDavid van Moolenbroek      * TODO: Also add per-callsite index to handle the following:
491*b2ed49a5SDavid van Moolenbroek      * for (;;) { p = malloc(); }
492*b2ed49a5SDavid van Moolenbroek      */
493*b2ed49a5SDavid van Moolenbroek     if (magic_mem_create_dsentry_site_id) {
494*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_WRAPPER_BEGIN();
495*b2ed49a5SDavid van Moolenbroek         /*
496*b2ed49a5SDavid van Moolenbroek          * XXX: This is so damn ugly, but we don't want to include
497*b2ed49a5SDavid van Moolenbroek          * any magic_* functions in the stacktrace hash.
498*b2ed49a5SDavid van Moolenbroek          * This should probably be done in a much more elegant manner.
499*b2ed49a5SDavid van Moolenbroek          */
500*b2ed49a5SDavid van Moolenbroek         dsentry->site_id = util_stacktrace_hash_skip((char *)"("MAGIC_PREFIX_STR);
501*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_WRAPPER_END();
502*b2ed49a5SDavid van Moolenbroek     }
503*b2ed49a5SDavid van Moolenbroek 
504*b2ed49a5SDavid van Moolenbroek     if (save_linkage) {
505*b2ed49a5SDavid van Moolenbroek         dsentry->next = saved_next;
506*b2ed49a5SDavid van Moolenbroek         return 0;
507*b2ed49a5SDavid van Moolenbroek     }
508*b2ed49a5SDavid van Moolenbroek 
509*b2ed49a5SDavid van Moolenbroek     /* Add the new dsentry before the first dsentry atomically.
510*b2ed49a5SDavid van Moolenbroek      * Skip memblock dsentries to make pool reset/destruction faster.
511*b2ed49a5SDavid van Moolenbroek      */
512*b2ed49a5SDavid van Moolenbroek     if (!MAGIC_STATE_FLAG(sentry, MAGIC_STATE_MEMBLOCK)) {
513*b2ed49a5SDavid van Moolenbroek         do {
514*b2ed49a5SDavid van Moolenbroek             next_dsentry = _magic_first_dsentry;
515*b2ed49a5SDavid van Moolenbroek             MAGIC_DSENTRY_NEXT(dsentry) = next_dsentry;
516*b2ed49a5SDavid van Moolenbroek         } while(MAGIC_CAS(&_magic_first_dsentry, next_dsentry, dsentry) != next_dsentry);
517*b2ed49a5SDavid van Moolenbroek     }
518*b2ed49a5SDavid van Moolenbroek 
519*b2ed49a5SDavid van Moolenbroek #if MAGIC_DSENTRY_ALLOW_PREV
520*b2ed49a5SDavid van Moolenbroek     next_dsentry = MAGIC_DSENTRY_NEXT(dsentry);
521*b2ed49a5SDavid van Moolenbroek     if (next_dsentry) {
522*b2ed49a5SDavid van Moolenbroek         MAGIC_DSENTRY_PREV(next_dsentry) = dsentry;
523*b2ed49a5SDavid van Moolenbroek     }
524*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_PREV(dsentry) = NULL;
525*b2ed49a5SDavid van Moolenbroek #endif
526*b2ed49a5SDavid van Moolenbroek 
527*b2ed49a5SDavid van Moolenbroek     if (MAGIC_STATE_FLAG(sentry, MAGIC_STATE_MEMPOOL)) {
528*b2ed49a5SDavid van Moolenbroek         /* Add the new dsentry before the first mempool dsentry atomically. */
529*b2ed49a5SDavid van Moolenbroek         do {
530*b2ed49a5SDavid van Moolenbroek             next_mempool_dsentry = _magic_first_mempool_dsentry;
531*b2ed49a5SDavid van Moolenbroek             MAGIC_DSENTRY_NEXT_MEMPOOL(dsentry) = next_mempool_dsentry;
532*b2ed49a5SDavid van Moolenbroek         } while(MAGIC_CAS(&_magic_first_mempool_dsentry, next_mempool_dsentry, dsentry) != next_mempool_dsentry);
533*b2ed49a5SDavid van Moolenbroek     }
534*b2ed49a5SDavid van Moolenbroek     magic_update_dsentry_ranges = 1;
535*b2ed49a5SDavid van Moolenbroek 
536*b2ed49a5SDavid van Moolenbroek     if (magic_mem_create_dsentry_cb)
537*b2ed49a5SDavid van Moolenbroek         magic_mem_create_dsentry_cb(dsentry);
538*b2ed49a5SDavid van Moolenbroek 
539*b2ed49a5SDavid van Moolenbroek     return 0;
540*b2ed49a5SDavid van Moolenbroek }
541*b2ed49a5SDavid van Moolenbroek 
542*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
543*b2ed49a5SDavid van Moolenbroek  *                      magic_create_obdsentry                               *
544*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_create_obdsentry(void * data_ptr,struct _magic_type * type,size_t size,int flags,const char * name,const char * parent_name)545*b2ed49a5SDavid van Moolenbroek PUBLIC struct _magic_obdsentry* magic_create_obdsentry(void *data_ptr,
546*b2ed49a5SDavid van Moolenbroek     struct _magic_type *type, size_t size, int flags,
547*b2ed49a5SDavid van Moolenbroek     const char *name, const char *parent_name)
548*b2ed49a5SDavid van Moolenbroek {
549*b2ed49a5SDavid van Moolenbroek     struct _magic_obdsentry *obdsentry = NULL;
550*b2ed49a5SDavid van Moolenbroek     int i, ret;
551*b2ed49a5SDavid van Moolenbroek 
552*b2ed49a5SDavid van Moolenbroek     /* Check name. */
553*b2ed49a5SDavid van Moolenbroek     if(!name || !strcmp(name, "")) {
554*b2ed49a5SDavid van Moolenbroek         return NULL;
555*b2ed49a5SDavid van Moolenbroek     }
556*b2ed49a5SDavid van Moolenbroek     else if(strlen(name) >= MAGIC_MAX_OBDSENTRY_NAME_LEN) {
557*b2ed49a5SDavid van Moolenbroek         return NULL;
558*b2ed49a5SDavid van Moolenbroek     }
559*b2ed49a5SDavid van Moolenbroek 
560*b2ed49a5SDavid van Moolenbroek     /* Check parent name. */
561*b2ed49a5SDavid van Moolenbroek     if(!parent_name || !strcmp(parent_name, "")) {
562*b2ed49a5SDavid van Moolenbroek         parent_name = MAGIC_OBDSENTRY_DEFAULT_PARENT_NAME;
563*b2ed49a5SDavid van Moolenbroek     }
564*b2ed49a5SDavid van Moolenbroek     if(strlen(parent_name) >= MAGIC_MAX_OBDSENTRY_PARENT_NAME_LEN) {
565*b2ed49a5SDavid van Moolenbroek         return NULL;
566*b2ed49a5SDavid van Moolenbroek     }
567*b2ed49a5SDavid van Moolenbroek 
568*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_LBEGIN();
569*b2ed49a5SDavid van Moolenbroek 
570*b2ed49a5SDavid van Moolenbroek     /* Find a free slot. */
571*b2ed49a5SDavid van Moolenbroek     for(i=0;i<MAGIC_MAX_OBDSENTRIES;i++) {
572*b2ed49a5SDavid van Moolenbroek         if(MAGIC_OBDSENTRY_IS_FREE(&_magic_obdsentries[i])) {
573*b2ed49a5SDavid van Moolenbroek             obdsentry = &_magic_obdsentries[i];
574*b2ed49a5SDavid van Moolenbroek             break;
575*b2ed49a5SDavid van Moolenbroek         }
576*b2ed49a5SDavid van Moolenbroek     }
577*b2ed49a5SDavid van Moolenbroek     if(!obdsentry) {
578*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_WRAPPER_LEND();
579*b2ed49a5SDavid van Moolenbroek         return NULL;
580*b2ed49a5SDavid van Moolenbroek     }
581*b2ed49a5SDavid van Moolenbroek 
582*b2ed49a5SDavid van Moolenbroek     /* Create the dsentry. */
583*b2ed49a5SDavid van Moolenbroek     strcpy(obdsentry->name, name);
584*b2ed49a5SDavid van Moolenbroek     strcpy(obdsentry->parent_name, parent_name);
585*b2ed49a5SDavid van Moolenbroek     flags |= MAGIC_STATE_OUT_OF_BAND;
586*b2ed49a5SDavid van Moolenbroek     ret = magic_create_dsentry(MAGIC_OBDSENTRY_TO_DSENTRY(obdsentry), data_ptr, type,
587*b2ed49a5SDavid van Moolenbroek         size, flags, obdsentry->name, obdsentry->parent_name);
588*b2ed49a5SDavid van Moolenbroek 
589*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_LEND();
590*b2ed49a5SDavid van Moolenbroek 
591*b2ed49a5SDavid van Moolenbroek     if(ret < 0) {
592*b2ed49a5SDavid van Moolenbroek         return NULL;
593*b2ed49a5SDavid van Moolenbroek     }
594*b2ed49a5SDavid van Moolenbroek     assert(!MAGIC_OBDSENTRY_IS_FREE(obdsentry));
595*b2ed49a5SDavid van Moolenbroek 
596*b2ed49a5SDavid van Moolenbroek     return obdsentry;
597*b2ed49a5SDavid van Moolenbroek }
598*b2ed49a5SDavid van Moolenbroek 
599*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
600*b2ed49a5SDavid van Moolenbroek  *                       magic_update_dsentry_state                          *
601*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_update_dsentry_state(struct _magic_dsentry * dsentry,unsigned long state)602*b2ed49a5SDavid van Moolenbroek PUBLIC int magic_update_dsentry_state(struct _magic_dsentry *dsentry,
603*b2ed49a5SDavid van Moolenbroek     unsigned long state)
604*b2ed49a5SDavid van Moolenbroek {
605*b2ed49a5SDavid van Moolenbroek     int ret = 0;
606*b2ed49a5SDavid van Moolenbroek     unsigned long old_state;
607*b2ed49a5SDavid van Moolenbroek     unsigned long num_dead_dsentries;
608*b2ed49a5SDavid van Moolenbroek     unsigned long size, size_dead_dsentries;
609*b2ed49a5SDavid van Moolenbroek     size = MAGIC_DSENTRY_TO_SENTRY(dsentry)->type->size;
610*b2ed49a5SDavid van Moolenbroek 
611*b2ed49a5SDavid van Moolenbroek     switch(state) {
612*b2ed49a5SDavid van Moolenbroek         case MAGIC_DSENTRY_MSTATE_FREED:
613*b2ed49a5SDavid van Moolenbroek             old_state = MAGIC_CAS(&dsentry->magic_state, MAGIC_DSENTRY_MSTATE_DEAD,
614*b2ed49a5SDavid van Moolenbroek                 MAGIC_DSENTRY_MSTATE_FREED);
615*b2ed49a5SDavid van Moolenbroek             if(old_state != MAGIC_DSENTRY_MSTATE_DEAD) {
616*b2ed49a5SDavid van Moolenbroek                 ret = MAGIC_EBADMSTATE;
617*b2ed49a5SDavid van Moolenbroek                 break;
618*b2ed49a5SDavid van Moolenbroek             }
619*b2ed49a5SDavid van Moolenbroek             if (!MAGIC_STATE_FLAG(MAGIC_DSENTRY_TO_SENTRY(dsentry), MAGIC_STATE_MEMBLOCK)) {
620*b2ed49a5SDavid van Moolenbroek                 num_dead_dsentries = MAGIC_FAS(&magic_num_dead_dsentries, 1) - 1;
621*b2ed49a5SDavid van Moolenbroek                 size_dead_dsentries = MAGIC_FAS(&magic_size_dead_dsentries, size) - size;
622*b2ed49a5SDavid van Moolenbroek                 MAGIC_MEM_PRINTF("magic_update_dsentry_state:  --magic_num_dead_dsentries (num=%d, size=%d)\n", num_dead_dsentries, size_dead_dsentries);
623*b2ed49a5SDavid van Moolenbroek             }
624*b2ed49a5SDavid van Moolenbroek         break;
625*b2ed49a5SDavid van Moolenbroek         case MAGIC_DSENTRY_MSTATE_DEAD:
626*b2ed49a5SDavid van Moolenbroek             old_state = MAGIC_CAS(&dsentry->magic_state, MAGIC_DSENTRY_MSTATE_ALIVE,
627*b2ed49a5SDavid van Moolenbroek                 MAGIC_DSENTRY_MSTATE_DEAD);
628*b2ed49a5SDavid van Moolenbroek             if(old_state != MAGIC_DSENTRY_MSTATE_ALIVE) {
629*b2ed49a5SDavid van Moolenbroek                 ret = (old_state == MAGIC_DSENTRY_MSTATE_DEAD
630*b2ed49a5SDavid van Moolenbroek                     || old_state == MAGIC_DSENTRY_MSTATE_FREED)
631*b2ed49a5SDavid van Moolenbroek                     ? MAGIC_EBADMSTATE : MAGIC_EBADENT;
632*b2ed49a5SDavid van Moolenbroek                 break;
633*b2ed49a5SDavid van Moolenbroek             }
634*b2ed49a5SDavid van Moolenbroek             MAGIC_DSENTRY_TO_SENTRY(dsentry)->id = MAGIC_FAA(&_magic_sentries_next_id, 1);
635*b2ed49a5SDavid van Moolenbroek             assert(_magic_sentries_next_id < MAGIC_ID_MAX);
636*b2ed49a5SDavid van Moolenbroek             if (!MAGIC_STATE_FLAG(MAGIC_DSENTRY_TO_SENTRY(dsentry), MAGIC_STATE_MEMBLOCK)) {
637*b2ed49a5SDavid van Moolenbroek                 num_dead_dsentries = MAGIC_FAA(&magic_num_dead_dsentries, 1) + 1;
638*b2ed49a5SDavid van Moolenbroek                 size_dead_dsentries = MAGIC_FAA(&magic_size_dead_dsentries, size) + size;
639*b2ed49a5SDavid van Moolenbroek                 MAGIC_MEM_PRINTF("magic_update_dsentry_state:  ++magic_num_dead_dsentries (num=%d, size=%d)\n", num_dead_dsentries, size_dead_dsentries);
640*b2ed49a5SDavid van Moolenbroek                 if(!magic_ignore_dead_dsentries
641*b2ed49a5SDavid van Moolenbroek                     && MAGIC_DEAD_DSENTRIES_NEED_FREEING()) {
642*b2ed49a5SDavid van Moolenbroek                     magic_free_dead_dsentries();
643*b2ed49a5SDavid van Moolenbroek                 }
644*b2ed49a5SDavid van Moolenbroek             }
645*b2ed49a5SDavid van Moolenbroek         break;
646*b2ed49a5SDavid van Moolenbroek         default:
647*b2ed49a5SDavid van Moolenbroek             ret = MAGIC_EINVAL;
648*b2ed49a5SDavid van Moolenbroek         break;
649*b2ed49a5SDavid van Moolenbroek     }
650*b2ed49a5SDavid van Moolenbroek 
651*b2ed49a5SDavid van Moolenbroek     return ret;
652*b2ed49a5SDavid van Moolenbroek }
653*b2ed49a5SDavid van Moolenbroek 
654*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
655*b2ed49a5SDavid van Moolenbroek  *                            magic_free_dsentry                             *
656*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_free_dsentry(struct _magic_dsentry * dsentry)657*b2ed49a5SDavid van Moolenbroek PRIVATE int magic_free_dsentry(struct _magic_dsentry *dsentry)
658*b2ed49a5SDavid van Moolenbroek {
659*b2ed49a5SDavid van Moolenbroek     int ret = 0;
660*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry);
661*b2ed49a5SDavid van Moolenbroek     int region = MAGIC_STATE_REGION(sentry);
662*b2ed49a5SDavid van Moolenbroek     void *ptr = MAGIC_PTR_FROM_DSENTRY(dsentry);
663*b2ed49a5SDavid van Moolenbroek     size_t page_size, size;
664*b2ed49a5SDavid van Moolenbroek     void *data_ptr, *aligned_ptr;
665*b2ed49a5SDavid van Moolenbroek     int from_wrapper = MAGIC_MEM_WRAPPER_IS_ACTIVE();
666*b2ed49a5SDavid van Moolenbroek     assert(dsentry->magic_number == MAGIC_DSENTRY_MNUM_NULL);
667*b2ed49a5SDavid van Moolenbroek 
668*b2ed49a5SDavid van Moolenbroek     if (!from_wrapper) {
669*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_WRAPPER_BEGIN();
670*b2ed49a5SDavid van Moolenbroek     }
671*b2ed49a5SDavid van Moolenbroek 
672*b2ed49a5SDavid van Moolenbroek     if (magic_mem_heap_free_cb) {
673*b2ed49a5SDavid van Moolenbroek         ret = magic_mem_heap_free_cb(dsentry);
674*b2ed49a5SDavid van Moolenbroek         if (ret != MAGIC_ENOENT)
675*b2ed49a5SDavid van Moolenbroek             return ret;
676*b2ed49a5SDavid van Moolenbroek 
677*b2ed49a5SDavid van Moolenbroek         /*
678*b2ed49a5SDavid van Moolenbroek          * If the callback returned MAGIC_ENOENT, fallback to
679*b2ed49a5SDavid van Moolenbroek          * the default behavior.
680*b2ed49a5SDavid van Moolenbroek          */
681*b2ed49a5SDavid van Moolenbroek         ret = 0;
682*b2ed49a5SDavid van Moolenbroek     }
683*b2ed49a5SDavid van Moolenbroek 
684*b2ed49a5SDavid van Moolenbroek     /* A MAP_SHARED region will have both MAGIC_STATE_MAP and MAGIC_STATE_SHM. */
685*b2ed49a5SDavid van Moolenbroek     if (region == (MAGIC_STATE_MAP | MAGIC_STATE_SHM))
686*b2ed49a5SDavid van Moolenbroek         region = MAGIC_STATE_MAP;
687*b2ed49a5SDavid van Moolenbroek     switch (region) {
688*b2ed49a5SDavid van Moolenbroek         case MAGIC_STATE_HEAP:
689*b2ed49a5SDavid van Moolenbroek             MAGIC_MEM_DEBUG_FREE(ptr);
690*b2ed49a5SDavid van Moolenbroek             free(ptr);
691*b2ed49a5SDavid van Moolenbroek         break;
692*b2ed49a5SDavid van Moolenbroek         case MAGIC_STATE_MAP:
693*b2ed49a5SDavid van Moolenbroek         case MAGIC_STATE_SHM:
694*b2ed49a5SDavid van Moolenbroek             page_size = MAGIC_PAGE_SIZE;
695*b2ed49a5SDavid van Moolenbroek             size = MAGIC_DSENTRY_TO_SENTRY(dsentry)->type->size;
696*b2ed49a5SDavid van Moolenbroek             data_ptr = MAGIC_PTR_TO_DATA(ptr);
697*b2ed49a5SDavid van Moolenbroek             aligned_ptr = ((char *)data_ptr) - page_size;
698*b2ed49a5SDavid van Moolenbroek 
699*b2ed49a5SDavid van Moolenbroek             if (!MAGIC_STATE_FLAG(sentry, MAGIC_STATE_DETACHED)) {
700*b2ed49a5SDavid van Moolenbroek                 size_t padding_size = (size_t) dsentry->ext;
701*b2ed49a5SDavid van Moolenbroek                 MAGIC_MEM_DEBUG_FREE(ptr);
702*b2ed49a5SDavid van Moolenbroek                 ret = munmap((char *)aligned_ptr, page_size + size + padding_size);
703*b2ed49a5SDavid van Moolenbroek             }
704*b2ed49a5SDavid van Moolenbroek             else {
705*b2ed49a5SDavid van Moolenbroek #ifndef __MINIX
706*b2ed49a5SDavid van Moolenbroek                 if (MAGIC_STATE_FLAG(sentry, MAGIC_STATE_SHM))
707*b2ed49a5SDavid van Moolenbroek                     ret = shmdt(data_ptr);
708*b2ed49a5SDavid van Moolenbroek                 else
709*b2ed49a5SDavid van Moolenbroek #endif
710*b2ed49a5SDavid van Moolenbroek                     ret = munmap(data_ptr, size);
711*b2ed49a5SDavid van Moolenbroek                 MAGIC_MEM_DEBUG_FREE(ptr);
712*b2ed49a5SDavid van Moolenbroek                 munmap(aligned_ptr, page_size);
713*b2ed49a5SDavid van Moolenbroek             }
714*b2ed49a5SDavid van Moolenbroek             if (ret != 0) {
715*b2ed49a5SDavid van Moolenbroek                 ret = MAGIC_EBADENT;
716*b2ed49a5SDavid van Moolenbroek             }
717*b2ed49a5SDavid van Moolenbroek         break;
718*b2ed49a5SDavid van Moolenbroek         default:
719*b2ed49a5SDavid van Moolenbroek             ret = MAGIC_EBADENT;
720*b2ed49a5SDavid van Moolenbroek         break;
721*b2ed49a5SDavid van Moolenbroek     }
722*b2ed49a5SDavid van Moolenbroek     if (!from_wrapper) {
723*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_WRAPPER_END();
724*b2ed49a5SDavid van Moolenbroek     }
725*b2ed49a5SDavid van Moolenbroek 
726*b2ed49a5SDavid van Moolenbroek     return ret;
727*b2ed49a5SDavid van Moolenbroek }
728*b2ed49a5SDavid van Moolenbroek 
729*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
730*b2ed49a5SDavid van Moolenbroek  *                    magic_free_dead_dsentries                              *
731*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_free_dead_dsentries()732*b2ed49a5SDavid van Moolenbroek PUBLIC void magic_free_dead_dsentries()
733*b2ed49a5SDavid van Moolenbroek {
734*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *prev_dsentry, *dsentry, *next_first_dsentry, *skipped_dsentry;
735*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *sentry;
736*b2ed49a5SDavid van Moolenbroek     unsigned long num_dead_dsentries;
737*b2ed49a5SDavid van Moolenbroek     int dead_dsentries_left;
738*b2ed49a5SDavid van Moolenbroek     int ret;
739*b2ed49a5SDavid van Moolenbroek 
740*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_LOCK();
741*b2ed49a5SDavid van Moolenbroek 
742*b2ed49a5SDavid van Moolenbroek     skipped_dsentry = NULL;
743*b2ed49a5SDavid van Moolenbroek     num_dead_dsentries = magic_num_dead_dsentries;
744*b2ed49a5SDavid van Moolenbroek     next_first_dsentry = _magic_first_dsentry;
745*b2ed49a5SDavid van Moolenbroek     if (next_first_dsentry) {
746*b2ed49a5SDavid van Moolenbroek         /* if the first dsentry is dead, skip it to eliminate contention on the list head */
747*b2ed49a5SDavid van Moolenbroek         if (next_first_dsentry->magic_state == MAGIC_DSENTRY_MSTATE_DEAD){
748*b2ed49a5SDavid van Moolenbroek             num_dead_dsentries--;
749*b2ed49a5SDavid van Moolenbroek         }
750*b2ed49a5SDavid van Moolenbroek     }
751*b2ed49a5SDavid van Moolenbroek 
752*b2ed49a5SDavid van Moolenbroek     if(!next_first_dsentry || num_dead_dsentries == 0) {
753*b2ed49a5SDavid van Moolenbroek         MAGIC_DSENTRY_UNLOCK();
754*b2ed49a5SDavid van Moolenbroek         return;
755*b2ed49a5SDavid van Moolenbroek     }
756*b2ed49a5SDavid van Moolenbroek 
757*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_PRINTF("magic_free_dead_dsentries: Freeing %d dead dsentries...\n", num_dead_dsentries);
758*b2ed49a5SDavid van Moolenbroek 
759*b2ed49a5SDavid van Moolenbroek     /* Eliminate the dead dsentries but always skip the first one to eliminate contention on the head. */
760*b2ed49a5SDavid van Moolenbroek     do {
761*b2ed49a5SDavid van Moolenbroek         dead_dsentries_left = 0;
762*b2ed49a5SDavid van Moolenbroek         MAGIC_DSENTRY_ITER(next_first_dsentry->next, prev_dsentry, dsentry, sentry,
763*b2ed49a5SDavid van Moolenbroek             /* normal dsentry to be freed */
764*b2ed49a5SDavid van Moolenbroek             if ((dsentry->magic_state != MAGIC_DSENTRY_MSTATE_DEAD) ||
765*b2ed49a5SDavid van Moolenbroek                     (magic_update_dsentry_state(dsentry, MAGIC_DSENTRY_MSTATE_FREED) < 0)) {
766*b2ed49a5SDavid van Moolenbroek                 next_first_dsentry = dsentry;
767*b2ed49a5SDavid van Moolenbroek             } else {
768*b2ed49a5SDavid van Moolenbroek                 magic_destroy_dsentry(dsentry, prev_dsentry);
769*b2ed49a5SDavid van Moolenbroek                 ret = magic_free_dsentry(dsentry);
770*b2ed49a5SDavid van Moolenbroek                 if(ret != 0) {
771*b2ed49a5SDavid van Moolenbroek                     _magic_printf("Warning: magic_free_dsentry failed with return code %d for: ", ret);
772*b2ed49a5SDavid van Moolenbroek                     MAGIC_DSENTRY_PRINT(dsentry, MAGIC_EXPAND_TYPE_STR);
773*b2ed49a5SDavid van Moolenbroek                     MAGIC_MEM_PRINTF("\n");
774*b2ed49a5SDavid van Moolenbroek                 }
775*b2ed49a5SDavid van Moolenbroek                 num_dead_dsentries--;
776*b2ed49a5SDavid van Moolenbroek                 dead_dsentries_left = 1;
777*b2ed49a5SDavid van Moolenbroek                 break;
778*b2ed49a5SDavid van Moolenbroek             }
779*b2ed49a5SDavid van Moolenbroek         );
780*b2ed49a5SDavid van Moolenbroek     } while(dead_dsentries_left && num_dead_dsentries > 0);
781*b2ed49a5SDavid van Moolenbroek     assert(num_dead_dsentries == 0);
782*b2ed49a5SDavid van Moolenbroek 
783*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_UNLOCK();
784*b2ed49a5SDavid van Moolenbroek }
785*b2ed49a5SDavid van Moolenbroek 
786*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
787*b2ed49a5SDavid van Moolenbroek  *                      magic_destroy_dsentry                                *
788*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_destroy_dsentry(struct _magic_dsentry * dsentry,struct _magic_dsentry * prev_dsentry)789*b2ed49a5SDavid van Moolenbroek PUBLIC void magic_destroy_dsentry(struct _magic_dsentry *dsentry,
790*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *prev_dsentry)
791*b2ed49a5SDavid van Moolenbroek {
792*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *next_dsentry, *next_mempool_dsentry, *prev_mempool_dsentry = NULL;
793*b2ed49a5SDavid van Moolenbroek     int dsentry_destroyed, mempool_dsentry_destroyed;
794*b2ed49a5SDavid van Moolenbroek 
795*b2ed49a5SDavid van Moolenbroek     if(magic_destroy_dsentry_ext_cb && MAGIC_DSENTRY_HAS_EXT(dsentry)) {
796*b2ed49a5SDavid van Moolenbroek         magic_destroy_dsentry_ext_cb(dsentry);
797*b2ed49a5SDavid van Moolenbroek     }
798*b2ed49a5SDavid van Moolenbroek     if (MAGIC_STATE_FLAG(MAGIC_DSENTRY_TO_SENTRY(dsentry), MAGIC_STATE_MEMPOOL)) {
799*b2ed49a5SDavid van Moolenbroek         do {
800*b2ed49a5SDavid van Moolenbroek             if(!prev_mempool_dsentry) {
801*b2ed49a5SDavid van Moolenbroek                 if(MAGIC_DSENTRY_NEXT_MEMPOOL(dsentry) != MAGIC_DSENTRY_NEXT_MEMPOOL(_magic_first_mempool_dsentry)) {
802*b2ed49a5SDavid van Moolenbroek                     prev_mempool_dsentry = magic_mempool_dsentry_prev_lookup(dsentry);
803*b2ed49a5SDavid van Moolenbroek                     assert(prev_mempool_dsentry != (struct _magic_dsentry *) MAGIC_ENOPTR && "Dsentry not found!");
804*b2ed49a5SDavid van Moolenbroek                 }
805*b2ed49a5SDavid van Moolenbroek             }
806*b2ed49a5SDavid van Moolenbroek             if(prev_mempool_dsentry) {
807*b2ed49a5SDavid van Moolenbroek                 MAGIC_DSENTRY_NEXT_MEMPOOL(prev_mempool_dsentry) = MAGIC_DSENTRY_NEXT_MEMPOOL(dsentry);
808*b2ed49a5SDavid van Moolenbroek                 mempool_dsentry_destroyed = 1;
809*b2ed49a5SDavid van Moolenbroek             }
810*b2ed49a5SDavid van Moolenbroek             else {
811*b2ed49a5SDavid van Moolenbroek                 /* Remove the first dsentry atomically. */
812*b2ed49a5SDavid van Moolenbroek                 next_mempool_dsentry = MAGIC_DSENTRY_NEXT_MEMPOOL(dsentry);
813*b2ed49a5SDavid van Moolenbroek                 mempool_dsentry_destroyed = (MAGIC_CAS(&_magic_first_mempool_dsentry,
814*b2ed49a5SDavid van Moolenbroek                     dsentry, next_mempool_dsentry) == dsentry);
815*b2ed49a5SDavid van Moolenbroek             }
816*b2ed49a5SDavid van Moolenbroek         } while(!mempool_dsentry_destroyed);
817*b2ed49a5SDavid van Moolenbroek         MAGIC_DSENTRY_NEXT_MEMPOOL(dsentry) = NULL;
818*b2ed49a5SDavid van Moolenbroek     }
819*b2ed49a5SDavid van Moolenbroek     do {
820*b2ed49a5SDavid van Moolenbroek #if MAGIC_DSENTRY_ALLOW_PREV
821*b2ed49a5SDavid van Moolenbroek         prev_dsentry = MAGIC_DSENTRY_PREV(dsentry);
822*b2ed49a5SDavid van Moolenbroek #else
823*b2ed49a5SDavid van Moolenbroek         if(!prev_dsentry) {
824*b2ed49a5SDavid van Moolenbroek             if(MAGIC_DSENTRY_NEXT(dsentry) != MAGIC_DSENTRY_NEXT(_magic_first_dsentry)) {
825*b2ed49a5SDavid van Moolenbroek                 prev_dsentry = magic_dsentry_prev_lookup(dsentry);
826*b2ed49a5SDavid van Moolenbroek                 assert(prev_dsentry != (struct _magic_dsentry *) MAGIC_ENOPTR && "Dsentry not found!");
827*b2ed49a5SDavid van Moolenbroek             }
828*b2ed49a5SDavid van Moolenbroek         }
829*b2ed49a5SDavid van Moolenbroek #endif
830*b2ed49a5SDavid van Moolenbroek 
831*b2ed49a5SDavid van Moolenbroek         if(prev_dsentry) {
832*b2ed49a5SDavid van Moolenbroek             MAGIC_DSENTRY_NEXT(prev_dsentry) = MAGIC_DSENTRY_NEXT(dsentry);
833*b2ed49a5SDavid van Moolenbroek             dsentry_destroyed = 1;
834*b2ed49a5SDavid van Moolenbroek         }
835*b2ed49a5SDavid van Moolenbroek         else {
836*b2ed49a5SDavid van Moolenbroek             /* Remove the first dsentry atomically. */
837*b2ed49a5SDavid van Moolenbroek             next_dsentry = MAGIC_DSENTRY_NEXT(dsentry);
838*b2ed49a5SDavid van Moolenbroek             dsentry_destroyed = (MAGIC_CAS(&_magic_first_dsentry,
839*b2ed49a5SDavid van Moolenbroek                 dsentry, next_dsentry) == dsentry);
840*b2ed49a5SDavid van Moolenbroek         }
841*b2ed49a5SDavid van Moolenbroek     } while(!dsentry_destroyed);
842*b2ed49a5SDavid van Moolenbroek 
843*b2ed49a5SDavid van Moolenbroek #if MAGIC_DSENTRY_ALLOW_PREV
844*b2ed49a5SDavid van Moolenbroek     next_dsentry = MAGIC_DSENTRY_NEXT(dsentry);
845*b2ed49a5SDavid van Moolenbroek     if(next_dsentry) {
846*b2ed49a5SDavid van Moolenbroek         MAGIC_DSENTRY_PREV(next_dsentry) = MAGIC_DSENTRY_PREV(dsentry);
847*b2ed49a5SDavid van Moolenbroek     }
848*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_PREV(dsentry) = NULL;
849*b2ed49a5SDavid van Moolenbroek #endif
850*b2ed49a5SDavid van Moolenbroek 
851*b2ed49a5SDavid van Moolenbroek     dsentry->magic_number = MAGIC_DSENTRY_MNUM_NULL;
852*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_NEXT(dsentry) = NULL;
853*b2ed49a5SDavid van Moolenbroek }
854*b2ed49a5SDavid van Moolenbroek 
855*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
856*b2ed49a5SDavid van Moolenbroek  *                       magic_destroy_obdsentry_by_addr                     *
857*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_destroy_obdsentry_by_addr(void * data_ptr)858*b2ed49a5SDavid van Moolenbroek PUBLIC int magic_destroy_obdsentry_by_addr(void *data_ptr)
859*b2ed49a5SDavid van Moolenbroek {
860*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *sentry;
861*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *dsentry;
862*b2ed49a5SDavid van Moolenbroek     struct _magic_obdsentry *obdsentry;
863*b2ed49a5SDavid van Moolenbroek     int obflags = (MAGIC_STATE_DYNAMIC|MAGIC_STATE_OUT_OF_BAND);
864*b2ed49a5SDavid van Moolenbroek 
865*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_LBEGIN();
866*b2ed49a5SDavid van Moolenbroek 
867*b2ed49a5SDavid van Moolenbroek     /* Lookup the obdsentry. */
868*b2ed49a5SDavid van Moolenbroek     sentry = magic_sentry_lookup_by_addr(data_ptr, NULL);
869*b2ed49a5SDavid van Moolenbroek     if(!sentry || ((sentry->flags & obflags) != obflags)) {
870*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_WRAPPER_LEND();
871*b2ed49a5SDavid van Moolenbroek         return MAGIC_EINVAL;
872*b2ed49a5SDavid van Moolenbroek     }
873*b2ed49a5SDavid van Moolenbroek     dsentry = MAGIC_DSENTRY_FROM_SENTRY(sentry);
874*b2ed49a5SDavid van Moolenbroek     obdsentry = MAGIC_OBDSENTRY_FROM_DSENTRY(dsentry);
875*b2ed49a5SDavid van Moolenbroek 
876*b2ed49a5SDavid van Moolenbroek     /* Destroy it and free obdsentry slot. */
877*b2ed49a5SDavid van Moolenbroek     magic_destroy_dsentry(dsentry, NULL);
878*b2ed49a5SDavid van Moolenbroek     MAGIC_OBDSENTRY_FREE(obdsentry);
879*b2ed49a5SDavid van Moolenbroek 
880*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_LEND();
881*b2ed49a5SDavid van Moolenbroek 
882*b2ed49a5SDavid van Moolenbroek     return 0;
883*b2ed49a5SDavid van Moolenbroek }
884*b2ed49a5SDavid van Moolenbroek 
885*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
886*b2ed49a5SDavid van Moolenbroek  *                       magic_destroy_dsentry_set_ext_cb                    *
887*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_destroy_dsentry_set_ext_cb(const magic_dsentry_cb_t cb)888*b2ed49a5SDavid van Moolenbroek PUBLIC void magic_destroy_dsentry_set_ext_cb(const magic_dsentry_cb_t cb)
889*b2ed49a5SDavid van Moolenbroek {
890*b2ed49a5SDavid van Moolenbroek     magic_destroy_dsentry_ext_cb = cb;
891*b2ed49a5SDavid van Moolenbroek }
892*b2ed49a5SDavid van Moolenbroek 
893*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
894*b2ed49a5SDavid van Moolenbroek  *                            magic_update_dsentry                           *
895*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_update_dsentry(void * addr,struct _magic_type * type)896*b2ed49a5SDavid van Moolenbroek PUBLIC int magic_update_dsentry(void* addr, struct _magic_type *type)
897*b2ed49a5SDavid van Moolenbroek {
898*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *prev_dsentry, *dsentry;
899*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry* sentry;
900*b2ed49a5SDavid van Moolenbroek     size_t size, type_size;
901*b2ed49a5SDavid van Moolenbroek     int is_varsized = 0;
902*b2ed49a5SDavid van Moolenbroek     int num_vsa_elements = 0;
903*b2ed49a5SDavid van Moolenbroek 
904*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_LOCK();
905*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_ALIVE_BLOCK_ITER(_magic_first_dsentry, prev_dsentry, dsentry, sentry,
906*b2ed49a5SDavid van Moolenbroek         if(sentry->address == addr) {
907*b2ed49a5SDavid van Moolenbroek             size = sentry->type->size;
908*b2ed49a5SDavid van Moolenbroek             type_size = type->size;
909*b2ed49a5SDavid van Moolenbroek 
910*b2ed49a5SDavid van Moolenbroek             /* Catch variable-sized struct allocation. */
911*b2ed49a5SDavid van Moolenbroek             if(magic_type_alloc_needs_varsized_array(type, size, &num_vsa_elements)) {
912*b2ed49a5SDavid van Moolenbroek                 is_varsized = 1;
913*b2ed49a5SDavid van Moolenbroek             }
914*b2ed49a5SDavid van Moolenbroek 
915*b2ed49a5SDavid van Moolenbroek             if(size % type_size != 0 && !is_varsized) {
916*b2ed49a5SDavid van Moolenbroek                 return MAGIC_EBADENT;
917*b2ed49a5SDavid van Moolenbroek             }
918*b2ed49a5SDavid van Moolenbroek             if(size == type_size && !is_varsized) {
919*b2ed49a5SDavid van Moolenbroek                 sentry->type = type;
920*b2ed49a5SDavid van Moolenbroek             }
921*b2ed49a5SDavid van Moolenbroek             else {
922*b2ed49a5SDavid van Moolenbroek                 struct _magic_type *array_type = &(dsentry->type);
923*b2ed49a5SDavid van Moolenbroek                 MAGIC_TYPE_ARRAY_CREATE_FROM_SIZE(array_type, type,
924*b2ed49a5SDavid van Moolenbroek                     MAGIC_DSENTRY_TO_TYPE_ARR(dsentry), size, num_vsa_elements);
925*b2ed49a5SDavid van Moolenbroek                 array_type->id = MAGIC_FAA(&_magic_types_next_id, 1);
926*b2ed49a5SDavid van Moolenbroek                 assert(_magic_types_next_id < MAGIC_ID_MAX);
927*b2ed49a5SDavid van Moolenbroek                 sentry->type = array_type;
928*b2ed49a5SDavid van Moolenbroek             }
929*b2ed49a5SDavid van Moolenbroek             return 0;
930*b2ed49a5SDavid van Moolenbroek         }
931*b2ed49a5SDavid van Moolenbroek     );
932*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_UNLOCK();
933*b2ed49a5SDavid van Moolenbroek 
934*b2ed49a5SDavid van Moolenbroek     return MAGIC_ENOENT;
935*b2ed49a5SDavid van Moolenbroek }
936*b2ed49a5SDavid van Moolenbroek 
937*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
938*b2ed49a5SDavid van Moolenbroek  *                              magic_stack_init                             *
939*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_stack_init()940*b2ed49a5SDavid van Moolenbroek PUBLIC void magic_stack_init()
941*b2ed49a5SDavid van Moolenbroek {
942*b2ed49a5SDavid van Moolenbroek     struct _magic_obdsentry *obdsentry;
943*b2ed49a5SDavid van Moolenbroek     char **ptr;
944*b2ed49a5SDavid van Moolenbroek     size_t size;
945*b2ed49a5SDavid van Moolenbroek     void *initial_stack_bottom, *initial_stack_top;
946*b2ed49a5SDavid van Moolenbroek     unsigned long* word_ptr;
947*b2ed49a5SDavid van Moolenbroek     int argc;
948*b2ed49a5SDavid van Moolenbroek     char **argv;
949*b2ed49a5SDavid van Moolenbroek 
950*b2ed49a5SDavid van Moolenbroek     assert(!_magic_first_stack_dsentry && !_magic_last_stack_dsentry);
951*b2ed49a5SDavid van Moolenbroek 
952*b2ed49a5SDavid van Moolenbroek     /* Find initial stack bottom and top, this should be portable enough */
953*b2ed49a5SDavid van Moolenbroek     for (ptr = environ ; *ptr ; ptr++);
954*b2ed49a5SDavid van Moolenbroek     if (ptr == environ){
955*b2ed49a5SDavid van Moolenbroek         /* the environment is empty, and ptr still points to environ.
956*b2ed49a5SDavid van Moolenbroek          * decrement ptr twice: once to point at the argv terminator,
957*b2ed49a5SDavid van Moolenbroek          * and once to point to point at the last argument, which will be the stack bottom
958*b2ed49a5SDavid van Moolenbroek          */
959*b2ed49a5SDavid van Moolenbroek         ptr -= 2;
960*b2ed49a5SDavid van Moolenbroek     } else {
961*b2ed49a5SDavid van Moolenbroek         /* environment is not empty. decrement the pointer,
962*b2ed49a5SDavid van Moolenbroek          * because the for loop walked past the last env variable pointer.
963*b2ed49a5SDavid van Moolenbroek          */
964*b2ed49a5SDavid van Moolenbroek         ptr--;
965*b2ed49a5SDavid van Moolenbroek     }
966*b2ed49a5SDavid van Moolenbroek 
967*b2ed49a5SDavid van Moolenbroek     if (*ptr) {
968*b2ed49a5SDavid van Moolenbroek         initial_stack_bottom = *ptr+strlen(*ptr)+1;
969*b2ed49a5SDavid van Moolenbroek         word_ptr = (unsigned long*) environ;
970*b2ed49a5SDavid van Moolenbroek         word_ptr--;
971*b2ed49a5SDavid van Moolenbroek         assert(*word_ptr == 0); /* argv terminator */
972*b2ed49a5SDavid van Moolenbroek         word_ptr--;
973*b2ed49a5SDavid van Moolenbroek         argc = 0;
974*b2ed49a5SDavid van Moolenbroek         while(*word_ptr != (unsigned long) argc) {
975*b2ed49a5SDavid van Moolenbroek             argc++;
976*b2ed49a5SDavid van Moolenbroek             word_ptr--;
977*b2ed49a5SDavid van Moolenbroek         }
978*b2ed49a5SDavid van Moolenbroek         argv = (char**) (word_ptr+1);
979*b2ed49a5SDavid van Moolenbroek         initial_stack_top = argv;
980*b2ed49a5SDavid van Moolenbroek     } else {
981*b2ed49a5SDavid van Moolenbroek         /* Environ and argv empty?. Resort to defaults. */
982*b2ed49a5SDavid van Moolenbroek         initial_stack_top = ptr;
983*b2ed49a5SDavid van Moolenbroek         initial_stack_bottom = environ;
984*b2ed49a5SDavid van Moolenbroek     }
985*b2ed49a5SDavid van Moolenbroek     size = (size_t)initial_stack_bottom - (size_t)initial_stack_top + 1;
986*b2ed49a5SDavid van Moolenbroek 
987*b2ed49a5SDavid van Moolenbroek     /* Create the first stack dsentry. */
988*b2ed49a5SDavid van Moolenbroek     obdsentry = magic_create_obdsentry(initial_stack_top, MAGIC_VOID_TYPE,
989*b2ed49a5SDavid van Moolenbroek       size, MAGIC_STATE_STACK, MAGIC_ALLOC_INITIAL_STACK_NAME, NULL);
990*b2ed49a5SDavid van Moolenbroek     assert(obdsentry);
991*b2ed49a5SDavid van Moolenbroek     _magic_first_stack_dsentry = _magic_last_stack_dsentry = MAGIC_OBDSENTRY_TO_DSENTRY(obdsentry);
992*b2ed49a5SDavid van Moolenbroek }
993*b2ed49a5SDavid van Moolenbroek 
994*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
995*b2ed49a5SDavid van Moolenbroek  *                        magic_stack_dsentries_create                       *
996*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_stack_dsentries_create(struct _magic_dsentry ** prev_last_stack_dsentry,int num_dsentries,...)997*b2ed49a5SDavid van Moolenbroek PUBLIC void magic_stack_dsentries_create(
998*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry **prev_last_stack_dsentry, int num_dsentries,
999*b2ed49a5SDavid van Moolenbroek     /* struct _magic_dsentry *dsentry, struct _magic_type *type, void* data_ptr, const char* function_name, const char* name, */ ...)
1000*b2ed49a5SDavid van Moolenbroek {
1001*b2ed49a5SDavid van Moolenbroek     int i;
1002*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *dsentry;
1003*b2ed49a5SDavid van Moolenbroek     struct _magic_type *type;
1004*b2ed49a5SDavid van Moolenbroek     void* data_ptr;
1005*b2ed49a5SDavid van Moolenbroek     const char* function_name;
1006*b2ed49a5SDavid van Moolenbroek     const char* name;
1007*b2ed49a5SDavid van Moolenbroek     char *min_data_ptr = NULL, *max_data_ptr = NULL;
1008*b2ed49a5SDavid van Moolenbroek     va_list va;
1009*b2ed49a5SDavid van Moolenbroek 
1010*b2ed49a5SDavid van Moolenbroek     assert(num_dsentries > 0);
1011*b2ed49a5SDavid van Moolenbroek 
1012*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_LOCK();
1013*b2ed49a5SDavid van Moolenbroek     assert(_magic_first_stack_dsentry && "First stack dsentry not found!");
1014*b2ed49a5SDavid van Moolenbroek     va_start(va, num_dsentries);
1015*b2ed49a5SDavid van Moolenbroek     *prev_last_stack_dsentry = _magic_last_stack_dsentry;
1016*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < num_dsentries ; i++) {
1017*b2ed49a5SDavid van Moolenbroek         dsentry = va_arg(va, struct _magic_dsentry *);
1018*b2ed49a5SDavid van Moolenbroek         type = va_arg(va, struct _magic_type *);
1019*b2ed49a5SDavid van Moolenbroek         data_ptr = va_arg(va, void *);
1020*b2ed49a5SDavid van Moolenbroek         function_name = va_arg(va, const char *);
1021*b2ed49a5SDavid van Moolenbroek         name = va_arg(va, const char *);
1022*b2ed49a5SDavid van Moolenbroek         if (i == num_dsentries - 1) {
1023*b2ed49a5SDavid van Moolenbroek             /* Return address. */
1024*b2ed49a5SDavid van Moolenbroek             int *value_set = (void*) type;
1025*b2ed49a5SDavid van Moolenbroek             data_ptr = MAGIC_FRAMEADDR_TO_RETADDR_PTR(data_ptr);
1026*b2ed49a5SDavid van Moolenbroek             type = &(dsentry->type);
1027*b2ed49a5SDavid van Moolenbroek             magic_create_dsentry(dsentry, data_ptr, MAGIC_VOID_TYPE, MAGIC_VOID_TYPE->size,
1028*b2ed49a5SDavid van Moolenbroek                 MAGIC_STATE_STACK | MAGIC_STATE_CONSTANT | MAGIC_STATE_ADDR_NOT_TAKEN,
1029*b2ed49a5SDavid van Moolenbroek                 name, function_name);
1030*b2ed49a5SDavid van Moolenbroek             memcpy(type, &magic_default_ret_addr_type, sizeof(struct _magic_type));
1031*b2ed49a5SDavid van Moolenbroek             type->contained_types = MAGIC_DSENTRY_TO_TYPE_ARR(dsentry);
1032*b2ed49a5SDavid van Moolenbroek             type->contained_types[0] = MAGIC_VOID_TYPE;
1033*b2ed49a5SDavid van Moolenbroek             type->value_set = value_set;
1034*b2ed49a5SDavid van Moolenbroek             value_set[0] = 1;
1035*b2ed49a5SDavid van Moolenbroek             value_set[1] = *((int *)data_ptr);
1036*b2ed49a5SDavid van Moolenbroek 
1037*b2ed49a5SDavid van Moolenbroek             /* Safe to override the type non-atomically.
1038*b2ed49a5SDavid van Moolenbroek             * The new type is only more restrictive, and nobody could
1039*b2ed49a5SDavid van Moolenbroek             * have touched this stack dsentry in the meantime.
1040*b2ed49a5SDavid van Moolenbroek             */
1041*b2ed49a5SDavid van Moolenbroek             MAGIC_DSENTRY_TO_SENTRY(dsentry)->type = type;
1042*b2ed49a5SDavid van Moolenbroek         } else {
1043*b2ed49a5SDavid van Moolenbroek             /* Local variable. */
1044*b2ed49a5SDavid van Moolenbroek             magic_create_dsentry(dsentry, data_ptr, type, type->size,
1045*b2ed49a5SDavid van Moolenbroek                 MAGIC_STATE_STACK, name, function_name);
1046*b2ed49a5SDavid van Moolenbroek             if (!min_data_ptr || min_data_ptr > (char *) data_ptr) {
1047*b2ed49a5SDavid van Moolenbroek                 min_data_ptr = (char *) data_ptr;
1048*b2ed49a5SDavid van Moolenbroek             }
1049*b2ed49a5SDavid van Moolenbroek             if (!max_data_ptr || max_data_ptr < (char *) data_ptr) {
1050*b2ed49a5SDavid van Moolenbroek                 max_data_ptr = (char *) data_ptr;
1051*b2ed49a5SDavid van Moolenbroek             }
1052*b2ed49a5SDavid van Moolenbroek         }
1053*b2ed49a5SDavid van Moolenbroek     }
1054*b2ed49a5SDavid van Moolenbroek 
1055*b2ed49a5SDavid van Moolenbroek #if MAGIC_FORCE_DYN_MEM_ZERO_INIT
1056*b2ed49a5SDavid van Moolenbroek     if (min_data_ptr && max_data_ptr) {
1057*b2ed49a5SDavid van Moolenbroek         memset(min_data_ptr, 0, max_data_ptr - min_data_ptr + 1);
1058*b2ed49a5SDavid van Moolenbroek     }
1059*b2ed49a5SDavid van Moolenbroek #endif
1060*b2ed49a5SDavid van Moolenbroek 
1061*b2ed49a5SDavid van Moolenbroek     _magic_last_stack_dsentry = dsentry;
1062*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_UNLOCK();
1063*b2ed49a5SDavid van Moolenbroek 
1064*b2ed49a5SDavid van Moolenbroek     va_end(va);
1065*b2ed49a5SDavid van Moolenbroek }
1066*b2ed49a5SDavid van Moolenbroek 
1067*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1068*b2ed49a5SDavid van Moolenbroek  *                        magic_stack_dsentries_destroy                      *
1069*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_stack_dsentries_destroy(struct _magic_dsentry ** prev_last_stack_dsentry,int num_dsentries,...)1070*b2ed49a5SDavid van Moolenbroek PUBLIC void magic_stack_dsentries_destroy(
1071*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry **prev_last_stack_dsentry, int num_dsentries,
1072*b2ed49a5SDavid van Moolenbroek     /* struct _magic_dsentry *dsentry, */ ...)
1073*b2ed49a5SDavid van Moolenbroek {
1074*b2ed49a5SDavid van Moolenbroek     int i;
1075*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *dsentry;
1076*b2ed49a5SDavid van Moolenbroek     va_list va;
1077*b2ed49a5SDavid van Moolenbroek 
1078*b2ed49a5SDavid van Moolenbroek     assert(num_dsentries > 0);
1079*b2ed49a5SDavid van Moolenbroek 
1080*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_LBEGIN();
1081*b2ed49a5SDavid van Moolenbroek 
1082*b2ed49a5SDavid van Moolenbroek     va_start(va, num_dsentries);
1083*b2ed49a5SDavid van Moolenbroek     _magic_last_stack_dsentry = *prev_last_stack_dsentry;
1084*b2ed49a5SDavid van Moolenbroek     for (i = 0 ; i < num_dsentries ; i++) {
1085*b2ed49a5SDavid van Moolenbroek         dsentry = va_arg(va, struct _magic_dsentry *);
1086*b2ed49a5SDavid van Moolenbroek         magic_destroy_dsentry(dsentry, NULL);
1087*b2ed49a5SDavid van Moolenbroek     }
1088*b2ed49a5SDavid van Moolenbroek     va_end(va);
1089*b2ed49a5SDavid van Moolenbroek 
1090*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_LEND();
1091*b2ed49a5SDavid van Moolenbroek }
1092*b2ed49a5SDavid van Moolenbroek 
1093*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1094*b2ed49a5SDavid van Moolenbroek  *                         magic_create_dfunction                            *
1095*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_create_dfunction(struct _magic_dfunction * dfunction,void * data_ptr,struct _magic_type * type,int flags,const char * name,const char * parent_name)1096*b2ed49a5SDavid van Moolenbroek PUBLIC int magic_create_dfunction(struct _magic_dfunction *dfunction,
1097*b2ed49a5SDavid van Moolenbroek     void *data_ptr, struct _magic_type *type, int flags,
1098*b2ed49a5SDavid van Moolenbroek     const char *name, const char *parent_name)
1099*b2ed49a5SDavid van Moolenbroek {
1100*b2ed49a5SDavid van Moolenbroek     struct _magic_function *function = MAGIC_DFUNCTION_TO_FUNCTION(dfunction);
1101*b2ed49a5SDavid van Moolenbroek 
1102*b2ed49a5SDavid van Moolenbroek     if(!type) {
1103*b2ed49a5SDavid van Moolenbroek         type = MAGIC_VOID_TYPE;
1104*b2ed49a5SDavid van Moolenbroek     }
1105*b2ed49a5SDavid van Moolenbroek 
1106*b2ed49a5SDavid van Moolenbroek     memcpy(dfunction, &magic_default_dfunction, sizeof(struct _magic_dfunction));
1107*b2ed49a5SDavid van Moolenbroek 
1108*b2ed49a5SDavid van Moolenbroek     assert(!(type->flags & MAGIC_TYPE_DYNAMIC) && "bad type!");
1109*b2ed49a5SDavid van Moolenbroek 
1110*b2ed49a5SDavid van Moolenbroek     function->type = type;
1111*b2ed49a5SDavid van Moolenbroek     function->flags |= flags;
1112*b2ed49a5SDavid van Moolenbroek     function->address = data_ptr;
1113*b2ed49a5SDavid van Moolenbroek     if(name) {
1114*b2ed49a5SDavid van Moolenbroek         function->name = name;
1115*b2ed49a5SDavid van Moolenbroek     }
1116*b2ed49a5SDavid van Moolenbroek     if(parent_name) {
1117*b2ed49a5SDavid van Moolenbroek         dfunction->parent_name = parent_name;
1118*b2ed49a5SDavid van Moolenbroek     }
1119*b2ed49a5SDavid van Moolenbroek     function->id = MAGIC_FAA(&_magic_functions_next_id, 1);
1120*b2ed49a5SDavid van Moolenbroek     assert(_magic_functions_next_id < MAGIC_ID_MAX);
1121*b2ed49a5SDavid van Moolenbroek 
1122*b2ed49a5SDavid van Moolenbroek     if(_magic_first_dfunction) {
1123*b2ed49a5SDavid van Moolenbroek         assert(_magic_last_dfunction);
1124*b2ed49a5SDavid van Moolenbroek         MAGIC_DFUNCTION_NEXT(_magic_last_dfunction) = dfunction;
1125*b2ed49a5SDavid van Moolenbroek     }
1126*b2ed49a5SDavid van Moolenbroek     else {
1127*b2ed49a5SDavid van Moolenbroek         assert(!_magic_last_dfunction);
1128*b2ed49a5SDavid van Moolenbroek         assert(_magic_dfunctions_num == 0);
1129*b2ed49a5SDavid van Moolenbroek         _magic_first_dfunction = dfunction;
1130*b2ed49a5SDavid van Moolenbroek     }
1131*b2ed49a5SDavid van Moolenbroek     MAGIC_DFUNCTION_PREV(dfunction) = _magic_last_dfunction;
1132*b2ed49a5SDavid van Moolenbroek     MAGIC_DFUNCTION_NEXT(dfunction) = NULL;
1133*b2ed49a5SDavid van Moolenbroek     _magic_last_dfunction = dfunction;
1134*b2ed49a5SDavid van Moolenbroek     _magic_dfunctions_num++;
1135*b2ed49a5SDavid van Moolenbroek 
1136*b2ed49a5SDavid van Moolenbroek     assert(magic_check_dfunction(dfunction, 0) && "Bad magic dfunction created!");
1137*b2ed49a5SDavid van Moolenbroek     magic_update_dfunction_ranges = 1;
1138*b2ed49a5SDavid van Moolenbroek 
1139*b2ed49a5SDavid van Moolenbroek     return 0;
1140*b2ed49a5SDavid van Moolenbroek }
1141*b2ed49a5SDavid van Moolenbroek 
1142*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1143*b2ed49a5SDavid van Moolenbroek  *                         magic_destroy_dfunction                           *
1144*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_destroy_dfunction(struct _magic_dfunction * dfunction)1145*b2ed49a5SDavid van Moolenbroek PUBLIC void magic_destroy_dfunction(struct _magic_dfunction *dfunction)
1146*b2ed49a5SDavid van Moolenbroek {
1147*b2ed49a5SDavid van Moolenbroek     dfunction->magic_number = MAGIC_DFUNCTION_MNUM_NULL;
1148*b2ed49a5SDavid van Moolenbroek     if(MAGIC_DFUNCTION_HAS_NEXT(dfunction)) {
1149*b2ed49a5SDavid van Moolenbroek         MAGIC_DFUNCTION_PREV(MAGIC_DFUNCTION_NEXT(dfunction)) = MAGIC_DFUNCTION_PREV(dfunction);
1150*b2ed49a5SDavid van Moolenbroek     }
1151*b2ed49a5SDavid van Moolenbroek     else {
1152*b2ed49a5SDavid van Moolenbroek         _magic_last_dfunction = MAGIC_DFUNCTION_PREV(dfunction);
1153*b2ed49a5SDavid van Moolenbroek     }
1154*b2ed49a5SDavid van Moolenbroek     if(MAGIC_DFUNCTION_HAS_PREV(dfunction)) {
1155*b2ed49a5SDavid van Moolenbroek         MAGIC_DFUNCTION_NEXT(MAGIC_DFUNCTION_PREV(dfunction)) = MAGIC_DFUNCTION_NEXT(dfunction);
1156*b2ed49a5SDavid van Moolenbroek     }
1157*b2ed49a5SDavid van Moolenbroek     else {
1158*b2ed49a5SDavid van Moolenbroek         _magic_first_dfunction = MAGIC_DFUNCTION_NEXT(dfunction);
1159*b2ed49a5SDavid van Moolenbroek     }
1160*b2ed49a5SDavid van Moolenbroek     MAGIC_DFUNCTION_NEXT(dfunction) = NULL;
1161*b2ed49a5SDavid van Moolenbroek     MAGIC_DFUNCTION_PREV(dfunction) = NULL;
1162*b2ed49a5SDavid van Moolenbroek     _magic_dfunctions_num--;
1163*b2ed49a5SDavid van Moolenbroek     if(_magic_dfunctions_num == 0) {
1164*b2ed49a5SDavid van Moolenbroek         assert(!_magic_first_dfunction && !_magic_last_dfunction);
1165*b2ed49a5SDavid van Moolenbroek     }
1166*b2ed49a5SDavid van Moolenbroek     else {
1167*b2ed49a5SDavid van Moolenbroek         assert(_magic_first_dfunction && _magic_last_dfunction);
1168*b2ed49a5SDavid van Moolenbroek     }
1169*b2ed49a5SDavid van Moolenbroek }
1170*b2ed49a5SDavid van Moolenbroek 
1171*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1172*b2ed49a5SDavid van Moolenbroek  *                          magic_create_sodesc                              *
1173*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_create_sodesc(struct _magic_sodesc * sodesc)1174*b2ed49a5SDavid van Moolenbroek PUBLIC int magic_create_sodesc(struct _magic_sodesc *sodesc)
1175*b2ed49a5SDavid van Moolenbroek {
1176*b2ed49a5SDavid van Moolenbroek     if(_magic_first_sodesc) {
1177*b2ed49a5SDavid van Moolenbroek         assert(_magic_last_sodesc);
1178*b2ed49a5SDavid van Moolenbroek         MAGIC_SODESC_NEXT(_magic_last_sodesc) = sodesc;
1179*b2ed49a5SDavid van Moolenbroek     }
1180*b2ed49a5SDavid van Moolenbroek     else {
1181*b2ed49a5SDavid van Moolenbroek         assert(!_magic_last_sodesc);
1182*b2ed49a5SDavid van Moolenbroek         assert(_magic_sodescs_num == 0);
1183*b2ed49a5SDavid van Moolenbroek         _magic_first_sodesc = sodesc;
1184*b2ed49a5SDavid van Moolenbroek     }
1185*b2ed49a5SDavid van Moolenbroek     MAGIC_SODESC_PREV(sodesc) = _magic_last_sodesc;
1186*b2ed49a5SDavid van Moolenbroek     MAGIC_SODESC_NEXT(sodesc) = NULL;
1187*b2ed49a5SDavid van Moolenbroek     _magic_last_sodesc = sodesc;
1188*b2ed49a5SDavid van Moolenbroek     _magic_sodescs_num++;
1189*b2ed49a5SDavid van Moolenbroek 
1190*b2ed49a5SDavid van Moolenbroek     return 0;
1191*b2ed49a5SDavid van Moolenbroek }
1192*b2ed49a5SDavid van Moolenbroek 
1193*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1194*b2ed49a5SDavid van Moolenbroek  *                          magic_destroy_sodesc                             *
1195*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_destroy_sodesc(struct _magic_sodesc * sodesc)1196*b2ed49a5SDavid van Moolenbroek PUBLIC int magic_destroy_sodesc(struct _magic_sodesc *sodesc)
1197*b2ed49a5SDavid van Moolenbroek {
1198*b2ed49a5SDavid van Moolenbroek     /*
1199*b2ed49a5SDavid van Moolenbroek      * NB!: This function requires the calling thread to already
1200*b2ed49a5SDavid van Moolenbroek      * hold the DSENTRY and DFUNCTION locks.
1201*b2ed49a5SDavid van Moolenbroek      */
1202*b2ed49a5SDavid van Moolenbroek     int ret;
1203*b2ed49a5SDavid van Moolenbroek     const char *name;
1204*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *prev_dsentry, *dsentry, *last_dsentry;
1205*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *sentry;
1206*b2ed49a5SDavid van Moolenbroek     struct _magic_dfunction *dfunction, *last_dfunction;
1207*b2ed49a5SDavid van Moolenbroek 
1208*b2ed49a5SDavid van Moolenbroek     /*
1209*b2ed49a5SDavid van Moolenbroek      * Time to destroy all the dsentries and dfunctions
1210*b2ed49a5SDavid van Moolenbroek      * linked to the descriptor.
1211*b2ed49a5SDavid van Moolenbroek      */
1212*b2ed49a5SDavid van Moolenbroek     name = sodesc->lib.name;
1213*b2ed49a5SDavid van Moolenbroek     last_dsentry = NULL;
1214*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_ALIVE_ITER(_magic_first_dsentry, prev_dsentry,
1215*b2ed49a5SDavid van Moolenbroek         dsentry, sentry,
1216*b2ed49a5SDavid van Moolenbroek         if (last_dsentry)
1217*b2ed49a5SDavid van Moolenbroek             magic_destroy_dsentry(last_dsentry, NULL);
1218*b2ed49a5SDavid van Moolenbroek         last_dsentry = dsentry->parent_name == name ? dsentry : NULL;
1219*b2ed49a5SDavid van Moolenbroek     );
1220*b2ed49a5SDavid van Moolenbroek     if (last_dsentry)
1221*b2ed49a5SDavid van Moolenbroek         magic_destroy_dsentry(last_dsentry, NULL);
1222*b2ed49a5SDavid van Moolenbroek     last_dfunction = NULL;
1223*b2ed49a5SDavid van Moolenbroek     MAGIC_DFUNCTION_ITER(_magic_first_dfunction, dfunction,
1224*b2ed49a5SDavid van Moolenbroek         if (last_dfunction)
1225*b2ed49a5SDavid van Moolenbroek             magic_destroy_dfunction(last_dfunction);
1226*b2ed49a5SDavid van Moolenbroek         last_dfunction = dfunction->parent_name == name ? dfunction : NULL;
1227*b2ed49a5SDavid van Moolenbroek     );
1228*b2ed49a5SDavid van Moolenbroek     if(last_dfunction) magic_destroy_dfunction(last_dfunction);
1229*b2ed49a5SDavid van Moolenbroek 
1230*b2ed49a5SDavid van Moolenbroek     /* Now get rid of the descriptor. */
1231*b2ed49a5SDavid van Moolenbroek     if (MAGIC_SODESC_HAS_NEXT(sodesc)) {
1232*b2ed49a5SDavid van Moolenbroek         MAGIC_SODESC_PREV(MAGIC_SODESC_NEXT(sodesc)) =
1233*b2ed49a5SDavid van Moolenbroek             MAGIC_SODESC_PREV(sodesc);
1234*b2ed49a5SDavid van Moolenbroek     }
1235*b2ed49a5SDavid van Moolenbroek     else {
1236*b2ed49a5SDavid van Moolenbroek         _magic_last_sodesc = MAGIC_SODESC_PREV(sodesc);
1237*b2ed49a5SDavid van Moolenbroek     }
1238*b2ed49a5SDavid van Moolenbroek     if (MAGIC_SODESC_HAS_PREV(sodesc)) {
1239*b2ed49a5SDavid van Moolenbroek         MAGIC_SODESC_NEXT(MAGIC_SODESC_PREV(sodesc)) =
1240*b2ed49a5SDavid van Moolenbroek             MAGIC_SODESC_NEXT(sodesc);
1241*b2ed49a5SDavid van Moolenbroek     }
1242*b2ed49a5SDavid van Moolenbroek     else {
1243*b2ed49a5SDavid van Moolenbroek         _magic_first_sodesc = MAGIC_SODESC_NEXT(sodesc);
1244*b2ed49a5SDavid van Moolenbroek     }
1245*b2ed49a5SDavid van Moolenbroek     MAGIC_SODESC_NEXT(sodesc) = NULL;
1246*b2ed49a5SDavid van Moolenbroek     MAGIC_SODESC_PREV(sodesc) = NULL;
1247*b2ed49a5SDavid van Moolenbroek     _magic_sodescs_num--;
1248*b2ed49a5SDavid van Moolenbroek     if (_magic_sodescs_num == 0) {
1249*b2ed49a5SDavid van Moolenbroek         assert(!_magic_first_sodesc && !_magic_last_sodesc);
1250*b2ed49a5SDavid van Moolenbroek     }
1251*b2ed49a5SDavid van Moolenbroek     else {
1252*b2ed49a5SDavid van Moolenbroek         assert(_magic_first_sodesc && _magic_last_sodesc);
1253*b2ed49a5SDavid van Moolenbroek     }
1254*b2ed49a5SDavid van Moolenbroek 
1255*b2ed49a5SDavid van Moolenbroek     /*
1256*b2ed49a5SDavid van Moolenbroek      * Unmap the memory area that contained the dsentries and dfunctions
1257*b2ed49a5SDavid van Moolenbroek      * of this descriptor.
1258*b2ed49a5SDavid van Moolenbroek      */
1259*b2ed49a5SDavid van Moolenbroek     ret = munmap(sodesc->lib.alloc_address, sodesc->lib.alloc_size);
1260*b2ed49a5SDavid van Moolenbroek     assert(ret == 0 && "Unable to unmap SODESC memory segment!");
1261*b2ed49a5SDavid van Moolenbroek 
1262*b2ed49a5SDavid van Moolenbroek     return 0;
1263*b2ed49a5SDavid van Moolenbroek }
1264*b2ed49a5SDavid van Moolenbroek 
1265*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1266*b2ed49a5SDavid van Moolenbroek  *                          magic_create_dsodesc                             *
1267*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_create_dsodesc(struct _magic_dsodesc * dsodesc)1268*b2ed49a5SDavid van Moolenbroek PUBLIC int magic_create_dsodesc(struct _magic_dsodesc *dsodesc)
1269*b2ed49a5SDavid van Moolenbroek {
1270*b2ed49a5SDavid van Moolenbroek     /*
1271*b2ed49a5SDavid van Moolenbroek      * NB!: This function requires the calling thread to already
1272*b2ed49a5SDavid van Moolenbroek      * hold the DSODESC lock.
1273*b2ed49a5SDavid van Moolenbroek      */
1274*b2ed49a5SDavid van Moolenbroek     if (_magic_first_dsodesc) {
1275*b2ed49a5SDavid van Moolenbroek         assert(_magic_last_dsodesc);
1276*b2ed49a5SDavid van Moolenbroek         MAGIC_DSODESC_NEXT(_magic_last_dsodesc) = dsodesc;
1277*b2ed49a5SDavid van Moolenbroek     }
1278*b2ed49a5SDavid van Moolenbroek     else {
1279*b2ed49a5SDavid van Moolenbroek         assert(!_magic_last_dsodesc);
1280*b2ed49a5SDavid van Moolenbroek         assert(_magic_dsodescs_num == 0);
1281*b2ed49a5SDavid van Moolenbroek         _magic_first_dsodesc = dsodesc;
1282*b2ed49a5SDavid van Moolenbroek     }
1283*b2ed49a5SDavid van Moolenbroek     MAGIC_DSODESC_PREV(dsodesc) = _magic_last_dsodesc;
1284*b2ed49a5SDavid van Moolenbroek     MAGIC_DSODESC_NEXT(dsodesc) = NULL;
1285*b2ed49a5SDavid van Moolenbroek     _magic_last_dsodesc = dsodesc;
1286*b2ed49a5SDavid van Moolenbroek     _magic_dsodescs_num++;
1287*b2ed49a5SDavid van Moolenbroek 
1288*b2ed49a5SDavid van Moolenbroek     return 0;
1289*b2ed49a5SDavid van Moolenbroek }
1290*b2ed49a5SDavid van Moolenbroek 
1291*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1292*b2ed49a5SDavid van Moolenbroek  *                          magic_destroy_dsodesc                            *
1293*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_destroy_dsodesc(struct _magic_dsodesc * dsodesc)1294*b2ed49a5SDavid van Moolenbroek PUBLIC int magic_destroy_dsodesc(struct _magic_dsodesc *dsodesc)
1295*b2ed49a5SDavid van Moolenbroek {
1296*b2ed49a5SDavid van Moolenbroek     /*
1297*b2ed49a5SDavid van Moolenbroek      * NB!: This function requires the calling thread to already
1298*b2ed49a5SDavid van Moolenbroek      * hold the DSENTRY, DFUNCTION and DSODESC locks.
1299*b2ed49a5SDavid van Moolenbroek      */
1300*b2ed49a5SDavid van Moolenbroek     int ret;
1301*b2ed49a5SDavid van Moolenbroek     const char *name;
1302*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *prev_dsentry, *dsentry, *last_dsentry;
1303*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *sentry;
1304*b2ed49a5SDavid van Moolenbroek     struct _magic_dfunction *dfunction, *last_dfunction;
1305*b2ed49a5SDavid van Moolenbroek 
1306*b2ed49a5SDavid van Moolenbroek     dsodesc->ref_count--;
1307*b2ed49a5SDavid van Moolenbroek     /* Don't destroy the DSO descriptor quite yet, we still have references. */
1308*b2ed49a5SDavid van Moolenbroek     if (dsodesc->ref_count > 0) {
1309*b2ed49a5SDavid van Moolenbroek         return dsodesc->ref_count;
1310*b2ed49a5SDavid van Moolenbroek     }
1311*b2ed49a5SDavid van Moolenbroek 
1312*b2ed49a5SDavid van Moolenbroek     /*
1313*b2ed49a5SDavid van Moolenbroek      * Time to destroy all the dsentries and dfunctions
1314*b2ed49a5SDavid van Moolenbroek      * linked to the descriptor.
1315*b2ed49a5SDavid van Moolenbroek      */
1316*b2ed49a5SDavid van Moolenbroek     name = dsodesc->lib.name;
1317*b2ed49a5SDavid van Moolenbroek     last_dsentry = NULL;
1318*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_ALIVE_ITER(_magic_first_dsentry, prev_dsentry,
1319*b2ed49a5SDavid van Moolenbroek         dsentry, sentry,
1320*b2ed49a5SDavid van Moolenbroek         if (last_dsentry)
1321*b2ed49a5SDavid van Moolenbroek             magic_destroy_dsentry(last_dsentry, NULL);
1322*b2ed49a5SDavid van Moolenbroek         last_dsentry = dsentry->parent_name == name ? dsentry : NULL;
1323*b2ed49a5SDavid van Moolenbroek     );
1324*b2ed49a5SDavid van Moolenbroek     if (last_dsentry)
1325*b2ed49a5SDavid van Moolenbroek         magic_destroy_dsentry(last_dsentry, NULL);
1326*b2ed49a5SDavid van Moolenbroek     last_dfunction = NULL;
1327*b2ed49a5SDavid van Moolenbroek     MAGIC_DFUNCTION_ITER(_magic_first_dfunction, dfunction,
1328*b2ed49a5SDavid van Moolenbroek         if (last_dfunction)
1329*b2ed49a5SDavid van Moolenbroek             magic_destroy_dfunction(last_dfunction);
1330*b2ed49a5SDavid van Moolenbroek         last_dfunction = dfunction->parent_name == name ? dfunction : NULL;
1331*b2ed49a5SDavid van Moolenbroek     );
1332*b2ed49a5SDavid van Moolenbroek     if (last_dfunction)
1333*b2ed49a5SDavid van Moolenbroek         magic_destroy_dfunction(last_dfunction);
1334*b2ed49a5SDavid van Moolenbroek 
1335*b2ed49a5SDavid van Moolenbroek     /* Now get rid of the descriptor. */
1336*b2ed49a5SDavid van Moolenbroek     if (MAGIC_DSODESC_HAS_NEXT(dsodesc)) {
1337*b2ed49a5SDavid van Moolenbroek         MAGIC_DSODESC_PREV(MAGIC_DSODESC_NEXT(dsodesc)) =
1338*b2ed49a5SDavid van Moolenbroek             MAGIC_DSODESC_PREV(dsodesc);
1339*b2ed49a5SDavid van Moolenbroek     }
1340*b2ed49a5SDavid van Moolenbroek     else {
1341*b2ed49a5SDavid van Moolenbroek         _magic_last_dsodesc = MAGIC_DSODESC_PREV(dsodesc);
1342*b2ed49a5SDavid van Moolenbroek     }
1343*b2ed49a5SDavid van Moolenbroek     if (MAGIC_DSODESC_HAS_PREV(dsodesc)) {
1344*b2ed49a5SDavid van Moolenbroek         MAGIC_DSODESC_NEXT(MAGIC_DSODESC_PREV(dsodesc)) =
1345*b2ed49a5SDavid van Moolenbroek             MAGIC_DSODESC_NEXT(dsodesc);
1346*b2ed49a5SDavid van Moolenbroek     }
1347*b2ed49a5SDavid van Moolenbroek     else {
1348*b2ed49a5SDavid van Moolenbroek         _magic_first_dsodesc = MAGIC_DSODESC_NEXT(dsodesc);
1349*b2ed49a5SDavid van Moolenbroek     }
1350*b2ed49a5SDavid van Moolenbroek     MAGIC_DSODESC_NEXT(dsodesc) = NULL;
1351*b2ed49a5SDavid van Moolenbroek     MAGIC_DSODESC_PREV(dsodesc) = NULL;
1352*b2ed49a5SDavid van Moolenbroek     _magic_dsodescs_num--;
1353*b2ed49a5SDavid van Moolenbroek     if (_magic_dsodescs_num == 0) {
1354*b2ed49a5SDavid van Moolenbroek         assert(!_magic_first_dsodesc && !_magic_last_dsodesc);
1355*b2ed49a5SDavid van Moolenbroek     }
1356*b2ed49a5SDavid van Moolenbroek     else {
1357*b2ed49a5SDavid van Moolenbroek         assert(_magic_first_dsodesc && _magic_last_dsodesc);
1358*b2ed49a5SDavid van Moolenbroek     }
1359*b2ed49a5SDavid van Moolenbroek 
1360*b2ed49a5SDavid van Moolenbroek     /*
1361*b2ed49a5SDavid van Moolenbroek      * Unmap the memory area that contained the dsentries and dfunctions
1362*b2ed49a5SDavid van Moolenbroek      * of this descriptor.
1363*b2ed49a5SDavid van Moolenbroek      */
1364*b2ed49a5SDavid van Moolenbroek     ret = munmap(dsodesc->lib.alloc_address, dsodesc->lib.alloc_size);
1365*b2ed49a5SDavid van Moolenbroek     assert(ret == 0 && "Unable to unmap DSODESC memory segment!");
1366*b2ed49a5SDavid van Moolenbroek 
1367*b2ed49a5SDavid van Moolenbroek     return 0; /* no more references, descriptor is gone. */
1368*b2ed49a5SDavid van Moolenbroek }
1369*b2ed49a5SDavid van Moolenbroek 
1370*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1371*b2ed49a5SDavid van Moolenbroek  *                              magic_alloc                                  *
1372*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_alloc(__MA_ARGS__ void * ptr,size_t size,int flags)1373*b2ed49a5SDavid van Moolenbroek PUBLIC void *magic_alloc(__MA_ARGS__ void *ptr, size_t size, int flags)
1374*b2ed49a5SDavid van Moolenbroek {
1375*b2ed49a5SDavid van Moolenbroek     int ret;
1376*b2ed49a5SDavid van Moolenbroek     void *data_ptr;
1377*b2ed49a5SDavid van Moolenbroek     struct _magic_dsentry *dsentry;
1378*b2ed49a5SDavid van Moolenbroek 
1379*b2ed49a5SDavid van Moolenbroek     if(ptr == NULL) {
1380*b2ed49a5SDavid van Moolenbroek         return NULL;
1381*b2ed49a5SDavid van Moolenbroek     }
1382*b2ed49a5SDavid van Moolenbroek     data_ptr = MAGIC_PTR_TO_DATA(ptr);
1383*b2ed49a5SDavid van Moolenbroek     dsentry = MAGIC_PTR_TO_DSENTRY(ptr);
1384*b2ed49a5SDavid van Moolenbroek     /* Catch pool allocations and update the name & flags */
1385*b2ed49a5SDavid van Moolenbroek     if (MAGIC_MEMPOOL_MGMT_IS_ACTIVE() && !(flags & MAGIC_STATE_MEMBLOCK)) {
1386*b2ed49a5SDavid van Moolenbroek         flags |= MAGIC_STATE_MEMPOOL;
1387*b2ed49a5SDavid van Moolenbroek         name = MAGIC_MEMPOOL_GET_NAME();
1388*b2ed49a5SDavid van Moolenbroek     }
1389*b2ed49a5SDavid van Moolenbroek     ret = magic_create_dsentry(dsentry, data_ptr, type, size, flags, name, parent_name);
1390*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_PRINTF("magic_alloc: ret = magic_create_dsentry(dsentry, data_ptr, type, size, flags, NULL, NULL) <-> %d = magic_create_dsentry(0x%08x, 0x%08x, 0x%08x, %d, 0x%08x, NULL, NULL)\n", ret, (unsigned) dsentry, (unsigned) data_ptr, type, size, flags);
1391*b2ed49a5SDavid van Moolenbroek     if(ret < 0) {
1392*b2ed49a5SDavid van Moolenbroek         return MAGIC_MEM_FAILED;
1393*b2ed49a5SDavid van Moolenbroek     }
1394*b2ed49a5SDavid van Moolenbroek 
1395*b2ed49a5SDavid van Moolenbroek     /* this way we skip the memory pool blocks -they are not real allocations and should not be logged */
1396*b2ed49a5SDavid van Moolenbroek     if (!(flags & MAGIC_STATE_MEMBLOCK)) {
1397*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_DEBUG_ALLOC(ptr, (MAGIC_SIZE_TO_REAL(size)));
1398*b2ed49a5SDavid van Moolenbroek     }
1399*b2ed49a5SDavid van Moolenbroek 
1400*b2ed49a5SDavid van Moolenbroek #if DEBUG
1401*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_PRINTF("magic_alloc: magic_create_dsentry created sentry: ");
1402*b2ed49a5SDavid van Moolenbroek     MAGIC_DSENTRY_PRINT(dsentry, MAGIC_EXPAND_TYPE_STR);
1403*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_PRINTF("\n");
1404*b2ed49a5SDavid van Moolenbroek #endif
1405*b2ed49a5SDavid van Moolenbroek 
1406*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_PRINTF("magic_alloc: return 0x%08x\n", (unsigned) data_ptr);
1407*b2ed49a5SDavid van Moolenbroek 
1408*b2ed49a5SDavid van Moolenbroek     return data_ptr;
1409*b2ed49a5SDavid van Moolenbroek }
1410*b2ed49a5SDavid van Moolenbroek 
1411*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1412*b2ed49a5SDavid van Moolenbroek  *                           magic_malloc_positioned                         *
1413*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_malloc_positioned(__MA_ARGS__ size_t size,void * ptr)1414*b2ed49a5SDavid van Moolenbroek PUBLIC void *magic_malloc_positioned(__MA_ARGS__ size_t size, void *ptr)
1415*b2ed49a5SDavid van Moolenbroek {
1416*b2ed49a5SDavid van Moolenbroek     void *data_ptr;
1417*b2ed49a5SDavid van Moolenbroek     int dsentry_flags = MAGIC_STATE_HEAP;
1418*b2ed49a5SDavid van Moolenbroek 
1419*b2ed49a5SDavid van Moolenbroek #if MAGIC_FORCE_DYN_MEM_ZERO_INIT
1420*b2ed49a5SDavid van Moolenbroek     assert(!_magic_vars->fake_malloc);
1421*b2ed49a5SDavid van Moolenbroek     do {
1422*b2ed49a5SDavid van Moolenbroek         return magic_calloc(__MA_VALUES__ size, 1);
1423*b2ed49a5SDavid van Moolenbroek     } while(0);
1424*b2ed49a5SDavid van Moolenbroek #endif
1425*b2ed49a5SDavid van Moolenbroek 
1426*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_BEGIN();
1427*b2ed49a5SDavid van Moolenbroek 
1428*b2ed49a5SDavid van Moolenbroek     if(size > 0) {
1429*b2ed49a5SDavid van Moolenbroek         if (!ptr || !_magic_vars->fake_malloc) {
1430*b2ed49a5SDavid van Moolenbroek             /*
1431*b2ed49a5SDavid van Moolenbroek              * Check the external callback first.
1432*b2ed49a5SDavid van Moolenbroek              */
1433*b2ed49a5SDavid van Moolenbroek             if (magic_mem_heap_alloc_cb)
1434*b2ed49a5SDavid van Moolenbroek                 ptr = magic_mem_heap_alloc_cb(MAGIC_SIZE_TO_REAL(size) + magic_asr_get_padding_size(MAGIC_STATE_HEAP), name, parent_name);
1435*b2ed49a5SDavid van Moolenbroek 
1436*b2ed49a5SDavid van Moolenbroek             if (!ptr)
1437*b2ed49a5SDavid van Moolenbroek                 ptr = malloc(MAGIC_SIZE_TO_REAL(size) + magic_asr_get_padding_size(MAGIC_STATE_HEAP));
1438*b2ed49a5SDavid van Moolenbroek             MAGIC_MEM_PRINTF("magic_malloc: ptr = malloc(size) <-> 0x%08x = malloc(%d)\n", (unsigned) ptr, MAGIC_SIZE_TO_REAL(size));
1439*b2ed49a5SDavid van Moolenbroek         }
1440*b2ed49a5SDavid van Moolenbroek         data_ptr = magic_alloc(__MA_VALUES__ ptr, size, dsentry_flags);
1441*b2ed49a5SDavid van Moolenbroek         if (data_ptr == MAGIC_MEM_FAILED) {
1442*b2ed49a5SDavid van Moolenbroek             /*
1443*b2ed49a5SDavid van Moolenbroek              * XXX: This doesn't seem likely to happen. However, if it does,
1444*b2ed49a5SDavid van Moolenbroek              * we need to distinguish between regular malloc() memory
1445*b2ed49a5SDavid van Moolenbroek              * and super-objects. See llvm/shared/libst/include/heap.h for
1446*b2ed49a5SDavid van Moolenbroek              * more information.
1447*b2ed49a5SDavid van Moolenbroek              */
1448*b2ed49a5SDavid van Moolenbroek             free(ptr);
1449*b2ed49a5SDavid van Moolenbroek             data_ptr = NULL;
1450*b2ed49a5SDavid van Moolenbroek             errno = ENOMEM;
1451*b2ed49a5SDavid van Moolenbroek         }
1452*b2ed49a5SDavid van Moolenbroek         magic_heap_end = ((char *)sbrk(0)) - 1;
1453*b2ed49a5SDavid van Moolenbroek     }
1454*b2ed49a5SDavid van Moolenbroek     else {
1455*b2ed49a5SDavid van Moolenbroek         data_ptr = NULL;
1456*b2ed49a5SDavid van Moolenbroek     }
1457*b2ed49a5SDavid van Moolenbroek 
1458*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_END();
1459*b2ed49a5SDavid van Moolenbroek 
1460*b2ed49a5SDavid van Moolenbroek     return data_ptr;
1461*b2ed49a5SDavid van Moolenbroek }
1462*b2ed49a5SDavid van Moolenbroek 
1463*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1464*b2ed49a5SDavid van Moolenbroek  *                               magic_malloc                                *
1465*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_malloc(__MA_ARGS__ size_t size)1466*b2ed49a5SDavid van Moolenbroek PUBLIC void *magic_malloc(__MA_ARGS__ size_t size)
1467*b2ed49a5SDavid van Moolenbroek {
1468*b2ed49a5SDavid van Moolenbroek     return magic_malloc_positioned(__MA_VALUES__ size, NULL);
1469*b2ed49a5SDavid van Moolenbroek }
1470*b2ed49a5SDavid van Moolenbroek 
1471*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1472*b2ed49a5SDavid van Moolenbroek  *                               magic_calloc                                *
1473*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_calloc(__MA_ARGS__ size_t nmemb,size_t size)1474*b2ed49a5SDavid van Moolenbroek PUBLIC void *magic_calloc(__MA_ARGS__ size_t nmemb, size_t size)
1475*b2ed49a5SDavid van Moolenbroek {
1476*b2ed49a5SDavid van Moolenbroek     void *ptr = NULL, *data_ptr;
1477*b2ed49a5SDavid van Moolenbroek     size_t real_size;
1478*b2ed49a5SDavid van Moolenbroek     int dsentry_flags = MAGIC_STATE_HEAP;
1479*b2ed49a5SDavid van Moolenbroek 
1480*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_BEGIN();
1481*b2ed49a5SDavid van Moolenbroek 
1482*b2ed49a5SDavid van Moolenbroek     if(size > 0) {
1483*b2ed49a5SDavid van Moolenbroek         real_size = MAGIC_SIZE_TO_REAL(size*nmemb);
1484*b2ed49a5SDavid van Moolenbroek         /*
1485*b2ed49a5SDavid van Moolenbroek          * Check the external callback first.
1486*b2ed49a5SDavid van Moolenbroek          */
1487*b2ed49a5SDavid van Moolenbroek         if (magic_mem_heap_alloc_cb)
1488*b2ed49a5SDavid van Moolenbroek             ptr = magic_mem_heap_alloc_cb(real_size + magic_asr_get_padding_size(MAGIC_STATE_HEAP), name, parent_name);
1489*b2ed49a5SDavid van Moolenbroek 
1490*b2ed49a5SDavid van Moolenbroek         if (!ptr)
1491*b2ed49a5SDavid van Moolenbroek             ptr = calloc(real_size + magic_asr_get_padding_size(MAGIC_STATE_HEAP), 1);
1492*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_PRINTF("magic_calloc: ptr = calloc(nmemb, size) <-> 0x%08x = calloc(%d, %d)\n", (unsigned) ptr, nmemb, real_size);
1493*b2ed49a5SDavid van Moolenbroek         data_ptr = magic_alloc(__MA_VALUES__ ptr, size*nmemb, dsentry_flags);
1494*b2ed49a5SDavid van Moolenbroek         if(data_ptr == MAGIC_MEM_FAILED) {
1495*b2ed49a5SDavid van Moolenbroek             /*
1496*b2ed49a5SDavid van Moolenbroek              * XXX: This doesn't seem likely to happen. However, if it does,
1497*b2ed49a5SDavid van Moolenbroek              * we need to distinguish between regular malloc() memory
1498*b2ed49a5SDavid van Moolenbroek              * and super-objects. See llvm/shared/libst/include/heap.h for
1499*b2ed49a5SDavid van Moolenbroek              * more information.
1500*b2ed49a5SDavid van Moolenbroek              */
1501*b2ed49a5SDavid van Moolenbroek             free(ptr);
1502*b2ed49a5SDavid van Moolenbroek             data_ptr = NULL;
1503*b2ed49a5SDavid van Moolenbroek             errno = ENOMEM;
1504*b2ed49a5SDavid van Moolenbroek         }
1505*b2ed49a5SDavid van Moolenbroek         magic_heap_end = ((char*)sbrk(0))-1;
1506*b2ed49a5SDavid van Moolenbroek     }
1507*b2ed49a5SDavid van Moolenbroek     else {
1508*b2ed49a5SDavid van Moolenbroek         data_ptr = NULL;
1509*b2ed49a5SDavid van Moolenbroek     }
1510*b2ed49a5SDavid van Moolenbroek 
1511*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_END();
1512*b2ed49a5SDavid van Moolenbroek 
1513*b2ed49a5SDavid van Moolenbroek     return data_ptr;
1514*b2ed49a5SDavid van Moolenbroek }
1515*b2ed49a5SDavid van Moolenbroek 
1516*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1517*b2ed49a5SDavid van Moolenbroek  *                                magic_free                                 *
1518*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_free(__MD_ARGS__ void * data_ptr)1519*b2ed49a5SDavid van Moolenbroek PUBLIC void magic_free(__MD_ARGS__ void *data_ptr)
1520*b2ed49a5SDavid van Moolenbroek {
1521*b2ed49a5SDavid van Moolenbroek     void *ptr;
1522*b2ed49a5SDavid van Moolenbroek     int ret;
1523*b2ed49a5SDavid van Moolenbroek 
1524*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_BEGIN();
1525*b2ed49a5SDavid van Moolenbroek 
1526*b2ed49a5SDavid van Moolenbroek     if(data_ptr) {
1527*b2ed49a5SDavid van Moolenbroek         ptr = MAGIC_PTR_FROM_DATA(data_ptr);
1528*b2ed49a5SDavid van Moolenbroek 
1529*b2ed49a5SDavid van Moolenbroek         /* Check for legitimate non-indexed chunks of memory and skip. */
1530*b2ed49a5SDavid van Moolenbroek         if((!magic_libcommon_active || !MAGIC_USE_DYN_MEM_WRAPPERS)
1531*b2ed49a5SDavid van Moolenbroek             && !MAGIC_DSENTRY_MNUM_OK(MAGIC_PTR_TO_DSENTRY(ptr))) {
1532*b2ed49a5SDavid van Moolenbroek             MAGIC_MEM_WRAPPER_END();
1533*b2ed49a5SDavid van Moolenbroek             free(data_ptr);
1534*b2ed49a5SDavid van Moolenbroek             return;
1535*b2ed49a5SDavid van Moolenbroek         }
1536*b2ed49a5SDavid van Moolenbroek 
1537*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_PRINTF("magic_free: magic_free(0x%08x) / free(0x%08x)\n", (unsigned) data_ptr, (unsigned) ptr);
1538*b2ed49a5SDavid van Moolenbroek         assert(magic_check_dsentry(MAGIC_PTR_TO_DSENTRY(ptr), MAGIC_STATE_HEAP) && "XXX Bad magic dsentry: corruption or memory not allocated from a magic wrapper?");
1539*b2ed49a5SDavid van Moolenbroek 
1540*b2ed49a5SDavid van Moolenbroek         if(magic_allow_dead_dsentries) {
1541*b2ed49a5SDavid van Moolenbroek             ret = magic_update_dsentry_state(MAGIC_PTR_TO_DSENTRY(ptr), MAGIC_DSENTRY_MSTATE_DEAD);
1542*b2ed49a5SDavid van Moolenbroek             assert(ret == 0 && "Bad free!");
1543*b2ed49a5SDavid van Moolenbroek         }
1544*b2ed49a5SDavid van Moolenbroek         else {
1545*b2ed49a5SDavid van Moolenbroek             MAGIC_DSENTRY_LOCK();
1546*b2ed49a5SDavid van Moolenbroek             magic_destroy_dsentry(MAGIC_PTR_TO_DSENTRY(ptr), NULL);
1547*b2ed49a5SDavid van Moolenbroek             ret = magic_free_dsentry(MAGIC_PTR_TO_DSENTRY(ptr));
1548*b2ed49a5SDavid van Moolenbroek             assert(ret == 0 && "Bad free!");
1549*b2ed49a5SDavid van Moolenbroek             MAGIC_DSENTRY_UNLOCK();
1550*b2ed49a5SDavid van Moolenbroek         }
1551*b2ed49a5SDavid van Moolenbroek     }
1552*b2ed49a5SDavid van Moolenbroek 
1553*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_END();
1554*b2ed49a5SDavid van Moolenbroek }
1555*b2ed49a5SDavid van Moolenbroek 
1556*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1557*b2ed49a5SDavid van Moolenbroek  *                              magic_realloc                                *
1558*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_realloc(__MA_ARGS__ void * data_ptr,size_t size)1559*b2ed49a5SDavid van Moolenbroek PUBLIC void *magic_realloc(__MA_ARGS__ void *data_ptr, size_t size)
1560*b2ed49a5SDavid van Moolenbroek {
1561*b2ed49a5SDavid van Moolenbroek     void *ptr, *new_ptr, *new_data_ptr;
1562*b2ed49a5SDavid van Moolenbroek     size_t old_size;
1563*b2ed49a5SDavid van Moolenbroek 
1564*b2ed49a5SDavid van Moolenbroek     if(!data_ptr) {
1565*b2ed49a5SDavid van Moolenbroek         return magic_malloc(__MA_VALUES__ size);
1566*b2ed49a5SDavid van Moolenbroek     }
1567*b2ed49a5SDavid van Moolenbroek     if(size == 0) {
1568*b2ed49a5SDavid van Moolenbroek         magic_free(__MD_VALUES_DEFAULT__ data_ptr);
1569*b2ed49a5SDavid van Moolenbroek         return NULL;
1570*b2ed49a5SDavid van Moolenbroek     }
1571*b2ed49a5SDavid van Moolenbroek 
1572*b2ed49a5SDavid van Moolenbroek     ptr = MAGIC_PTR_FROM_DATA(data_ptr);
1573*b2ed49a5SDavid van Moolenbroek     new_data_ptr = magic_malloc(__MA_VALUES__ size);
1574*b2ed49a5SDavid van Moolenbroek     if(!new_data_ptr) {
1575*b2ed49a5SDavid van Moolenbroek         return NULL;
1576*b2ed49a5SDavid van Moolenbroek     }
1577*b2ed49a5SDavid van Moolenbroek     new_ptr = MAGIC_PTR_FROM_DATA(new_data_ptr);
1578*b2ed49a5SDavid van Moolenbroek     assert(magic_check_dsentry(MAGIC_PTR_TO_DSENTRY(ptr), MAGIC_STATE_HEAP) && "XXX Bad magic dsentry: corruption or memory not allocated from a magic wrapper?");
1579*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_PRINTF("magic_realloc: ptr = realloc(ptr, size) <-> 0x%08x = realloc(0x%08x, %d)\n", (unsigned) new_ptr, (unsigned) ptr, MAGIC_SIZE_TO_REAL(size));
1580*b2ed49a5SDavid van Moolenbroek 
1581*b2ed49a5SDavid van Moolenbroek     old_size = MAGIC_DSENTRY_TO_SENTRY(MAGIC_PTR_TO_DSENTRY(ptr))->type->size;
1582*b2ed49a5SDavid van Moolenbroek     memcpy(new_data_ptr, data_ptr, old_size < size ? old_size : size);
1583*b2ed49a5SDavid van Moolenbroek     magic_free(__MD_VALUES_DEFAULT__ data_ptr);
1584*b2ed49a5SDavid van Moolenbroek 
1585*b2ed49a5SDavid van Moolenbroek     return new_data_ptr;
1586*b2ed49a5SDavid van Moolenbroek }
1587*b2ed49a5SDavid van Moolenbroek 
1588*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1589*b2ed49a5SDavid van Moolenbroek  *                           magic_posix_memalign                            *
1590*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_posix_memalign(__MA_ARGS__ void ** memptr,size_t alignment,size_t size)1591*b2ed49a5SDavid van Moolenbroek PUBLIC int magic_posix_memalign(__MA_ARGS__ void **memptr, size_t alignment, size_t size)
1592*b2ed49a5SDavid van Moolenbroek {
1593*b2ed49a5SDavid van Moolenbroek     int ret = 0;
1594*b2ed49a5SDavid van Moolenbroek     void *ptr = NULL, *data_ptr;
1595*b2ed49a5SDavid van Moolenbroek     int dsentry_flags = MAGIC_STATE_HEAP;
1596*b2ed49a5SDavid van Moolenbroek 
1597*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_BEGIN();
1598*b2ed49a5SDavid van Moolenbroek 
1599*b2ed49a5SDavid van Moolenbroek     if(size > 0) {
1600*b2ed49a5SDavid van Moolenbroek         /*
1601*b2ed49a5SDavid van Moolenbroek          * Check the external callback first.
1602*b2ed49a5SDavid van Moolenbroek          */
1603*b2ed49a5SDavid van Moolenbroek         if (magic_mem_heap_alloc_cb)
1604*b2ed49a5SDavid van Moolenbroek             ptr = magic_mem_heap_alloc_cb(MAGIC_SIZE_TO_REAL(size), name, parent_name);
1605*b2ed49a5SDavid van Moolenbroek 
1606*b2ed49a5SDavid van Moolenbroek         if (!ptr)
1607*b2ed49a5SDavid van Moolenbroek             ret = posix_memalign(&ptr, alignment, MAGIC_SIZE_TO_REAL(size));
1608*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_PRINTF("magic_posix_memalign: ret = posix_memalign(ptr, alignment, size) <-> %d = posix_memalign(%p, %d, %d)\n", ret, ptr, alignment, MAGIC_SIZE_TO_REAL(size));
1609*b2ed49a5SDavid van Moolenbroek         if(ret == 0) {
1610*b2ed49a5SDavid van Moolenbroek             data_ptr = magic_alloc(__MA_VALUES__ ptr, size, dsentry_flags);
1611*b2ed49a5SDavid van Moolenbroek             if(data_ptr == MAGIC_MEM_FAILED) {
1612*b2ed49a5SDavid van Moolenbroek                 /*
1613*b2ed49a5SDavid van Moolenbroek                  * XXX: This doesn't seem likely to happen. However, if it does,
1614*b2ed49a5SDavid van Moolenbroek                  * we need to distinguish between regular malloc() memory
1615*b2ed49a5SDavid van Moolenbroek                  * and super-objects. See llvm/shared/libst/include/heap.h for
1616*b2ed49a5SDavid van Moolenbroek                  * more information.
1617*b2ed49a5SDavid van Moolenbroek                  */
1618*b2ed49a5SDavid van Moolenbroek                 free(ptr);
1619*b2ed49a5SDavid van Moolenbroek                 ret = ENOMEM;
1620*b2ed49a5SDavid van Moolenbroek             }
1621*b2ed49a5SDavid van Moolenbroek             else {
1622*b2ed49a5SDavid van Moolenbroek                 *memptr = data_ptr;
1623*b2ed49a5SDavid van Moolenbroek #if MAGIC_FORCE_DYN_MEM_ZERO_INIT
1624*b2ed49a5SDavid van Moolenbroek                 memset(data_ptr, 0, size);
1625*b2ed49a5SDavid van Moolenbroek #endif
1626*b2ed49a5SDavid van Moolenbroek             }
1627*b2ed49a5SDavid van Moolenbroek             magic_heap_end = ((char*)sbrk(0))-1;
1628*b2ed49a5SDavid van Moolenbroek         }
1629*b2ed49a5SDavid van Moolenbroek     }
1630*b2ed49a5SDavid van Moolenbroek     else {
1631*b2ed49a5SDavid van Moolenbroek         ret = EINVAL;
1632*b2ed49a5SDavid van Moolenbroek     }
1633*b2ed49a5SDavid van Moolenbroek 
1634*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_END();
1635*b2ed49a5SDavid van Moolenbroek 
1636*b2ed49a5SDavid van Moolenbroek     return ret;
1637*b2ed49a5SDavid van Moolenbroek }
1638*b2ed49a5SDavid van Moolenbroek 
1639*b2ed49a5SDavid van Moolenbroek #ifndef __MINIX
1640*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1641*b2ed49a5SDavid van Moolenbroek  *                              magic_valloc                                 *
1642*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_valloc(__MA_ARGS__ size_t size)1643*b2ed49a5SDavid van Moolenbroek PUBLIC void *magic_valloc(__MA_ARGS__ size_t size)
1644*b2ed49a5SDavid van Moolenbroek {
1645*b2ed49a5SDavid van Moolenbroek     return magic_memalign(__MA_VALUES__ MAGIC_PAGE_SIZE, size);
1646*b2ed49a5SDavid van Moolenbroek }
1647*b2ed49a5SDavid van Moolenbroek 
1648*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1649*b2ed49a5SDavid van Moolenbroek  *                              magic_memalign                               *
1650*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_memalign(__MA_ARGS__ size_t boundary,size_t size)1651*b2ed49a5SDavid van Moolenbroek PUBLIC void *magic_memalign(__MA_ARGS__ size_t boundary, size_t size)
1652*b2ed49a5SDavid van Moolenbroek {
1653*b2ed49a5SDavid van Moolenbroek     void *ptr;
1654*b2ed49a5SDavid van Moolenbroek     int ret = magic_posix_memalign(__MA_VALUES__ &ptr, boundary, size);
1655*b2ed49a5SDavid van Moolenbroek     if(ret != 0) {
1656*b2ed49a5SDavid van Moolenbroek         return NULL;
1657*b2ed49a5SDavid van Moolenbroek     }
1658*b2ed49a5SDavid van Moolenbroek     return ptr;
1659*b2ed49a5SDavid van Moolenbroek }
1660*b2ed49a5SDavid van Moolenbroek 
1661*b2ed49a5SDavid van Moolenbroek #endif
1662*b2ed49a5SDavid van Moolenbroek 
1663*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1664*b2ed49a5SDavid van Moolenbroek  *                           magic_mmap_positioned                           *
1665*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_mmap_positioned(__MA_ARGS__ void * start,size_t length,int prot,int flags,int fd,off_t offset,struct _magic_dsentry * cached_dsentry)1666*b2ed49a5SDavid van Moolenbroek PUBLIC void *magic_mmap_positioned(__MA_ARGS__ void *start, size_t length, int prot, int flags,
1667*b2ed49a5SDavid van Moolenbroek     int fd, off_t offset, struct _magic_dsentry *cached_dsentry)
1668*b2ed49a5SDavid van Moolenbroek {
1669*b2ed49a5SDavid van Moolenbroek     void *ptr, *data_ptr, *aligned_start, *aligned_ptr;
1670*b2ed49a5SDavid van Moolenbroek     void *new_ptr, *new_start;
1671*b2ed49a5SDavid van Moolenbroek     int dsentry_flags = MAGIC_STATE_MAP;
1672*b2ed49a5SDavid van Moolenbroek     size_t alloc_length;
1673*b2ed49a5SDavid van Moolenbroek     size_t page_size = MAGIC_PAGE_SIZE;
1674*b2ed49a5SDavid van Moolenbroek     int padding_type, padding_size;
1675*b2ed49a5SDavid van Moolenbroek     static THREAD_LOCAL int magic_is_first_mmap = 1;
1676*b2ed49a5SDavid van Moolenbroek 
1677*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_BEGIN();
1678*b2ed49a5SDavid van Moolenbroek 
1679*b2ed49a5SDavid van Moolenbroek     if (flags & MAP_FIXED) {
1680*b2ed49a5SDavid van Moolenbroek         /* Allow safe overmapping. */
1681*b2ed49a5SDavid van Moolenbroek         struct _magic_sentry *sentry = magic_sentry_lookup_by_range(start, NULL);
1682*b2ed49a5SDavid van Moolenbroek         if (sentry && sentry == magic_sentry_lookup_by_range((char*)start+length-1, NULL))
1683*b2ed49a5SDavid van Moolenbroek             return mmap(start, length, prot, flags, fd, offset);
1684*b2ed49a5SDavid van Moolenbroek     }
1685*b2ed49a5SDavid van Moolenbroek     assert(!(flags & MAP_FIXED) && "MAP_FIXED may override existing mapping, currently not implemented!");
1686*b2ed49a5SDavid van Moolenbroek     if (length > 0) {
1687*b2ed49a5SDavid van Moolenbroek         if (magic_is_first_mmap) {
1688*b2ed49a5SDavid van Moolenbroek             magic_is_first_mmap = 0;
1689*b2ed49a5SDavid van Moolenbroek             padding_type = MAGIC_STATE_MAP | MAGIC_ASR_FLAG_INIT;
1690*b2ed49a5SDavid van Moolenbroek         } else {
1691*b2ed49a5SDavid van Moolenbroek             padding_type = MAGIC_STATE_MAP;
1692*b2ed49a5SDavid van Moolenbroek         }
1693*b2ed49a5SDavid van Moolenbroek         padding_size = start ? 0 : magic_asr_get_padding_size(padding_type);
1694*b2ed49a5SDavid van Moolenbroek 
1695*b2ed49a5SDavid van Moolenbroek         assert(MAGIC_SIZE_TO_REAL(length) <= page_size + length);
1696*b2ed49a5SDavid van Moolenbroek         aligned_start = start ? ((char *)start) - page_size : NULL;
1697*b2ed49a5SDavid van Moolenbroek         alloc_length = length + (length % page_size == 0 ? 0 : page_size - (length % page_size));
1698*b2ed49a5SDavid van Moolenbroek #if 0
1699*b2ed49a5SDavid van Moolenbroek         if (_magic_vars->do_skip_mmap) {
1700*b2ed49a5SDavid van Moolenbroek             ptr = cached_dsentry ? ((char *)cached_dsentry) - (padding_size + page_size - MAGIC_SIZE_TO_REAL(0)) : NULL;
1701*b2ed49a5SDavid van Moolenbroek         } else
1702*b2ed49a5SDavid van Moolenbroek #endif
1703*b2ed49a5SDavid van Moolenbroek         if (!(flags & MAP_ANONYMOUS) && !(flags & MAP_SHARED) && ((prot & magic_mmap_dsentry_header_prot) == magic_mmap_dsentry_header_prot)) {
1704*b2ed49a5SDavid van Moolenbroek             ptr = mmap(aligned_start, page_size + alloc_length + padding_size, prot, flags, fd, offset);
1705*b2ed49a5SDavid van Moolenbroek         }
1706*b2ed49a5SDavid van Moolenbroek         else {
1707*b2ed49a5SDavid van Moolenbroek             /* Preallocate memory for metadata + data. */
1708*b2ed49a5SDavid van Moolenbroek             ptr = mmap(aligned_start, page_size + alloc_length + padding_size, magic_mmap_dsentry_header_prot, MAP_ANONYMOUS | MAP_PRIVATE | (flags & MAP_FIXED), -1, 0);
1709*b2ed49a5SDavid van Moolenbroek 
1710*b2ed49a5SDavid van Moolenbroek             /* Remap the data part the way the caller wants us to. */
1711*b2ed49a5SDavid van Moolenbroek             if (ptr != MAP_FAILED) {
1712*b2ed49a5SDavid van Moolenbroek                 new_start = ((char *)ptr) + page_size;
1713*b2ed49a5SDavid van Moolenbroek                 new_ptr = mmap(new_start, length, prot, flags | MAP_FIXED, fd, offset);
1714*b2ed49a5SDavid van Moolenbroek                 if (new_ptr == MAP_FAILED) {
1715*b2ed49a5SDavid van Moolenbroek                     munmap(ptr, page_size + alloc_length + padding_size);
1716*b2ed49a5SDavid van Moolenbroek                     ptr = MAP_FAILED;
1717*b2ed49a5SDavid van Moolenbroek                 }
1718*b2ed49a5SDavid van Moolenbroek             }
1719*b2ed49a5SDavid van Moolenbroek         }
1720*b2ed49a5SDavid van Moolenbroek         aligned_ptr = ptr;
1721*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_PRINTF("magic_mmap: ptr = mmap(start, length, prot, flags, fd, offset) <-> 0x%08x = mmap(0x%08x, %d, 0x%08x, 0x%08x, %d, %d)\n", (unsigned) aligned_ptr, aligned_start, page_size + length, prot, flags, fd, offset);
1722*b2ed49a5SDavid van Moolenbroek         if (ptr != MAP_FAILED) {
1723*b2ed49a5SDavid van Moolenbroek             ptr = ((char *)ptr) + page_size - MAGIC_SIZE_TO_REAL(0);
1724*b2ed49a5SDavid van Moolenbroek         }
1725*b2ed49a5SDavid van Moolenbroek         else {
1726*b2ed49a5SDavid van Moolenbroek             ptr = NULL;
1727*b2ed49a5SDavid van Moolenbroek         }
1728*b2ed49a5SDavid van Moolenbroek         if (flags & MAP_SHARED)
1729*b2ed49a5SDavid van Moolenbroek             dsentry_flags |= MAGIC_STATE_SHM;
1730*b2ed49a5SDavid van Moolenbroek         data_ptr = magic_alloc(__MA_VALUES__ ptr, alloc_length, dsentry_flags);
1731*b2ed49a5SDavid van Moolenbroek         if (data_ptr == MAGIC_MEM_FAILED) {
1732*b2ed49a5SDavid van Moolenbroek             munmap(aligned_ptr, page_size + alloc_length + padding_size);
1733*b2ed49a5SDavid van Moolenbroek             data_ptr = NULL;
1734*b2ed49a5SDavid van Moolenbroek         }
1735*b2ed49a5SDavid van Moolenbroek         if (!data_ptr) {
1736*b2ed49a5SDavid van Moolenbroek             errno = ENOMEM;
1737*b2ed49a5SDavid van Moolenbroek             data_ptr = MAP_FAILED;
1738*b2ed49a5SDavid van Moolenbroek         } else {
1739*b2ed49a5SDavid van Moolenbroek             assert(data_ptr == (char *)aligned_ptr + page_size);
1740*b2ed49a5SDavid van Moolenbroek             MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_mmap_flags = flags;
1741*b2ed49a5SDavid van Moolenbroek             MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_mmap_prot = prot;
1742*b2ed49a5SDavid van Moolenbroek             MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->ext = (void *) padding_size;
1743*b2ed49a5SDavid van Moolenbroek         }
1744*b2ed49a5SDavid van Moolenbroek     }
1745*b2ed49a5SDavid van Moolenbroek     else {
1746*b2ed49a5SDavid van Moolenbroek         data_ptr = MAP_FAILED;
1747*b2ed49a5SDavid van Moolenbroek         errno = EINVAL;
1748*b2ed49a5SDavid van Moolenbroek     }
1749*b2ed49a5SDavid van Moolenbroek 
1750*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_END();
1751*b2ed49a5SDavid van Moolenbroek 
1752*b2ed49a5SDavid van Moolenbroek     return data_ptr;
1753*b2ed49a5SDavid van Moolenbroek }
1754*b2ed49a5SDavid van Moolenbroek 
1755*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1756*b2ed49a5SDavid van Moolenbroek  *                               magic_mmap                                  *
1757*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_mmap(__MA_ARGS__ void * start,size_t length,int prot,int flags,int fd,off_t offset)1758*b2ed49a5SDavid van Moolenbroek PUBLIC void *magic_mmap(__MA_ARGS__ void *start, size_t length, int prot, int flags,
1759*b2ed49a5SDavid van Moolenbroek     int fd, off_t offset)
1760*b2ed49a5SDavid van Moolenbroek {
1761*b2ed49a5SDavid van Moolenbroek     return magic_mmap_positioned(__MA_VALUES__ start, length, prot, flags, fd, offset, NULL);
1762*b2ed49a5SDavid van Moolenbroek }
1763*b2ed49a5SDavid van Moolenbroek 
1764*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1765*b2ed49a5SDavid van Moolenbroek  *                              magic_munmap                                 *
1766*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_munmap(__MD_ARGS__ void * data_ptr,size_t length)1767*b2ed49a5SDavid van Moolenbroek PUBLIC int magic_munmap(__MD_ARGS__ void *data_ptr, size_t length)
1768*b2ed49a5SDavid van Moolenbroek {
1769*b2ed49a5SDavid van Moolenbroek     int ret;
1770*b2ed49a5SDavid van Moolenbroek     void *ptr, *aligned_ptr;
1771*b2ed49a5SDavid van Moolenbroek     struct _magic_sentry *sentry;
1772*b2ed49a5SDavid van Moolenbroek     size_t alloc_length, old_size;
1773*b2ed49a5SDavid van Moolenbroek     size_t page_size = MAGIC_PAGE_SIZE;
1774*b2ed49a5SDavid van Moolenbroek 
1775*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_BEGIN();
1776*b2ed49a5SDavid van Moolenbroek 
1777*b2ed49a5SDavid van Moolenbroek     if(data_ptr) {
1778*b2ed49a5SDavid van Moolenbroek         ptr = MAGIC_PTR_FROM_DATA(data_ptr);
1779*b2ed49a5SDavid van Moolenbroek 
1780*b2ed49a5SDavid van Moolenbroek         /* Check for legitimate non-indexed chunks of memory and skip. */
1781*b2ed49a5SDavid van Moolenbroek         if((!magic_libcommon_active || !MAGIC_USE_DYN_MEM_WRAPPERS)
1782*b2ed49a5SDavid van Moolenbroek             && !MAGIC_DSENTRY_MNUM_OK(MAGIC_PTR_TO_DSENTRY(ptr))) {
1783*b2ed49a5SDavid van Moolenbroek             MAGIC_MEM_WRAPPER_END();
1784*b2ed49a5SDavid van Moolenbroek             return munmap(data_ptr, length);
1785*b2ed49a5SDavid van Moolenbroek         }
1786*b2ed49a5SDavid van Moolenbroek 
1787*b2ed49a5SDavid van Moolenbroek         sentry = MAGIC_DSENTRY_TO_SENTRY(MAGIC_PTR_TO_DSENTRY(ptr));
1788*b2ed49a5SDavid van Moolenbroek         aligned_ptr = ((char*)data_ptr) - page_size;
1789*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_PRINTF("magic_munmap: magic_munmap(0x%08x, %d) / unmap(0x%08x, %d)\n", (unsigned) data_ptr, length, (unsigned) aligned_ptr, page_size+length);
1790*b2ed49a5SDavid van Moolenbroek         assert(magic_check_dsentry(MAGIC_PTR_TO_DSENTRY(ptr), MAGIC_STATE_MAP) && "XXX Bad magic dsentry: corruption or memory not allocated from a magic wrapper?");
1791*b2ed49a5SDavid van Moolenbroek         old_size = MAGIC_DSENTRY_TO_SENTRY(MAGIC_PTR_TO_DSENTRY(ptr))->type->size;
1792*b2ed49a5SDavid van Moolenbroek         alloc_length = length + (length % page_size == 0 ? 0 : page_size-(length % page_size));
1793*b2ed49a5SDavid van Moolenbroek 
1794*b2ed49a5SDavid van Moolenbroek         if(alloc_length != old_size) {
1795*b2ed49a5SDavid van Moolenbroek             assert(alloc_length >= old_size && "Partial unmapping not supported!");
1796*b2ed49a5SDavid van Moolenbroek             ret = -1;
1797*b2ed49a5SDavid van Moolenbroek             errno = EINVAL;
1798*b2ed49a5SDavid van Moolenbroek         }
1799*b2ed49a5SDavid van Moolenbroek         else {
1800*b2ed49a5SDavid van Moolenbroek             if(magic_allow_dead_dsentries) {
1801*b2ed49a5SDavid van Moolenbroek                 ret = magic_update_dsentry_state(MAGIC_PTR_TO_DSENTRY(ptr), MAGIC_DSENTRY_MSTATE_DEAD);
1802*b2ed49a5SDavid van Moolenbroek                 assert(ret == 0 && "Bad munmap!");
1803*b2ed49a5SDavid van Moolenbroek             }
1804*b2ed49a5SDavid van Moolenbroek             else {
1805*b2ed49a5SDavid van Moolenbroek                 MAGIC_DSENTRY_LOCK();
1806*b2ed49a5SDavid van Moolenbroek                 magic_destroy_dsentry(MAGIC_PTR_TO_DSENTRY(ptr), NULL);
1807*b2ed49a5SDavid van Moolenbroek                 ret = magic_free_dsentry(MAGIC_PTR_TO_DSENTRY(ptr));
1808*b2ed49a5SDavid van Moolenbroek                 assert(ret == 0 && "Bad munmap!");
1809*b2ed49a5SDavid van Moolenbroek                 MAGIC_DSENTRY_UNLOCK();
1810*b2ed49a5SDavid van Moolenbroek             }
1811*b2ed49a5SDavid van Moolenbroek         }
1812*b2ed49a5SDavid van Moolenbroek     }
1813*b2ed49a5SDavid van Moolenbroek     else {
1814*b2ed49a5SDavid van Moolenbroek         ret = -1;
1815*b2ed49a5SDavid van Moolenbroek         errno = EINVAL;
1816*b2ed49a5SDavid van Moolenbroek     }
1817*b2ed49a5SDavid van Moolenbroek 
1818*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_END();
1819*b2ed49a5SDavid van Moolenbroek 
1820*b2ed49a5SDavid van Moolenbroek     return ret;
1821*b2ed49a5SDavid van Moolenbroek }
1822*b2ed49a5SDavid van Moolenbroek 
1823*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1824*b2ed49a5SDavid van Moolenbroek  *                               magic_brk                                   *
1825*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_brk(__MA_ARGS__ void * addr)1826*b2ed49a5SDavid van Moolenbroek PUBLIC int magic_brk(__MA_ARGS__ void *addr)
1827*b2ed49a5SDavid van Moolenbroek {
1828*b2ed49a5SDavid van Moolenbroek     void *ptr;
1829*b2ed49a5SDavid van Moolenbroek     void *break_addr;
1830*b2ed49a5SDavid van Moolenbroek     int ret;
1831*b2ed49a5SDavid van Moolenbroek 
1832*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_PRINTF("magic_brk: Warning: somebody calling magic_brk()!");
1833*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_LBLOCK( break_addr = sbrk(0); );
1834*b2ed49a5SDavid van Moolenbroek     if(addr >= break_addr) {
1835*b2ed49a5SDavid van Moolenbroek         ptr = magic_sbrk(__MA_VALUES__ (char*)addr - (char*)break_addr);
1836*b2ed49a5SDavid van Moolenbroek         ret = (ptr == (void*) -1 ? -1 : 0);
1837*b2ed49a5SDavid van Moolenbroek         if(ret == -1) {
1838*b2ed49a5SDavid van Moolenbroek             errno = ENOMEM;
1839*b2ed49a5SDavid van Moolenbroek         }
1840*b2ed49a5SDavid van Moolenbroek     }
1841*b2ed49a5SDavid van Moolenbroek     else {
1842*b2ed49a5SDavid van Moolenbroek         magic_free(__MD_VALUES_DEFAULT__ addr);
1843*b2ed49a5SDavid van Moolenbroek         ret = 0;
1844*b2ed49a5SDavid van Moolenbroek     }
1845*b2ed49a5SDavid van Moolenbroek 
1846*b2ed49a5SDavid van Moolenbroek     return ret;
1847*b2ed49a5SDavid van Moolenbroek }
1848*b2ed49a5SDavid van Moolenbroek 
1849*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1850*b2ed49a5SDavid van Moolenbroek  *                              magic_sbrk                                   *
1851*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_sbrk(__MA_ARGS__ intptr_t increment)1852*b2ed49a5SDavid van Moolenbroek PUBLIC void *magic_sbrk(__MA_ARGS__ intptr_t increment)
1853*b2ed49a5SDavid van Moolenbroek {
1854*b2ed49a5SDavid van Moolenbroek     void *ptr;
1855*b2ed49a5SDavid van Moolenbroek 
1856*b2ed49a5SDavid van Moolenbroek     if(increment == 0) {
1857*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_WRAPPER_LBLOCK( ptr = sbrk(0); );
1858*b2ed49a5SDavid van Moolenbroek     }
1859*b2ed49a5SDavid van Moolenbroek     else {
1860*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_PRINTF("magic_sbrk: Warning: somebody calling magic_sbrk(), resorting to magic_malloc()!");
1861*b2ed49a5SDavid van Moolenbroek         ptr = magic_malloc(__MA_VALUES__ increment);
1862*b2ed49a5SDavid van Moolenbroek     }
1863*b2ed49a5SDavid van Moolenbroek 
1864*b2ed49a5SDavid van Moolenbroek     return ptr;
1865*b2ed49a5SDavid van Moolenbroek }
1866*b2ed49a5SDavid van Moolenbroek 
1867*b2ed49a5SDavid van Moolenbroek #ifndef __MINIX
1868*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1869*b2ed49a5SDavid van Moolenbroek  *                             magic_shmat                                   *
1870*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_shmat(__MA_ARGS__ int shmid,const void * shmaddr,int shmflg)1871*b2ed49a5SDavid van Moolenbroek PUBLIC void *magic_shmat(__MA_ARGS__ int shmid, const void *shmaddr, int shmflg)
1872*b2ed49a5SDavid van Moolenbroek {
1873*b2ed49a5SDavid van Moolenbroek     void *ptr, *data_ptr, *aligned_shmaddr, *aligned_ptr;
1874*b2ed49a5SDavid van Moolenbroek     void *new_ptr, *new_shmaddr;
1875*b2ed49a5SDavid van Moolenbroek     size_t size;
1876*b2ed49a5SDavid van Moolenbroek     struct shmid_ds buf;
1877*b2ed49a5SDavid van Moolenbroek     int ret, flags;
1878*b2ed49a5SDavid van Moolenbroek     size_t page_size = MAGIC_PAGE_SIZE;
1879*b2ed49a5SDavid van Moolenbroek 
1880*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_BEGIN();
1881*b2ed49a5SDavid van Moolenbroek 
1882*b2ed49a5SDavid van Moolenbroek     assert(!(shmflg & SHM_REMAP) && "Linux-specific SHM_REMAP not supported!");
1883*b2ed49a5SDavid van Moolenbroek     ret = shmctl(shmid, IPC_STAT, &buf);
1884*b2ed49a5SDavid van Moolenbroek     if (ret == -1) {
1885*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_WRAPPER_END();
1886*b2ed49a5SDavid van Moolenbroek         return NULL;
1887*b2ed49a5SDavid van Moolenbroek     }
1888*b2ed49a5SDavid van Moolenbroek     size = buf.shm_segsz;
1889*b2ed49a5SDavid van Moolenbroek     if (size > 0) {
1890*b2ed49a5SDavid van Moolenbroek         assert(size % page_size == 0);
1891*b2ed49a5SDavid van Moolenbroek         assert(MAGIC_SIZE_TO_REAL(size) <= size + page_size);
1892*b2ed49a5SDavid van Moolenbroek         if (shmaddr && (shmflg & SHM_RND)) {
1893*b2ed49a5SDavid van Moolenbroek             unsigned long shmlba = SHMLBA;
1894*b2ed49a5SDavid van Moolenbroek             shmflg &= ~SHM_RND;
1895*b2ed49a5SDavid van Moolenbroek             shmaddr = (void *) ((((unsigned long)shmaddr) / shmlba) * shmlba);
1896*b2ed49a5SDavid van Moolenbroek         }
1897*b2ed49a5SDavid van Moolenbroek 
1898*b2ed49a5SDavid van Moolenbroek         /* Preallocate memory for metadata + data. */
1899*b2ed49a5SDavid van Moolenbroek         aligned_shmaddr = shmaddr ? ((char *)shmaddr) - page_size : NULL;
1900*b2ed49a5SDavid van Moolenbroek         flags = MAP_ANONYMOUS | MAP_PRIVATE | (aligned_shmaddr ? MAP_FIXED : 0);
1901*b2ed49a5SDavid van Moolenbroek         ptr = mmap(aligned_shmaddr, page_size + size, magic_mmap_dsentry_header_prot, flags, -1, 0);
1902*b2ed49a5SDavid van Moolenbroek 
1903*b2ed49a5SDavid van Moolenbroek         /* Remap the data part the way the caller wants us to. */
1904*b2ed49a5SDavid van Moolenbroek         if (ptr != MAP_FAILED) {
1905*b2ed49a5SDavid van Moolenbroek             new_shmaddr = ((char *)ptr) + page_size;
1906*b2ed49a5SDavid van Moolenbroek             munmap(new_shmaddr, size);
1907*b2ed49a5SDavid van Moolenbroek             new_ptr = shmat(shmid, new_shmaddr, shmflg);
1908*b2ed49a5SDavid van Moolenbroek             if(new_ptr == (void *) -1) {
1909*b2ed49a5SDavid van Moolenbroek                 munmap(ptr, page_size);
1910*b2ed49a5SDavid van Moolenbroek                 ptr = MAP_FAILED;
1911*b2ed49a5SDavid van Moolenbroek             }
1912*b2ed49a5SDavid van Moolenbroek         }
1913*b2ed49a5SDavid van Moolenbroek         aligned_ptr = ptr;
1914*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_PRINTF("magic_shmat: ptr = shmat(shmid, shmaddr, shmflg) <-> 0x%08x = shmat(%d, 0x%08x, 0x%08x)\n", (unsigned) aligned_ptr, shmid, aligned_shmaddr, shmflg);
1915*b2ed49a5SDavid van Moolenbroek         if (ptr != MAP_FAILED) {
1916*b2ed49a5SDavid van Moolenbroek             ptr = ((char *)ptr) + page_size - MAGIC_SIZE_TO_REAL(0);
1917*b2ed49a5SDavid van Moolenbroek         }
1918*b2ed49a5SDavid van Moolenbroek         else {
1919*b2ed49a5SDavid van Moolenbroek             ptr = NULL;
1920*b2ed49a5SDavid van Moolenbroek         }
1921*b2ed49a5SDavid van Moolenbroek         data_ptr = magic_alloc(__MA_VALUES__ ptr, size, MAGIC_STATE_SHM | MAGIC_STATE_DETACHED);
1922*b2ed49a5SDavid van Moolenbroek         if (data_ptr == MAGIC_MEM_FAILED) {
1923*b2ed49a5SDavid van Moolenbroek             munmap(aligned_ptr, page_size);
1924*b2ed49a5SDavid van Moolenbroek             munmap(new_ptr, size);
1925*b2ed49a5SDavid van Moolenbroek             data_ptr = (void *) -1;
1926*b2ed49a5SDavid van Moolenbroek             errno = ENOMEM;
1927*b2ed49a5SDavid van Moolenbroek         }
1928*b2ed49a5SDavid van Moolenbroek         else {
1929*b2ed49a5SDavid van Moolenbroek             MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_shmat_flags = shmflg;
1930*b2ed49a5SDavid van Moolenbroek             MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_shmat_shmid = shmid;
1931*b2ed49a5SDavid van Moolenbroek         }
1932*b2ed49a5SDavid van Moolenbroek     }
1933*b2ed49a5SDavid van Moolenbroek     else {
1934*b2ed49a5SDavid van Moolenbroek         data_ptr = (void *) -1;
1935*b2ed49a5SDavid van Moolenbroek         errno = EINVAL;
1936*b2ed49a5SDavid van Moolenbroek     }
1937*b2ed49a5SDavid van Moolenbroek 
1938*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_END();
1939*b2ed49a5SDavid van Moolenbroek 
1940*b2ed49a5SDavid van Moolenbroek     return data_ptr;
1941*b2ed49a5SDavid van Moolenbroek }
1942*b2ed49a5SDavid van Moolenbroek 
1943*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1944*b2ed49a5SDavid van Moolenbroek  *                             magic_shmdt                                   *
1945*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_shmdt(__MD_ARGS__ const void * data_ptr)1946*b2ed49a5SDavid van Moolenbroek PUBLIC int magic_shmdt(__MD_ARGS__ const void *data_ptr)
1947*b2ed49a5SDavid van Moolenbroek {
1948*b2ed49a5SDavid van Moolenbroek     int ret;
1949*b2ed49a5SDavid van Moolenbroek     void *ptr, *aligned_ptr;
1950*b2ed49a5SDavid van Moolenbroek     size_t page_size = MAGIC_PAGE_SIZE;
1951*b2ed49a5SDavid van Moolenbroek 
1952*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_LBEGIN();
1953*b2ed49a5SDavid van Moolenbroek 
1954*b2ed49a5SDavid van Moolenbroek     if (data_ptr) {
1955*b2ed49a5SDavid van Moolenbroek         ptr = MAGIC_PTR_FROM_DATA(data_ptr);
1956*b2ed49a5SDavid van Moolenbroek 
1957*b2ed49a5SDavid van Moolenbroek         /* Check for legitimate non-indexed chunks of memory and skip. */
1958*b2ed49a5SDavid van Moolenbroek         if ((!magic_libcommon_active || !MAGIC_USE_DYN_MEM_WRAPPERS)
1959*b2ed49a5SDavid van Moolenbroek             && !MAGIC_DSENTRY_MNUM_OK(MAGIC_PTR_TO_DSENTRY(ptr))) {
1960*b2ed49a5SDavid van Moolenbroek             MAGIC_MEM_WRAPPER_LEND();
1961*b2ed49a5SDavid van Moolenbroek             return shmdt(data_ptr);
1962*b2ed49a5SDavid van Moolenbroek         }
1963*b2ed49a5SDavid van Moolenbroek 
1964*b2ed49a5SDavid van Moolenbroek         aligned_ptr = ((char*)data_ptr) - page_size;
1965*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_PRINTF("magic_shmdt: magic_shmdt(0x%08x) / shmdt(0x%08x)\n", (unsigned) data_ptr, (unsigned) aligned_ptr);
1966*b2ed49a5SDavid van Moolenbroek         assert(magic_check_dsentry(MAGIC_PTR_TO_DSENTRY(ptr), MAGIC_STATE_SHM) && "XXX Bad magic dsentry: corruption or memory not allocated from a magic wrapper?");
1967*b2ed49a5SDavid van Moolenbroek         ret = shmdt(data_ptr);
1968*b2ed49a5SDavid van Moolenbroek         if (ret == 0) {
1969*b2ed49a5SDavid van Moolenbroek             magic_destroy_dsentry(MAGIC_PTR_TO_DSENTRY(ptr), NULL);
1970*b2ed49a5SDavid van Moolenbroek             munmap(aligned_ptr, page_size);
1971*b2ed49a5SDavid van Moolenbroek         }
1972*b2ed49a5SDavid van Moolenbroek     }
1973*b2ed49a5SDavid van Moolenbroek     else {
1974*b2ed49a5SDavid van Moolenbroek         ret = -1;
1975*b2ed49a5SDavid van Moolenbroek         errno = EINVAL;
1976*b2ed49a5SDavid van Moolenbroek     }
1977*b2ed49a5SDavid van Moolenbroek 
1978*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_LEND();
1979*b2ed49a5SDavid van Moolenbroek 
1980*b2ed49a5SDavid van Moolenbroek     return ret;
1981*b2ed49a5SDavid van Moolenbroek }
1982*b2ed49a5SDavid van Moolenbroek 
1983*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
1984*b2ed49a5SDavid van Moolenbroek  *                               magic_mmap64                                *
1985*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_mmap64(__MA_ARGS__ void * start,size_t length,int prot,int flags,int fd,off_t pgoffset)1986*b2ed49a5SDavid van Moolenbroek PUBLIC void *magic_mmap64(__MA_ARGS__ void *start, size_t length, int prot, int flags,
1987*b2ed49a5SDavid van Moolenbroek     int fd, off_t pgoffset)
1988*b2ed49a5SDavid van Moolenbroek {
1989*b2ed49a5SDavid van Moolenbroek     void *ptr, *data_ptr, *aligned_start, *aligned_ptr;
1990*b2ed49a5SDavid van Moolenbroek     void *new_ptr, *new_start;
1991*b2ed49a5SDavid van Moolenbroek     int dsentry_flags = MAGIC_STATE_MAP;
1992*b2ed49a5SDavid van Moolenbroek     size_t alloc_length;
1993*b2ed49a5SDavid van Moolenbroek     size_t page_size = MAGIC_PAGE_SIZE;
1994*b2ed49a5SDavid van Moolenbroek 
1995*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_BEGIN();
1996*b2ed49a5SDavid van Moolenbroek 
1997*b2ed49a5SDavid van Moolenbroek     if (flags & MAP_FIXED) {
1998*b2ed49a5SDavid van Moolenbroek 	/* Allow safe overmapping. */
1999*b2ed49a5SDavid van Moolenbroek 	struct _magic_sentry *sentry = magic_sentry_lookup_by_range(start, NULL);
2000*b2ed49a5SDavid van Moolenbroek 	if (sentry && sentry == magic_sentry_lookup_by_range((char*)start+length-1, NULL))
2001*b2ed49a5SDavid van Moolenbroek             return mmap64(start, length, prot, flags, fd, pgoffset);
2002*b2ed49a5SDavid van Moolenbroek     }
2003*b2ed49a5SDavid van Moolenbroek     assert(!(flags & MAP_FIXED) && "MAP_FIXED may override existing mapping, currently not implemented!");
2004*b2ed49a5SDavid van Moolenbroek     if(length > 0) {
2005*b2ed49a5SDavid van Moolenbroek         assert(MAGIC_SIZE_TO_REAL(length) <= page_size+length);
2006*b2ed49a5SDavid van Moolenbroek         aligned_start = start ? ((char*)start) - page_size : NULL;
2007*b2ed49a5SDavid van Moolenbroek         alloc_length = length + (length % page_size == 0 ? 0 : page_size-(length % page_size));
2008*b2ed49a5SDavid van Moolenbroek         if((flags & MAP_ANONYMOUS) && !(flags & MAP_SHARED) && ((prot & magic_mmap_dsentry_header_prot) == magic_mmap_dsentry_header_prot)) {
2009*b2ed49a5SDavid van Moolenbroek             ptr = mmap64(aligned_start, page_size+length, prot, flags, fd, pgoffset);
2010*b2ed49a5SDavid van Moolenbroek         }
2011*b2ed49a5SDavid van Moolenbroek         else {
2012*b2ed49a5SDavid van Moolenbroek             /* Preallocate memory for metadata + data. */
2013*b2ed49a5SDavid van Moolenbroek             ptr = mmap64(aligned_start, page_size+alloc_length, magic_mmap_dsentry_header_prot, MAP_ANONYMOUS|MAP_PRIVATE|(flags & MAP_FIXED), -1, 0);
2014*b2ed49a5SDavid van Moolenbroek 
2015*b2ed49a5SDavid van Moolenbroek             /* Remap the data part the way the caller wants us to. */
2016*b2ed49a5SDavid van Moolenbroek             if(ptr != MAP_FAILED) {
2017*b2ed49a5SDavid van Moolenbroek                 new_start = ((char*)ptr) + page_size;
2018*b2ed49a5SDavid van Moolenbroek                 new_ptr = mmap64(new_start, length, prot, flags|MAP_FIXED, fd, pgoffset);
2019*b2ed49a5SDavid van Moolenbroek                 if(new_ptr == MAP_FAILED) {
2020*b2ed49a5SDavid van Moolenbroek                     munmap(ptr, page_size+alloc_length);
2021*b2ed49a5SDavid van Moolenbroek                     ptr = MAP_FAILED;
2022*b2ed49a5SDavid van Moolenbroek                 }
2023*b2ed49a5SDavid van Moolenbroek             }
2024*b2ed49a5SDavid van Moolenbroek         }
2025*b2ed49a5SDavid van Moolenbroek         aligned_ptr = ptr;
2026*b2ed49a5SDavid van Moolenbroek         MAGIC_MEM_PRINTF("magic_mmap64: ptr = mmap64(start, length, prot, flags, fd, pgoffset) <-> 0x%08x = mmap64(0x%08x, %d, 0x%08x, 0x%08x, %d, %d)\n", (unsigned) aligned_ptr, aligned_start, page_size+length, prot, flags, fd, pgoffset);
2027*b2ed49a5SDavid van Moolenbroek         if(ptr != MAP_FAILED) {
2028*b2ed49a5SDavid van Moolenbroek             ptr = ((char*)ptr) + page_size - MAGIC_SIZE_TO_REAL(0);
2029*b2ed49a5SDavid van Moolenbroek         }
2030*b2ed49a5SDavid van Moolenbroek         else {
2031*b2ed49a5SDavid van Moolenbroek             ptr = NULL;
2032*b2ed49a5SDavid van Moolenbroek         }
2033*b2ed49a5SDavid van Moolenbroek         if (flags & MAP_SHARED)
2034*b2ed49a5SDavid van Moolenbroek             dsentry_flags |= MAGIC_STATE_SHM;
2035*b2ed49a5SDavid van Moolenbroek         data_ptr = magic_alloc(__MA_VALUES__ ptr, alloc_length, dsentry_flags);
2036*b2ed49a5SDavid van Moolenbroek         if(data_ptr == MAGIC_MEM_FAILED) {
2037*b2ed49a5SDavid van Moolenbroek             munmap(aligned_ptr, page_size+length);
2038*b2ed49a5SDavid van Moolenbroek             data_ptr = NULL;
2039*b2ed49a5SDavid van Moolenbroek             errno = ENOMEM;
2040*b2ed49a5SDavid van Moolenbroek         }
2041*b2ed49a5SDavid van Moolenbroek         if(!data_ptr) {
2042*b2ed49a5SDavid van Moolenbroek             errno = ENOMEM;
2043*b2ed49a5SDavid van Moolenbroek             data_ptr = MAP_FAILED;
2044*b2ed49a5SDavid van Moolenbroek         } else {
2045*b2ed49a5SDavid van Moolenbroek             MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_mmap_flags = flags;
2046*b2ed49a5SDavid van Moolenbroek             MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_mmap_prot = prot;
2047*b2ed49a5SDavid van Moolenbroek         }
2048*b2ed49a5SDavid van Moolenbroek     }
2049*b2ed49a5SDavid van Moolenbroek     else {
2050*b2ed49a5SDavid van Moolenbroek         data_ptr = MAP_FAILED;
2051*b2ed49a5SDavid van Moolenbroek         errno = EINVAL;
2052*b2ed49a5SDavid van Moolenbroek     }
2053*b2ed49a5SDavid van Moolenbroek 
2054*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_END();
2055*b2ed49a5SDavid van Moolenbroek 
2056*b2ed49a5SDavid van Moolenbroek     return data_ptr;
2057*b2ed49a5SDavid van Moolenbroek }
2058*b2ed49a5SDavid van Moolenbroek 
2059*b2ed49a5SDavid van Moolenbroek #else
2060*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
2061*b2ed49a5SDavid van Moolenbroek  *                               magic_vm_map_cacheblock                                *
2062*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
magic_vm_map_cacheblock(__MA_ARGS__ dev_t dev,off_t dev_offset,ino_t ino,off_t ino_offset,u32_t * flags,int length)2063*b2ed49a5SDavid van Moolenbroek PUBLIC void *magic_vm_map_cacheblock(__MA_ARGS__ dev_t dev, off_t dev_offset,
2064*b2ed49a5SDavid van Moolenbroek     ino_t ino, off_t ino_offset, u32_t *flags, int length)
2065*b2ed49a5SDavid van Moolenbroek {
2066*b2ed49a5SDavid van Moolenbroek     void *ptr, *data_ptr, *aligned_ptr;
2067*b2ed49a5SDavid van Moolenbroek     int dsentry_flags = MAGIC_STATE_MAP;
2068*b2ed49a5SDavid van Moolenbroek     size_t alloc_length;
2069*b2ed49a5SDavid van Moolenbroek     size_t page_size = MAGIC_PAGE_SIZE;
2070*b2ed49a5SDavid van Moolenbroek 
2071*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_BEGIN();
2072*b2ed49a5SDavid van Moolenbroek 
2073*b2ed49a5SDavid van Moolenbroek     if(length > 0) {
2074*b2ed49a5SDavid van Moolenbroek         assert(MAGIC_SIZE_TO_REAL(length) <= page_size+length);
2075*b2ed49a5SDavid van Moolenbroek         alloc_length = length + (length % page_size == 0 ? 0 : page_size-(length % page_size));
2076*b2ed49a5SDavid van Moolenbroek         data_ptr = vm_map_cacheblock(dev, dev_offset, ino, ino_offset, flags, length);
2077*b2ed49a5SDavid van Moolenbroek         if (data_ptr != MAP_FAILED) {
2078*b2ed49a5SDavid van Moolenbroek             ptr = mmap((char *)data_ptr-page_size, page_size, magic_mmap_dsentry_header_prot, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2079*b2ed49a5SDavid van Moolenbroek             MAGIC_MEM_PRINTF("vm_map_cacheblock: ptr = mmap(start, length, prot, flags, fd, offset) <-> 0x%08x = mmap(0x%08x, %d, 0x%08x, 0x%08x, %d, %d)\n", (unsigned) ptr, (char *)data_ptr-page_size, page_size, magic_mmap_dsentry_header_prot, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2080*b2ed49a5SDavid van Moolenbroek             assert(ptr == (char *)data_ptr-page_size); /* Ensured by VM. */
2081*b2ed49a5SDavid van Moolenbroek             aligned_ptr = ptr;
2082*b2ed49a5SDavid van Moolenbroek             ptr = ((char*)ptr) + page_size - MAGIC_SIZE_TO_REAL(0);
2083*b2ed49a5SDavid van Moolenbroek         }
2084*b2ed49a5SDavid van Moolenbroek         else {
2085*b2ed49a5SDavid van Moolenbroek             aligned_ptr = NULL;
2086*b2ed49a5SDavid van Moolenbroek             ptr = NULL;
2087*b2ed49a5SDavid van Moolenbroek         }
2088*b2ed49a5SDavid van Moolenbroek         data_ptr = magic_alloc(__MA_VALUES__ ptr, alloc_length, dsentry_flags);
2089*b2ed49a5SDavid van Moolenbroek         if(data_ptr == MAGIC_MEM_FAILED) {
2090*b2ed49a5SDavid van Moolenbroek             munmap(aligned_ptr, page_size+length);
2091*b2ed49a5SDavid van Moolenbroek             data_ptr = NULL;
2092*b2ed49a5SDavid van Moolenbroek         }
2093*b2ed49a5SDavid van Moolenbroek         if(!data_ptr) {
2094*b2ed49a5SDavid van Moolenbroek             data_ptr = MAP_FAILED;
2095*b2ed49a5SDavid van Moolenbroek             errno = ENOMEM;
2096*b2ed49a5SDavid van Moolenbroek         } else {
2097*b2ed49a5SDavid van Moolenbroek             MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_mmap_flags = MAP_ANONYMOUS | MAP_PRIVATE;
2098*b2ed49a5SDavid van Moolenbroek             MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_mmap_prot = magic_mmap_dsentry_header_prot;
2099*b2ed49a5SDavid van Moolenbroek         }
2100*b2ed49a5SDavid van Moolenbroek     }
2101*b2ed49a5SDavid van Moolenbroek     else {
2102*b2ed49a5SDavid van Moolenbroek         data_ptr = MAP_FAILED;
2103*b2ed49a5SDavid van Moolenbroek         errno = EINVAL;
2104*b2ed49a5SDavid van Moolenbroek     }
2105*b2ed49a5SDavid van Moolenbroek 
2106*b2ed49a5SDavid van Moolenbroek     MAGIC_MEM_WRAPPER_END();
2107*b2ed49a5SDavid van Moolenbroek 
2108*b2ed49a5SDavid van Moolenbroek     return data_ptr;
2109*b2ed49a5SDavid van Moolenbroek }
2110*b2ed49a5SDavid van Moolenbroek 
2111*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
2112*b2ed49a5SDavid van Moolenbroek  *				magic_nested_mmap			     *
2113*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
2114*b2ed49a5SDavid van Moolenbroek void *
magic_nested_mmap(void * start,size_t length,int prot,int flags,int fd,off_t offset)2115*b2ed49a5SDavid van Moolenbroek magic_nested_mmap(void *start, size_t length, int prot, int flags,
2116*b2ed49a5SDavid van Moolenbroek 	int fd, off_t offset)
2117*b2ed49a5SDavid van Moolenbroek {
2118*b2ed49a5SDavid van Moolenbroek 	void *ptr;
2119*b2ed49a5SDavid van Moolenbroek 	int i;
2120*b2ed49a5SDavid van Moolenbroek 
2121*b2ed49a5SDavid van Moolenbroek 	ptr = mmap(start, length, prot, flags, fd, offset);
2122*b2ed49a5SDavid van Moolenbroek 
2123*b2ed49a5SDavid van Moolenbroek 	if (ptr != MAP_FAILED) {
2124*b2ed49a5SDavid van Moolenbroek 		MAGIC_MEM_PRINTF("MAGIC: nested mmap (%p, %zu)\n", ptr,
2125*b2ed49a5SDavid van Moolenbroek 		    length);
2126*b2ed49a5SDavid van Moolenbroek 
2127*b2ed49a5SDavid van Moolenbroek 		/*
2128*b2ed49a5SDavid van Moolenbroek 		 * Find a free entry.  We do not expect the malloc code to have
2129*b2ed49a5SDavid van Moolenbroek 		 * more than two areas mapped at any time.
2130*b2ed49a5SDavid van Moolenbroek 		 */
2131*b2ed49a5SDavid van Moolenbroek 		for (i = 0; i < MAGIC_UNMAP_MEM_ENTRIES; i++)
2132*b2ed49a5SDavid van Moolenbroek 			if (_magic_unmap_mem[i].length == 0)
2133*b2ed49a5SDavid van Moolenbroek 				break;
2134*b2ed49a5SDavid van Moolenbroek 		assert(i < MAGIC_UNMAP_MEM_ENTRIES);
2135*b2ed49a5SDavid van Moolenbroek 
2136*b2ed49a5SDavid van Moolenbroek 		/* Store the mapping in this entry. */
2137*b2ed49a5SDavid van Moolenbroek 		_magic_unmap_mem[i].start = ptr;
2138*b2ed49a5SDavid van Moolenbroek 		_magic_unmap_mem[i].length = length;
2139*b2ed49a5SDavid van Moolenbroek 	}
2140*b2ed49a5SDavid van Moolenbroek 
2141*b2ed49a5SDavid van Moolenbroek 	return ptr;
2142*b2ed49a5SDavid van Moolenbroek }
2143*b2ed49a5SDavid van Moolenbroek 
2144*b2ed49a5SDavid van Moolenbroek /*===========================================================================*
2145*b2ed49a5SDavid van Moolenbroek  *				magic_nested_munmap			     *
2146*b2ed49a5SDavid van Moolenbroek  *===========================================================================*/
2147*b2ed49a5SDavid van Moolenbroek int
magic_nested_munmap(void * start,size_t length)2148*b2ed49a5SDavid van Moolenbroek magic_nested_munmap(void *start, size_t length)
2149*b2ed49a5SDavid van Moolenbroek {
2150*b2ed49a5SDavid van Moolenbroek 	int i, r;
2151*b2ed49a5SDavid van Moolenbroek 
2152*b2ed49a5SDavid van Moolenbroek 	r = munmap(start, length);
2153*b2ed49a5SDavid van Moolenbroek 
2154*b2ed49a5SDavid van Moolenbroek 	if (r == 0) {
2155*b2ed49a5SDavid van Moolenbroek 		MAGIC_MEM_PRINTF("MAGIC: nested munmap (%p, %zu)\n", start,
2156*b2ed49a5SDavid van Moolenbroek 		    length);
2157*b2ed49a5SDavid van Moolenbroek 
2158*b2ed49a5SDavid van Moolenbroek 		/* Find the corresponding entry.  This must always succeed. */
2159*b2ed49a5SDavid van Moolenbroek 		for (i = 0; i < MAGIC_UNMAP_MEM_ENTRIES; i++)
2160*b2ed49a5SDavid van Moolenbroek 			if (_magic_unmap_mem[i].start == start &&
2161*b2ed49a5SDavid van Moolenbroek 			    _magic_unmap_mem[i].length == length)
2162*b2ed49a5SDavid van Moolenbroek 				break;
2163*b2ed49a5SDavid van Moolenbroek 		assert(i < MAGIC_UNMAP_MEM_ENTRIES);
2164*b2ed49a5SDavid van Moolenbroek 
2165*b2ed49a5SDavid van Moolenbroek 		/* Clear the entry. */
2166*b2ed49a5SDavid van Moolenbroek 		_magic_unmap_mem[i].start = NULL;
2167*b2ed49a5SDavid van Moolenbroek 		_magic_unmap_mem[i].length = 0;
2168*b2ed49a5SDavid van Moolenbroek 	}
2169*b2ed49a5SDavid van Moolenbroek 
2170*b2ed49a5SDavid van Moolenbroek 	return r;
2171*b2ed49a5SDavid van Moolenbroek }
2172*b2ed49a5SDavid van Moolenbroek #endif
2173*b2ed49a5SDavid van Moolenbroek 
2174