summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2014-04-22 19:17:26 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2014-04-22 19:19:24 +0900
commitf21cfc0554820f6eccad780ddbf4958d28364b3b (patch)
treec258dd49123f9d3f5e240c0c85ff6ecda59e302f
parent59b660aae9a912eee8e0bd458352fba435943284 (diff)
eo - callstack. realloc is a bad idea. use mmap and keep addr fixed
this fixes and eo2 problem where when callstack grows (or shrinks) and realloc nas to relocate memory, the frame ptrs like fptr become invalid and all sorts of hell ensues. this uses mmap so blowing the stack will segv, not scribble over memory, also its separated from malloc heap, and now big enough to not need to size ... ever (1024 entries).
-rw-r--r--src/lib/eo/eo.c79
1 files changed, 75 insertions, 4 deletions
diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
index d74229c..6ad7fc5 100644
--- a/src/lib/eo/eo.c
+++ b/src/lib/eo/eo.c
@@ -254,7 +254,9 @@ EAPI Eo_Hook_Call eo_hook_call_post = NULL;
254 254
255// FIXME: Thread Local Storage 255// FIXME: Thread Local Storage
256#define EO_INVALID_DATA (void *) -1 256#define EO_INVALID_DATA (void *) -1
257#define EO_CALL_STACK_DEPTH 30 257// 1024 entries == 8k or 16k (32 or 64bit) for eo call stack. that's 1024
258// recursion entires it can handle before barfing. i'd say that's ok
259#define EO_CALL_STACK_DEPTH 1024
258 260
259typedef struct _Eo_Stack_Frame 261typedef struct _Eo_Stack_Frame
260{ 262{
@@ -276,6 +278,62 @@ typedef struct _Eo_Call_Stack {
276 Eo_Stack_Frame *shrink_frame; 278 Eo_Stack_Frame *shrink_frame;
277} Eo_Call_Stack; 279} Eo_Call_Stack;
278 280
281#define MEM_PAGE_SIZE 4096
282
283static void *
284_eo_call_stack_mem_alloc(size_t maxsize)
285{
286#ifdef __linux__
287 // allocate eo call stack via mmped anon segment if on linux - more
288 // secure and safe. also gives page aligned memory allowing madvise
289 void *ptr;
290 size_t newsize;
291 newsize = MEM_PAGE_SIZE * ((maxsize + MEM_PAGE_SIZE - 1) /
292 MEM_PAGE_SIZE);
293 ptr = mmap(NULL, newsize, PROT_READ | PROT_WRITE,
294 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
295 if (ptr == MAP_FAILED)
296 {
297 ERR("mmap of eo callstack failed!");
298 return NULL;
299 }
300 return ptr;
301#else
302 //in regular cases just use malloc
303 return malloc(maxsize);
304#endif
305}
306
307static void
308_eo_call_stack_mem_resize(void **ptr EINA_UNUSED, size_t newsize, size_t maxsize)
309{
310#ifdef __linux__
311 // resize call stack down - currently won't ever be called
312 if (newsize > maxsize)
313 {
314 ERR("eo callstack overflow");
315 abort();
316 }
317 size_t addr = MEM_PAGE_SIZE * ((newsize + MEM_PAGE_SIZE - 1) /
318 MEM_PAGE_SIZE);
319 madvise(((unsigned char *)*ptr) + addr, maxsize - addr, MADV_DONTNEED);
320#else
321 // just grow in regular cases
322#endif
323}
324
325static void
326_eo_call_stack_mem_free(void *ptr, size_t maxsize)
327{
328#ifdef __linux__
329 // free mmaped memory
330 munmap(ptr, maxsize);
331#else
332 // free regular memory
333 free(ptr);
334#endif
335}
336
279static Eo_Call_Stack * 337static Eo_Call_Stack *
280_eo_call_stack_create() 338_eo_call_stack_create()
281{ 339{
@@ -285,7 +343,10 @@ _eo_call_stack_create()
285 if (!stack) 343 if (!stack)
286 return NULL; 344 return NULL;
287 345
288 stack->frames = calloc(EO_CALL_STACK_DEPTH, sizeof(Eo_Stack_Frame)); 346// XXX: leave in for noew in case this breaks, but remove later when ok
347// stack->frames = calloc(EO_CALL_STACK_DEPTH, sizeof(Eo_Stack_Frame));
348 stack->frames = _eo_call_stack_mem_alloc(EO_CALL_STACK_DEPTH *
349 sizeof(Eo_Stack_Frame));
289 if (!stack->frames) 350 if (!stack->frames)
290 { 351 {
291 free(stack); 352 free(stack);
@@ -308,7 +369,13 @@ _eo_call_stack_free(void *ptr)
308 if (!stack) return; 369 if (!stack) return;
309 370
310 if (stack->frames) 371 if (stack->frames)
311 free(stack->frames); 372 {
373// XXX: leave in for noew in case this breaks, but remove later when ok
374// free(stack->frames);
375 _eo_call_stack_mem_free(stack->frames,
376 (stack->last_frame - stack->frames + 1) *
377 sizeof(Eo_Stack_Frame));
378 }
312 free(stack); 379 free(stack);
313} 380}
314 381
@@ -350,7 +417,11 @@ _eo_call_stack_resize(Eo_Call_Stack *stack, Eina_Bool grow)
350 next_sz = sz >> 1; 417 next_sz = sz >> 1;
351 418
352 DBG("resize from %lu to %lu", (long unsigned int)sz, (long unsigned int)next_sz); 419 DBG("resize from %lu to %lu", (long unsigned int)sz, (long unsigned int)next_sz);
353 stack->frames = realloc(stack->frames, next_sz * sizeof(Eo_Stack_Frame)); 420// XXX: leave in for noew in case this breaks, but remove later when ok
421// stack->frames = realloc(stack->frames, next_sz * sizeof(Eo_Stack_Frame));
422 _eo_call_stack_mem_resize((void **)&(stack->frames),
423 next_sz * sizeof(Eo_Stack_Frame),
424 sz * sizeof(Eo_Stack_Frame));
354 if (!stack->frames) 425 if (!stack->frames)
355 { 426 {
356 CRI("unable to resize call stack, abort."); 427 CRI("unable to resize call stack, abort.");