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
dwfl_errno(void)48 dwfl_errno (void)
49 {
50 int result = global_error;
51 global_error = DWFL_E_NOERROR;
52 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
canonicalize(Dwfl_Error error)94 canonicalize (Dwfl_Error error)
95 {
96 unsigned int value;
97
98 switch (error)
99 {
100 default:
101 value = error;
102 if ((value &~ 0xffff) != 0)
103 break;
104 assert (value < nmsgidx);
105 break;
106 case DWFL_E_ERRNO:
107 value = DWFL_E (ERRNO, errno);
108 break;
109 case DWFL_E_LIBELF:
110 value = DWFL_E (LIBELF, elf_errno ());
111 break;
112 case DWFL_E_LIBDW:
113 value = DWFL_E (LIBDW, INTUSE(dwarf_errno) ());
114 break;
115 #if 0
116 DWFL_E_LIBEBL:
117 value = DWFL_E (LIBEBL, ebl_errno ());
118 break;
119 #endif
120 }
121
122 return value;
123 }
124
125 int
126 internal_function
__libdwfl_canon_error(Dwfl_Error error)127 __libdwfl_canon_error (Dwfl_Error error)
128 {
129 return canonicalize (error);
130 }
131
132 void
133 internal_function
__libdwfl_seterrno(Dwfl_Error error)134 __libdwfl_seterrno (Dwfl_Error error)
135 {
136 global_error = canonicalize (error);
137 }
138
139
140 const char *
dwfl_errmsg(int error)141 dwfl_errmsg (int error)
142 {
143 if (error == 0 || error == -1)
144 {
145 int last_error = global_error;
146
147 if (error == 0 && last_error == 0)
148 return NULL;
149
150 error = last_error;
151 global_error = DWFL_E_NOERROR;
152 }
153
154 switch (error &~ 0xffff)
155 {
156 case OTHER_ERROR (ERRNO):
157 return strerror_r (error & 0xffff, "bad", 0);
158 case OTHER_ERROR (LIBELF):
159 return elf_errmsg (error & 0xffff);
160 case OTHER_ERROR (LIBDW):
161 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 return _(&msgstr[msgidx[(unsigned int) error < nmsgidx
169 ? error : DWFL_E_UNKNOWN_ERROR]]);
170 }
171 INTDEF (dwfl_errmsg)
172