Back to index

glibc  2.9
tst-dlmodcount.c
Go to the documentation of this file.
00001 /* Copyright (C) 2004 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by David Mosberger <davidm@hpl.hp.com>, 2004.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <link.h>
00021 #include <stddef.h>
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 
00025 #define SET   0
00026 #define ADD   1
00027 #define REMOVE       2
00028 
00029 #define leq(l,r)     (((r) - (l)) <= ~0ULL / 2)
00030 
00031 static int
00032 callback (struct dl_phdr_info *info, size_t size, void *ptr)
00033 {
00034   static int last_adds = 0, last_subs = 0;
00035   intptr_t cmd = (intptr_t) ptr;
00036 
00037   printf ("  size = %Zu\n", size);
00038   if (size < (offsetof (struct dl_phdr_info, dlpi_subs)
00039              + sizeof (info->dlpi_subs)))
00040     {
00041       fprintf (stderr, "dl_iterate_phdr failed to pass dlpi_adds/dlpi_subs\n");
00042       exit (5);
00043     }
00044 
00045   printf ("  dlpi_adds = %Lu dlpi_subs = %Lu\n",
00046          info->dlpi_adds, info->dlpi_subs);
00047 
00048   switch (cmd)
00049     {
00050     case SET:
00051       break;
00052 
00053     case ADD:
00054       if (leq (info->dlpi_adds, last_adds))
00055        {
00056          fprintf (stderr, "dlpi_adds failed to get incremented!\n");
00057          exit (3);
00058        }
00059       break;
00060 
00061     case REMOVE:
00062       if (leq (info->dlpi_subs, last_subs))
00063        {
00064          fprintf (stderr, "dlpi_subs failed to get incremented!\n");
00065          exit (4);
00066        }
00067       break;
00068     }
00069   last_adds = info->dlpi_adds;
00070   last_subs = info->dlpi_subs;
00071   return -1;
00072 }
00073 
00074 static void *
00075 load (const char *path)
00076 {
00077   void *handle;
00078 
00079   printf ("loading `%s'\n", path);
00080   handle = dlopen (path, RTLD_LAZY);
00081   if (!handle)
00082     exit (1);
00083   dl_iterate_phdr (callback, (void *)(intptr_t) ADD);
00084   return handle;
00085 }
00086 
00087 static void
00088 unload (const char *path, void *handle)
00089 {
00090   printf ("unloading `%s'\n", path);
00091   if (dlclose (handle) < 0)
00092     exit (2);
00093   dl_iterate_phdr (callback, (void *)(intptr_t) REMOVE);
00094 }
00095 
00096 int
00097 main (int argc, char **argv)
00098 {
00099   void *handle1, *handle2;
00100 
00101   dl_iterate_phdr (callback, (void *)(intptr_t) SET);
00102   handle1 = load ("firstobj.so");
00103   handle2 = load ("globalmod1.so");
00104   unload ("firstobj.so", handle1);
00105   unload ("globalmod1.so", handle2);
00106   return 0;
00107 }