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 <libintl.h>
35 : #include <stdbool.h>
36 : #include <stdint.h>
37 : #include <stdlib.h>
38 : #include <errno.h>
39 :
40 : #include "libdwflP.h"
41 :
42 :
43 : /* The error number. */
44 : static __thread int global_error;
45 :
46 :
47 : int
48 1044 : dwfl_errno (void)
49 : {
50 1044 : int result = global_error;
51 1044 : global_error = DWFL_E_NOERROR;
52 1044 : return result;
53 : }
54 : INTDEF (dwfl_errno)
55 :
56 :
57 : struct msgtable
58 : {
59 : #define DWFL_ERROR(name, text) char msg_##name[sizeof text];
60 : DWFL_ERRORS
61 : #undef DWFL_ERROR
62 : };
63 :
64 : static const union
65 : {
66 : struct msgtable table;
67 : char strings[
68 : #define DWFL_ERROR(name, text) + sizeof text
69 : DWFL_ERRORS
70 : #undef DWFL_ERROR
71 : ];
72 : } msgtable =
73 : {
74 : .table =
75 : {
76 : #define DWFL_ERROR(name, text) text,
77 : DWFL_ERRORS
78 : #undef DWFL_ERROR
79 : }
80 : };
81 : #define msgstr (msgtable.strings)
82 :
83 : static const uint_fast16_t msgidx[] =
84 : {
85 : #define DWFL_ERROR(name, text) \
86 : [DWFL_E_##name] = offsetof (struct msgtable, msg_##name),
87 : DWFL_ERRORS
88 : #undef DWFL_ERROR
89 : };
90 : #define nmsgidx (sizeof msgidx / sizeof msgidx[0])
91 :
92 :
93 : static inline int
94 2255 : canonicalize (Dwfl_Error error)
95 : {
96 : unsigned int value;
97 :
98 2255 : switch (error)
99 : {
100 2162 : default:
101 2162 : value = error;
102 2162 : if ((value &~ 0xffff) != 0)
103 : break;
104 2149 : assert (value < nmsgidx);
105 : break;
106 1 : case DWFL_E_ERRNO:
107 1 : value = DWFL_E (ERRNO, errno);
108 1 : break;
109 0 : case DWFL_E_LIBELF:
110 0 : value = DWFL_E (LIBELF, elf_errno ());
111 0 : break;
112 92 : case DWFL_E_LIBDW:
113 92 : value = DWFL_E (LIBDW, INTUSE(dwarf_errno) ());
114 92 : break;
115 : #if 0
116 : DWFL_E_LIBEBL:
117 : value = DWFL_E (LIBEBL, ebl_errno ());
118 : break;
119 : #endif
120 : }
121 :
122 2268 : return value;
123 : }
124 :
125 : int
126 : internal_function
127 1 : __libdwfl_canon_error (Dwfl_Error error)
128 : {
129 1 : return canonicalize (error);
130 : }
131 :
132 : void
133 : internal_function
134 2254 : __libdwfl_seterrno (Dwfl_Error error)
135 : {
136 2254 : global_error = canonicalize (error);
137 2254 : }
138 :
139 :
140 : const char *
141 15 : dwfl_errmsg (int error)
142 : {
143 15 : if (error == 0 || error == -1)
144 : {
145 14 : int last_error = global_error;
146 :
147 14 : if (error == 0 && last_error == 0)
148 : return NULL;
149 :
150 14 : error = last_error;
151 14 : global_error = DWFL_E_NOERROR;
152 : }
153 :
154 15 : switch (error &~ 0xffff)
155 : {
156 0 : case OTHER_ERROR (ERRNO):
157 0 : return strerror_r (error & 0xffff, "bad", 0);
158 0 : case OTHER_ERROR (LIBELF):
159 0 : return elf_errmsg (error & 0xffff);
160 4 : case OTHER_ERROR (LIBDW):
161 4 : return INTUSE(dwarf_errmsg) (error & 0xffff);
162 : #if 0
163 : case OTHER_ERROR (LIBEBL):
164 : return ebl_errmsg (error & 0xffff);
165 : #endif
166 : }
167 :
168 11 : return _(&msgstr[msgidx[(unsigned int) error < nmsgidx
169 : ? error : DWFL_E_UNKNOWN_ERROR]]);
170 : }
171 : INTDEF (dwfl_errmsg)
|