]>
Commit | Line | Data |
---|---|---|
d66e34cd | 1 | /* Error handling for runtime dynamic linker. |
df4ef2ab | 2 | Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. |
afd4eb37 UD |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Library General Public License as | |
7 | published by the Free Software Foundation; either version 2 of the | |
8 | 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 | Library General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Library General Public | |
16 | License along with the GNU C Library; see the file COPYING.LIB. If not, | |
17 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
18 | Boston, MA 02111-1307, USA. */ | |
d66e34cd RM |
19 | |
20 | #include <stddef.h> | |
21 | #include <link.h> | |
22 | #include <setjmp.h> | |
14bab8de | 23 | #include <stdlib.h> |
0200214b RM |
24 | #include <string.h> |
25 | ||
26 | /* This structure communicates state between _dl_catch_error and | |
27 | _dl_signal_error. */ | |
28 | struct catch | |
29 | { | |
14bab8de UD |
30 | char *errstring; /* Error detail filled in here. */ |
31 | const char *objname; | |
0200214b RM |
32 | jmp_buf env; /* longjmp here on error. */ |
33 | }; | |
34 | ||
35 | /* This points to such a structure during a call to _dl_catch_error. | |
36 | During implicit startup and run-time work for needed shared libraries, | |
37 | this is null. */ | |
38 | static struct catch *catch; | |
d66e34cd | 39 | |
fd26970f UD |
40 | /* This points to a function which is called when an error is |
41 | received. Unlike the handling of `catch' this function may return. | |
42 | The arguments will be the `errstring' and `objname'. */ | |
43 | static receiver_fct receiver; | |
44 | ||
d66e34cd RM |
45 | |
46 | void | |
421f82e5 RM |
47 | _dl_signal_error (int errcode, |
48 | const char *objname, | |
49 | const char *errstring) | |
d66e34cd | 50 | { |
0200214b RM |
51 | if (! errstring) |
52 | errstring = "DYNAMIC LINKER BUG!!!"; | |
53 | ||
54 | if (catch) | |
55 | { | |
dcf0671d UD |
56 | /* We are inside _dl_catch_error. Return to it. We have to |
57 | duplicate the error string since it might be allocated on the | |
58 | stack. */ | |
59 | size_t len = strlen (errstring) + 1; | |
60 | catch->errstring = malloc (len); | |
61 | if (catch->errstring != NULL) | |
62 | memcpy (catch->errstring, errstring, len); | |
0200214b RM |
63 | catch->objname = objname; |
64 | longjmp (catch->env, errcode ?: -1); | |
65 | } | |
fd26970f UD |
66 | else if (receiver) |
67 | { | |
68 | /* We are inside _dl_receive_error. Call the user supplied | |
c84142e8 | 69 | handler and resume the work. The receiver will still be |
fd26970f | 70 | installed. */ |
c84142e8 | 71 | (*receiver) (errcode, objname, errstring); |
fd26970f | 72 | } |
0200214b RM |
73 | else |
74 | { | |
75 | /* Lossage while resolving the program's own symbols is always fatal. */ | |
76 | extern char **_dl_argv; /* Set in rtld.c at startup. */ | |
77 | _dl_sysdep_fatal (_dl_argv[0] ?: "<program name unknown>", | |
78 | ": error in loading shared libraries\n", | |
79 | objname ?: "", objname ? ": " : "", | |
80 | errstring, errcode ? ": " : "", | |
81 | errcode ? strerror (errcode) : "", "\n", NULL); | |
82 | } | |
d66e34cd RM |
83 | } |
84 | ||
85 | int | |
14bab8de | 86 | _dl_catch_error (char **errstring, |
421f82e5 RM |
87 | const char **objname, |
88 | void (*operate) (void)) | |
d66e34cd RM |
89 | { |
90 | int errcode; | |
df4ef2ab | 91 | struct catch *old, c = { errstring: NULL, objname: NULL }; |
fd26970f UD |
92 | /* We need not handle `receiver' since setting a `catch' is handle |
93 | before it. */ | |
d66e34cd | 94 | |
df4ef2ab | 95 | old = catch; |
0200214b | 96 | errcode = setjmp (c.env); |
a1a9d215 RM |
97 | if (errcode == 0) |
98 | { | |
0200214b | 99 | catch = &c; |
a1a9d215 | 100 | (*operate) (); |
df4ef2ab | 101 | catch = old; |
14bab8de UD |
102 | *errstring = NULL; |
103 | *objname = NULL; | |
a1a9d215 RM |
104 | return 0; |
105 | } | |
106 | ||
107 | /* We get here only if we longjmp'd out of OPERATE. */ | |
df4ef2ab | 108 | catch = old; |
0200214b RM |
109 | *errstring = c.errstring; |
110 | *objname = c.objname; | |
a1a9d215 | 111 | return errcode == -1 ? 0 : errcode; |
d66e34cd | 112 | } |
fd26970f UD |
113 | |
114 | void | |
115 | _dl_receive_error (receiver_fct fct, void (*operate) (void)) | |
116 | { | |
117 | struct catch *old_catch; | |
118 | receiver_fct old_receiver; | |
119 | ||
120 | old_catch = catch; | |
121 | old_receiver = receiver; | |
122 | ||
123 | /* Set the new values. */ | |
124 | catch = NULL; | |
125 | receiver = fct; | |
126 | ||
127 | (*operate) (); | |
128 | ||
129 | catch = old_catch; | |
130 | receiver = old_receiver; | |
131 | } |