]>
Commit | Line | Data |
---|---|---|
ccdb048d | 1 | /* Test recursive dlopen using malloc hooks. |
191220b3 | 2 | Copyright (C) 2015 Free Software Foundation, Inc. |
ccdb048d | 3 | This file is part of the GNU C Library. |
ccdb048d CD |
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 <stdio.h> | |
20 | #include <stdlib.h> | |
21 | #include <malloc.h> | |
22 | #include <dlfcn.h> | |
23 | ||
24 | #define DSO "moddummy1.so" | |
25 | #define FUNC "dummy1" | |
26 | ||
27 | #define DSO1 "moddummy2.so" | |
28 | #define FUNC1 "dummy2" | |
29 | ||
30 | /* Result of the called function. */ | |
31 | int func_result; | |
32 | ||
33 | /* Prototype for my hook. */ | |
34 | void *custom_malloc_hook (size_t, const void *); | |
35 | ||
36 | /* Pointer to old malloc hooks. */ | |
37 | void *(*old_malloc_hook) (size_t, const void *); | |
38 | ||
39 | /* Call function func_name in DSO dso_name via dlopen. */ | |
40 | void | |
41 | call_func (const char *dso_name, const char *func_name) | |
42 | { | |
43 | int ret; | |
44 | void *dso; | |
45 | int (*func) (void); | |
46 | char *err; | |
47 | ||
48 | /* Open the DSO. */ | |
49 | dso = dlopen (dso_name, RTLD_NOW|RTLD_GLOBAL); | |
50 | if (dso == NULL) | |
51 | { | |
52 | err = dlerror (); | |
53 | fprintf (stderr, "%s\n", err); | |
54 | exit (1); | |
55 | } | |
56 | /* Clear any errors. */ | |
57 | dlerror (); | |
58 | ||
59 | /* Lookup func. */ | |
60 | *(void **) (&func) = dlsym (dso, func_name); | |
61 | if (func == NULL) | |
62 | { | |
63 | err = dlerror (); | |
64 | if (err != NULL) | |
65 | { | |
66 | fprintf (stderr, "%s\n", err); | |
67 | exit (1); | |
68 | } | |
69 | } | |
70 | /* Call func. */ | |
71 | func_result = (*func) (); | |
72 | ||
73 | /* Close the library and look for errors too. */ | |
74 | ret = dlclose (dso); | |
75 | if (ret != 0) | |
76 | { | |
77 | err = dlerror (); | |
78 | fprintf (stderr, "%s\n", err); | |
79 | exit (1); | |
80 | } | |
81 | ||
82 | } | |
83 | ||
84 | /* Empty hook that does nothing. */ | |
85 | void * | |
86 | custom_malloc_hook (size_t size, const void *caller) | |
87 | { | |
88 | void *result; | |
89 | /* Restore old hooks. */ | |
90 | __malloc_hook = old_malloc_hook; | |
91 | /* First call a function in another library via dlopen. */ | |
92 | call_func (DSO1, FUNC1); | |
93 | /* Called recursively. */ | |
94 | result = malloc (size); | |
95 | /* Restore new hooks. */ | |
96 | __malloc_hook = custom_malloc_hook; | |
97 | return result; | |
98 | } | |
99 | ||
100 | static int | |
101 | do_test (void) | |
102 | { | |
103 | /* Save old hook. */ | |
104 | old_malloc_hook = __malloc_hook; | |
105 | /* Install new hook. */ | |
106 | __malloc_hook = custom_malloc_hook; | |
107 | ||
108 | /* Bug 17702 fixes two things: | |
109 | * A recursive dlopen unmapping the ld.so.cache. | |
110 | * An assertion that _r_debug is RT_CONSISTENT at entry to dlopen. | |
111 | We can only test the latter. Testing the former requires modifying | |
112 | ld.so.conf to cache the dummy libraries, then running ldconfig, | |
113 | then run the test. If you do all of that (and glibc's test | |
114 | infrastructure doesn't support that yet) then the test will | |
115 | SEGFAULT without the fix. If you don't do that, then the test | |
116 | will abort because of the assert described in detail below. */ | |
117 | call_func (DSO, FUNC); | |
118 | ||
119 | /* Restore old hook. */ | |
120 | __malloc_hook = old_malloc_hook; | |
121 | ||
122 | /* The function dummy2() is called by the malloc hook. Check to | |
123 | see that it was called. This ensures the second recursive | |
124 | dlopen happened and we called the function in that library. | |
125 | Before the fix you either get a SIGSEGV when accessing mmap'd | |
126 | ld.so.cache data or an assertion failure about _r_debug not | |
127 | beint RT_CONSISTENT. We don't test for the SIGSEGV since it | |
128 | would require finding moddummy1 or moddummy2 in the cache and | |
129 | we don't have any infrastructure to test that, but the _r_debug | |
130 | assertion triggers. */ | |
131 | printf ("Returned result is %d\n", func_result); | |
132 | if (func_result <= 0) | |
133 | { | |
134 | printf ("FAIL: Function call_func() not called.\n"); | |
135 | exit (1); | |
136 | } | |
137 | ||
138 | printf ("PASS: Function call_func() called more than once.\n"); | |
139 | return 0; | |
140 | } | |
141 | ||
142 | #define TEST_FUNCTION do_test () | |
143 | #include "../test-skeleton.c" |