Skip to content

Commit 0acb639

Browse files
[libc] move strerror and strsignal to OS msg maps
Other OSes may have different mappings from error number to message. This creates a system to allow new platforms to define their own mappings. Reviewed By: sivachandra Differential Revision: https://reviews.llvm.org/D147967
1 parent 6e9ca8c commit 0acb639

15 files changed

+501
-208
lines changed

libc/src/__support/StringUtil/CMakeLists.txt

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,41 @@ add_header_library(
33
HDRS
44
message_mapper.h
55
DEPENDS
6-
libc.src.__support.CPP.string_view
7-
libc.src.__support.CPP.optional
6+
libc.src.__support.CPP.string_view
7+
libc.src.__support.CPP.optional
88
)
99

10+
# The table maps depend on message_mapper.
11+
add_subdirectory(tables)
12+
1013
add_object_library(
1114
error_to_string
1215
HDRS
1316
error_to_string.h
1417
SRCS
1518
error_to_string.cpp
1619
DEPENDS
17-
.message_mapper
18-
libc.src.errno.errno
19-
libc.src.__support.CPP.span
20-
libc.src.__support.CPP.string_view
21-
libc.src.__support.CPP.stringstream
22-
libc.src.__support.integer_to_string
20+
.message_mapper
21+
libc.src.errno.errno
22+
libc.src.__support.CPP.span
23+
libc.src.__support.CPP.string_view
24+
libc.src.__support.CPP.stringstream
25+
libc.src.__support.integer_to_string
26+
libc.src.__support.StringUtil.tables.error_table
2327
)
2428

25-
2629
add_object_library(
2730
signal_to_string
2831
HDRS
2932
signal_to_string.h
3033
SRCS
3134
signal_to_string.cpp
3235
DEPENDS
33-
.message_mapper
34-
libc.include.signal
35-
libc.src.__support.CPP.span
36-
libc.src.__support.CPP.string_view
37-
libc.src.__support.CPP.stringstream
38-
libc.src.__support.integer_to_string
36+
.message_mapper
37+
libc.include.signal
38+
libc.src.__support.CPP.span
39+
libc.src.__support.CPP.string_view
40+
libc.src.__support.CPP.stringstream
41+
libc.src.__support.integer_to_string
42+
libc.src.__support.StringUtil.tables.signal_table
3943
)

libc/src/__support/StringUtil/error_to_string.cpp

Lines changed: 16 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@
88

99
#include "src/__support/StringUtil/error_to_string.h"
1010

11+
#include "src/errno/libc_errno.h" // For error macros
12+
13+
#include "src/__support/CPP/array.h"
1114
#include "src/__support/CPP/span.h"
1215
#include "src/__support/CPP/string_view.h"
1316
#include "src/__support/CPP/stringstream.h"
1417
#include "src/__support/StringUtil/message_mapper.h"
1518
#include "src/__support/integer_to_string.h"
16-
#include "src/errno/libc_errno.h" // For error macros
19+
20+
#include "src/__support/StringUtil/tables/error_table.h"
1721

1822
#include <stddef.h>
1923

