Merge "Reduce strerror(3)'s impact on .data.rel.ro." am: d264aaf95d
am: 6b16fcc713
Change-Id: I52f8a463b1fb88bde3d4d640dbca7f194b429824
This commit is contained in:
commit
2194f7edb2
4 changed files with 179 additions and 198 deletions
|
@ -1142,7 +1142,6 @@ cc_library_static {
|
|||
"bionic/stdlib_l.cpp",
|
||||
"bionic/strchrnul.cpp",
|
||||
"bionic/strerror.cpp",
|
||||
"bionic/strerror_r.cpp",
|
||||
"bionic/string_l.cpp",
|
||||
"bionic/strings_l.cpp",
|
||||
"bionic/strsignal.cpp",
|
||||
|
|
|
@ -26,11 +26,188 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// G++ automatically defines _GNU_SOURCE, which then means that <string.h>
|
||||
// gives us the GNU variant.
|
||||
#undef _GNU_SOURCE
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <async_safe/log.h>
|
||||
|
||||
#include "private/ErrnoRestorer.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "bionic/pthread_internal.h"
|
||||
|
||||
extern "C" const char* __strerror_lookup(int);
|
||||
static const char* __sys_error_strings[] = {
|
||||
[0] = "Success",
|
||||
[EPERM] = "Operation not permitted",
|
||||
[ENOENT] = "No such file or directory",
|
||||
[ESRCH] = "No such process",
|
||||
[EINTR] = "Interrupted system call",
|
||||
[EIO] = "I/O error",
|
||||
[ENXIO] = "No such device or address",
|
||||
[E2BIG] = "Argument list too long",
|
||||
[ENOEXEC] = "Exec format error",
|
||||
[EBADF] = "Bad file descriptor",
|
||||
[ECHILD] = "No child processes",
|
||||
[EAGAIN] = "Try again",
|
||||
[ENOMEM] = "Out of memory",
|
||||
[EACCES] = "Permission denied",
|
||||
[EFAULT] = "Bad address",
|
||||
[ENOTBLK] = "Block device required",
|
||||
[EBUSY] = "Device or resource busy",
|
||||
[EEXIST] = "File exists",
|
||||
[EXDEV] = "Cross-device link",
|
||||
[ENODEV] = "No such device",
|
||||
[ENOTDIR] = "Not a directory",
|
||||
[EISDIR] = "Is a directory",
|
||||
[EINVAL] = "Invalid argument",
|
||||
[ENFILE] = "File table overflow",
|
||||
[EMFILE] = "Too many open files",
|
||||
[ENOTTY] = "Not a typewriter",
|
||||
[ETXTBSY] = "Text file busy",
|
||||
[EFBIG] = "File too large",
|
||||
[ENOSPC] = "No space left on device",
|
||||
[ESPIPE] = "Illegal seek",
|
||||
[EROFS] = "Read-only file system",
|
||||
[EMLINK] = "Too many links",
|
||||
[EPIPE] = "Broken pipe",
|
||||
[EDOM] = "Math argument out of domain of func",
|
||||
[ERANGE] = "Math result not representable",
|
||||
[EDEADLK] = "Resource deadlock would occur",
|
||||
[ENAMETOOLONG] = "File name too long",
|
||||
[ENOLCK] = "No record locks available",
|
||||
[ENOSYS] = "Function not implemented",
|
||||
[ENOTEMPTY] = "Directory not empty",
|
||||
[ELOOP] = "Too many symbolic links encountered",
|
||||
[ENOMSG] = "No message of desired type",
|
||||
[EIDRM] = "Identifier removed",
|
||||
[ECHRNG] = "Channel number out of range",
|
||||
[EL2NSYNC] = "Level 2 not synchronized",
|
||||
[EL3HLT] = "Level 3 halted",
|
||||
[EL3RST] = "Level 3 reset",
|
||||
[ELNRNG] = "Link number out of range",
|
||||
[EUNATCH] = "Protocol driver not attached",
|
||||
[ENOCSI] = "No CSI structure available",
|
||||
[EL2HLT] = "Level 2 halted",
|
||||
[EBADE] = "Invalid exchange",
|
||||
[EBADR] = "Invalid request descriptor",
|
||||
[EXFULL] = "Exchange full",
|
||||
[ENOANO] = "No anode",
|
||||
[EBADRQC] = "Invalid request code",
|
||||
[EBADSLT] = "Invalid slot",
|
||||
[EBFONT] = "Bad font file format",
|
||||
[ENOSTR] = "Device not a stream",
|
||||
[ENODATA] = "No data available",
|
||||
[ETIME] = "Timer expired",
|
||||
[ENOSR] = "Out of streams resources",
|
||||
[ENONET] = "Machine is not on the network",
|
||||
[ENOPKG] = "Package not installed",
|
||||
[EREMOTE] = "Object is remote",
|
||||
[ENOLINK] = "Link has been severed",
|
||||
[EADV] = "Advertise error",
|
||||
[ESRMNT] = "Srmount error",
|
||||
[ECOMM] = "Communication error on send",
|
||||
[EPROTO] = "Protocol error",
|
||||
[EMULTIHOP] = "Multihop attempted",
|
||||
[EDOTDOT] = "RFS specific error",
|
||||
[EBADMSG] = "Not a data message",
|
||||
[EOVERFLOW] = "Value too large for defined data type",
|
||||
[ENOTUNIQ] = "Name not unique on network",
|
||||
[EBADFD] = "File descriptor in bad state",
|
||||
[EREMCHG] = "Remote address changed",
|
||||
[ELIBACC] = "Can not access a needed shared library",
|
||||
[ELIBBAD] = "Accessing a corrupted shared library",
|
||||
[ELIBSCN] = ".lib section in a.out corrupted",
|
||||
[ELIBMAX] = "Attempting to link in too many shared libraries",
|
||||
[ELIBEXEC] = "Cannot exec a shared library directly",
|
||||
[EILSEQ] = "Illegal byte sequence",
|
||||
[ERESTART] = "Interrupted system call should be restarted",
|
||||
[ESTRPIPE] = "Streams pipe error",
|
||||
[EUSERS] = "Too many users",
|
||||
[ENOTSOCK] = "Socket operation on non-socket",
|
||||
[EDESTADDRREQ] = "Destination address required",
|
||||
[EMSGSIZE] = "Message too long",
|
||||
[EPROTOTYPE] = "Protocol wrong type for socket",
|
||||
[ENOPROTOOPT] = "Protocol not available",
|
||||
[EPROTONOSUPPORT] = "Protocol not supported",
|
||||
[ESOCKTNOSUPPORT] = "Socket type not supported",
|
||||
[EOPNOTSUPP] = "Operation not supported on transport endpoint",
|
||||
[EPFNOSUPPORT] = "Protocol family not supported",
|
||||
[EAFNOSUPPORT] = "Address family not supported by protocol",
|
||||
[EADDRINUSE] = "Address already in use",
|
||||
[EADDRNOTAVAIL] = "Cannot assign requested address",
|
||||
[ENETDOWN] = "Network is down",
|
||||
[ENETUNREACH] = "Network is unreachable",
|
||||
[ENETRESET] = "Network dropped connection because of reset",
|
||||
[ECONNABORTED] = "Software caused connection abort",
|
||||
[ECONNRESET] = "Connection reset by peer",
|
||||
[ENOBUFS] = "No buffer space available",
|
||||
[EISCONN] = "Transport endpoint is already connected",
|
||||
[ENOTCONN] = "Transport endpoint is not connected",
|
||||
[ESHUTDOWN] = "Cannot send after transport endpoint shutdown",
|
||||
[ETOOMANYREFS] = "Too many references: cannot splice",
|
||||
[ETIMEDOUT] = "Connection timed out",
|
||||
[ECONNREFUSED] = "Connection refused",
|
||||
[EHOSTDOWN] = "Host is down",
|
||||
[EHOSTUNREACH] = "No route to host",
|
||||
[EALREADY] = "Operation already in progress",
|
||||
[EINPROGRESS] = "Operation now in progress",
|
||||
[ESTALE] = "Stale NFS file handle",
|
||||
[EUCLEAN] = "Structure needs cleaning",
|
||||
[ENOTNAM] = "Not a XENIX named type file",
|
||||
[ENAVAIL] = "No XENIX semaphores available",
|
||||
[EISNAM] = "Is a named type file",
|
||||
[EREMOTEIO] = "Remote I/O error",
|
||||
[EDQUOT] = "Quota exceeded",
|
||||
[ENOMEDIUM] = "No medium found",
|
||||
[EMEDIUMTYPE] = "Wrong medium type",
|
||||
[ECANCELED] = "Operation Canceled",
|
||||
[ENOKEY] = "Required key not available",
|
||||
[EKEYEXPIRED] = "Key has expired",
|
||||
[EKEYREVOKED] = "Key has been revoked",
|
||||
[EKEYREJECTED] = "Key was rejected by service",
|
||||
[EOWNERDEAD] = "Owner died",
|
||||
[ENOTRECOVERABLE] = "State not recoverable",
|
||||
[ERFKILL] = "Operation not possible due to RF-kill",
|
||||
[EHWPOISON] = "Memory page has hardware error",
|
||||
};
|
||||
|
||||
static inline const char* __strerror_lookup(int error_number) {
|
||||
if (error_number < 0 || error_number >= static_cast<int>(arraysize(__sys_error_strings))) {
|
||||
return nullptr;
|
||||
}
|
||||
return __sys_error_strings[error_number];
|
||||
}
|
||||
|
||||
int strerror_r(int error_number, char* buf, size_t buf_len) {
|
||||
ErrnoRestorer errno_restorer;
|
||||
size_t length;
|
||||
|
||||
const char* error_name = __strerror_lookup(error_number);
|
||||
if (error_name != nullptr) {
|
||||
length = strlcpy(buf, error_name, buf_len);
|
||||
} else {
|
||||
length = async_safe_format_buffer(buf, buf_len, "Unknown error %d", error_number);
|
||||
}
|
||||
if (length >= buf_len) {
|
||||
errno_restorer.override(ERANGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" char* __gnu_strerror_r(int error_number, char* buf, size_t buf_len) {
|
||||
ErrnoRestorer errno_restorer; // The glibc strerror_r doesn't set errno if it truncates...
|
||||
strerror_r(error_number, buf, buf_len);
|
||||
return buf; // ...and just returns whatever fit.
|
||||
}
|
||||
|
||||
char* strerror(int error_number) {
|
||||
// Just return the original constant in the easy cases.
|
||||
|
|
|
@ -1,195 +0,0 @@
|
|||
/* $OpenBSD: strerror_r.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */
|
||||
/* Public Domain <marc@snafu.org> */
|
||||
|
||||
// G++ automatically defines _GNU_SOURCE, which then means that <string.h>
|
||||
// gives us the GNU variant.
|
||||
#undef _GNU_SOURCE
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <async_safe/log.h>
|
||||
|
||||
#include "private/ErrnoRestorer.h"
|
||||
|
||||
struct Pair {
|
||||
int code;
|
||||
const char* msg;
|
||||
};
|
||||
|
||||
static const char* __code_string_lookup(const Pair* strings, int code) {
|
||||
for (size_t i = 0; strings[i].msg != nullptr; ++i) {
|
||||
if (strings[i].code == code) {
|
||||
return strings[i].msg;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const Pair _sys_error_strings[] = {
|
||||
{0, "Success"},
|
||||
{EPERM, "Operation not permitted"},
|
||||
{ENOENT, "No such file or directory"},
|
||||
{ESRCH, "No such process"},
|
||||
{EINTR, "Interrupted system call"},
|
||||
{EIO, "I/O error"},
|
||||
{ENXIO, "No such device or address"},
|
||||
{E2BIG, "Argument list too long"},
|
||||
{ENOEXEC, "Exec format error"},
|
||||
{EBADF, "Bad file descriptor"},
|
||||
{ECHILD, "No child processes"},
|
||||
{EAGAIN, "Try again"},
|
||||
{ENOMEM, "Out of memory"},
|
||||
{EACCES, "Permission denied"},
|
||||
{EFAULT, "Bad address"},
|
||||
{ENOTBLK, "Block device required"},
|
||||
{EBUSY, "Device or resource busy"},
|
||||
{EEXIST, "File exists"},
|
||||
{EXDEV, "Cross-device link"},
|
||||
{ENODEV, "No such device"},
|
||||
{ENOTDIR, "Not a directory"},
|
||||
{EISDIR, "Is a directory"},
|
||||
{EINVAL, "Invalid argument"},
|
||||
{ENFILE, "File table overflow"},
|
||||
{EMFILE, "Too many open files"},
|
||||
{ENOTTY, "Not a typewriter"},
|
||||
{ETXTBSY, "Text file busy"},
|
||||
{EFBIG, "File too large"},
|
||||
{ENOSPC, "No space left on device"},
|
||||
{ESPIPE, "Illegal seek"},
|
||||
{EROFS, "Read-only file system"},
|
||||
{EMLINK, "Too many links"},
|
||||
{EPIPE, "Broken pipe"},
|
||||
{EDOM, "Math argument out of domain of func"},
|
||||
{ERANGE, "Math result not representable"},
|
||||
{EDEADLK, "Resource deadlock would occur"},
|
||||
{ENAMETOOLONG, "File name too long"},
|
||||
{ENOLCK, "No record locks available"},
|
||||
{ENOSYS, "Function not implemented"},
|
||||
{ENOTEMPTY, "Directory not empty"},
|
||||
{ELOOP, "Too many symbolic links encountered"},
|
||||
{ENOMSG, "No message of desired type"},
|
||||
{EIDRM, "Identifier removed"},
|
||||
{ECHRNG, "Channel number out of range"},
|
||||
{EL2NSYNC, "Level 2 not synchronized"},
|
||||
{EL3HLT, "Level 3 halted"},
|
||||
{EL3RST, "Level 3 reset"},
|
||||
{ELNRNG, "Link number out of range"},
|
||||
{EUNATCH, "Protocol driver not attached"},
|
||||
{ENOCSI, "No CSI structure available"},
|
||||
{EL2HLT, "Level 2 halted"},
|
||||
{EBADE, "Invalid exchange"},
|
||||
{EBADR, "Invalid request descriptor"},
|
||||
{EXFULL, "Exchange full"},
|
||||
{ENOANO, "No anode"},
|
||||
{EBADRQC, "Invalid request code"},
|
||||
{EBADSLT, "Invalid slot"},
|
||||
{EBFONT, "Bad font file format"},
|
||||
{ENOSTR, "Device not a stream"},
|
||||
{ENODATA, "No data available"},
|
||||
{ETIME, "Timer expired"},
|
||||
{ENOSR, "Out of streams resources"},
|
||||
{ENONET, "Machine is not on the network"},
|
||||
{ENOPKG, "Package not installed"},
|
||||
{EREMOTE, "Object is remote"},
|
||||
{ENOLINK, "Link has been severed"},
|
||||
{EADV, "Advertise error"},
|
||||
{ESRMNT, "Srmount error"},
|
||||
{ECOMM, "Communication error on send"},
|
||||
{EPROTO, "Protocol error"},
|
||||
{EMULTIHOP, "Multihop attempted"},
|
||||
{EDOTDOT, "RFS specific error"},
|
||||
{EBADMSG, "Not a data message"},
|
||||
{EOVERFLOW, "Value too large for defined data type"},
|
||||
{ENOTUNIQ, "Name not unique on network"},
|
||||
{EBADFD, "File descriptor in bad state"},
|
||||
{EREMCHG, "Remote address changed"},
|
||||
{ELIBACC, "Can not access a needed shared library"},
|
||||
{ELIBBAD, "Accessing a corrupted shared library"},
|
||||
{ELIBSCN, ".lib section in a.out corrupted"},
|
||||
{ELIBMAX, "Attempting to link in too many shared libraries"},
|
||||
{ELIBEXEC, "Cannot exec a shared library directly"},
|
||||
{EILSEQ, "Illegal byte sequence"},
|
||||
{ERESTART, "Interrupted system call should be restarted"},
|
||||
{ESTRPIPE, "Streams pipe error"},
|
||||
{EUSERS, "Too many users"},
|
||||
{ENOTSOCK, "Socket operation on non-socket"},
|
||||
{EDESTADDRREQ, "Destination address required"},
|
||||
{EMSGSIZE, "Message too long"},
|
||||
{EPROTOTYPE, "Protocol wrong type for socket"},
|
||||
{ENOPROTOOPT, "Protocol not available"},
|
||||
{EPROTONOSUPPORT, "Protocol not supported"},
|
||||
{ESOCKTNOSUPPORT, "Socket type not supported"},
|
||||
{EOPNOTSUPP, "Operation not supported on transport endpoint"},
|
||||
{EPFNOSUPPORT, "Protocol family not supported"},
|
||||
{EAFNOSUPPORT, "Address family not supported by protocol"},
|
||||
{EADDRINUSE, "Address already in use"},
|
||||
{EADDRNOTAVAIL, "Cannot assign requested address"},
|
||||
{ENETDOWN, "Network is down"},
|
||||
{ENETUNREACH, "Network is unreachable"},
|
||||
{ENETRESET, "Network dropped connection because of reset"},
|
||||
{ECONNABORTED, "Software caused connection abort"},
|
||||
{ECONNRESET, "Connection reset by peer"},
|
||||
{ENOBUFS, "No buffer space available"},
|
||||
{EISCONN, "Transport endpoint is already connected"},
|
||||
{ENOTCONN, "Transport endpoint is not connected"},
|
||||
{ESHUTDOWN, "Cannot send after transport endpoint shutdown"},
|
||||
{ETOOMANYREFS, "Too many references: cannot splice"},
|
||||
{ETIMEDOUT, "Connection timed out"},
|
||||
{ECONNREFUSED, "Connection refused"},
|
||||
{EHOSTDOWN, "Host is down"},
|
||||
{EHOSTUNREACH, "No route to host"},
|
||||
{EALREADY, "Operation already in progress"},
|
||||
{EINPROGRESS, "Operation now in progress"},
|
||||
{ESTALE, "Stale NFS file handle"},
|
||||
{EUCLEAN, "Structure needs cleaning"},
|
||||
{ENOTNAM, "Not a XENIX named type file"},
|
||||
{ENAVAIL, "No XENIX semaphores available"},
|
||||
{EISNAM, "Is a named type file"},
|
||||
{EREMOTEIO, "Remote I/O error"},
|
||||
{EDQUOT, "Quota exceeded"},
|
||||
{ENOMEDIUM, "No medium found"},
|
||||
{EMEDIUMTYPE, "Wrong medium type"},
|
||||
{ECANCELED, "Operation Canceled"},
|
||||
{ENOKEY, "Required key not available"},
|
||||
{EKEYEXPIRED, "Key has expired"},
|
||||
{EKEYREVOKED, "Key has been revoked"},
|
||||
{EKEYREJECTED, "Key was rejected by service"},
|
||||
{EOWNERDEAD, "Owner died"},
|
||||
{ENOTRECOVERABLE, "State not recoverable"},
|
||||
{ERFKILL, "Operation not possible due to RF-kill"},
|
||||
{EHWPOISON, "Memory page has hardware error"},
|
||||
{0, nullptr}
|
||||
};
|
||||
|
||||
extern "C" __LIBC_HIDDEN__ const char* __strerror_lookup(int error_number) {
|
||||
return __code_string_lookup(_sys_error_strings, error_number);
|
||||
}
|
||||
|
||||
int strerror_r(int error_number, char* buf, size_t buf_len) {
|
||||
ErrnoRestorer errno_restorer;
|
||||
size_t length;
|
||||
|
||||
const char* error_name = __strerror_lookup(error_number);
|
||||
if (error_name != nullptr) {
|
||||
length = strlcpy(buf, error_name, buf_len);
|
||||
} else {
|
||||
length = async_safe_format_buffer(buf, buf_len, "Unknown error %d", error_number);
|
||||
}
|
||||
if (length >= buf_len) {
|
||||
errno_restorer.override(ERANGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" char* __gnu_strerror_r(int error_number, char* buf, size_t buf_len) {
|
||||
ErrnoRestorer errno_restorer; // The glibc strerror_r doesn't set errno if it truncates...
|
||||
strerror_r(error_number, buf, buf_len);
|
||||
return buf; // ...and just returns whatever fit.
|
||||
}
|
|
@ -61,7 +61,7 @@ TEST(STRING_TEST, strerror) {
|
|||
|
||||
// Invalid.
|
||||
ASSERT_STREQ("Unknown error -1", strerror(-1));
|
||||
ASSERT_STREQ("Unknown error 1234", strerror(1234));
|
||||
ASSERT_STREQ("Unknown error 134", strerror(EHWPOISON + 1));
|
||||
}
|
||||
|
||||
#if defined(__BIONIC__)
|
||||
|
|
Loading…
Reference in a new issue