xref: /netbsd-src/external/gpl3/binutils.old/dist/gprofng/src/dbe_memmgr.c (revision c42dbd0ed2e61fe6eda8590caa852ccf34719964)
1*c42dbd0eSchristos /* Copyright (C) 2021 Free Software Foundation, Inc.
2*c42dbd0eSchristos    Contributed by Oracle.
3*c42dbd0eSchristos 
4*c42dbd0eSchristos    This file is part of GNU Binutils.
5*c42dbd0eSchristos 
6*c42dbd0eSchristos    This program is free software; you can redistribute it and/or modify
7*c42dbd0eSchristos    it under the terms of the GNU General Public License as published by
8*c42dbd0eSchristos    the Free Software Foundation; either version 3, or (at your option)
9*c42dbd0eSchristos    any later version.
10*c42dbd0eSchristos 
11*c42dbd0eSchristos    This program is distributed in the hope that it will be useful,
12*c42dbd0eSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*c42dbd0eSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*c42dbd0eSchristos    GNU General Public License for more details.
15*c42dbd0eSchristos 
16*c42dbd0eSchristos    You should have received a copy of the GNU General Public License
17*c42dbd0eSchristos    along with this program; if not, write to the Free Software
18*c42dbd0eSchristos    Foundation, 51 Franklin Street - Fifth Floor, Boston,
19*c42dbd0eSchristos    MA 02110-1301, USA.  */
20*c42dbd0eSchristos 
21*c42dbd0eSchristos #include "config.h"
22*c42dbd0eSchristos #include <dlfcn.h>
23*c42dbd0eSchristos #include "util.h"
24*c42dbd0eSchristos 
25*c42dbd0eSchristos #define CHECK_OUT_OF_MEM(ptr, size) if (ptr == NULL) err_out_of_memory(size)
26*c42dbd0eSchristos 
27*c42dbd0eSchristos /* Report Out of Memory error and exit */
28*c42dbd0eSchristos static void
err_out_of_memory(unsigned nbytes)29*c42dbd0eSchristos err_out_of_memory (unsigned nbytes)
30*c42dbd0eSchristos {
31*c42dbd0eSchristos   char *nm = get_prog_name (1);
32*c42dbd0eSchristos   if (nm)
33*c42dbd0eSchristos     fprintf (stderr, GTXT ("%s: Error: Memory capacity exceeded.\n"), nm);
34*c42dbd0eSchristos   else
35*c42dbd0eSchristos     fprintf (stderr, GTXT ("Error: Memory capacity exceeded.\n"));
36*c42dbd0eSchristos   fprintf (stderr, GTXT ("  Requested %u bytes.\n"), nbytes);
37*c42dbd0eSchristos   exit (16);
38*c42dbd0eSchristos }
39*c42dbd0eSchristos 
40*c42dbd0eSchristos #define CALL_REAL(x) (__real_##x)
41*c42dbd0eSchristos #define NULL_PTR(x) ( __real_##x == NULL )
42*c42dbd0eSchristos 
43*c42dbd0eSchristos static void *(*__real_malloc)(size_t) = NULL;
44*c42dbd0eSchristos static void (*__real_free)(void *) = NULL;
45*c42dbd0eSchristos static void *(*__real_realloc)(void *, size_t) = NULL;
46*c42dbd0eSchristos static void *(*__real_calloc)(size_t, size_t) = NULL;
47*c42dbd0eSchristos static char *(*__real_strdup)(const char*) = NULL;
48*c42dbd0eSchristos static volatile int in_init = 0;
49*c42dbd0eSchristos 
50*c42dbd0eSchristos static int
init_heap_intf()51*c42dbd0eSchristos init_heap_intf ()
52*c42dbd0eSchristos {
53*c42dbd0eSchristos   in_init = 1;
54*c42dbd0eSchristos   __real_malloc = (void*(*)(size_t))dlsym (RTLD_NEXT, "malloc");
55*c42dbd0eSchristos   __real_free = (void(*)(void *))dlsym (RTLD_NEXT, "free");
56*c42dbd0eSchristos   __real_realloc = (void*(*)(void *, size_t))dlsym (RTLD_NEXT, "realloc");
57*c42dbd0eSchristos   __real_calloc = (void*(*)(size_t, size_t))dlsym (RTLD_NEXT, "calloc");
58*c42dbd0eSchristos   __real_strdup = (char*(*)(const char*))dlsym (RTLD_NEXT, "strdup");
59*c42dbd0eSchristos   in_init = 0;
60*c42dbd0eSchristos   return 0;
61*c42dbd0eSchristos }
62*c42dbd0eSchristos 
63*c42dbd0eSchristos /* --------------------------------------------------------------------------- */
64*c42dbd0eSchristos /* libc's memory management functions substitutions */
65*c42dbd0eSchristos 
66*c42dbd0eSchristos /* Allocate memory and make sure we got some */
67*c42dbd0eSchristos void *
malloc(size_t size)68*c42dbd0eSchristos malloc (size_t size)
69*c42dbd0eSchristos {
70*c42dbd0eSchristos   if (NULL_PTR (malloc))
71*c42dbd0eSchristos     init_heap_intf ();
72*c42dbd0eSchristos   void *ptr = CALL_REAL (malloc)(size);
73*c42dbd0eSchristos   CHECK_OUT_OF_MEM (ptr, size);
74*c42dbd0eSchristos   return ptr;
75*c42dbd0eSchristos }
76*c42dbd0eSchristos 
77*c42dbd0eSchristos 
78*c42dbd0eSchristos /* Implement a workaround for a libdl recursion problem */
79*c42dbd0eSchristos void *
calloc(size_t nelem,size_t size)80*c42dbd0eSchristos calloc (size_t nelem, size_t size)
81*c42dbd0eSchristos {
82*c42dbd0eSchristos   if (NULL_PTR (calloc))
83*c42dbd0eSchristos     {
84*c42dbd0eSchristos       /* If a program is linked with libpthread then the following
85*c42dbd0eSchristos        * calling sequence occurs:
86*c42dbd0eSchristos        * init_heap_intf -> dlsym -> calloc -> malloc -> init_heap_intf
87*c42dbd0eSchristos        * We break some performance improvement in libdl by returning
88*c42dbd0eSchristos        * NULL but preserve functionality.
89*c42dbd0eSchristos        */
90*c42dbd0eSchristos       if (in_init)
91*c42dbd0eSchristos 	return NULL;
92*c42dbd0eSchristos       init_heap_intf ();
93*c42dbd0eSchristos     }
94*c42dbd0eSchristos   return CALL_REAL (calloc)(nelem, size);
95*c42dbd0eSchristos }
96*c42dbd0eSchristos 
97*c42dbd0eSchristos /* Free the storage associated with data */
98*c42dbd0eSchristos void
free(void * ptr)99*c42dbd0eSchristos free (void *ptr)
100*c42dbd0eSchristos {
101*c42dbd0eSchristos   if (ptr == NULL)
102*c42dbd0eSchristos     return;
103*c42dbd0eSchristos   if (NULL_PTR (free))
104*c42dbd0eSchristos     init_heap_intf ();
105*c42dbd0eSchristos   CALL_REAL (free)(ptr);
106*c42dbd0eSchristos   return;
107*c42dbd0eSchristos }
108*c42dbd0eSchristos 
109*c42dbd0eSchristos /* Reallocate buffer */
110*c42dbd0eSchristos void *
realloc(void * ptr,size_t size)111*c42dbd0eSchristos realloc (void *ptr, size_t size)
112*c42dbd0eSchristos {
113*c42dbd0eSchristos   if (NULL_PTR (realloc))
114*c42dbd0eSchristos     init_heap_intf ();
115*c42dbd0eSchristos   ptr = CALL_REAL (realloc)(ptr, size);
116*c42dbd0eSchristos   CHECK_OUT_OF_MEM (ptr, size);
117*c42dbd0eSchristos   return ptr;
118*c42dbd0eSchristos }
119