Coverage Report

Created: 2026-02-26 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/elfutils/libdwfl/dwfl_error.c
Line
Count
Source
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 <stdbool.h>
35
#include <stdint.h>
36
#include <stdlib.h>
37
#include <errno.h>
38
39
#include "libdwflP.h"
40
41
42
/* The error number.  */
43
static __thread int global_error;
44
45
46
int
47
dwfl_errno (void)
48
0
{
49
0
  int result = global_error;
50
0
  global_error = DWFL_E_NOERROR;
51
0
  return result;
52
0
}
53
INTDEF (dwfl_errno)
54
55
56
struct msgtable
57
{
58
#define DWFL_ERROR(name, text) char msg_##name[sizeof text];
59
  DWFL_ERRORS
60
#undef  DWFL_ERROR
61
};
62
63
static const union
64
{
65
  struct msgtable table;
66
  char strings[
67
#define DWFL_ERROR(name, text)  + sizeof text
68
         DWFL_ERRORS
69
#undef  DWFL_ERROR
70
         ];
71
} msgtable =
72
  {
73
    .table =
74
    {
75
#define DWFL_ERROR(name, text) text,
76
      DWFL_ERRORS
77
#undef  DWFL_ERROR
78
    }
79
  };
80
#define msgstr (msgtable.strings)
81
82
static const uint_fast16_t msgidx[] =
83
{
84
#define DWFL_ERROR(name, text) \
85
  [DWFL_E_##name] = offsetof (struct msgtable, msg_##name),
86
  DWFL_ERRORS
87
#undef  DWFL_ERROR
88
};
89
#define nmsgidx (sizeof msgidx / sizeof msgidx[0])
90
91
92
static inline int
93
canonicalize (Dwfl_Error error)
94
44.5k
{
95
44.5k
  unsigned int value;
96
97
44.5k
  switch (error)
98
44.5k
    {
99
42.0k
    default:
100
42.0k
      value = error;
101
42.0k
      if ((value &~ 0xffff) != 0)
102
3.94k
  break;
103
42.0k
      assert (value < nmsgidx);
104
38.1k
      break;
105
38.1k
    case DWFL_E_ERRNO:
106
0
      value = DWFL_E (ERRNO, errno);
107
0
      break;
108
2.49k
    case DWFL_E_LIBELF:
109
2.49k
      value = DWFL_E (LIBELF, elf_errno ());
110
2.49k
      break;
111
0
    case DWFL_E_LIBDW:
112
0
      value = DWFL_E (LIBDW, INTUSE(dwarf_errno) ());
113
0
      break;
114
#if 0
115
    DWFL_E_LIBEBL:
116
      value = DWFL_E (LIBEBL, ebl_errno ());
117
      break;
118
#endif
119
44.5k
    }
120
121
44.5k
  return value;
122
44.5k
}
123
124
int
125
internal_function
126
__libdwfl_canon_error (Dwfl_Error error)
127
17.7k
{
128
17.7k
  return canonicalize (error);
129
17.7k
}
130
131
void
132
internal_function
133
__libdwfl_seterrno (Dwfl_Error error)
134
26.8k
{
135
26.8k
  global_error = canonicalize (error);
136
26.8k
}
137
138
139
static const char *
140
errnomsg(int error)
141
0
{
142
  /* Won't be changed by strerror_r, but not const so compiler doesn't throw warning */
143
0
  static char unknown[] = "unknown error";
144
145
0
#ifdef STRERROR_R_CHAR_P
146
0
  return strerror_r (error, unknown, 0);
147
#else
148
  /* To store the error message from strerror_r in a thread-safe manner */
149
  static __thread char msg[128];
150
  return strerror_r (error, msg, sizeof (msg)) ? unknown : msg;
151
#endif
152
0
}
153
154
const char *
155
dwfl_errmsg (int error)
156
0
{
157
0
  if (error == 0 || error == -1)
158
0
    {
159
0
      int last_error = global_error;
160
161
0
      if (error == 0 && last_error == 0)
162
0
  return NULL;
163
164
0
      error = last_error;
165
0
      global_error = DWFL_E_NOERROR;
166
0
    }
167
168
0
  switch (error &~ 0xffff)
169
0
    {
170
0
    case OTHER_ERROR (ERRNO):
171
0
      return errnomsg (error & 0xffff);
172
0
    case OTHER_ERROR (LIBELF):
173
0
      return elf_errmsg (error & 0xffff);
174
0
    case OTHER_ERROR (LIBDW):
175
0
      return INTUSE(dwarf_errmsg) (error & 0xffff);
176
#if 0
177
    case OTHER_ERROR (LIBEBL):
178
      return ebl_errmsg (error & 0xffff);
179
#endif
180
0
    }
181
182
0
  return _(&msgstr[msgidx[(unsigned int) error < nmsgidx
183
0
        ? error : DWFL_E_UNKNOWN_ERROR]]);
184
0
}
185
INTDEF (dwfl_errmsg)