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 <stdio.h>
      22  #include <stdlib.h>
      23  #include <dlfcn.h>
      24  #include <errno.h>
      25  #include <string.h>
      26  #include "stopwatch.h"
      27  
      28  
      29  #define DYNSOROUTINE    "so_cputime"
      30  #define DYNSONAME       "./so_syn.so"
      31  
      32  /* callso -- dynamically link a shared object, and call a routine in it */
      33  
      34  #ifndef NONSHARED
      35  
      36  static void *so_object = NULL;
      37  static void closeso (void);
      38  
      39  int
      40  callso (int k)
      41  {
      42    int i;
      43    char buf[1024];
      44    char *p;
      45    char *q = DYNSONAME;
      46    int errnum;
      47  
      48    hrtime_t start = gethrtime ();
      49    hrtime_t vstart = gethrvtime ();
      50  
      51    /* Log the event */
      52    wlog ("start of callso", NULL);
      53  
      54    /* see if already linked */
      55    if (so_object != NULL)
      56      {
      57        fprintf (stderr, "Execution error -- callso: so_object already linked\n");
      58        return 0;
      59      }
      60  
      61    /* open the dynamic shared object */
      62    so_object = NULL;
      63    while (so_object == NULL)
      64      {
      65        so_object = dlopen (DYNSONAME, RTLD_NOW);
      66        if (so_object != NULL)
      67          break;
      68        p = dlerror ();
      69        if (q == NULL)
      70          q = "DYNSONAME";
      71        if (p == NULL)
      72          p = "dlerror() returns NULL";
      73        errnum = errno;
      74        if (errnum == EINTR)
      75          continue;   /* retry */
      76        else
      77          {
      78            fprintf (stderr, "Execution error -- callso: dlopen of %s failed--%s, errno=%d (%s)\n",
      79                     q, p, errnum, strerror (errnum));
      80            return (0);
      81          }
      82      }
      83  
      84    /* look up the routine name in it */
      85    int (*so_routine)() = (int (*)())dlsym (so_object, DYNSOROUTINE);
      86    if (so_routine == NULL)
      87      {
      88        fprintf (stderr, "Execution error -- callso: dlsym %s not found\n",
      89                 DYNSOROUTINE);
      90        return (0);
      91      }
      92  
      93    /* invoke the routine */
      94    long long count = 0;
      95    do
      96      {
      97        i = (*so_routine)();
      98        count++;
      99      }
     100    while (start + testtime * 1e9 > gethrtime ());
     101  
     102    closeso ();
     103    sprintf (buf, "end of callso, %s returned %d", DYNSOROUTINE, i);
     104    wlog (buf, NULL);
     105    fprintf (stderr, "   Performed %lld while-loop iterations\n", count);
     106    whrvlog ((gethrtime () - start), (gethrvtime () - vstart), "callso", NULL);
     107    return 0;
     108  }
     109  
     110  /* closeso -- close a DSO */
     111  void
     112  closeso (void)
     113  {
     114    /* Log the event */
     115    wlog ("start of closeso", NULL);
     116  
     117    /* ensure already linked */
     118    if (so_object == NULL)
     119      {
     120        fprintf (stderr, "Execution error -- closeso: so_object not linked\n");
     121        return;
     122      }
     123  
     124    /* close the dynamic shared object */
     125    int rc = dlclose (so_object);
     126    if (rc != 0)
     127      {
     128        fprintf (stderr, "Execution error -- closeso: dlclose() failed--%s\n",
     129                 dlerror ());
     130        return;
     131      }
     132  
     133    /* clear the pointer */
     134    so_object = NULL;
     135    wlog ("end of closeso", NULL);
     136    return;
     137  }
     138  
     139  #else /* NONSHARED */
     140  
     141  int
     142  callso (int i)
     143  {
     144    return 0;
     145  }
     146  
     147  void
     148  closeso (void)
     149  {
     150    return;
     151  }
     152  #endif /* NONSHARED */