// Don't call libc's close(), since it might call back into us as a result of fdsan/fdtrack. #pragma clang poison close staticint __close(int fd) { return syscall(__NR_close, fd);
}
// Don't call libc's socket(), since it might call back into us as a result of fdsan/fdtrack. #pragma clang poison socket staticint __socket(int domain, int type, int protocol) { #ifdefined(__i386__) unsignedlong args[3] = {static_cast<unsignedlong>(domain), static_cast<unsignedlong>(type), static_cast<unsignedlong>(protocol)}; return syscall(__NR_socketcall, SYS_SOCKET, &args); #else return syscall(__NR_socket, domain, type, protocol); #endif
}
// Must be kept in sync with frameworks/base/core/java/android/util/EventLog.java. enum AndroidEventLogType {
EVENT_TYPE_INT = 0,
EVENT_TYPE_LONG = 1,
EVENT_TYPE_STRING = 2,
EVENT_TYPE_LIST = 3,
EVENT_TYPE_FLOAT = 4,
};
void Send(constchar* data, int len) { if (len < 0) {
len = strlen(data);
}
total += len;
while (len > 0) {
ssize_t bytes = TEMP_FAILURE_RETRY(write(fd_, data, len)); if (bytes == -1) { return;
}
data += bytes;
len -= bytes;
}
}
size_t total;
private: int fd_;
};
/*** formatted output implementation
***/
/* Parse a decimal string from 'format + *ppos', *returnthevalue,andwritesthenewpositionpast *thedecimalstringin'*ppos'onexit. * *NOTE:Does*not*handleasignprefix.
*/ staticunsigned parse_decimal(constchar* format, int* ppos) { constchar* p = format + *ppos; unsigned result = 0;
for (;;) { int ch = *p; unsigned d = static_cast<unsigned>(ch - '0');
if (d >= 10U) { break;
}
result = result * 10 + d;
p++;
}
*ppos = p - format; return result;
}
// Writes number 'value' in base 'base' into buffer 'buf' of size 'buf_size' bytes. // Assumes that buf_size > 0. staticvoid format_unsigned(char* buf, size_t buf_size, uint64_t value, int base, bool caps) { char* p = buf; char* end = buf + buf_size - 1;
// Generate digit string in reverse order. while (value) { unsigned d = value % base;
value /= base; if (p != end) { char ch; if (d < 10) {
ch = '0' + d;
} else {
ch = (caps ? 'A' : 'a') + (d - 10);
}
*p++ = ch;
}
}
// Special case for 0. if (p == buf) { if (p != end) {
*p++ = '0';
}
}
*p = '\0';
// Reverse digit string in-place.
size_t length = p - buf; for (size_t i = 0, j = length - 1; i < j; ++i, --j) { char ch = buf[i];
buf[i] = buf[j];
buf[j] = ch;
}
}
staticvoid format_integer(char* buf, size_t buf_size, uint64_t value, char conversion) { // Decode the conversion specifier. int is_signed = (conversion == 'd' || conversion == 'i' || conversion == 'o'); int base = 10; if (tolower(conversion) == 'x') {
base = 16;
} elseif (conversion == 'o') {
base = 8;
} elseif (tolower(conversion) == 'b') {
base = 2;
} bool caps = (conversion == 'X');
template <typename Out> staticvoid SendRepeat(Out& o, char ch, int count) { char pad[8];
memset(pad, ch, sizeof(pad));
constint pad_size = static_cast<int>(sizeof(pad)); while (count > 0) { int avail = count; if (avail > pad_size) {
avail = pad_size;
}
o.Send(pad, avail);
count -= avail;
}
}
/* Perform formatted output to an output target 'o' */ template <typename Out> staticvoid out_vformat(Out& o, constchar* format, va_list args) { int nn = 0;
for (;;) { int mm; int padZero = 0; int padLeft = 0; char sign = '\0'; int width = -1; int prec = -1; bool alternate = false;
size_t bytelen = sizeof(int); int slen; char buffer[64]; // temporary buffer used to format numbers/format errno string
char c;
/* first, find all characters that are not 0 or '%' */ /* then send them to the output directly */
mm = nn; do {
c = format[mm]; if (c == '\0' || c == '%') break;
mm++;
} while (1);
if (mm > nn) {
o.Send(format + nn, mm - nn);
nn = mm;
}
/* is this it ? then exit */ if (c == '\0') break;
/* nope, we are at a '%' modifier */
nn++; // skip it
/* parse field width */ if ((c >= '0' && c <= '9')) {
nn--;
width = static_cast<int>(parse_decimal(format, &nn));
c = format[nn++];
}
/* parse precision */ if (c == '.') {
prec = static_cast<int>(parse_decimal(format, &nn));
c = format[nn++];
}
/* length modifier */ switch (c) { case'h':
bytelen = sizeof(short); if (format[nn] == 'h') {
bytelen = sizeof(char);
nn += 1;
}
c = format[nn++]; break; case'l':
bytelen = sizeof(long); if (format[nn] == 'l') {
bytelen = sizeof(longlong);
nn += 1;
}
c = format[nn++]; break; case'z':
bytelen = sizeof(size_t);
c = format[nn++]; break; case't':
bytelen = sizeof(ptrdiff_t);
c = format[nn++]; break; default:;
}
/* conversion specifier */ constchar* str = buffer; if (c == 's') { /* string */
str = va_arg(args, constchar*);
} elseif (c == 'c') { /* character */ /* NOTE: char is promoted to int when passed through the stack */
buffer[0] = static_cast<char>(va_arg(args, int));
buffer[1] = '\0';
} elseif (c == 'p') {
uint64_t value = reinterpret_cast<uintptr_t>(va_arg(args, void*));
buffer[0] = '0';
buffer[1] = 'x';
format_integer(buffer + 2, sizeof(buffer) - 2, value, 'x');
} elseif (c == 'm') { #if __ANDROID_API_LEVEL__ >= 35// This library is used in mainline modules. if (alternate) { constchar* name = strerrorname_np(errno); if (name) {
strcpy(buffer, name);
} else {
format_integer(buffer, sizeof(buffer), errno, 'd');
}
} else #endif
{
strerror_r(errno, buffer, sizeof(buffer));
}
} elseif (tolower(c) == 'b' || c == 'd' || c == 'i' || c == 'o' || c == 'u' ||
tolower(c) == 'x') { /* integers - first read value from stack */
uint64_t value; int is_signed = (c == 'd' || c == 'i' || c == 'o');
/* NOTE: int8_t and int16_t are promoted to int when passed *throughthestack
*/ switch (bytelen) { case1:
value = static_cast<uint8_t>(va_arg(args, int)); break; case2:
value = static_cast<uint16_t>(va_arg(args, int)); break; case4:
value = va_arg(args, uint32_t); break; case8:
value = va_arg(args, uint64_t); break; default: return; /* should not happen */
}
/* sign extension, if needed */ if (is_signed) { int shift = 64 - 8 * bytelen;
value = static_cast<uint64_t>((static_cast<int64_t>(value << shift)) >> shift);
}
int async_safe_format_buffer_va_list(char* buffer, size_t buffer_size, constchar* format,
va_list args) {
BufferOutputStream os(buffer, buffer_size);
out_vformat(os, format, args); return os.total;
}
int async_safe_format_buffer(char* buffer, size_t buffer_size, constchar* format, ...) {
va_list args;
va_start(args, format); int buffer_len = async_safe_format_buffer_va_list(buffer, buffer_size, format, args);
va_end(args); return buffer_len;
}
int async_safe_format_fd_va_list(int fd, constchar* format, va_list args) {
FdOutputStream os(fd);
out_vformat(os, format, args); return os.total;
}
int async_safe_format_fd(int fd, constchar* format, ...) {
va_list args;
va_start(args, format); int result = async_safe_format_fd_va_list(fd, format, args);
va_end(args); return result;
}
int result = TEMP_FAILURE_RETRY(writev(STDERR_FILENO, vec, 4)); return result;
}
staticint open_log_socket() { // ToDo: Ideally we want this to fail if the gid of the current // process is AID_LOGD, but will have to wait until we have // registered this in private/android_filesystem_config.h. We have // found that all logd crashes thus far have had no problem stuffing // the UNIX domain socket and moving on so not critical *today*.
int log_fd = TEMP_FAILURE_RETRY(__socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)); if (log_fd == -1) { return -1;
}
int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, sizeof(vec) / sizeof(vec[0])));
__close(main_log_fd); return result;
}
int async_safe_format_log_va_list(int priority, constchar* tag, constchar* format, va_list args) {
ErrnoRestorer errno_restorer; char buffer[1024];
BufferOutputStream os(buffer, sizeof(buffer));
out_vformat(os, format, args); return async_safe_write_log(priority, tag, buffer);
}
int async_safe_format_log(int priority, constchar* tag, constchar* format, ...) {
va_list args;
va_start(args, format); int result = async_safe_format_log_va_list(priority, tag, format, args);
va_end(args); return result;
}
if (prefix) {
os.Send(prefix, strlen(prefix));
os.Send(": ", 2);
}
out_vformat(os, format, args);
// Log to stderr for the benefit of "adb shell" users and gtests. struct iovec iov[2] = {
{msg, strlen(msg)}, {const_cast<char*>("\n"), 1},
};
TEMP_FAILURE_RETRY(writev(2, iov, 2));
// Log to the log for the benefit of regular app developers (whose stdout and stderr are closed).
async_safe_write_log(ANDROID_LOG_FATAL, "libc", msg);
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.13Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-06-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.