Mention IFUNC enhancements to testsuite in NEWS.
[platform/upstream/glibc.git] / elf / tst-dlmodcount.c
1 /* Copyright (C) 2004 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by David Mosberger <davidm@hpl.hp.com>, 2004.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <link.h>
20 #include <stddef.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23
24 #define SET     0
25 #define ADD     1
26 #define REMOVE  2
27
28 #define leq(l,r)        (((r) - (l)) <= ~0ULL / 2)
29
30 static int
31 callback (struct dl_phdr_info *info, size_t size, void *ptr)
32 {
33   static int last_adds = 0, last_subs = 0;
34   intptr_t cmd = (intptr_t) ptr;
35
36   printf ("  size = %Zu\n", size);
37   if (size < (offsetof (struct dl_phdr_info, dlpi_subs)
38               + sizeof (info->dlpi_subs)))
39     {
40       fprintf (stderr, "dl_iterate_phdr failed to pass dlpi_adds/dlpi_subs\n");
41       exit (5);
42     }
43
44   printf ("  dlpi_adds = %Lu dlpi_subs = %Lu\n",
45           info->dlpi_adds, info->dlpi_subs);
46
47   switch (cmd)
48     {
49     case SET:
50       break;
51
52     case ADD:
53       if (leq (info->dlpi_adds, last_adds))
54         {
55           fprintf (stderr, "dlpi_adds failed to get incremented!\n");
56           exit (3);
57         }
58       break;
59
60     case REMOVE:
61       if (leq (info->dlpi_subs, last_subs))
62         {
63           fprintf (stderr, "dlpi_subs failed to get incremented!\n");
64           exit (4);
65         }
66       break;
67     }
68   last_adds = info->dlpi_adds;
69   last_subs = info->dlpi_subs;
70   return -1;
71 }
72
73 static void *
74 load (const char *path)
75 {
76   void *handle;
77
78   printf ("loading `%s'\n", path);
79   handle = dlopen (path, RTLD_LAZY);
80   if (!handle)
81     exit (1);
82   dl_iterate_phdr (callback, (void *)(intptr_t) ADD);
83   return handle;
84 }
85
86 static void
87 unload (const char *path, void *handle)
88 {
89   printf ("unloading `%s'\n", path);
90   if (dlclose (handle) < 0)
91     exit (2);
92   dl_iterate_phdr (callback, (void *)(intptr_t) REMOVE);
93 }
94
95 int
96 main (int argc, char **argv)
97 {
98   void *handle1, *handle2;
99
100   dl_iterate_phdr (callback, (void *)(intptr_t) SET);
101   handle1 = load ("firstobj.so");
102   handle2 = load ("globalmod1.so");
103   unload ("firstobj.so", handle1);
104   unload ("globalmod1.so", handle2);
105   return 0;
106 }