Home | History | Annotate | Download | only in tests
      1 /* Test program for libdwfl file decriptors leakage.
      2    Copyright (C) 2007, 2008 Red Hat, Inc.
      3    This file is part of elfutils.
      4 
      5    This file is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by
      7    the Free Software Foundation; either version 3 of the License, or
      8    (at your option) any later version.
      9 
     10    elfutils is distributed in the hope that it will be useful, but
     11    WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13    GNU General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public License
     16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     17 
     18 #include <config.h>
     19 #include <assert.h>
     20 #include <inttypes.h>
     21 #include <stdio.h>
     22 #include <stdio_ext.h>
     23 #include <locale.h>
     24 #include <dirent.h>
     25 #include <stdlib.h>
     26 #include <errno.h>
     27 #include <error.h>
     28 #include <unistd.h>
     29 #include <dwarf.h>
     30 
     31 #ifndef __linux__
     32 int
     33 main (void)
     34 {
     35   return 77; /* dwfl_linux_proc_report is linux specific.  */
     36 }
     37 #else
     38 
     39 #include <sys/resource.h>
     40 #include ELFUTILS_HEADER(dwfl)
     41 
     42 
     43 static Dwfl *
     44 elfutils_open (pid_t pid, Dwarf_Addr address)
     45 {
     46   static char *debuginfo_path;
     47   static const Dwfl_Callbacks proc_callbacks =
     48     {
     49       .find_debuginfo = dwfl_standard_find_debuginfo,
     50       .debuginfo_path = &debuginfo_path,
     51 
     52       .find_elf = dwfl_linux_proc_find_elf,
     53     };
     54   Dwfl *dwfl = dwfl_begin (&proc_callbacks);
     55   if (dwfl == NULL)
     56     error (2, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
     57 
     58   int result = dwfl_linux_proc_report (dwfl, pid);
     59   if (result < 0)
     60     error (2, 0, "dwfl_linux_proc_report: %s", dwfl_errmsg (-1));
     61   else if (result > 0)
     62     error (2, result, "dwfl_linux_proc_report");
     63 
     64   if (dwfl_report_end (dwfl, NULL, NULL) != 0)
     65     error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
     66 
     67   Dwarf_Addr bias;
     68   Dwarf *dbg = dwfl_addrdwarf (dwfl, address, &bias);
     69   if (dbg != NULL)
     70     {
     71       Elf *elf = dwarf_getelf (dbg);
     72       if (elf == NULL)
     73 	error (2, 0, "dwarf_getelf: %s", dwarf_errmsg (-1));
     74     }
     75   else
     76     {
     77       Dwfl_Module *module = dwfl_addrmodule (dwfl, address);
     78       if (module == NULL)
     79 	error (2, 0, "dwfl_addrmodule: no module available for 0x%" PRIx64 "",
     80 	       address);
     81       Elf *elf = dwfl_module_getelf (module, &bias);
     82       if (elf == NULL)
     83 	error (2, 0, "dwfl_module_getelf: %s", dwfl_errmsg (-1));
     84     }
     85 
     86   return dwfl;
     87 }
     88 
     89 static void
     90 elfutils_close (Dwfl *dwfl)
     91 {
     92   dwfl_end (dwfl);
     93 }
     94 
     95 int
     96 main (void)
     97 {
     98   /* We use no threads here which can interfere with handling a stream.  */
     99   (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
    100 
    101   /* Set locale.  */
    102   (void) setlocale (LC_ALL, "");
    103 
    104   struct rlimit fd_limit = { .rlim_cur = 32, .rlim_max = 32 };
    105   if (setrlimit (RLIMIT_NOFILE, &fd_limit) < 0)
    106     error (2, errno, "setrlimit");
    107 
    108   for (int i = 0; i < 5000; ++i)
    109     {
    110       Dwfl *dwfl = elfutils_open (getpid (), (Dwarf_Addr) (uintptr_t) &main);
    111       elfutils_close (dwfl);
    112     }
    113 
    114   return 0;
    115 }
    116 #endif
    117