HPCToolkit
data-overrides.c
Go to the documentation of this file.
1 // -*-Mode: C++;-*- // technically C99
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL$
6 // $Id$
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2018, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 // DATACENTRIC overrides the malloc family of functions and provides two
48 // metrics: number of bytes allocated and the start address
49 // dynamic context.
50 //
51 // Override functions:
52 // posix_memalign, memalign, valloc
53 // malloc, calloc, free, realloc
54 
55 /******************************************************************************
56  * standard include files
57  *****************************************************************************/
58 
59 #define __USE_XOPEN_EXTENDED
60 #include <sys/stat.h>
61 #include <sys/time.h>
62 #include <sys/types.h>
63 #include <assert.h>
64 #include <errno.h>
65 #include <fcntl.h>
66 #include <stdint.h>
67 #include <string.h>
68 #include <ucontext.h>
69 
70 /* definition for posix memalign */
71 #undef _XOPEN_SOURCE // avoid complaint about redefinition
72 #define _XOPEN_SOURCE 600
73 #include <stdlib.h>
74 
75 /* definition for valloc, memalign */
76 #include <malloc.h>
77 
78 /* definition for sysconf */
79 #include <unistd.h>
80 
81 /* definition for _SC_PAGESIZE */
82 #include <sys/mman.h>
83 
84 
85 
86 /******************************************************************************
87  * local include files
88  *****************************************************************************/
89 
90 #include <messages/messages.h>
91 #include <safe-sampling.h>
92 #include <sample_event.h>
94 
96 
97 #include "data_tree.h"
98 #include "data-overrides.h"
99 
100 
101 // FIXME: the inline getcontext macro is broken on 32-bit x86, so
102 // revert to the getcontext syscall for now.
103 #if defined(__i386__)
104 #ifndef USE_SYS_GCTXT
105 #define USE_SYS_GCTXT
106 #endif
107 #else // ! __i386__
109 #include <utilities/arch/mcontext.h>
110 #endif
111 
112 #define NUM_DATA_METRICS 2
113 
114 
115 /******************************************************************************
116  * type definitions
117  *****************************************************************************/
118 
119 typedef void *memalign_fcn(size_t, size_t);
120 typedef void *valloc_fcn(size_t);
121 typedef void *malloc_fcn(size_t);
122 typedef void free_fcn(void *);
123 typedef void *realloc_fcn(void *, size_t);
124 
125 
126 
127 /******************************************************************************
128  * macros
129  *****************************************************************************/
130 
131 #define DATACENTRIC_USE_HYBRID_LAYOUT 0
132 
133 #define DATACENTRIC_MAGIC 0x68706374
134 #define DATACENTRIC_DEFAULT_PAGESIZE 4096
135 
136 #define HPCRUN_DATACENTRIC_PROB "HPCRUN_DATACENTRIC_PROB"
137 #define DEFAULT_PROB 0.1
138 
139 #ifdef HPCRUN_STATIC_LINK
140 #define real_memalign __real_memalign
141 #define real_valloc __real_valloc
142 #define real_malloc __real_malloc
143 #define real_free __real_free
144 #define real_realloc __real_realloc
145 #else
146 #define real_memalign __libc_memalign
147 #define real_valloc __libc_valloc
148 #define real_malloc __libc_malloc
149 #define real_free __libc_free
150 #define real_realloc __libc_realloc
151 #endif
152 
154 extern valloc_fcn real_valloc;
155 extern malloc_fcn real_malloc;
156 extern free_fcn real_free;
158 
159 
160 enum {
164 };
165 
168 };
169 
170 /******************************************************************************
171  * private data
172  *****************************************************************************/
173 
175 
176 static int use_datacentric_prob = 0;
177 static float datacentric_prob = 0.0;
178 
180 
181 static char *loc_name[4] = {
182  NULL, "header", "footer", "none"
183 };
184 
185 static int datainfo_size = sizeof(struct datatree_info_s);
186 
187 static int addr_end_metric_id = -1;
188 static int addr_start_metric_id = -1;
189 
190 
191 /******************************************************************************
192  * private operations
193  *****************************************************************************/
194 
195 // Accept 0.ddd as floating point or x/y as fraction.
196 static float
197 string_to_prob(char *str)
198 {
199  int x, y;
200  float ans;
201 
202  if (strchr(str, '/') != NULL) {
203  if (sscanf(str, "%d/%d", &x, &y) == 2 && y > 0) {
204  ans = (float)x / (float)y;
205  } else {
206  ans = DEFAULT_PROB;
207  }
208  } else {
209  if (sscanf(str, "%f", &ans) < 1) {
210  ans = DEFAULT_PROB;
211  }
212  }
213 
214  return ans;
215 }
216 
220 static bool
222 {
224 }
225 
226 
230 static int
232 {
233  return datacentric_get_metric_addr_end() >= 0;
234 }
235 
236 
237 static const unsigned int MAX_CHAR_FORMULA = 32;
238 
243 static void
245 {
246  if (addr_end_metric_id >= 0)
247  return; // been registered
248 
251 
252  // set the formula for metric start address and end address
253  // the start address metric is the minimum address
254  // the end address metric is the maximum of all accessed memory
255 
260 
261  metric_start->formula = (char*) hpcrun_malloc(sizeof(char) * MAX_CHAR_FORMULA);
262  sprintf(metric_start->formula, "min($%d)", addr_start_metric_id);
263 
264  metric_end->formula = (char*) hpcrun_malloc(sizeof(char) * MAX_CHAR_FORMULA);
265  sprintf(metric_end->formula, "max($%d)", addr_end_metric_id);
266 }
267 
271 static void
273 {
274  struct timeval tv;
275  char *prob_str;
276  unsigned int seed;
277  int fd;
278 
279  if (is_initialized())
280  return;
281 
282 #ifdef _SC_PAGESIZE
283  datacentric_pagesize = sysconf(_SC_PAGESIZE);
284 #else
286 #endif
287 
288  // If we are sampling the mallocs, then read the probability and
289  // seed the random number generator.
290  prob_str = getenv(HPCRUN_DATACENTRIC_PROB);
291  if (prob_str != NULL) {
293  datacentric_prob = string_to_prob(prob_str);
294  TMSG(DATACENTRIC, "sampling mallocs with prob = %f", datacentric_prob);
295 
296  seed = 0;
297  fd = open("/dev/urandom", O_RDONLY);
298  if (fd >= 0) {
299  read(fd, &seed, sizeof(seed));
300  close(fd);
301  }
302  gettimeofday(&tv, NULL);
303  seed += (getpid() << 16) + (tv.tv_usec << 4);
304  srandom(seed);
305  }
306 
308 
310 
311  TMSG(DATACENTRIC, "initialized");
312 }
313 
314 
315 
316 
317 // Choose the location of the leakinfo struct at malloc(). Use a
318 // header if the system and application pointers are on the same page
319 // (so free can look for a header without risking a segfault). Note:
320 // aligned mallocs never get headers.
321 //
322 // sys_ptr = pointer returned by sysem malloc
323 // bytes = size of application's region
324 // align = non-zero if an aligned malloc
325 //
326 // Returns: enum constant for header/footer
327 // appl_ptr = value given to the application
328 // info_ptr = location of the leakinfo struct
329 //
330 static int
331 datacentric_get_malloc_loc(void *sys_ptr, size_t bytes, size_t align,
332  void **appl_ptr, datatree_info_t **info_ptr)
333 {
334 #if DATACENTRIC_USE_HYBRID_LAYOUT
335  if (datacentric_same_page(sys_ptr, sys_ptr + datainfo_size) && align == 0) {
336  *appl_ptr = sys_ptr + datainfo_size;
337  *info_ptr = sys_ptr;
338  return DATACENTRIC_LOC_HEAD;
339  }
340 #endif
341 
342  // footer
343  *appl_ptr = sys_ptr;
344  *info_ptr = sys_ptr + bytes;
345  return DATACENTRIC_LOC_FOOT;
346 }
347 
348 
349 // Find the location of the leakinfo struct at free().
350 //
351 // Returns: enum constant for header/footer/none,
352 // and system and leakinfo pointers.
353 //
354 static int
355 datacentric_get_free_loc(void *appl_ptr, void **sys_ptr, datatree_info_t **info_ptr)
356 {
357  static int num_errors = 0;
358 
359 #if DATACENTRIC_USE_HYBRID_LAYOUT
360  // try header first
361  *info_ptr = (datatree_info_t *) (appl_ptr - datainfo_size);
362  if (datacentric_same_page(*info_ptr, appl_ptr)
363  && (*info_ptr)->magic == DATACENTRIC_MAGIC
364  && (*info_ptr)->memblock == appl_ptr) {
365  *sys_ptr = *info_ptr;
366  return DATACENTRIC_LOC_HEAD;
367  }
368 #endif
369 
370  // always try footer
371  *sys_ptr = appl_ptr;
372  *info_ptr = datatree_splay_delete(appl_ptr);
373  if (*info_ptr == NULL) {
374  return DATACENTRIC_LOC_NONE;
375  }
376  if ((*info_ptr)->magic == DATACENTRIC_MAGIC
377  && (*info_ptr)->memblock == appl_ptr) {
378  return DATACENTRIC_LOC_FOOT;
379  }
380 
381  // must be memory corruption somewhere. maybe a bug in our code,
382  // but more likely someone else has stomped on our data.
383  num_errors++;
384  if (num_errors < 100) {
385  AMSG("DATACENTRIC: Warning: memory corruption in leakinfo node: %p "
386  "sys: %p appl: %p magic: 0x%lx context: %p bytes: %ld memblock: %p",
387  *info_ptr, *sys_ptr, appl_ptr, (*info_ptr)->magic, (*info_ptr)->context,
388  (*info_ptr)->bytes, (*info_ptr)->memblock);
389  }
390  *info_ptr = NULL;
391  return DATACENTRIC_LOC_NONE;
392 }
393 
394 
395 // Fill in the leakinfo struct, add metric to CCT, add to splay tree
396 // (if footer) and print TMSG.
397 //
398 static void
399 datacentric_add_leakinfo(const char *name, void *sys_ptr, void *appl_ptr,
400  datatree_info_t *info_ptr, size_t bytes, ucontext_t *uc,
401  int loc)
402 {
403  char *loc_str;
404 
405  if (info_ptr == NULL) {
406  TMSG(DATACENTRIC, "Warning: %s: bytes: %ld sys: %p appl: %p info: %p "
407  "(NULL leakinfo pointer, this should not happen)",
408  name, bytes, sys_ptr, appl_ptr, info_ptr);
409  return;
410  }
411 
412  info_ptr->magic = DATACENTRIC_MAGIC;
413  info_ptr->bytes = bytes;
414  info_ptr->memblock = appl_ptr;
415  info_ptr->rmemblock = info_ptr->memblock + info_ptr->bytes;
416 
417  info_ptr->left = NULL;
418  info_ptr->right = NULL;
419 
420  if (is_active()) {
422  if (!td || !td->core_profile_trace_data.epoch) {
423  // if we are called too early and epoch is not set,
424  // we return immediately, and no need to get malloc information
425  // this mostly happens inside a library initialization
426  return;
427  }
428 
429  int metric_start_addr = datacentric_get_metric_addr_start();
430 
431  // record the call path to this allocation, and the address
432  sample_val_t smpl = hpcrun_sample_callpath(uc, metric_start_addr,
433  (hpcrun_metricVal_t) {.p=appl_ptr},
434  0, 1, NULL);
435 
436  // update the number of metric counter
437  metric_aux_info_t *info_aux = &(td->core_profile_trace_data.perf_event_info[metric_start_addr]);
438  info_aux->num_samples++;
439 
440  // record the end address of this allocation
442  hpcrun_metricVal_t value;
443  value.p = appl_ptr + bytes;
444  int metric_end_addr = datacentric_get_metric_addr_end();
445 
446  hpcrun_metric_std_set(metric_end_addr, mset, value);
447 
448  // update the number of metric counter
449  info_aux = &(td->core_profile_trace_data.perf_event_info[metric_end_addr]);
450  info_aux->num_samples++;
451 
452  info_ptr->context = smpl.sample_node;
453  loc_str = loc_name[loc];
454 
455  // mark that this node is an allocation node
456  // inside hpcrun file, we'll give a special flag in this node so that
457  // hpcprof will keep its id and link it to the mem_access node
459 
460  } else {
461  info_ptr->context = NULL;
462  loc_str = "inactive";
463  }
464  if (loc == DATACENTRIC_LOC_FOOT) {
465  datatree_splay_insert(info_ptr);
466  }
467 
468  TMSG(DATACENTRIC, "%s: bytes: %ld sys: %p appl: %p info: %p cct: %p (%s)",
469  name, bytes, sys_ptr, appl_ptr, info_ptr, info_ptr->context, loc_str);
470 }
471 
472 
473 // Unified function for all of the mallocs, aligned and unaligned.
474 // Do the malloc, add the leakinfo struct and print TMSG.
475 //
476 // bytes = size of application region
477 // align = size of alignment, or 0 for unaligned
478 // clear = 1 if want region memset to 0 (for calloc)
479 // ret = return value from posix_memalign()
480 //
481 static void *
482 datacentric_malloc_helper(const char *name, size_t bytes, size_t align,
483  int clear, ucontext_t *uc, int *ret)
484 {
485  void *sys_ptr, *appl_ptr;
486  datatree_info_t *info_ptr;
487  char *inactive_mesg = "inactive";
488  int active, loc;
489  size_t size;
490 
491  // do the real malloc, aligned or not. note: we can't track malloc
492  // inside dlopen, that would lead to deadlock.
493  active = 1;
494  if (! (is_initialized() && is_active())) {
495  active = 0;
496  } else if (TD_GET(inside_dlfcn)) {
497  active = 0;
498  inactive_mesg = "unable to monitor: inside dlfcn";
499  } else if (use_datacentric_prob && (random()/(float)RAND_MAX > datacentric_prob)) {
500  active = 0;
501  inactive_mesg = "not sampled";
502  }
503  size = bytes + (active ? datainfo_size : 0);
504  if (align != 0) {
505  // there is no __libc_posix_memalign(), so we use __libc_memalign()
506  // instead, or else use dlsym().
507  sys_ptr = real_memalign(align, size);
508  if (ret != NULL) {
509  *ret = (sys_ptr == NULL) ? errno : 0;
510  }
511  } else {
512  sys_ptr = real_malloc(size);
513  }
514  if (clear && sys_ptr != NULL) {
515  memset(sys_ptr, 0, size);
516  }
517 
518  // inactive or failed malloc
519  if (! active) {
520  TMSG(DATACENTRIC, "%s: bytes: %ld, sys: %p (%s)",
521  name, bytes, sys_ptr, inactive_mesg);
522  return sys_ptr;
523  }
524  if (sys_ptr == NULL) {
525  TMSG(DATACENTRIC, "%s: bytes: %ld, sys: %p (failed)",
526  name, bytes, sys_ptr);
527  return sys_ptr;
528  }
529  if (bytes <= DATACENTRIC_MIN_BYTES) return sys_ptr;
530 
531  TMSG(DATACENTRIC, "%s: bytes: %ld", name, bytes);
532 
533  loc = datacentric_get_malloc_loc(sys_ptr, bytes, align, &appl_ptr, &info_ptr);
534  datacentric_add_leakinfo(name, sys_ptr, appl_ptr, info_ptr, bytes, uc, loc);
535 
536  return appl_ptr;
537 }
538 
539 
540 
541 /******************************************************************************
542  * interface operations
543  *****************************************************************************/
544 
545 // The datacentric overrides pose extra challenges for safe sampling.
546 // When we enter a datacentric override, if we're coming from inside our
547 // own code, we can't just automatically call the real version of the
548 // function and return. The problem is that sometimes we put headers
549 // in front of the malloc'd region and thus the application and the
550 // system don't use the same pointer for the beginning of the region.
551 //
552 // For malloc, memalign, etc, it's ok to return the real version
553 // without a header. The free code checks for the case of no header
554 // or footer. And actually, there are always a few system mallocs
555 // that happen before we get initialized that go untracked.
556 //
557 // But for free, we can't just call the real free if the region might
558 // have a header. In that case, we'd be freeing the wrong pointer and
559 // the memory system would crash.
560 //
561 // Now, we could call the real free if we were 100% certain that the
562 // malloc also came from our code and thus had no header. But if
563 // there's anything that slips through the cracks, then the program
564 // crashes. OTOH, running our code looking for a header might hit
565 // deadlock if the debug MSGS are on. Choose your poison, but
566 // probably this case never happens.
567 //
568 // The moral is: be careful not to use malloc or free in our code.
569 // Use mmap and hpcrun_malloc instead.
570 
571 int
572 MONITOR_EXT_WRAP_NAME(posix_memalign)(void **memptr, size_t alignment,
573  size_t bytes)
574 {
575  ucontext_t uc;
576  int ret;
577 
578  if (! hpcrun_safe_enter()) {
579  *memptr = real_memalign(alignment, bytes);
580  return (*memptr == NULL) ? errno : 0;
581  }
583 
584 #ifdef USE_SYS_GCTXT
585  getcontext(&uc);
586 #else // ! USE_SYS_GCTXT
587  INLINE_ASM_GCTXT(uc);
588 #endif // USE_SYS_GCTXT
589 
590  *memptr = datacentric_malloc_helper("posix_memalign", bytes, alignment, 0, &uc, &ret);
592  return ret;
593 }
594 
595 
596 void *
597 MONITOR_EXT_WRAP_NAME(memalign)(size_t boundary, size_t bytes)
598 {
599  ucontext_t uc;
600  void *ptr;
601 
602  if (! hpcrun_safe_enter()) {
603  return real_memalign(boundary, bytes);
604  }
606 
607 #ifdef USE_SYS_GCTXT
608  getcontext(&uc);
609 #else // ! USE_SYS_GCTXT
610  INLINE_ASM_GCTXT(uc);
611 #endif // USE_SYS_GCTXT
612 
613  ptr = datacentric_malloc_helper("memalign", bytes, boundary, 0, &uc, NULL);
615  return ptr;
616 }
617 
618 
619 void *
621 {
622  ucontext_t uc;
623  void *ptr;
624 
625  if (! hpcrun_safe_enter()) {
626  return real_valloc(bytes);
627  }
629 
630 #ifdef USE_SYS_GCTXT
631  getcontext(&uc);
632 #else // ! USE_SYS_GCTXT
633  INLINE_ASM_GCTXT(uc);
634 #endif // USE_SYS_GCTXT
635 
636  ptr = datacentric_malloc_helper("valloc", bytes, datacentric_pagesize, 0, &uc, NULL);
638  return ptr;
639 }
640 
641 
642 void *
644 {
645  ucontext_t uc;
646  void *ptr;
647 
648  if (! hpcrun_safe_enter()) {
649  return real_malloc(bytes);
650  }
652 
653 #ifdef USE_SYS_GCTXT
654  getcontext(&uc);
655 #else // ! USE_SYS_GCTXT
656  INLINE_ASM_GCTXT(uc);
657 #endif // USE_SYS_GCTXT
658 
659  ptr = datacentric_malloc_helper("malloc", bytes, 0, 0, &uc, NULL);
661  return ptr;
662 }
663 
664 
665 void *
666 MONITOR_EXT_WRAP_NAME(calloc)(size_t nmemb, size_t bytes)
667 {
668  ucontext_t uc;
669  void *ptr;
670 
671  if (! hpcrun_safe_enter()) {
672  ptr = real_malloc(nmemb * bytes);
673  if (ptr != NULL) {
674  memset(ptr, 0, nmemb * bytes);
675  }
676  return ptr;
677  }
679 
680 #ifdef USE_SYS_GCTXT
681  getcontext(&uc);
682 #else // ! USE_SYS_GCTXT
683  INLINE_ASM_GCTXT(uc);
684 #endif // USE_SYS_GCTXT
685 
686  ptr = datacentric_malloc_helper("calloc", nmemb * bytes, 0, 1, &uc, NULL);
688  return ptr;
689 }
690 
691 
692 // For free() and realloc(), we must always look for a header, even if
693 // the metric is inactive and we don't record it in the CCT (unless
694 // datacentric is entirely disabled). If the region has a header, then
695 // the system ptr is not the application ptr, and we must find the
696 // sytem ptr or else free() will crash.
697 //
698 void
700 {
701  datatree_info_t *info_ptr;
702  void *sys_ptr;
703  int loc;
704 
705  // look for header, even if came from inside our code.
706  int safe = hpcrun_safe_enter();
707 
709 
710  if (! is_initialized()) {
711  real_free(ptr);
712  TMSG(DATACENTRIC, "free: ptr: %p (inactive)", ptr);
713  goto finish;
714  }
715  if (ptr == NULL) {
716  goto finish;
717  }
718 
719  loc = datacentric_get_free_loc(ptr, &sys_ptr, &info_ptr);
720  if (loc != DATACENTRIC_LOC_NONE) {
721  real_free(sys_ptr);
722  } else {
723  real_free(ptr);
724  }
725 
726 finish:
727  if (safe) {
729  }
730  return;
731 }
732 
733 
734 void *
735 MONITOR_EXT_WRAP_NAME(realloc)(void *ptr, size_t bytes)
736 {
737  ucontext_t uc;
738  datatree_info_t *info_ptr;
739  void *ptr2, *appl_ptr, *sys_ptr;
740  char *inactive_mesg = "inactive";
741  int loc, loc2, active;
742 
743  // look for header, even if came from inside our code.
744  int safe = hpcrun_safe_enter();
745 
747 
748  if (! is_initialized()) {
749  appl_ptr = real_realloc(ptr, bytes);
750  goto finish;
751  }
752 
753 #ifdef USE_SYS_GCTXT
754  getcontext(&uc);
755 #else // ! USE_SYS_GCTXT
756  INLINE_ASM_GCTXT(uc);
757 #endif // USE_SYS_GCTXT
758 
759  // realloc(NULL, bytes) means malloc(bytes)
760  if (ptr == NULL) {
761  appl_ptr = datacentric_malloc_helper("realloc/malloc", bytes, 0, 0, &uc, NULL);
762  goto finish;
763  }
764 
765  // for datacentric metric, treat realloc as a free of the old bytes
766  loc = datacentric_get_free_loc(ptr, &sys_ptr, &info_ptr);
767 
768  // realloc(ptr, 0) means free(ptr)
769  if (bytes == 0) {
770  real_free(sys_ptr);
771  appl_ptr = NULL;
772  goto finish;
773  }
774 
775  // if inactive, then do real_realloc() and return.
776  // but if there used to be a header, then must slide user data.
777  // again, can't track malloc inside dlopen.
778  active = 1;
779  if (! (is_initialized() && is_active())) {
780  active = 0;
781  } else if (TD_GET(inside_dlfcn)) {
782  active = 0;
783  inactive_mesg = "unable to monitor: inside dlfcn";
784  } else if (use_datacentric_prob && (random()/(float)RAND_MAX > datacentric_prob)) {
785  active = 0;
786  inactive_mesg = "not sampled";
787  } else if (bytes <= DATACENTRIC_MIN_BYTES) {
788  active = 0;
789  inactive_mesg = "size too small";
790  }
791  if (! active) {
792  if (loc == DATACENTRIC_LOC_HEAD) {
793  // slide left
794  memmove(sys_ptr, ptr, bytes);
795  }
796  appl_ptr = real_realloc(sys_ptr, bytes);
797  TMSG(DATACENTRIC, "realloc: bytes: %ld ptr: %p (%s)",
798  bytes, appl_ptr, inactive_mesg);
799  goto finish;
800  }
801 
802  // realloc and add leak info to new location. treat this as a
803  // malloc of the new size. note: if realloc moves the data and
804  // switches header/footer, then need to slide the user data.
805  size_t size = bytes + datainfo_size;
806  ptr2 = real_realloc(sys_ptr, size);
807  loc2 = datacentric_get_malloc_loc(ptr2, bytes, 0, &appl_ptr, &info_ptr);
808  if (loc == DATACENTRIC_LOC_HEAD && loc2 != DATACENTRIC_LOC_HEAD) {
809  // slide left
810  memmove(ptr2, ptr2 + datainfo_size, bytes);
811  }
812  else if (loc != DATACENTRIC_LOC_HEAD && loc2 == DATACENTRIC_LOC_HEAD) {
813  // slide right
814  memmove(ptr2 + datainfo_size, ptr, bytes);
815  }
816  datacentric_add_leakinfo("realloc/malloc", ptr2, appl_ptr, info_ptr, bytes, &uc, loc2);
817 
818 finish:
819  if (safe) {
821  }
822  return appl_ptr;
823 }
824 
825 
826 
828 // INTERFACES
829 //
830 // Exported functions
832 
833 /***
834  * @return the metric id of allocation
835  */
836 int
838 {
839  return addr_end_metric_id;
840 }
841 
842 int
844 {
845  return addr_start_metric_id;
846 }
847 
void * memalign_fcn(size_t, size_t)
metric_aux_info_t * perf_event_info
void * memblock
Definition: data_tree.h:70
void MONITOR_EXT_WRAP_NAME() free(void *ptr)
metric_set_t * hpcrun_reify_metric_set(cct_node_id_t cct_id)
Definition: cct2metrics.c:115
static float datacentric_prob
static void datacentric_initialize(void)
struct datatree_info_s * right
Definition: data_tree.h:74
static void hpcrun_safe_exit(void)
static int datacentric_get_malloc_loc(void *sys_ptr, size_t bytes, size_t align, void **appl_ptr, datatree_info_t **info_ptr)
sample_val_t hpcrun_sample_callpath(void *context, int metricId, hpcrun_metricVal_t metricIncr, int skipInner, int isSync, sampling_info_t *data)
Definition: sample_event.c:160
void * realloc_fcn(void *, size_t)
#define real_free
void *MONITOR_EXT_WRAP_NAME() valloc(size_t bytes)
int datacentric_get_metric_addr_end()
static const unsigned int MAX_CHAR_FORMULA
#define MONITOR_EXT_WRAP_NAME(name)
Definition: monitor_ext.h:92
static int is_active()
static int addr_end_metric_id
void *MONITOR_EXT_WRAP_NAME() calloc(size_t nmemb, size_t bytes)
void hpcrun_metric_std_set(int metric_id, metric_set_t *set, hpcrun_metricVal_t value)
Definition: metrics.c:525
#define real_realloc
cct_node_t * sample_node
Definition: sample_event.h:96
data_overrides_status_e
static int datainfo_size
static void * datacentric_malloc_helper(const char *name, size_t bytes, size_t align, int clear, ucontext_t *uc, int *ret)
size_t bytes
Definition: data_tree.h:69
#define DEFAULT_PROB
#define DATACENTRIC_MIN_BYTES
Definition: data_tree.h:59
void * malloc_fcn(size_t)
void datatree_splay_insert(struct datatree_info_s *node)
Definition: data_tree.c:129
struct datatree_info_s * left
Definition: data_tree.h:73
metric_desc_t * hpcrun_set_metric_and_attributes(int metric_id, const char *name, MetricFlags_ValFmt_t valFmt, size_t period, metric_desc_properties_t prop, uint8_t show, uint8_t show_percent)
Definition: metrics.c:397
uint64_t num_samples
Definition: hpcfmt.h:349
static int use_datacentric_prob
void * valloc_fcn(size_t)
void *MONITOR_EXT_WRAP_NAME() memalign(size_t boundary, size_t bytes)
struct datatree_info_s * datatree_splay_delete(void *memblock)
Definition: data_tree.c:165
#define real_memalign
static void datacentric_add_leakinfo(const char *name, void *sys_ptr, void *appl_ptr, datatree_info_t *info_ptr, size_t bytes, ucontext_t *uc, int loc)
void free_fcn(void *)
static long datacentric_pagesize
core_profile_trace_data_t core_profile_trace_data
Definition: thread_data.h:168
static void DATACENTRIC()
Definition: cct_bundle.c:71
void * hpcrun_malloc(size_t size)
Definition: mem.c:275
static char * loc_name[4]
cct_node_t * context
Definition: data_tree.h:68
static enum data_overrides_status_e overrides_status
static int num_errors
#define TD_GET(field)
Definition: thread_data.h:256
#define real_valloc
int datacentric_get_metric_addr_start()
static int datacentric_get_free_loc(void *appl_ptr, void **sys_ptr, datatree_info_t **info_ptr)
void *MONITOR_EXT_WRAP_NAME() realloc(void *ptr, size_t bytes)
#define TMSG(f,...)
Definition: messages.h:93
#define HPCRUN_DATACENTRIC_PROB
static int addr_start_metric_id
char * formula
Definition: hpcrun-fmt.h:378
#define AMSG
Definition: messages.h:71
ssize_t MONITOR_EXT_WRAP_NAME() read(int fd, void *buf, size_t count)
Definition: io-over.c:152
void *MONITOR_EXT_WRAP_NAME() malloc(size_t bytes)
#define NULL
Definition: ElfHelper.cpp:85
unsigned char uc
Definition: amd-xop.c:3
int hpcrun_new_metric(void)
Definition: metrics.c:333
#define DATACENTRIC_MAGIC
#define DATACENTRIC_METRIC_PREFIX
Definition: datacentric.h:64
#define real_malloc
int MONITOR_EXT_WRAP_NAME() posix_memalign(void **memptr, size_t alignment, size_t bytes)
#define DATACENTRIC_DEFAULT_PAGESIZE
void hpcrun_cct_set_node_allocation(cct_node_t *node)
Definition: cct.c:468
void * rmemblock
Definition: data_tree.h:71
static float string_to_prob(char *str)
static bool is_initialized()
static int hpcrun_safe_enter(void)
#define INLINE_ASM_GCTXT(uc)
thread_data_t *(* hpcrun_get_thread_data)(void)
Definition: thread_data.c:168
#define metric_property_none
Definition: hpcrun-fmt.h:202
static void metric_initialize()