• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static const char *
errnomsg(int error)141 errnomsg(int error)
142 {
143   /* Won't be changed by strerror_r, but not const so compiler doesn't throw warning */
144   static char unknown[] = "unknown error";
145 
146 #ifdef STRERROR_R_CHAR_P
147   return strerror_r (error, unknown, 0);
148 #else
149   /* To store the error message from strerror_r in a thread-safe manner */
150   static __thread char msg[128];
151   return strerror_r (error, msg, sizeof (msg)) ? unknown : msg;
152 #endif
153 }
154 
155 const char *
dwfl_errmsg(int error)156 dwfl_errmsg (int error)
157 {
158   if (error == 0 || error == -1)
159     {
160       int last_error = global_error;
161 
162       if (error == 0 && last_error == 0)
163 	return NULL;
164 
165       error = last_error;
166       global_error = DWFL_E_NOERROR;
167     }
168 
169   switch (error &~ 0xffff)
170     {
171     case OTHER_ERROR (ERRNO):
172       return errnomsg (error & 0xffff);
173     case OTHER_ERROR (LIBELF):
174       return elf_errmsg (error & 0xffff);
175     case OTHER_ERROR (LIBDW):
176       return INTUSE(dwarf_errmsg) (error & 0xffff);
177 #if 0
178     case OTHER_ERROR (LIBEBL):
179       return ebl_errmsg (error & 0xffff);
180 #endif
181     }
182 
183   return _(&msgstr[msgidx[(unsigned int) error < nmsgidx
184 			  ? error : DWFL_E_UNKNOWN_ERROR]]);
185 }
186 INTDEF (dwfl_errmsg)
187