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