@@ -33,157 +37,21 @@ constexpr size_t max_buff_size() {
3337
constexpr size_t ERR_BUFFER_SIZE = max_buff_size();
3438
thread_local char error_buffer[ERR_BUFFER_SIZE];
3539

40+
constexpr size_t RAW_ARRAY_LEN = PLATFORM_ERRORS.size();
41+
constexpr size_t TOTAL_STR_LEN =
42+
total_str_len(PLATFORM_ERRORS.data(), RAW_ARRAY_LEN);
43+
3644
// Since the StringMappings array is a map from error numbers to their
3745
// corresponding strings, we have to have an array large enough we can use the
38-
// error numbers as indexes. Thankfully there are 132 errors in the above list
39-
// (41 and 58 are skipped) and the highest number is 133. If other platforms use
40-
// different error numbers, then this number may need to be adjusted.
41-
// Also if negative numbers or particularly large numbers are used, then the
42-
// array should be turned into a proper hashmap.
43-
constexpr size_t ERR_ARRAY_SIZE = 134;
44-
45-
constexpr MsgMapping raw_err_array[] = {
46-
MsgMapping(0, "Success"),
47-
MsgMapping(EPERM, "Operation not permitted"),
48-
MsgMapping(ENOENT, "No such file or directory"),
49-
MsgMapping(ESRCH, "No such process"),
50-
MsgMapping(EINTR, "Interrupted system call"),
51-
MsgMapping(EIO, "Input/output error"),
52-
MsgMapping(ENXIO, "No such device or address"),
53-
MsgMapping(E2BIG, "Argument list too long"),
54-
MsgMapping(ENOEXEC, "Exec format error"),
55-
MsgMapping(EBADF, "Bad file descriptor"),
56-
MsgMapping(ECHILD, "No child processes"),
57-
MsgMapping(EAGAIN, "Resource temporarily unavailable"),
58-
MsgMapping(ENOMEM, "Cannot allocate memory"),
59-
MsgMapping(EACCES, "Permission denied"),
60-
MsgMapping(EFAULT, "Bad address"),
61-
MsgMapping(ENOTBLK, "Block device required"),
62-
MsgMapping(EBUSY, "Device or resource busy"),
63-
MsgMapping(EEXIST, "File exists"),
64-
MsgMapping(EXDEV, "Invalid cross-device link"),
65-
MsgMapping(ENODEV, "No such device"),
66-
MsgMapping(ENOTDIR, "Not a directory"),
67-
MsgMapping(EISDIR, "Is a directory"),
68-
MsgMapping(EINVAL, "Invalid argument"),
69-
MsgMapping(ENFILE, "Too many open files in system"),
70-
MsgMapping(EMFILE, "Too many open files"),
71-
MsgMapping(ENOTTY, "Inappropriate ioctl for device"),
72-
MsgMapping(ETXTBSY, "Text file busy"),
73-
MsgMapping(EFBIG, "File too large"),
74-
MsgMapping(ENOSPC, "No space left on device"),
75-
MsgMapping(ESPIPE, "Illegal seek"),
76-
MsgMapping(EROFS, "Read-only file system"),
77-
MsgMapping(EMLINK, "Too many links"),
78-
MsgMapping(EPIPE, "Broken pipe"),
79-
MsgMapping(EDOM, "Numerical argument out of domain"),
80-
MsgMapping(ERANGE, "Numerical result out of range"),
81-
MsgMapping(EDEADLK, "Resource deadlock avoided"),
82-
MsgMapping(ENAMETOOLONG, "File name too long"),
83-
MsgMapping(ENOLCK, "No locks available"),
84-
MsgMapping(ENOSYS, "Function not implemented"),
85-
MsgMapping(ENOTEMPTY, "Directory not empty"),
86-
MsgMapping(ELOOP, "Too many levels of symbolic links"),
87-
// No error for 41. Would be EWOULDBLOCK
88-
MsgMapping(ENOMSG, "No message of desired type"),
89-
MsgMapping(EIDRM, "Identifier removed"),
90-
MsgMapping(ECHRNG, "Channel number out of range"),
91-
MsgMapping(EL2NSYNC, "Level 2 not synchronized"),
92-
MsgMapping(EL3HLT, "Level 3 halted"),
93-
MsgMapping(EL3RST, "Level 3 reset"),
94-
MsgMapping(ELNRNG, "Link number out of range"),
95-
MsgMapping(EUNATCH, "Protocol driver not attached"),
96-
MsgMapping(ENOCSI, "No CSI structure available"),
97-
MsgMapping(EL2HLT, "Level 2 halted"),
98-
MsgMapping(EBADE, "Invalid exchange"),
99-
MsgMapping(EBADR, "Invalid request descriptor"),
100-
MsgMapping(EXFULL, "Exchange full"),
101-
MsgMapping(ENOANO, "No anode"),
102-
MsgMapping(EBADRQC, "Invalid request code"),
103-
MsgMapping(EBADSLT, "Invalid slot"),
104-
// No error for 58. Would be EDEADLOCK.
105-
MsgMapping(EBFONT, "Bad font file format"),
106-
MsgMapping(ENOSTR, "Device not a stream"),
107-
MsgMapping(ENODATA, "No data available"),
108-
MsgMapping(ETIME, "Timer expired"),
109-
MsgMapping(ENOSR, "Out of streams resources"),
110-
MsgMapping(ENONET, "Machine is not on the network"),
111-
MsgMapping(ENOPKG, "Package not installed"),
112-
MsgMapping(EREMOTE, "Object is remote"),
113-
MsgMapping(ENOLINK, "Link has been severed"),
114-
MsgMapping(EADV, "Advertise error"),
115-
MsgMapping(ESRMNT, "Srmount error"),
116-
MsgMapping(ECOMM, "Communication error on send"),
117-
MsgMapping(EPROTO, "Protocol error"),
118-
MsgMapping(EMULTIHOP, "Multihop attempted"),
119-
MsgMapping(EDOTDOT, "RFS specific error"),
120-
MsgMapping(EBADMSG, "Bad message"),
121-
MsgMapping(EOVERFLOW, "Value too large for defined data type"),
122-
MsgMapping(ENOTUNIQ, "Name not unique on network"),
123-
MsgMapping(EBADFD, "File descriptor in bad state"),
124-
MsgMapping(EREMCHG, "Remote address changed"),
125-
MsgMapping(ELIBACC, "Can not access a needed shared library"),
126-
MsgMapping(ELIBBAD, "Accessing a corrupted shared library"),
127-
MsgMapping(ELIBSCN, ".lib section in a.out corrupted"),
128-
MsgMapping(ELIBMAX, "Attempting to link in too many shared libraries"),
129-
MsgMapping(ELIBEXEC, "Cannot exec a shared library directly"),
130-
MsgMapping(EILSEQ, "Invalid or incomplete multibyte or wide character"),
131-
MsgMapping(ERESTART, "Interrupted system call should be restarted"),
132-
MsgMapping(ESTRPIPE, "Streams pipe error"),
133-
MsgMapping(EUSERS, "Too many users"),
134-
MsgMapping(ENOTSOCK, "Socket operation on non-socket"),
135-
MsgMapping(EDESTADDRREQ, "Destination address required"),
136-
MsgMapping(EMSGSIZE, "Message too long"),
137-
MsgMapping(EPROTOTYPE, "Protocol wrong type for socket"),
138-
MsgMapping(ENOPROTOOPT, "Protocol not available"),
139-
MsgMapping(EPROTONOSUPPORT, "Protocol not supported"),
140-
MsgMapping(ESOCKTNOSUPPORT, "Socket type not supported"),
141-
MsgMapping(ENOTSUP, "Operation not supported"),
142-
MsgMapping(EPFNOSUPPORT, "Protocol family not supported"),
143-
MsgMapping(EAFNOSUPPORT, "Address family not supported by protocol"),
144-
MsgMapping(EADDRINUSE, "Address already in use"),
145-
MsgMapping(EADDRNOTAVAIL, "Cannot assign requested address"),
146-
MsgMapping(ENETDOWN, "Network is down"),
147-
MsgMapping(ENETUNREACH, "Network is unreachable"),
148-
MsgMapping(ENETRESET, "Network dropped connection on reset"),
149-
MsgMapping(ECONNABORTED, "Software caused connection abort"),
150-
MsgMapping(ECONNRESET, "Connection reset by peer"),
151-
MsgMapping(ENOBUFS, "No buffer space available"),
152-
MsgMapping(EISCONN, "Transport endpoint is already connected"),
153-
MsgMapping(ENOTCONN, "Transport endpoint is not connected"),
154-
MsgMapping(ESHUTDOWN, "Cannot send after transport endpoint shutdown"),
155-
MsgMapping(ETOOMANYREFS, "Too many references: cannot splice"),
156-
MsgMapping(ETIMEDOUT, "Connection timed out"),
157-
MsgMapping(ECONNREFUSED, "Connection refused"),
158-
MsgMapping(EHOSTDOWN, "Host is down"),
159-
MsgMapping(EHOSTUNREACH, "No route to host"),
160-
MsgMapping(EALREADY, "Operation already in progress"),
161-
MsgMapping(EINPROGRESS, "Operation now in progress"),
162-
MsgMapping(ESTALE, "Stale file handle"),
163-
MsgMapping(EUCLEAN, "Structure needs cleaning"),
164-
MsgMapping(ENOTNAM, "Not a XENIX named type file"),
165-
MsgMapping(ENAVAIL, "No XENIX semaphores available"),
166-
MsgMapping(EISNAM, "Is a named type file"),
167-
MsgMapping(EREMOTEIO, "Remote I/O error"),
168-
MsgMapping(EDQUOT, "Disk quota exceeded"),
169-
MsgMapping(ENOMEDIUM, "No medium found"),
170-
MsgMapping(EMEDIUMTYPE, "Wrong medium type"),
171-
MsgMapping(ECANCELED, "Operation canceled"),
172-
MsgMapping(ENOKEY, "Required key not available"),
173-
MsgMapping(EKEYEXPIRED, "Key has expired"),
174-
MsgMapping(EKEYREVOKED, "Key has been revoked"),
175-
MsgMapping(EKEYREJECTED, "Key was rejected by service"),
176-
MsgMapping(EOWNERDEAD, "Owner died"),
177-
MsgMapping(ENOTRECOVERABLE, "State not recoverable"),
178-
MsgMapping(ERFKILL, "Operation not possible due to RF-kill"),
179-
MsgMapping(EHWPOISON, "Memory page has hardware error"),
180-
};
181-
182-
constexpr size_t RAW_ARRAY_LEN = sizeof(raw_err_array) / sizeof(MsgMapping);
183-
constexpr size_t TOTAL_STR_LEN = total_str_len(raw_err_array, RAW_ARRAY_LEN);
46+
// error numbers as indexes. The current linux configuration has 132 values with
47+
// the maximum value being 133 (41 and 58 are skipped). If other platforms use
48+
// negative numbers or discontiguous ranges, then the array should be turned
49+
// into a proper hashmap.
50+
constexpr size_t ERR_ARRAY_SIZE =
51+
max_key_val(PLATFORM_ERRORS.data(), RAW_ARRAY_LEN) + 1;
18452

18553
static constexpr MessageMapper<ERR_ARRAY_SIZE, TOTAL_STR_LEN>
186-
error_mapper(raw_err_array, RAW_ARRAY_LEN);
54+
error_mapper(PLATFORM_ERRORS.data(), RAW_ARRAY_LEN);
18755

18856
cpp::string_view build_error_string(int err_num, cpp::span<char> buffer) {
18957
// if the buffer can't hold "Unknown error" + ' ' + num_str, then just

libc/src/__support/StringUtil/error_to_string.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include "src/__support/CPP/span.h"
10-
#include "src/__support/CPP/string_view.h"
11-
129
#ifndef LLVM_LIBC_SRC_SUPPORT_ERROR_TO_STRING_H
1310
#define LLVM_LIBC_SRC_SUPPORT_ERROR_TO_STRING_H
1411

12+
#include "src/__support/CPP/span.h"
13+
#include "src/__support/CPP/string_view.h"
14+
1515
namespace __llvm_libc {
1616

1717
cpp::string_view get_error_string(int err_num);

libc/src/__support/StringUtil/message_mapper.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLVM_LIBC_SRC_SUPPORT_STRING_UTIL_MESSAGE_MAPPER_H
1010
#define LLVM_LIBC_SRC_SUPPORT_STRING_UTIL_MESSAGE_MAPPER_H
1111

12+
#include "src/__support/CPP/array.h"
1213
#include "src/__support/CPP/optional.h"
1314
#include "src/__support/CPP/string_view.h"
1415
#include <stddef.h>
@@ -20,6 +21,8 @@ struct MsgMapping {
2021
int num;
2122
cpp::string_view msg;
2223

24+
constexpr MsgMapping() : num(0), msg() { ; }
25+
2326
constexpr MsgMapping(int init_num, const char *init_msg)
2427
: num(init_num), msg(init_msg) {
2528
;
@@ -35,6 +38,18 @@ constexpr size_t total_str_len(const MsgMapping *array, size_t len) {
3538
return total;
3639
}
3740

41+
constexpr size_t max_key_val(const MsgMapping *array, size_t len) {
42+
int max = 0;
43+
for (size_t i = 0; i < len; ++i) {
44+
if (array[i].num > max) {
45+
max = array[i].num;
46+
}
47+
}
48+
// max will never be negative since the starting value is 0. This is good,
49+
// since it's used as a length.
50+
return static_cast<size_t>(max);
51+
}
52+
3853
template <size_t ARR_SIZE, size_t TOTAL_STR_LEN> class MessageMapper {
3954
int msg_offsets[ARR_SIZE] = {-1};
4055
char string_array[TOTAL_STR_LEN] = {'\0'};
@@ -71,6 +86,19 @@ template <size_t ARR_SIZE, size_t TOTAL_STR_LEN> class MessageMapper {
7186
}
7287
};
7388

89+
template <size_t N> using MsgTable = cpp::array<MsgMapping, N>;
90+
91+
template <size_t N1, size_t N2>
92+
constexpr MsgTable<N1 + N2> operator+(const MsgTable<N1> &t1,
93+
const MsgTable<N2> &t2) {
94+
MsgTable<N1 + N2> res{};
95+
for (size_t i = 0; i < N1; ++i)
96+
res[i] = t1[i];
97+
for (size_t i = 0; i < N2; ++i)
98+
res[N1 + i] = t2[i];
99+
return res;
100+
}
101+
74102
} // namespace internal
75103
} // namespace __llvm_libc
76104

libc/src/__support/StringUtil/signal_to_string.cpp

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "src/__support/CPP/string_view.h"
1313
#include "src/__support/CPP/stringstream.h"
1414
#include "src/__support/StringUtil/message_mapper.h"
15+
#include "src/__support/StringUtil/tables/signal_table.h"
1516
#include "src/__support/integer_to_string.h"
1617

1718
#include <signal.h>
@@ -33,50 +34,15 @@ constexpr size_t max_buff_size() {
3334
constexpr size_t SIG_BUFFER_SIZE = max_buff_size();
3435
thread_local char signal_buffer[SIG_BUFFER_SIZE];
3536

36-
constexpr MsgMapping raw_sig_array[] = {
37-
MsgMapping(SIGHUP, "Hangup"), MsgMapping(SIGINT, "Interrupt"),
38-
MsgMapping(SIGQUIT, "Quit"), MsgMapping(SIGILL, "Illegal instruction"),
39-
MsgMapping(SIGTRAP, "Trace/breakpoint trap"),
40-
MsgMapping(SIGABRT, "Aborted"), MsgMapping(SIGBUS, "Bus error"),
41-
MsgMapping(SIGFPE, "Floating point exception"),
42-
MsgMapping(SIGKILL, "Killed"), MsgMapping(SIGUSR1, "User defined signal 1"),
43-
MsgMapping(SIGSEGV, "Segmentation fault"),
44-
MsgMapping(SIGUSR2, "User defined signal 2"),
45-
MsgMapping(SIGPIPE, "Broken pipe"), MsgMapping(SIGALRM, "Alarm clock"),
46-
MsgMapping(SIGTERM, "Terminated"),
47-
// SIGSTKFLT (may not exist)
48-
MsgMapping(SIGCHLD, "Child exited"), MsgMapping(SIGCONT, "Continued"),
49-
MsgMapping(SIGSTOP, "Stopped (signal)"), MsgMapping(SIGTSTP, "Stopped"),
50-
MsgMapping(SIGTTIN, "Stopped (tty input)"),
51-
MsgMapping(SIGTTOU, "Stopped (tty output)"),
52-
MsgMapping(SIGURG, "Urgent I/O condition"),
53-
MsgMapping(SIGXCPU, "CPU time limit exceeded"),
54-
MsgMapping(SIGXFSZ, "File size limit exceeded"),
55-
MsgMapping(SIGVTALRM, "Virtual timer expired"),
56-
MsgMapping(SIGPROF, "Profiling timer expired"),
57-
MsgMapping(SIGWINCH, "Window changed"), MsgMapping(SIGPOLL, "I/O possible"),
58-
// SIGPWR (may not exist)
59-
MsgMapping(SIGSYS, "Bad system call"),
60-
61-
#ifdef SIGSTKFLT
62-
MsgMapping(SIGSTKFLT, "Stack fault"), // unused
63-
#endif
64-
#ifdef SIGPWR
65-
MsgMapping(SIGPWR, "Power failure"), // ignored
66-
#endif
67-
};
68-
69-
// Since the string_mappings array is a map from signal numbers to their
70-
// corresponding strings, we have to have an array large enough we can use the
71-
// signal numbers as indexes. The highest signal is SIGSYS at 31, so an array of
72-
// 32 elements will be large enough to hold all of them.
73-
constexpr size_t SIG_ARRAY_SIZE = 32;
74-
75-
constexpr size_t RAW_ARRAY_LEN = sizeof(raw_sig_array) / sizeof(MsgMapping);
76-
constexpr size_t TOTAL_STR_LEN = total_str_len(raw_sig_array, RAW_ARRAY_LEN);
37+
constexpr size_t RAW_ARRAY_LEN = PLATFORM_SIGNALS.size();
38+
constexpr size_t TOTAL_STR_LEN =
39+
total_str_len(PLATFORM_SIGNALS.data(), RAW_ARRAY_LEN);
40+
41+
constexpr size_t SIG_ARRAY_SIZE =
42+
max_key_val(PLATFORM_SIGNALS.data(), RAW_ARRAY_LEN) + 1;
7743

7844
static constexpr MessageMapper<SIG_ARRAY_SIZE, TOTAL_STR_LEN>
79-
signal_mapper(raw_sig_array, RAW_ARRAY_LEN);
45+
signal_mapper(PLATFORM_SIGNALS.data(), RAW_ARRAY_LEN);
8046

8147
cpp::string_view build_signal_string(int sig_num, cpp::span<char> buffer) {
8248
cpp::string_view base_str;

0 commit comments

Comments
 (0)