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