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  /* C and Fortran stubs for collector API */
      22  
      23  #include "config.h"
      24  #include <dlfcn.h>
      25  #include "gp-defs.h"
      26  #include "collectorAPI.h"
      27  #include "gp-experiment.h"
      28  
      29  static void *__real_collector_sample = NULL;
      30  static void *__real_collector_pause = NULL;
      31  static void *__real_collector_resume = NULL;
      32  static void *__real_collector_terminate_expt = NULL;
      33  static void *__real_collector_func_load = NULL;
      34  static void *__real_collector_func_unload = NULL;
      35  
      36  #define INIT_API        if (init_API == 0) collectorAPI_initAPI()
      37  #define NULL_PTR(x)     (__real_##x == NULL)
      38  #define CALL_REAL(x)    (*(void(*)())__real_##x)
      39  #define CALL_IF_REAL(x) INIT_API; if (!NULL_PTR(x)) CALL_REAL(x)
      40  
      41  static int init_API = 0;
      42  
      43  void
      44  collectorAPI_initAPI (void)
      45  {
      46    void *libcollector = dlopen (SP_LIBCOLLECTOR_NAME, RTLD_NOLOAD);
      47    if (libcollector == NULL)
      48      libcollector = RTLD_DEFAULT;
      49    __real_collector_sample = dlsym (libcollector, "__collector_sample");
      50    __real_collector_pause = dlsym (libcollector, "__collector_pause");
      51    __real_collector_resume = dlsym (libcollector, "__collector_resume");
      52    __real_collector_terminate_expt = dlsym (libcollector, "__collector_terminate_expt");
      53    __real_collector_func_load = dlsym (libcollector, "__collector_func_load");
      54    __real_collector_func_unload = dlsym (libcollector, "__collector_func_unload");
      55    init_API = 1;
      56  }
      57  
      58  /* initialization -- init section routine */
      59  static void collectorAPI_init () __attribute__ ((constructor));
      60  
      61  static void
      62  collectorAPI_init (void)
      63  {
      64    collectorAPI_initAPI ();
      65  }
      66  
      67  /* C API */
      68  void
      69  collector_pause (void)
      70  {
      71    CALL_IF_REAL (collector_pause)();
      72  }
      73  
      74  void
      75  collector_resume (void)
      76  {
      77    CALL_IF_REAL (collector_resume)();
      78  }
      79  
      80  void
      81  collector_sample (const char *name)
      82  {
      83    CALL_IF_REAL (collector_sample)(name);
      84  }
      85  
      86  void
      87  collector_terminate_expt (void)
      88  {
      89    CALL_IF_REAL (collector_terminate_expt)();
      90  }
      91  
      92  void
      93  collector_func_load (const char *name, const char *alias, const char *sourcename,
      94  		     void *vaddr, int size, int lntsize, Lineno *lntable)
      95  {
      96    CALL_IF_REAL (collector_func_load)(name, alias, sourcename,
      97  				     vaddr, size, lntsize, lntable);
      98  }
      99  
     100  void
     101  collector_func_unload (void *vaddr)
     102  {
     103    CALL_IF_REAL (collector_func_unload)(vaddr);
     104  }
     105  
     106  /* Fortran API */
     107  void
     108  collector_pause_ (void)
     109  {
     110    CALL_IF_REAL (collector_pause)();
     111  }
     112  
     113  void
     114  collector_resume_ (void)
     115  {
     116    CALL_IF_REAL (collector_resume)();
     117  }
     118  
     119  void
     120  collector_terminate_expt_ (void)
     121  {
     122    CALL_IF_REAL (collector_terminate_expt)();
     123  }
     124  
     125  void
     126  collector_sample_ (char *name, long name_length)
     127  {
     128    INIT_API;
     129    if (!NULL_PTR (collector_sample))
     130      {
     131        char name_string[256];
     132        long length = sizeof (name_string) - 1;
     133        if (name_length < length)
     134  	length = name_length;
     135        for (long i = 0; i < length; i++)
     136  	name_string[i] = name[i];
     137        name_string[length] = '\0';
     138        CALL_REAL (collector_sample)(name_string);
     139      }
     140  }