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