Ltest-nocalloc.c revision 65f936402d0dd0e62191ed249f86946203476e28
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* libunwind - a platform-independent unwind library
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   Copyright (C) 2011 Google, Inc
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	Contributed by Paul Pluzhnikov <ppluzhnikov@google.com>
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Permission is hereby granted, free of charge, to any person obtaining
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)a copy of this software and associated documentation files (the
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"Software"), to deal in the Software without restriction, including
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)without limitation the rights to use, copy, modify, merge, publish,
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)distribute, sublicense, and/or sell copies of the Software, and to
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)permit persons to whom the Software is furnished to do so, subject to
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)the following conditions:
1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)The above copyright notice and this permission notice shall be
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)included in all copies or substantial portions of the Software.
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UNW_LOCAL_ONLY
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libunwind.h>
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
2858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include <stdio.h>
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dlfcn.h>
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pthread.h>
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define panic(args...)				\
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ fprintf (stderr, args); exit (-1); }
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint num_mallocs;
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint num_callocs;
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint in_unwind;
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid *
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccicalloc(size_t n, size_t s)
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci{
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void * (*func)(size_t, size_t);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifdef __GLIBC__
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* In glibc, dlsym() calls calloc. Calling dlsym(RTLD_NEXT, "calloc") here
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     causes infinite recursion.  Instead, we simply use it by its other
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     name.  */
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extern void *__libc_calloc(size_t, size_t);
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  func = &__libc_calloc;
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#else
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if(!func)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    func = dlsym(RTLD_NEXT, "calloc");
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (in_unwind) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_callocs++;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  } else {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return func(n, s);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid *
65116680a4aac90f2aa7413d9095a592090648e557Ben Murdochmalloc(size_t s)
66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch{
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void * (*func)(size_t);
68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if(!func)
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    func = dlsym(RTLD_NEXT, "malloc");
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (in_unwind) {
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    num_mallocs++;
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return NULL;
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return func(s);
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic void
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)do_backtrace (void)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int num_levels = 100;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *pc[num_levels];
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  in_unwind = 1;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unw_backtrace(pc, num_levels);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  in_unwind = 0;
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)foo3 (void)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  do_backtrace ();
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)foo2 (void)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  foo3 ();
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccifoo1 (void)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  foo2 ();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)main (void)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i, num_errors;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Create (and leak) 100 TSDs, then call backtrace()
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     and check that it doesn't call malloc()/calloc().  */
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < 100; ++i) {
117    pthread_key_t key;
118    if (pthread_key_create (&key, NULL))
119      panic ("FAILURE: unable to create key %d\n", i);
120  }
121  /* Call backtrace right after thread creation,
122   * where we are sure that we're not inside malloc */
123  do_backtrace();
124  num_mallocs = num_callocs = 0;
125  foo1 ();
126  num_errors = num_mallocs + num_callocs;
127  if (num_errors > 0)
128    {
129      fprintf (stderr,
130	       "FAILURE: detected %d error%s (malloc: %d, calloc: %d)\n",
131	       num_errors, num_errors > 1 ? "s" : "",
132	       num_mallocs, num_callocs);
133      exit (-1);
134    }
135  return 0;
136}
137