#define _GNU_SOURCE
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>
#include <pthread.h>

/* glibc fortified _chk functions -- just call the non-checked version */
void *__memcpy_chk(void *dest, const void *src, size_t n, size_t destlen) {
    (void)destlen;
    return memcpy(dest, src, n);
}

size_t __mbsrtowcs_chk(wchar_t *dest, const char **src, size_t n, size_t destlen) {
    (void)destlen;
    return mbsrtowcs(dest, src, n, NULL);
}

int __vsnprintf_chk(char *s, size_t n, int flags, size_t slen, const char *fmt, va_list ap) {
    (void)flags;
    (void)slen;
    return vsnprintf(s, n, fmt, ap);
}

/* LFS64 large-file aliases.
 * Use fileno+lseek instead of fseeko/ftello so we only depend on
 * low-level syscall wrappers (available in both glibc and musl). */
#include <unistd.h>
#include <stdint.h>
#undef fseeko64
#undef ftello64
int fseeko64(FILE *stream, off_t offset, int whence) {
    int fd = fileno(stream);
    if (fd < 0) return -1;
    return lseek(fd, offset, whence) == (off_t)-1 ? -1 : 0;
}

off_t ftello64(FILE *stream) {
    int fd = fileno(stream);
    if (fd < 0) return -1;
    return lseek(fd, 0, SEEK_CUR);
}

/* glibc internal singleton: always single-threaded in our static binary */
int __libc_single_threaded = 1;

/* __cxa_thread_atexit_impl -- thread-local destructors */
struct cxa_atexit_entry {
    void (*dtor)(void *);
    void *obj;
    struct cxa_atexit_entry *next;
};

static __thread struct cxa_atexit_entry *atexit_list = NULL;

static void run_cxa_dtors(void *unused) {
    (void)unused;
    struct cxa_atexit_entry *e = atexit_list;
    while (e) {
        struct cxa_atexit_entry *next = e->next;
        e->dtor(e->obj);
        free(e);
        e = next;
    }
    atexit_list = NULL;
}

static pthread_once_t dtor_key_once = PTHREAD_ONCE_INIT;
static pthread_key_t dtor_key;

static void make_dtor_key(void) {
    pthread_key_create(&dtor_key, run_cxa_dtors);
}

/* C23 strtoul/strtoll (glibc 2.38+ provides __isoc23_*; musl lacks it) */
unsigned long __isoc23_strtoul(const char *nptr, char **endptr, int base) {
    return strtoul(nptr, endptr, base);
}
long long __isoc23_strtoll(const char *nptr, char **endptr, int base) {
    return strtoll(nptr, endptr, base);
}

/* wmemset fortified */
wchar_t *__wmemset_chk(wchar_t *s, wchar_t c, size_t n, size_t destlen) {
    (void)destlen;
    return wmemset(s, c, n);
}

/* Additional fortified functions from glibc's libstdc++.a */
int __fprintf_chk(FILE *stream, int flag, const char *format, ...) {
    (void)flag;
    int r;
    va_list ap;
    va_start(ap, format);
    r = vfprintf(stream, format, ap);
    va_end(ap);
    return r;
}

int __snprintf_chk(char *s, size_t n, int flag, size_t slen, const char *format, ...) {
    (void)flag;
    (void)slen;
    int r;
    va_list ap;
    va_start(ap, format);
    r = vsnprintf(s, n, format, ap);
    va_end(ap);
    return r;
}

int __sprintf_chk(char *s, int flag, size_t slen, const char *format, ...) {
    (void)flag;
    (void)slen;
    int r;
    va_list ap;
    va_start(ap, format);
    r = vsnprintf(s, SIZE_MAX, format, ap);
    va_end(ap);
    return r;
}

/* More fortified string functions */
char *__strncpy_chk(char *dest, const char *src, size_t n, size_t destlen) {
    (void)destlen;
    return strncpy(dest, src, n);
}

void *__memmove_chk(void *dest, const void *src, size_t n, size_t destlen) {
    (void)destlen;
    return memmove(dest, src, n);
}

void *__memset_chk(void *s, int c, size_t n, size_t destlen) {
    (void)destlen;
    return memset(s, c, n);
}

int __cxa_thread_atexit_impl(void (*dtor)(void *), void *obj, void *dso_handle) {
    (void)dso_handle;
    struct cxa_atexit_entry *e = malloc(sizeof(*e));
    if (!e) return -1;
    e->dtor = dtor;
    e->obj = obj;
    e->next = atexit_list;
    atexit_list = e;

    pthread_once(&dtor_key_once, make_dtor_key);
    pthread_setspecific(dtor_key, (void *)1);
    return 0;
}

Изменить пасту