#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <unistd.h>
#include <bits/wordsize.h>
#ifndef AT_NULL
#define AT_NULL 0
#endif
#ifndef SIZE_MAX
#define SIZE_MAX ((size_t)-1)
#endif
#ifndef PR_GET_NAME
#define PR_GET_NAME 16
#endif
#ifndef PR_SET_NAME
#define PR_SET_NAME 15
#endif
#ifndef O_CLOEXEC
#define O_CLOEXEC 02000000
#endif
__attribute__((weak)) unsigned long getauxval(unsigned long type) {
int fd = open("/proc/self/auxv", O_RDONLY | O_CLOEXEC);
if (fd < 0) {
if (errno != ENOENT && errno != EACCES) {
errno = ENOENT;
}
return 0;
}
typedef struct auxv_entry {
#if __WORDSIZE == 64
uint64_t a_type;
uint64_t a_val;
#elif __WORDSIZE == 32
uint32_t a_type;
uint32_t a_val;
#else
#error "unknown arch size, please contact Memfault support"
#endif
} auxv_entry_t;
auxv_entry_t entry;
while (1) {
size_t bytes_read = 0;
while (bytes_read < sizeof(entry)) {
ssize_t n = read(fd, ((char*)&entry) + bytes_read,
sizeof(entry) - bytes_read);
if (n < 0) {
if (errno == EINTR) {
continue;
}
close(fd);
errno = ENOENT;
return 0;
}
if (n == 0) {
close(fd);
errno = ENOENT;
return 0;
}
bytes_read += n;
}
if (entry.a_type == AT_NULL) {
break;
}
if (entry.a_type == type) {
unsigned long result = entry.a_val;
close(fd);
return result;
}
}
close(fd);
errno = ENOENT;
return 0;
}
__attribute__((weak)) int pthread_setname_np(pthread_t thread, const char *name) {
if (name == NULL) {
return EINVAL;
}
size_t name_len = strnlen(name, 16);
if (name_len > 15) {
return ERANGE;
}
if (name[name_len] != '\0') {
return ERANGE;
}
if (!pthread_equal(thread, pthread_self())) {
return ENOSYS;
}
if (prctl(PR_SET_NAME, (unsigned long)name, 0UL, 0UL, 0UL) != 0) {
int err = errno;
return err ? err : EINVAL; }
return 0;
}