(root)/
glibc-2.38/
dlfcn/
bug-dl-leaf-lib.c
       1  /* Make sure dlopen/dlclose are not marked as leaf functions.
       2  
       3     Copyright (C) 2013-2023 Free Software Foundation, Inc.
       4     This file is part of the GNU C Library.
       5  
       6     The GNU C Library is free software; you can redistribute it and/or
       7     modify it under the terms of the GNU Lesser General Public
       8     License as published by the Free Software Foundation; either
       9     version 2.1 of the License, or (at your option) any later version.
      10  
      11     The GNU C Library 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 GNU
      14     Lesser General Public License for more details.
      15  
      16     You should have received a copy of the GNU Lesser General Public
      17     License along with the GNU C Library; if not, see
      18     <https://www.gnu.org/licenses/>.  */
      19  
      20  /* The bug-dl-leaf.c file will call our lib_main directly.  We do this to
      21     keep things simple -- no need to use --export-dynamic with the linker
      22     or build the main ELF as a PIE.
      23  
      24     The lib_main func will modify some of its state while dlopening and
      25     dlclosing the bug-dl-leaf-lib-cb.so library.  The constructors and
      26     destructors in that library will call back into this library to also
      27     muck with state (the check_val_xxx funcs).
      28  
      29     If dlclose/dlopen are marked as "leaf" functions, then with newer
      30     versions of gcc, the state modification won't work correctly.  */
      31  
      32  #include <assert.h>
      33  #include <dlfcn.h>
      34  
      35  static int val = 1;
      36  static int called = 0;
      37  
      38  void check_val_init (void)
      39  {
      40    called = 1;
      41    assert (val == 2);
      42  }
      43  
      44  void check_val_fini (void)
      45  {
      46    called = 2;
      47    assert (val == 4);
      48  }
      49  
      50  int lib_main (void)
      51  {
      52    int ret __attribute__ ((unused));
      53    void *hdl;
      54  
      55    /* Make sure the constructor sees the updated val.  */
      56    val = 2;
      57    hdl = dlopen ("bug-dl-leaf-lib-cb.so", RTLD_GLOBAL | RTLD_LAZY);
      58    val = 3;
      59    assert (hdl);
      60    assert (called == 1);
      61  
      62    /* Make sure the destructor sees the updated val.  */
      63    val = 4;
      64    ret = dlclose (hdl);
      65    val = 5;
      66    assert (ret == 0);
      67    assert (called == 2);
      68  
      69    return !val;
      70  }