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