Branch data Line data Source code
1 : : /* Error handling in libdwfl.
2 : : Copyright (C) 2005-2015 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 either
7 : :
8 : : * the GNU Lesser General Public License as published by the Free
9 : : Software Foundation; either version 3 of the License, or (at
10 : : your option) any later version
11 : :
12 : : or
13 : :
14 : : * the GNU General Public License as published by the Free
15 : : Software Foundation; either version 2 of the License, or (at
16 : : your option) any later version
17 : :
18 : : or both in parallel, as here.
19 : :
20 : : elfutils is distributed in the hope that it will be useful, but
21 : : WITHOUT ANY WARRANTY; without even the implied warranty of
22 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 : : General Public License for more details.
24 : :
25 : : You should have received copies of the GNU General Public License and
26 : : the GNU Lesser General Public License along with this program. If
27 : : not, see <http://www.gnu.org/licenses/>. */
28 : :
29 : : #ifdef HAVE_CONFIG_H
30 : : # include <config.h>
31 : : #endif
32 : :
33 : : #include <assert.h>
34 : : #include <stdbool.h>
35 : : #include <stdint.h>
36 : : #include <stdlib.h>
37 : : #include <errno.h>
38 : :
39 : : #include "libdwflP.h"
40 : :
41 : :
42 : : /* The error number. */
43 : : static __thread int global_error;
44 : :
45 : :
46 : : int
47 : 396 : dwfl_errno (void)
48 : : {
49 : 396 : int result = global_error;
50 : 396 : global_error = DWFL_E_NOERROR;
51 : 396 : return result;
52 : : }
53 : : INTDEF (dwfl_errno)
54 : :
55 : :
56 : : struct msgtable
57 : : {
58 : : #define DWFL_ERROR(name, text) char msg_##name[sizeof text];
59 : : DWFL_ERRORS
60 : : #undef DWFL_ERROR
61 : : };
62 : :
63 : : static const union
64 : : {
65 : : struct msgtable table;
66 : : char strings[
67 : : #define DWFL_ERROR(name, text) + sizeof text
68 : : DWFL_ERRORS
69 : : #undef DWFL_ERROR
70 : : ];
71 : : } msgtable =
72 : : {
73 : : .table =
74 : : {
75 : : #define DWFL_ERROR(name, text) text,
76 : : DWFL_ERRORS
77 : : #undef DWFL_ERROR
78 : : }
79 : : };
80 : : #define msgstr (msgtable.strings)
81 : :
82 : : static const uint_fast16_t msgidx[] =
83 : : {
84 : : #define DWFL_ERROR(name, text) \
85 : : [DWFL_E_##name] = offsetof (struct msgtable, msg_##name),
86 : : DWFL_ERRORS
87 : : #undef DWFL_ERROR
88 : : };
89 : : #define nmsgidx (sizeof msgidx / sizeof msgidx[0])
90 : :
91 : :
92 : : static inline int
93 : 3246 : canonicalize (Dwfl_Error error)
94 : : {
95 : 3246 : unsigned int value;
96 : :
97 [ + + + + ]: 3246 : switch (error)
98 : : {
99 : 3054 : default:
100 : 3054 : value = error;
101 [ + + ]: 3054 : if ((value &~ 0xffff) != 0)
102 : : break;
103 [ - + ]: 3028 : assert (value < nmsgidx);
104 : : break;
105 : 2 : case DWFL_E_ERRNO:
106 : 2 : value = DWFL_E (ERRNO, errno);
107 : 2 : break;
108 : 6 : case DWFL_E_LIBELF:
109 : 6 : value = DWFL_E (LIBELF, elf_errno ());
110 : 6 : break;
111 : 184 : case DWFL_E_LIBDW:
112 : 184 : value = DWFL_E (LIBDW, INTUSE(dwarf_errno) ());
113 : 184 : break;
114 : : #if 0
115 : : DWFL_E_LIBEBL:
116 : : value = DWFL_E (LIBEBL, ebl_errno ());
117 : : break;
118 : : #endif
119 : : }
120 : :
121 : 3246 : return value;
122 : : }
123 : :
124 : : int
125 : : internal_function
126 : 2 : __libdwfl_canon_error (Dwfl_Error error)
127 : : {
128 : 2 : return canonicalize (error);
129 : : }
130 : :
131 : : void
132 : : internal_function
133 : 3244 : __libdwfl_seterrno (Dwfl_Error error)
134 : : {
135 : 3244 : global_error = canonicalize (error);
136 : 3244 : }
137 : :
138 : :
139 : : static const char *
140 : 0 : errnomsg(int error)
141 : : {
142 : : /* Won't be changed by strerror_r, but not const so compiler doesn't throw warning */
143 : 0 : static char unknown[] = "unknown error";
144 : :
145 : : #ifdef STRERROR_R_CHAR_P
146 : 0 : return strerror_r (error, unknown, 0);
147 : : #else
148 : : /* To store the error message from strerror_r in a thread-safe manner */
149 : : static __thread char msg[128];
150 : : return strerror_r (error, msg, sizeof (msg)) ? unknown : msg;
151 : : #endif
152 : : }
153 : :
154 : : const char *
155 : 30 : dwfl_errmsg (int error)
156 : : {
157 [ + + ]: 30 : if (error == 0 || error == -1)
158 : : {
159 : 28 : int last_error = global_error;
160 : :
161 [ + - ]: 28 : if (error == 0 && last_error == 0)
162 : : return NULL;
163 : :
164 : 28 : error = last_error;
165 : 28 : global_error = DWFL_E_NOERROR;
166 : : }
167 : :
168 [ - - + + ]: 30 : switch (error &~ 0xffff)
169 : : {
170 : 0 : case OTHER_ERROR (ERRNO):
171 : 0 : return errnomsg (error & 0xffff);
172 : 0 : case OTHER_ERROR (LIBELF):
173 : 0 : return elf_errmsg (error & 0xffff);
174 : 8 : case OTHER_ERROR (LIBDW):
175 : 8 : return INTUSE(dwarf_errmsg) (error & 0xffff);
176 : : #if 0
177 : : case OTHER_ERROR (LIBEBL):
178 : : return ebl_errmsg (error & 0xffff);
179 : : #endif
180 : : }
181 : :
182 [ - + ]: 22 : return _(&msgstr[msgidx[(unsigned int) error < nmsgidx
183 : : ? error : DWFL_E_UNKNOWN_ERROR]]);
184 : : }
185 : : INTDEF (dwfl_errmsg)
|